因为我熟悉的是DX,所以,大多只标出OPENGL.
OPENGL:
1)用角度。
2)纹理坐标向上。
3)Z轴正方向,向屏幕外。右手坐标系.
4)矩阵变化是累积制的.
5)三角形正面(逆时针)
关于Opengl和Dx的矩阵问题
我们知道信息是, 1)左乘(Dx采取),右乘(Opengl采取)2)矩阵的乘法就是行乘列,不变的,矩阵不满足交换律。3)最终矩阵数据似乎应该有某种意义上的相等. 因为平移后旋转和旋转后平移效果是不同的.
左乘: object * matrix;
右乘: matrix * object;
运算基于函数,而对于矩阵的运算又是基于栈的。
如果,将Opengl的矩阵从栈中抽出。
即:
由于OpenGL的栈结构,后入栈的先乘。
OPENGL左乘:
proj * view * world * obj;
DX右乘:
obj * world * view * proj;
2)列主序矩阵 * object;
行主序(Dx采取),列主序(Opengl采取)
比如矩阵:
v0(0,1,2,3)
v1(4,5,6,7)
v2(8,9,10,11)
v3(12,13,14,15)
a)行主序矩阵为:
|0 1 2 3|
|4 5 6 7|
|8 9 10 11|
|12 13 14 15|
b)列主序矩阵为:
|0 4 8 12|
|1 5 9 13|
|2 6 10 14|
|3 7 11 15|
假设object行主序为:
|a b c d|
|e f g h|
|i j k l|
|m n o p|
按照1,则为:
a*0+b*4+c*8+d*12 a*1+b*5+c*9+d*13 a*2+b*6+c*10+d*14 a*3+b*7+c*11+d*15
即:4b+8c+12d a+5b+9c+13d 2a+6b+10c+14d 3a+7b+11c+15d
.....(后面,我就不写了。这里,只取一行)
计算列主序的:
|0 4 8 12|
|1 5 9 13|
|2 6 10 14|
|3 7 11 15|
*
a e i m
b f j n
c g k o
d h l p
按照2,则为:
= 0*a+4*b+8*c+12*d 0*e+4*f+8*g+12*h 0*i+4*j+8*k+12*l 0*m+4*n+8*o+12*p
即:4b+8c+12d 4f+8g+12h 4j+8k+12l 4n+8o+12p
=1*a+5*b+9*c+13*d 1*e+5*f+6*g+7*h 1*i+5*j+9*k+13*l 1*m+5*n+9*o+13*p
即:a+5b+9c+13d e+5f+6g+7h i+5j+9k+13l m+5n+9o+13p
....
发现是最终结果是转置的.
而我们知道:行主序 = 转置列主序;
根据上面结果我们知道:行主序(mat1) *行主序(mat2) = 转置(列主序(mat2) * 列主序(mat1)) :定理A
即DX计算的矩阵一列的变换最终结构和opengl,仍为行主序,列主序问题(即,只需轻轻一转置);
翻开维基查看到矩阵有该性质:
http://zh.wikipedia.org/wiki/%E8%BD%89%E7%BD%AE
这就是为什么DX,相关矩阵运算移植到OPENGL要这样写:
即满足左乘和右乘式子,和定理A:
左乘: object * matrix;右乘: matrix * object;
D3DXMATRIX RotaZ10, RotaY20, RotaX30, Trans0, MatZ120, Mat3;
D3DXMatrixTranslation(&Trans0, 1, 2, 3);
D3DXMatrixRotationY(&RotaY20, D3DXToRadian(20));
D3DXMatrixRotationZ(&RotaZ10, D3DXToRadian(10));
D3DXMatrixRotationX(&RotaX30, D3DXToRadian(30));
D3DXMatrixRotationZ(&MatZ120, D3DXToRadian(120));
Mat3 = Trans0 * RotaZ10 * RotaY20 * RotaX30 * MatZ120 ;
移植到OPENGL:
glLoadIdentity(); //
glTranslatef(1,2,3);
glRotatef(10, 0,0,1);
glRotatef(20, 0,1,0);
glRotatef(30, 1,0,0);
glRotatef(120, 0,0,1);
OPENGL右手坐标系,Z轴问题和显示:
opengl的正Z轴向外, 那么我们像往屏幕内移动,该怎么办呢, 将z值设小, 不,不,不.
glLoadIdentity();
glTranslatef(0,-0.5f,walk_on_z);
这里的walk_on_z值仍然是越大,越往屏幕内移动.
因为投影矩阵定义的关系吧.