为什么这个观看/投影转换不起作用?

时间:2014-11-01 17:59:14

标签: opengl matrix

我正在尝试更好地理解OpenGL的基本矩阵转换逻辑。这是从教科书复制并修改为处理3D的二维码;它“有点像”,但是当我自己进行矩阵乘法与使用glMultMatrix时,最终结果在视觉上是不同的。

标记为“XXX”的行允许在“我的乘法”和“OpenGL乘法”之间翻转。我尝试了一些显而易见的事情(例如,行与列专业,转换顺序等)

如果有人可以照亮我与OpenGL相比我做错了什么,我会很感激。

#include <iostream>
#include <math.h>
#include "glut.h"
#include "vector3.h"

typedef GLfloat Matrix4x4[4][4];

Matrix4x4 matComposite;

void matrix4x4SetIdentity(Matrix4x4 matIdent4x4){
    GLint row, col;
    for(row = 0; row<4; row++){
        for(col = 0; col<4; col++){
            matIdent4x4[row][col] = (row == col);
        }
    }
}

void matrix4x4PreMultiply(Matrix4x4 m1, Matrix4x4 m2){
    GLint row, col;
    Matrix4x4 matTemp;
    for(row=0; row<4; row++){
        for(col=0; col<4; col++){
            matTemp[row][col] = m1[row][0] * m2[0][col] + 
                                m1[row][1] * m2[1][col] + 
                                m1[row][2] * m2[2][col] + 
                                m1[row][3] * m2[3][col];
        }
    }
    for(row=0; row<4; row++){
        for(col=0; col<4; col++){
            m2[row][col] = matTemp[row][col];
        }
    }
}

vector3 matrixMult(GLfloat x, GLfloat y, GLfloat z){
    GLfloat tempX = matComposite[0][0] * x + matComposite[0][1] * y + matComposite[0][2] * z + matComposite[0][3];
    GLfloat tempY = matComposite[1][0] * x + matComposite[1][1] * y + matComposite[1][2] * z + matComposite[1][3];
    GLfloat tempZ = matComposite[2][0] * x + matComposite[2][1] * y + matComposite[2][2] * z + matComposite[2][3];
    GLfloat tempW = matComposite[3][0]     + matComposite[3][1]     + matComposite[3][2]     + matComposite[3][3];
    // XXX return vector3(tempX/tempW, tempY/tempW, tempZ/tempW); // XXX
    return vector3 (x, y, z);
}

void render() {
    // my version of viewing/projection multiplication
    GLfloat mvmX[4][4] = {{0.948683, 0.095346, -0.301511, 0.000000}, {0.000000, 0.953463, 0.301511, 0.000000}, {0.316228, -0.286039, 0.904534,  0.000000}, {0.000004, 0.000000, -132.664993, 1.000000}};
    GLfloat pmX[4][4]  = {{1.500000, 0.000000,  0.000000, 0.000000}, {0.000000, 1.500000, 0.000000, 0.000000}, {0.000000, 0.000000, -1.015113, -1.000000}, {0.000000, 0.000000,   -3.022670, 0.000000}};
    matrix4x4SetIdentity(matComposite);
    matrix4x4PreMultiply(pmX, matComposite);
    matrix4x4PreMultiply(mvmX, matComposite);
    // OpenGL's version of viewing/projection multiplication
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    GLfloat mvm[] = {0.948683, 0.095346, -0.301511, 0.000000, 0.000000, 0.953463, 0.301511, 0.000000, 0.316228, -0.286039, 0.904534, 0.000000, 0.000004, 0.000000, -132.664993, 1.000000};
    GLfloat pm[] = {1.500000, 0.000000, 0.000000, 0.000000, 0.000000, 1.500000, 0.000000, 0.000000, 0.000000, 0.000000, -1.015113, -1.000000, 0.000000, 0.000000, -3.022670, 0.000000};
    glMultMatrixf(pm); // XXX
    glMultMatrixf(mvm); // XXX
    // draw a shape
    glColor3f(1, 0, 0);
    glBegin(GL_POLYGON);
        vector3 vpt = matrixMult(0, 0, 0);
        glVertex3f(vpt.x, vpt.y, vpt.z);
        vpt = matrixMult(0, 50, 0);
        glVertex3f(vpt.x, vpt.y, vpt.z);
        vpt = matrixMult(50, 50, 0);
        glVertex3f(vpt.x, vpt.y, vpt.z);
        vpt = matrixMult(0, 50, 0);
        glVertex3f(vpt.x, vpt.y, vpt.z);
    glEnd();
}

void display(void) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    render();
    glutSwapBuffers();
}



void main(int argc, char **argv){
    glutInit( &argc, argv );
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH) ;
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    int windowHandle = glutCreateWindow("Testing MVM and PM Matrices");
    glutSetWindow(windowHandle);
    glutDisplayFunc(display);
    glutMainLoop();
}

1 个答案:

答案 0 :(得分:1)

从此

matTemp[row][col]

我推断您使用行主存储顺序进行操作。但是,OpenGL使用column major顺序。因此,您必须先转置矩阵,然后才能将它们与glLoadMatrix一起使用。

此外,您的输入矩阵与您的矩阵顺序不匹配:

GLfloat pmX[4][4]  = {{1.500000, 0.000000,  0.000000, 0.000000}, {0.000000, 1.500000, 0.000000, 0.000000}, {0.000000, 0.000000, -1.015113, -1.000000}, {0.000000, 0.000000,   -3.022670, 0.000000}};

投影矩阵的最后一行应该是0,0,-1,0,但代码解释矩阵的方式也会转换为,所以它会将(0, 0, -3.02267, 0)视为最后一行。因此,您需要首先转置,应用矩阵运算,并将结果转换为OpenGL - 或者您只需更改矩阵运算以匹配OpenGL的运算并且不要转置任何内容。

请注意,使用现代GL,您可以轻松使用您喜欢的任何矩阵。设置统一矩阵的代码具有transpose参数,该参数将告诉GL您使用的两个订单。