1.矩陣
矩陣其實就是個二維數(shù)組亿汞,如下圖熏迹,是個 3×3 矩陣哈肖,它有三行和三列受啥。
頂點和向量實際由一個1×3的矩陣表示:
笛卡爾坐標(biāo)系的三軸正向歸一向量可以用以下矩陣表示:
三軸可合成如下3x3矩陣(先x然后是y再后是z)
矩陣相乘
矩陣相乘的計算規(guī)則:以結(jié)果矩陣左上角第一個數(shù)字為例,是第一個矩陣第一行的每個數(shù)字炼幔,各自乘以第二個矩陣第一列對應(yīng)位置的數(shù)字秋茫,然后將乘積相加),得到結(jié)果矩陣左上角的那個值乃秀。
也就是說肛著,結(jié)果矩陣第m行與第n列交叉位置的那個值,等于第一個矩陣第m行與第二個矩陣第n列环形,對應(yīng)位置的每個值的乘積之和。
轉(zhuǎn)置矩陣
把矩陣A的行換成相應(yīng)的列衙傀,得到的新矩陣稱為A的轉(zhuǎn)置矩陣抬吟,記作AT
或A。
一個矩陣和它的轉(zhuǎn)置矩陣可以這么直觀地表示出來:
逆矩陣
設(shè)A是數(shù)域上的一個n階方陣统抬,若在相同數(shù)域上存在另一個n階矩陣B火本,使得: AB=BA=E危队。 則我們稱B是A的逆矩陣,而A則被稱為可逆矩陣钙畔。
初等變換法求逆矩陣:將一n階可逆矩陣A和n階單位矩陣I寫成一個nX2n的矩陣對B施行初等行變換茫陆,即對A與I進行完全相同的若干初等行變換,目標(biāo)是把A化為單位矩陣擎析。當(dāng)A化為單位矩陣I的同時簿盅,B的右一半矩陣同時化為了A。
2.四元數(shù)
復(fù)數(shù)是由實數(shù)加上虛數(shù)單位i組成揍魂,其中
相似地桨醋,四元數(shù)都是由實數(shù)加上三個元素i,j,k組成,而且它們有如下的關(guān)系:
每個四元數(shù)都是 1现斋、i喜最、j、k的線性組合庄蹋,即是四元數(shù)一般可表示為
瞬内。
要把兩個四元數(shù)相加只需將相類的系數(shù)加起來就可以,就像復(fù)數(shù)一樣限书。至于乘法則可跟隨以下的乘數(shù)表:
相對于將歐拉角信息存儲在3個GLfloats變量或一個 Vector3D 變量里來說, 使用四元數(shù)有2個優(yōu)點:
1.四元數(shù)不會造成萬向節(jié)死鎖(gimbal lock)虫蝶,但是歐拉角容易造成萬向節(jié)死鎖,使用四元數(shù)能夠讓我們的3D模型能夠全方位的移動蔗包。
2.相比于給每個歐拉角做矩陣旋轉(zhuǎn)轉(zhuǎn)換計算秉扑,使用四元數(shù)結(jié)合多角度旋轉(zhuǎn)可以顯著的減少計算量。
四元數(shù)結(jié)構(gòu)體
從數(shù)據(jù)上看來调限,四元數(shù)只不過是比Vector 3D多加了一個GLfloat舟陆,經(jīng)常把它當(dāng)成w字段。所以對我們來說一個四元數(shù)就象這樣:
typedef struct {
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat w;
} Quaternion3D;
從一個四元數(shù)中創(chuàng)建旋轉(zhuǎn)矩陣
這另外的一個方法相對簡單些耻矮。并且這個基本算法來自于Matrix FAQ秦躯,雖然我需要把它轉(zhuǎn)換成行優(yōu)先的順序。
static inline void Matrix3DSetUsingQuaternion3D(Matrix3D matrix, Quaternion3D quat)
{
matrix[0] = (1.0f - (2.0f * ((quat.y * quat.y) + (quat.z * quat.z))));
matrix[1] = (2.0f * ((quat.x * quat.y) - (quat.z * quat.w)));
matrix[2] = (2.0f * ((quat.x * quat.z) + (quat.y * quat.w)));
matrix[3] = 0.0f;
matrix[4] = (2.0f * ((quat.x * quat.y) + (quat.z * quat.w)));
matrix[5] = (1.0f - (2.0f * ((quat.x * quat.x) + (quat.z * quat.z))));
matrix[6] = (2.0f * ((quat.y * quat.z) - (quat.x * quat.w)));
matrix[7] = 0.0f;
matrix[8] = (2.0f * ((quat.x * quat.z) - (quat.y * quat.w)));
matrix[9] = (2.0f * ((quat.y * quat.z) + (quat.x * quat.w)));
matrix[10] = (1.0f - (2.0f * ((quat.x * quat.x) + (quat.y * quat.y))));
matrix[11] = 0.0f;
matrix[12] = 0.0f;
matrix[13] = 0.0f;
matrix[14] = 0.0f;
matrix[15] = 1.0f;
}
把一個角度和旋轉(zhuǎn)軸轉(zhuǎn)換成一個四元數(shù)
四元數(shù)可以做的另外一種轉(zhuǎn)換是裆装,表示成在一個Vector3D表示的軸線上進行旋轉(zhuǎn)踱承。這在骨骼動畫里面是非常有用的,因為這種表現(xiàn)形式通過矩陣是很難做到的哨免。創(chuàng)建一個基于角度和軸旋轉(zhuǎn)得四元數(shù)茎活,我們可以這樣做:
static inline Quaternion3D Quaternion3DMakeWithAxisAndAngle(Vector3D axis, GLfloat angle)
{
Quaternion3D quat;
GLfloat sinAngle;
angle *= 0.5f;
Vector3DNormalize(&axis);
sinAngle = sinf(angle);
quat.x = (axis.x * sinAngle);
quat.y = (axis.y * sinAngle);
quat.z = (axis.z * sinAngle);
quat.w = cos(angle);
return quat;
}