行向量,列向量,行主序矩阵,列主序矩阵
?
原理:?
PS: 很不喜歡OGL的列矩陣方式,不過本質上是一樣的。
?
v2 = v1 * ma * mb; (dx)
v2 = mb(T) * ma(T) * v1 (ogl)
?
關于這個話題,網上有n多個版本,今天,我也來說說這個話題。
(一)首先,無論dx還是opengl,所表示的矢量和矩陣都是依據線性代數中的標準定義的:
“矩陣A與B的乘積矩陣C的第i行第j列的元素c(ij)等于A的第i行于B的第j列的對應元素乘積的和。”(實用數學手冊,科學出版社,第二版)
例如c12 = a11*b11+a12*b21+a12*b13...
(二)在明確了這一點后,然后我們再看“矩陣的存儲方式”,矩陣存儲方式有兩種,一種是“行主序(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?和 ogl 中卻有不同的存儲順序
????????????? 線代: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
(三)矩陣乘法順序和規則
矩陣乘法在線性代數中的定義是確定的,然而在不同的實現中出現了“左乘”和“右乘”的區別,或者叫做“前乘(pre-multiply),后乘(post-multiply)”
這個規則取決于vector的表示形式,即行向量還是列向量。如果是行向量,其實就是一個行矩陣。那么表示線性代數意義的“行x列”,就是前乘。矩陣乘法也是如此。
如d3d
???????????????????????
D3D 是行向量,行優先存儲,OpenGL是列向量,列優先存儲。同一個矩陣用D3D存儲還是用opengl存儲雖然不同,但是變換的結果卻是相同,
因為opengl 變換向量是把向量視作列向量,并同矩陣的每一列相乘,用來實現線性代數中同一個變換。
我們通常很難看到opengl變換坐標的代碼,以下代碼出自opengl source code,讓我們一窺頂點變換的“廬山真面目”
void FASTCALL __glXForm3(__GLcoord *res, const __GLfloat v[3], const __GLmatrix *m)
{
??? __GLfloat x = v[0];
??? __GLfloat y = v[1];
??? __GLfloat z = v[2];
??? res->x = x*m->matrix[0][0] + y*m->matrix[1][0] + z*m->matrix[2][0]
?+ m->matrix[3][0];
??? res->y = x*m->matrix[0][1] + y*m->matrix[1][1] + z*m->matrix[2][1]
?+ m->matrix[3][1];
??? res->z = x*m->matrix[0][2] + y*m->matrix[1][2] + z*m->matrix[2][2]
?+ m->matrix[3][2];
??? res->w = x*m->matrix[0][3] + y*m->matrix[1][3] + z*m->matrix[2][3]
?+ m->matrix[3][3];
}
可見確實如上所述,“OPENGL列向量和矩陣的每一列相乘,仍然表示線性代數行向量和矩陣的每一行相乘”
再來看一下opengl 矩陣相乘,“用a的每一列去乘b的每一行”。
/*
** Compute r = a * b, where r can equal b.
*/
void FASTCALL __glMultMatrix(__GLmatrix *r, const __GLmatrix *a, const __GLmatrix *b)
{
??? __GLfloat b00, b01, b02, b03;
??? __GLfloat b10, b11, b12, b13;
??? __GLfloat b20, b21, b22, b23;
??? __GLfloat b30, b31, b32, b33;
??? GLint i;
??? b00 = b->matrix[0][0]; b01 = b->matrix[0][1];
??????? b02 = b->matrix[0][2]; b03 = b->matrix[0][3];
??? b10 = b->matrix[1][0]; b11 = b->matrix[1][1];
??????? b12 = b->matrix[1][2]; b13 = b->matrix[1][3];
??? b20 = b->matrix[2][0]; b21 = b->matrix[2][1];
??????? b22 = b->matrix[2][2]; b23 = b->matrix[2][3];
??? b30 = b->matrix[3][0]; b31 = b->matrix[3][1];
??????? b32 = b->matrix[3][2]; b33 = b->matrix[3][3];
??? for (i = 0; i < 4; i++) {
?r->matrix[i][0] = a->matrix[i][0]*b00 + a->matrix[i][1]*b10
???? + a->matrix[i][2]*b20 + a->matrix[i][3]*b30;
?r->matrix[i][1] = a->matrix[i][0]*b01 + a->matrix[i][1]*b11
???? + a->matrix[i][2]*b21 + a->matrix[i][3]*b31;
?r->matrix[i][2] = a->matrix[i][0]*b02 + a->matrix[i][1]*b12
???? + a->matrix[i][2]*b22 + a->matrix[i][3]*b32;
?r->matrix[i][3] = a->matrix[i][0]*b03 + a->matrix[i][1]*b13
???? + a->matrix[i][2]*b23 + a->matrix[i][3]*b33;
轉載于:https://www.cnblogs.com/zengqh/archive/2012/07/09/2583079.html
總結
以上是生活随笔為你收集整理的行向量,列向量,行主序矩阵,列主序矩阵的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Linux私房菜】第四期——管理
- 下一篇: 股票成本价买入价计算器 V1.3