OpenGL MV矩阵

来源:互联网 发布:js为什么禁止跨域请求 编辑:程序博客网 时间:2024/05/21 11:35
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;}


0 0
原创粉丝点击