2014-11-02 108 views
0

這是此Why doesn't this viewing/projection transform work?較早發佈的後續行動。投影轉換有什麼不同?

出於實驗目的,每次窗口繪製時,此代碼都會在OpenGL計算的轉換和我手動計算的轉換之間翻轉。第一次跟蹤來自OpenGL的Projection和ModelView矩陣值,所以我可以在自己做這些時使用它們。

如果我註釋掉投影變換,則視覺輸出是相同的。但隨着投影變換,它是「接近但不準確」(似乎有點扭曲)。

由於所有其他變換使用相同的邏輯工作,我相信我的數學,列與列,調換等是聲音(相對於我以前的帖子),並且必須有一些概念上的差異投影變換正在逃避我。有什麼建議?

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

bool useOpenGL = true; 
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){ 
    if(useOpenGL){ 
     return vector3(x, y, z); 
    } else { 
     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]; 
     return vector3(tempX/tempW, tempY/tempW, tempZ/tempW); 
    } 
} 

void transpose(Matrix4x4 mat){ 
    Matrix4x4 temp; 
    for(int i=0;i<4;i++) { 
     for(int j=0;j<4;j++) { 
      temp[i][j] = mat[j][i]; 
     } 
    } 
    for(int i=0;i<4;i++) { 
     for(int j=0;j<4;j++) { 
      mat[i][j] = temp[i][j]; 
     } 
    } 
} 

vector3 viewer(-.4, .4, .6); 

GLfloat mvm[4][4]; 
GLfloat pm[4][4]; 

void storeMatrices(){ 
    GLfloat got[16]; 
    glGetFloatv(GL_PROJECTION_MATRIX,got); 
    for(int i=0;i<16;i++){ 
     pm[i/4][i%4] = got[i]; 
    } 
    glGetFloatv(GL_MODELVIEW_MATRIX,got); 
    for(int i=0;i<16;i++){ 
     mvm[i/4][i%4] = got[i]; 
    } 
} 

void transformOpenGL(){ 
    std::cout << "BY OPENGL\n"; 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glFrustum(-1, 1, -1, 1, .1, 200); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(viewer.x, viewer.y, viewer.z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 
    // copy matrices before doing model transforms 
    storeMatrices(); 
    // setup scene 
    glScalef(.5, 1, 1); 
    glTranslatef(.4, .4, 0); 
    glScalef(.2, .1, .1); 
} 

void transformByHand(){ 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    std::cout << "BY HAND\n"; 
    matrix4x4SetIdentity(matComposite); 
    GLfloat mvm[4][4] = {{0.832050, 0.269069, -0.485071, 0.000000}, {0.000000, 0.874475, 0.485071, 0.000000}, {0.554700, -0.403604, 0.727607, 0.000000}, {0.000000, 0.000000, -0.824621, 1.000000}}; 
    GLfloat pm[4][4] = {{0.100000, 0.000000, 0.000000, 0.000000}, {0.000000, 0.100000, 0.000000, 0.000000}, {0.000000, 0.000000, -1.001001, -1.000000,}, {0.000000, 0.000000, -0.200100, 0.000000}}; 
    // order of transforms is opposite to OpenGL, and, 
    // eg. translations go in col[3], not row[3] 
    Matrix4x4 scale3 = {{.2, 0, 0, 0}, {0, .1, 0, 0}, {0, 0, .1, 0}, {0, 0, 0, 1}}; 
    matrix4x4PreMultiply(scale3, matComposite); 
    Matrix4x4 translate = {{1, 0, 0, .4}, {0, 1, 0, .4}, {0, 0, 1, 0}, {0, 0, 0, 1}}; 
    matrix4x4PreMultiply(translate, matComposite); 
    Matrix4x4 scale2 = {{.5, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; 
    matrix4x4PreMultiply(scale2, matComposite); 
    transpose(mvm); 
    matrix4x4PreMultiply(mvm, matComposite); 
    transpose(pm); 
    matrix4x4PreMultiply(pm, matComposite); 
} 

void render() { 
    if(useOpenGL){ 
     transformOpenGL(); 
    } else { 
     transformByHand(); 
    } 
    glColor3f(1, 0, 0); 
    glBegin(GL_POLYGON); 
     vector3 vpt = matrixMult(0, 0, 0); 
     glVertex3f(vpt.x, vpt.y, vpt.z); 
     vpt = matrixMult(0, 5, 0); 
     glVertex3f(vpt.x, vpt.y, vpt.z); 
     vpt = matrixMult(5, 5, 0); 
     glVertex3f(vpt.x, vpt.y, vpt.z); 
     vpt = matrixMult(0, 5, 0); 
     glVertex3f(vpt.x, vpt.y, vpt.z); 
    glEnd(); 
    useOpenGL = !useOpenGL; 
} 

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

我沒有完全研究你寫的部分來測試和比較兩個選項。但在你的矩陣*向量乘法問題:

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

tempW計算缺少與矢量分量的乘法,而只是增加了矩陣元素來代替。它應該是:

GLfloat tempW = matComposite[3][0] * x + matComposite[3][1] * y + 
       matComposite[3][2] * z + matComposite[3][3]; 

整個事情是用一個4元向量(x, y, z, 1) 4x4矩陣的一個普通的乘法。結果的每個分量都是矩陣行與向量的標量乘積。結果的w組件與所有其他組件的計算方法相同。

+0

我會嘗試;我想我誤解了W變量。非常感謝您的回覆。乾杯! – GregT 2014-11-02 14:35:55