1.矩阵
矩阵其实就是个二维数组,如下图,是个 3×3 矩阵,它有三行和三列。
1. 矩阵顶点和向量实际由一个1×3的矩阵表示:
2. 1x3矩阵笛卡尔坐标系的三轴正向归一向量可以用以下矩阵表示:
x轴
y轴
z轴
三轴可合成如下3x3矩阵(先x然后是y再后是z)
3. 三轴矩阵
矩阵相乘
矩阵相乘的计算规则:以结果矩阵左上角第一个数字为例,是第一个矩阵第一行的每个数字,各自乘以第二个矩阵第一列对应位置的数字,然后将乘积相加),得到结果矩阵左上角的那个值。
4. 矩阵相乘
也就是说,结果矩阵第m行与第n列交叉位置的那个值,等于第一个矩阵第m行与第二个矩阵第n列,对应位置的每个值的乘积之和。
转置矩阵
把矩阵A的行换成相应的列,得到的新矩阵称为A的转置矩阵,记作AT
或A。
一个矩阵和它的转置矩阵可以这么直观地表示出来:
7. 矩阵及其转置矩阵逆矩阵
设A是数域上的一个n阶方阵,若在相同数域上存在另一个n阶矩阵B,使得: AB=BA=E。 则我们称B是A的逆矩阵,而A则被称为可逆矩阵。
初等变换法求逆矩阵:将一n阶可逆矩阵A和n阶单位矩阵I写成一个nX2n的矩阵对B施行初等行变换,即对A与I进行完全相同的若干初等行变换,目标是把A化为单位矩阵。当A化为单位矩阵I的同时,B的右一半矩阵同时化为了A。
8. 初等变换法求逆矩阵2.四元数
复数是由实数加上虚数单位i组成,其中
9. 四元数乘法表
相对于将欧拉角信息存储在3个GLfloats变量或一个 Vector3D 变量里来说, 使用四元数有2个优点:
1.四元数不会造成万向节死锁(gimbal lock),但是欧拉角容易造成万向节死锁,使用四元数能够让我们的3D模型能够全方位的移动。
2.相比于给每个欧拉角做矩阵旋转转换计算,使用四元数结合多角度旋转可以显著的减少计算量。
四元数结构体
从数据上看来,四元数只不过是比Vector 3D多加了一个GLfloat,经常把它当成w字段。所以对我们来说一个四元数就象这样:
typedef struct {
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat w;
} Quaternion3D;
从一个四元数中创建旋转矩阵
这另外的一个方法相对简单些。并且这个基本算法来自于Matrix FAQ,虽然我需要把它转换成行优先的顺序。
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;
}
把一个角度和旋转轴转换成一个四元数
四元数可以做的另外一种转换是,表示成在一个Vector3D表示的轴线上进行旋转。这在骨骼动画里面是非常有用的,因为这种表现形式通过矩阵是很难做到的。创建一个基于角度和轴旋转得四元数,我们可以这样做:
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;
}
网友评论