OpenGL MV矩陣

1. 影響Model矩陣的函數
   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]=1
m[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     0
     0     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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章