glTranslate* 平移
glRotate* 旋轉
glScalef* 縮放
看幾個例子
1.1 glTranslatef(-1, 3, 5); 平移向量爲(-1, 3, 5)
由平移變換矩陣公式
1 0 0 Tx
0 1 0 Ty
0 0 1 Tz
0 0 0 1
1 0 0 -1
0 1 0 3
0 0 1 5
0 0 0 1
在OpenGL中存儲變換矩陣不是二維數組,而是一維數據,如float m[16]
且存儲是按列存儲的,
m[0] m[4] m[8] m[12]
m[1] m[5] m[9] m[13]
m[2] m[6] m[10] m[14]
m[3] m[7] m[11] m[15]
即上面的矩陣在數組中存儲如下:
m[0]=1m[1]=0
m[2]=0
m[3]=0
以上是變換矩陣的第1列
m[4]=0
m[5]=1
m[6]=0
m[7]=0
以上是變換矩陣的第2列
m[8]=0
m[9]=0
m[10]=1
m[11]=0
以上是變換矩陣的第3列
m[12]=-1
m[13]=3
m[14]=5
m[15]=1
以上是變換矩陣的第4列
1.2 glRotatef(45, 1, 1, 1); 旋轉變換,注意:opengl會把方向向量單位化,故
向量(1,1,1)單位化後的向量爲u=(ux,uy,uz)=(0.5773 0.5773 0.5773),c代表cos(theta)=0.7071,s代表sin(theta)=0.7071
由旋轉變換公式,
c+(1-c)*ux*ux (1-c)*uy*ux-s*uz (1-c)*uz*ux+s*uy 0
(1-c)*ux*uy+s*uz c+(1-c)*uy*uy (1-c)*uz*uy-s*ux 0
(1-c)*ux*uz-s*uy (1-c)*uy*uz+s*ux c+(1-c)*uz*uz 0
0 0 0 1
變換矩陣爲
0.8047 -0.3106 0.5059 0
0.5059 0.8047 -0.3106 0
-0.3106 0.5059 0.8047 0
0 0 0 1.0000
注意,存儲時是以列存儲的
1.3 glScalef(-3, 1, 2); 縮放變換,故變換矩陣爲
由縮放變換公式
Sx 0 0 0
0 Sy 0 0
0 0 Sz 0
0 0 0 1
可知縮放矩陣爲
-3 0 0 00 1 0 0
0 0 2 0
0 0 0 1
注意,存儲時是以列存儲的
如果將上述三個變換組合起來順序是什麼樣呢?
後調用的先變換,即M=trans*rot*scale
M =
-2.4142 -0.3106 1.0118 -1.0000
-1.5176 0.8047 -0.6212 3.0000
0.9319 0.5059 1.6095 5.0000
0 0 0 1.0000
注意,存儲時是以列存儲的
2. 影響View矩陣的函數
gluLookAt(eye.x, eye.y, eye.z, look.x, look.y, look.z, up.x, up.y, up.z)
2.1 gluLookAt(4, 4, 4, 0, 1, 0, 0, 1, 0);
n=eye-look=(4,4,4)-(0,1,0)=(4,3,4)
u=up x n = (0 1 0) x (4 3 4) = (4 0 -4)
v=n x u = (4 3 4) x (4 0 -4) = (-12 32 -12)
由公式求出相機的u,n,v向量分別爲(單位化後)
u=0.7071 0 -0.7071
n=0.6247 0.4685 0.6247
v=-0.3313 0.8835 -0.3313
所以View矩陣爲
V=
0.7071 0 -0.7071 0
-0.3313 0.8835 -0.3313 -0.8835
0.6247 0.4685 0.6247 -6.8716
0 0 0 1.0000
如果同時有ModelView變換將如何呢?
glTranslatef(-1, 3, 5);
glRotatef(45, 1, 1, 1);
glScalef(-3, 1, 2);
gluLookAt(4, 4, 4, 0, 1, 0, 0, 1, 0);
這時MV矩陣是什麼?注意後調用的先變換,即
M*V=
-0.9721 0.1996 2.4421 -7.6783
-1.7278 0.4199 0.4185 6.5578
1.4968 1.2010 0.1789 -6.5069
0 0 0 1.0000
本節測試源碼如下:
#define GLUT_DISABLE_ATEXIT_HACK
#include <gl/GLUT.H>
#include <stdio.h>
void printMatrix(float m[16])
{
printf("%10f %10f %10f %10f\n"
"%10f %10f %10f %10f\n"
"%10f %10f %10f %10f\n"
"%10f %10f %10f %10f\n",
m[0], m[4], m[8], m[12],
m[1], m[5], m[9], m[13],
m[2], m[6], m[10], m[14],
m[3], m[7], m[11], m[15]
);
}
void myDisplay()
{
float m[16] = { 0 };
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(4, 4, 4, 0, 1, 0, 0, 1, 0);
glTranslatef(-1, 3, 5);
glRotatef(45, 1, 1, 1);
glScalef(-3, 1, 2);
glGetFloatv(GL_MODELVIEW_MATRIX, m);
printMatrix(m);
glFlush();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); // RGB、單緩衝
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("MV矩陣");
glutDisplayFunc(myDisplay);
glutMainLoop();
return 0;
}