为什么此查看/投影转换不起作用? [英] Why doesn't this viewing/projection transform work?

查看:60
本文介绍了为什么此查看/投影转换不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图更好地理解OpenGL的基本矩阵转换逻辑.这是从教科书复制并经过修改以处理3D的2D代码;它是一种作品",但是当我自己进行矩阵乘法与使用glMultMatrix进行矩阵乘法时,最终结果在视觉上有所不同.

I'm trying to understand OpenGL's basic matrix transformation logic better. This is 2D code copied from a textbook and modified to handle 3D; it "sort of works", but the final result is visually different when I do the matrix multiplication myself vs. using glMultMatrix.

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

The lines marked 'XXX' allow flipping between 'my multiplication' and 'OpenGL multiplication'. I tried some obvious things (eg. row vs. column major, order of transforms, etc.)

与OpenGL相比,如果有人能向我说明我做错了什么,我将不胜感激.

If anyone can illuminate me as to what I'm doing wrong compared to OpenGL, I'd appreciate it.

#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();
}

推荐答案

从这里

matTemp[row][col]

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

I deduce that you use row major storage order for your operations. However, OpenGL uses column major order. So you have to transpose the matrices before you can use them with glLoadMatrix.

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

Also, your input matrices don't match your matrix order:

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的矩阵运算,就不进行任何转置.

The projection matrix should have the last row as 0,0,-1,0, but the way your code interprets your matrices is also transposed to that, so it will see (0, 0, -3.02267, 0) as the last row. So you need to transpose that first, apply your matrix operations, and transpose the result for OpenGL - or you just change your matrix operations to match those of OpenGL and don't transpose anything.

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

Note that with modern GL, you can easily use any matrix oder you like. The code to set a uniform matrix has a transpose parameter which will tell the GL wich of the two orders you use.

这篇关于为什么此查看/投影转换不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