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;
}