2016-04-24 2 views
-1

Ich habe OpenGl Super Bible Beispiel https://github.com/openglsuperbible/sb7code/blob/master/src/grass/grass.cpp mit C und Freeglut codiert. Das Ergebnis war, dass Punkte außerhalb der Ansicht liegen.Erstelle ich Blick- und Perspektivmatrizen korrekt?

Berechne und benutze ich Look-at- und Perspective-Matrizen korrekt?

Ein Teil der Rendering-Funktion:

Matrix proj=CreateProjectionMatrix(45.0f,CurrentWidth/CurrentHeight,0.1f,1000.0f); 

float t=glutGet(GLUT_ELAPSED_TIME)*0.002f; 
float eye[]={sinf(t)*550.0f,25.0f,cosf(t)*550.0f}; 
float center[]={0.0f,-50.0f,0.0f}; 
float up[]={0.0f,1.0f,0.0f}; 
Matrix look=lookAt(eye,center,up); 

Matrix final=MultiplyMatrices(&proj,&look); 

glUniformMatrix4fv(UniformsMvpMatrix,1,GL_FALSE,final.m); 

Berechnungen:

typedef struct Matrix{ 
    GLfloat m[16]; 
}Matrix; 

Matrix CreateProjectionMatrix(float fovy,float aspect,float Znear,float Zfar){ 
    // Array index in the matrix 
    // _   _ 
    // | 0 4 8 12 | 
    // | 1 5 9 13 | 
    // | 2 6 10 14 | 
    // |_3 7 11 15_| 
    // 
    Matrix out; 
    float tanhalffovy = tanf(DegreesToRadians(fovy/2)); 
    out.m[ 0]=1/(aspect*tanhalffovy); 
    out.m[ 5]=1/(tanhalffovy); 
    out.m[10]=(Zfar+Znear)/(Znear-Zfar); 
    out.m[11]=(2*Zfar*Znear)/(Znear-Zfar); 
    out.m[14]=-1; 
    out.m[ 1]=0; 
    out.m[ 2]=0; 
    out.m[ 3]=0; 
    out.m[ 4]=0; 
    out.m[ 6]=0; 
    out.m[ 7]=0; 
    out.m[ 8]=0; 
    out.m[ 9]=0; 
    out.m[12]=0; 
    out.m[13]=0; 
    out.m[15]=0; 
    return out; 
} 

Matrix lookAt(float eye[3],float center[3],float up[3]){ 
    // Array index in the matrix 
    // _   _ 
    // | 0 4 8 12 | 
    // | 1 5 9 13 | 
    // | 2 6 10 14 | 
    // |_3 7 11 15_| 
    // 
    double help=sqrt(up[0]*up[0]+up[1]*up[1]+up[2]*up[2]); 
    float upN[3]; 
    upN[0]=up[0]/help; 
    upN[1]=up[1]/help; 
    upN[2]=up[2]/help; 

    float f[3]; 
    f[0]=(center[0]-eye[0]); 
    f[1]=(center[1]-eye[1]); 
    f[2]=(center[2]-eye[2]); 
    help=sqrt(f[0]*f[0]+f[1]*f[1]+f[2]*f[2]); 
    f[0]/=help; 
    f[1]/=help; 
    f[2]/=help; 

    float s[3]; 
    s[0]=f[1]*upN[2]-upN[1]*f[2]; 
    s[1]=f[2]*upN[0]-upN[2]*f[0]; 
    s[2]=f[0]*upN[1]-upN[0]*f[1]; 

    float u[3]; 
    u[0]=s[1]*f[2]-f[1]*s[2]; 
    u[1]=s[2]*f[0]-f[2]*s[0]; 
    u[2]=s[0]*f[1]-f[0]*s[1]; 

    Matrix out={{s[0],s[1],s[2],0, u[0],u[1],u[2],0, f[0],f[1],f[2],0, -eye[0],-eye[1],-eye[2],1}}; 
    return out; 
} 

