通過四元數(shù)實(shí)現(xiàn)模型旋轉(zhuǎn)
早在1843年,William Roman Hamilton爵士就已經(jīng)發(fā)明了作為復(fù)數(shù)擴(kuò)展的四元數(shù)(quaternion),但是直到1985年才有一個(gè)叫Ken
ShoeMake的人在SIGGRAPH(Special
Interest Group on Computer Graphics,美國(guó)計(jì)算機(jī)協(xié)會(huì)的圖形專業(yè)組)把四元數(shù)引入計(jì)算機(jī)圖形處理領(lǐng)域。
四元數(shù)將三維空間中旋轉(zhuǎn)的概念擴(kuò)展到四維空間,這對(duì)于表示和處理3D中點(diǎn)的旋轉(zhuǎn)很有用。四元數(shù)還可以用于以下地方:
(1)骨骼動(dòng)畫(skeletal animation)
(2)反向動(dòng)力學(xué)動(dòng)畫(inverse cinimatic)
(3)3D物理學(xué)
在游戲中可以使用四元數(shù)來取代旋轉(zhuǎn)矩陣,它可用于描述3D空間中繞任意軸的任意旋轉(zhuǎn)。使用四元數(shù)來代替旋轉(zhuǎn)矩陣具有以下優(yōu)點(diǎn):
(1)四元數(shù)占用的空間比矩陣少。
(2)一些操作在視覺上會(huì)顯得更為平滑,比如可以在兩個(gè)四元數(shù)之間做插值運(yùn)算。
Direct3D擴(kuò)展實(shí)用庫函數(shù)D3DXQuaternionRotationYawPitchRoll()提供了將三個(gè)歐拉角轉(zhuǎn)換為一個(gè)四元數(shù)的功能,該函數(shù)聲明如下:
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變換引擎需要用矩陣來執(zhí)行旋轉(zhuǎn),所以需要將四元數(shù)轉(zhuǎn)換為矩陣格式。Direct3D擴(kuò)展實(shí)用庫函數(shù)D3DXMatrixRotationQuaternion()提供了將四元數(shù)轉(zhuǎn)換成矩陣的功能,該函數(shù)聲明如下:
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.
該示例程序同樣可以通過鍵盤控制飛機(jī)模型的位置和姿態(tài),控制方式和上一個(gè)示例程序完全相同,但實(shí)現(xiàn)代碼卻簡(jiǎn)潔得多,主要改動(dòng)代碼如下:
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);
}
在該示例程序中,通過用戶輸入,每一幀都對(duì)飛機(jī)模型進(jìn)行重新定位,不斷改變飛機(jī)模型在空間中的位置或姿態(tài),如果每?jī)蓭g的時(shí)間間隔足夠小,則感到飛機(jī)模型位置或姿態(tài)的變換是連續(xù)的,也就形成了連續(xù)的動(dòng)畫,實(shí)際上這就是三維動(dòng)畫的基本原理,通過不斷改變場(chǎng)景中各物體的位置和姿態(tài)使各物體運(yùn)動(dòng)起來。為了保證動(dòng)畫的連續(xù)性,幀速率要達(dá)到25幀/秒以上。
注意:模型的旋轉(zhuǎn)是繞自身坐標(biāo)軸的旋轉(zhuǎn),而不是繞世界坐標(biāo)系的3個(gè)坐標(biāo)軸旋轉(zhuǎn),而且在旋轉(zhuǎn)模型時(shí)其自身坐標(biāo)軸也在不斷變化。
下載示例工程