在内存中,矩阵存储方式有两种,一种是“行主序(row-major order)/行优先”,另一种就是“列主序(column-major order)/列优先”
1)Direct3D 采用行主序存储
“Effect matrix parameters and HLSL matrix variables can define whether the value is a row-major or column-major matrix; however, the DirectX APIs always treat D3DMATRIX and D3DXMATRIX as row-major.”(见d3d9 document/Casting and Conversion 一节)
2)OpenGL 采用列主序存储
“The m parameter points to a 4x4 matrix of single- or double-precision floating-point values stored in column-major order. That is, the matrix is stored as follows”
(见msdn glLoadMatrixf API说明)
存储顺序说明了线性代数中的矩阵如何在线性的内存数组中存储,d3d 将每一行在数组中按行存储,而opengl将每一列存储到数组的每一行中:
线性代数意义的同一个矩阵,在d3d 和gl 中却有不同的存储顺序
线代:a11,a12,a13,a14 d3d : a11,a12,a13,a14 gl: a11,a21,a31,a41
a21,a22,a23,a24 a21,a22,a23,a24 a12,a22,a32,a42
a31,a32,a33,a34 a31,a32,a33,a34 a13,a23,a33,a43
a41,a42,a43,a44 a41,a42,a43,a44 a14,a24,a34,a44
我们暂且不讨论,哪种存储好。但事实如此,微软D3D和Opengl的存储方式,是不一样的,谁让他俩是死对头呢。
计算方法是一致的,只是一个转置矩阵的差别。反转一下行列就可以了。
另外,纠正一下以前自己一些错误的想法:
模型的平移,缩放,旋转,都是通过4X4的矩阵相乘得来的。(平移,并不是矩阵相加,也是相乘而来)
想乘的时候,第一个行列式的列数,必须等于第二个行列式的行数。
模型点[ x0, y0, z0, w0]
相乘矩阵
a0, a1, a2, a3,
a4, a5, a6, a7,
a8, a9, a10, a11,
a12, a13, a14, a15,
a0, a5,a10是缩放系数;
a12,a13,a14 是平移系数;(为何是平移系数,取决于矩阵的乘法)
Matrix Matrix::createScaling(float x, float y, float z)
{
Matrix result = identityMatrix;
result.elements[ 0] = x;
result.elements[ 5] = y;
result.elements[10] = z;
return result;
}
Matrix Matrix::createTranslation(float x, float y, float z)
{
Matrix result = identityMatrix;
result.elements[12] = x;
result.elements[13] = y;
result.elements[14] = z;
return result;
}