Matrix MultiplyMatrices(const Matrix* m1, const Matrix* m2){  
    Matrix out; 
    // First column 
    out.m[ 0]=(m1->m[0])*(m2->m[0])+(m1->m[4])*(m2->m[1])+(m1->m[ 8])*(m2->m[2])+(m1->m[12])*(m2->m[3]); 
    out.m[ 1]=(m1->m[1])*(m2->m[0])+(m1->m[5])*(m2->m[1])+(m1->m[ 9])*(m2->m[2])+(m1->m[13])*(m2->m[3]); 
    out.m[ 2]=(m1->m[2])*(m2->m[0])+(m1->m[6])*(m2->m[1])+(m1->m[10])*(m2->m[2])+(m1->m[14])*(m2->m[3]); 
    out.m[ 3]=(m1->m[3])*(m2->m[0])+(m1->m[7])*(m2->m[1])+(m1->m[11])*(m2->m[2])+(m1->m[15])*(m2->m[3]); 
    // Second column 
    out.m[ 4]=(m1->m[0])*(m2->m[4])+(m1->m[4])*(m2->m[5])+(m1->m[ 8])*(m2->m[6])+(m1->m[12])*(m2->m[7]); 
    out.m[ 5]=(m1->m[1])*(m2->m[4])+(m1->m[5])*(m2->m[5])+(m1->m[ 9])*(m2->m[6])+(m1->m[13])*(m2->m[7]); 
    out.m[ 6]=(m1->m[2])*(m2->m[4])+(m1->m[6])*(m2->m[5])+(m1->m[10])*(m2->m[6])+(m1->m[14])*(m2->m[7]); 
    out.m[ 7]=(m1->m[3])*(m2->m[4])+(m1->m[7])*(m2->m[5])+(m1->m[11])*(m2->m[6])+(m1->m[15])*(m2->m[7]); 
    // Third column 
    out.m[ 8]=(m1->m[0])*(m2->m[8])+(m1->m[4])*(m2->m[9])+(m1->m[ 8])*(m2->m[10])+(m1->m[12])*(m2->m[11]); 
    out.m[ 9]=(m1->m[1])*(m2->m[8])+(m1->m[5])*(m2->m[9])+(m1->m[ 9])*(m2->m[10])+(m1->m[13])*(m2->m[11]); 
    out.m[10]=(m1->m[2])*(m2->m[8])+(m1->m[6])*(m2->m[9])+(m1->m[10])*(m2->m[10])+(m1->m[14])*(m2->m[11]); 
    out.m[11]=(m1->m[3])*(m2->m[8])+(m1->m[7])*(m2->m[9])+(m1->m[11])*(m2->m[10])+(m1->m[15])*(m2->m[11]); 
    // Fourth 
    out.m[12]=(m1->m[0])*(m2->m[12])+(m1->m[4])*(m2->m[13])+(m1->m[ 8])*(m2->m[14])+(m1->m[12])*(m2->m[15]); 
    out.m[13]=(m1->m[1])*(m2->m[12])+(m1->m[5])*(m2->m[13])+(m1->m[ 9])*(m2->m[14])+(m1->m[13])*(m2->m[15]); 
    out.m[14]=(m1->m[2])*(m2->m[12])+(m1->m[6])*(m2->m[13])+(m1->m[10])*(m2->m[14])+(m1->m[14])*(m2->m[15]); 
    out.m[15]=(m1->m[3])*(m2->m[12])+(m1->m[7])*(m2->m[13])+(m1->m[11])*(m2->m[14])+(m1->m[15])*(m2->m[15]); 

    return out; 
} 

Ich bin 99,9% sicher, dass Shader die gleichen wie im Beispiel.

Antwort

0

Ich sehe zwei Probleme mit dem Code:

  1. Es ist nicht wirklich klar, welche Matrix Speicherlayout Konvention Sie verwenden.

    Ihr lookAt Code setzte die -eye Übersetzung in die Elemente 12 bis 14, was bedeutet, Sie säulen große Layout, zusammen mit dem Standard-GL matrix * vector Multiplikation um im Shader verwenden. Ihre Projektionsmatrix ist jedoch auf diese Konvention transponiert. Elemente 11 und 14 sollten ausgetauscht werden.

  2. Ihre lookAt Funktion ist falsch:

    Die Ansicht Matrix der Welt Raum zu einem Auge Raum verwandeln sollte, wo die Kamera in der Mitte ist und schaut in Richtung -z. Dies kann als interpretiert werden, wobei alle Objekte in Bezug auf eine feste Kamera bewegt werden oder das neue Ansichtskoordinatensystem in Bezug auf die Weltkoordinaten definiert wird. Sie erhalten in beiden Fällen die Formel R * T(-eye). In der ersten Interpretation bedeutet dies, dass wir zuerst alle Objekte um -eye verschieben (so dass der Punkt eye in der Mitte endet), und dann um das neue Zentrum drehen, sodass die LookAt-Richtung in die -z-Achse und die up gedreht wird Vektor zu +y.

    Ihre lookAt Matrix tut dies jedoch nicht. Ihre Matrix kann in T(-eye) * R^-1 zerlegt werden. Also ist Ihre R nicht die Rotation, die Sie benötigen: Wenn Sie Ihre Matrix durch den -z Achsenvektor (0,0,-1,0)^T multiplizieren, werden Sie nur die dritte Spalte auswählen und negieren, so dass Sie am Ende mit -f enden. Aber Ihr Vorwärtsrichtungsvektor sollte f sein, also haben Sie vergessen, f zu negieren, bevor Sie es in die Matrix setzen.

    Das zweite Problem ist, dass die Drehung tatsächlich invertiert ist. Wenn Sie die dritte Spalte negieren, erhalten Sie V * (0 0 -1 0)^T = (f 0)^T, aber das ist die umgekehrte Transformationsrichtung, die Sie benötigen. Sie müssen eine Rotation erstellen, die V * (f 0)^T = (0 0 -1 0) ergibt. Nun ist das Schöne an Rotationsmatrizen, dass sie orthogonal sind, also R^-1 = R^T. Dies bedeutet, dass Sie einfach Ihre Rotationsmatrix transponieren können, um sie zu invertieren.

    Sie können jedoch nicht einfach Ihre Ansichtsmatrix transponieren. Und das bringt uns zur letzten Ausgabe: Sie schreiben einfach den Übersetzungsteil -eye in die vierte Spalte.Konzeptionell bedeutet dies, dass Sie V=T(-eye) * R tun, das heißt, Sie wenden die Übersetzung als letzten Schritt. Wie wir jedoch schon gesehen haben, müssen wir die Übersetzung zuerst anwenden. So beheben vollständig Ihre Matrix, Sie R^T zuerst bauen, indem Sie die Drehteile zur Umsetzung, das heißt, das Schreiben der s, u und -f Vektoren als rows in die Matrix und schließlich Sie mehrfach dass Matrix durch eine einfache Übersetzung Matrix mit T(-eye) .

+0

Dank derhass: D – lohikaarme2