-- 作者:卷积内核
-- 发布时间:6/1/2009 2:10:00 PM
-- 使用.x文件模型(3)
通过四元数实现模型旋转 早在1843年,William Roman Hamilton爵士就已经发明了作为复数扩展的四元数(quaternion),但是直到1985年才有一个叫Ken ShoeMake的人在SIGGRAPH(Special Interest Group on Computer Graphics,美国计算机协会的图形专业组)把四元数引入计算机图形处理领域。 四元数将三维空间中旋转的概念扩展到四维空间,这对于表示和处理3D中点的旋转很有用。四元数还可以用于以下地方: (1)骨骼动画(skeletal animation) (2)反向动力学动画(inverse cinimatic) (3)3D物理学 在游戏中可以使用四元数来取代旋转矩阵,它可用于描述3D空间中绕任意轴的任意旋转。使用四元数来代替旋转矩阵具有以下优点: (1)四元数占用的空间比矩阵少。 (2)一些操作在视觉上会显得更为平滑,比如可以在两个四元数之间做插值运算。 Direct3D扩展实用库函数D3DXQuaternionRotationYawPitchRoll()提供了将三个欧拉角转换为一个四元数的功能,该函数声明如下: Builds a quaternion with the given yaw, pitch, and roll. D3DXQUATERNION * D3DXQuaternionRotationYawPitchRoll( D3DXQUATERNION * pOut, FLOAT Yaw, FLOAT Pitch, FLOAT Roll); Parameters pOut [in, out] Pointer to the D3DXQUATERNION structure that is the result of the operation. Yaw [in] Yaw around the y-axis, in radians. Pitch [in] Pitch around the x-axis, in radians. Roll [in] Roll around the z-axis, in radians. Return Values Pointer to a D3DXQUATERNION structure with the specified yaw, pitch, and roll. Remarks The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXQuaternionRotationYawPitchRoll function can be used as a parameter for another function. Use D3DXQuaternionNormalize for any quaternion input that is not already normalized. 由于Direct3D变换引擎需要用矩阵来执行旋转,所以需要将四元数转换为矩阵格式。Direct3D扩展实用库函数D3DXMatrixRotationQuaternion()提供了将四元数转换成矩阵的功能,该函数声明如下: Builds a rotation matrix from a quaternion. D3DXMATRIX * D3DXMatrixRotationQuaternion( D3DXMATRIX * pOut, CONST D3DXQUATERNION * pQ); Parameters pOut [in, out] Pointer to the D3DXMATRIX structure that is the result of the operation. pQ [in] Pointer to the source D3DXQUATERNION structure. Return Values Pointer to a D3DXMATRIX structure built from the source quaternion. Remarks The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixRotationQuaternion function can be used as a parameter for another function. For information about how to calculate quaternion values from a direction vector ( x, y, z ) and an angle of rotation, see D3DXQUATERNION. 该示例程序同样可以通过键盘控制飞机模型的位置和姿态,控制方式和上一个示例程序完全相同,但实现代码却简洁得多,主要改动代码如下: void setup_world_matrix(){ static long previous_time = 0; static float elapsed_time = 0.0f; elapsed_time = (timeGetTime() - previous_time) / 1000.0f; previous_time = timeGetTime(); float angle_around_right = 0.0f, angle_around_up = 0.0f, angle_around_look = 0.0f; if(g_keys['D']) angle_around_look -= 3 * elapsed_time; if(g_keys['A']) angle_around_look += 3 * elapsed_time; if(g_keys['S']) angle_around_right -= 3 * elapsed_time; if(g_keys['W']) angle_around_right += 3 * elapsed_time; if(g_keys['Q']) angle_around_up -= 3 * elapsed_time; if(g_keys['E']) angle_around_up += 3 * elapsed_time; // now, calculate ratation matrix. D3DXQUATERNION quat; D3DXMATRIX mat_rotation; D3DXQuaternionRotationYawPitchRoll(&quat, angle_around_up, angle_around_right, angle_around_look); D3DXMatrixRotationQuaternion(&mat_rotation, &quat); D3DXMatrixMultiply(&g_mat_world, &mat_rotation, &g_mat_world); // get look vector D3DXVECTOR3 look; look.x = g_mat_world._31; look.y = g_mat_world._32; look.z = g_mat_world._33; // move model forward or backward if(g_keys['F']) { g_mat_world._41 += 30 * elapsed_time * look.x; g_mat_world._42 += 30 * elapsed_time * look.y; g_mat_world._43 += 30 * elapsed_time * look.z; } if(g_keys['V']) { g_mat_world._41 -= 30 * elapsed_time * look.x; g_mat_world._42 -= 30 * elapsed_time * look.y; g_mat_world._43 -= 30 * elapsed_time * look.z; } g_device->SetTransform(D3DTS_WORLD, &g_mat_world);} 在该示例程序中,通过用户输入,每一帧都对飞机模型进行重新定位,不断改变飞机模型在空间中的位置或姿态,如果每两帧间的时间间隔足够小,则感到飞机模型位置或姿态的变换是连续的,也就形成了连续的动画,实际上这就是三维动画的基本原理,通过不断改变场景中各物体的位置和姿态使各物体运动起来。为了保证动画的连续性,帧速率要达到25帧/秒以上。 注意:模型的旋转是绕自身坐标轴的旋转,而不是绕世界坐标系的3个坐标轴旋转,而且在旋转模型时其自身坐标轴也在不断变化。 [B][URL=http://www.cppblog.com/Files/changingnow/StateControlUseQuat.rar]下载示例工程[/URL][/B]
|