2016-02-12 2 views
3

J'essaye de construire une matrice de transformation de perspective en python pour une utilisation avec pyOpenGL. Mes transformations de vue et de modèle fonctionnent mais quand j'applique ma transformation de projection, je reçois un écran vide (je devrais voir un triangle à l'origine vu de (0,0, + 1)). J'ai regardé par-dessus les maths et autant que je peux dire que la transformation devrait fonctionner, j'ai donc besoin d'une deuxième paire d'yeux pour aider à trouver le problème.Matrice Perspective OpenGL en Python

def perspective(field_of_view_y, aspect, z_near, z_far): 

    fov_radians = math.radians(field_of_view_y) 
    f = math.tan(fov_radians/2) 

    a_11 = 1/(f*aspect) 
    a_22 = 1/f 
    a_33 = (z_near + z_far)/(z_near - z_far) 
    a_34 = -2*z_near*z_far/(z_near - z_far) 

    # a_33 = -(z_far + z_near)/(z_far - z_near) 
    # a_34 = 2*z_far*z_near/(z_far - z_near) 

    perspective_matrix = numpy.matrix([ 
     [a_11, 0, 0, 0],  
     [0, a_22, 0, 0],  
     [0, 0, a_33, a_34],  
     [0, 0, -1, 0]   
    ]).T 

    return perspective_matrix 

projection_matrix = perspective(45, 600/480, 0.1, 100) 
mvp_matrix = projection_matrix * view_matrix * model_matrix 

Je transpose la matrice parce que je suis assez sûr que les magasins numpy la matrice transposée à la façon dont OpenGL a besoin. J'ai essayé d'envoyer la matrice sans la transposer et elle n'avait aucun effet (visible) sur la sortie.

Et voici le vertex shader:

#version 330 core 

layout(location = 0) in vec3 position; 
uniform mat4 MVP; 

void main() 
{ 
    vec4 p = vec4(position, 1.0); 
    gl_Position = MVP * p; 
} 

Quelqu'un peut-il identifier ce que les éventuels problèmes avec ma transformation pourrait être?

EDIT: J'ai pris la matrice de sortie et j'ai effectué le calcul à la main. Après l'application de la division de perspective, tous les points du bord du tronc apparaissent le long de la boîte NDC, avec z aux points proches et lointains transformés respectivement à -1, +1 (précision mineure +/- due à l'erreur d'arrondi). Pour moi, cela suggère que mes maths ont raison et que le problème est ailleurs. C'est la matrice de sortie:

[ 1.93137085 0.   0.   0.  ] 
[ 0.   2.41421356 0.   0.  ] 
[ 0.   0.   -1.002002 -1.  ] 
[ 0.   0.   0.2002002 0.  ] 
+0

'600/480' va toujours retourner un' 1'. Faites-le '600.0/480.0'.Cela ne devrait pas être la raison de l'écran blanc si. –

+0

600/480 = 1,25 quand je l'exécute en python. – Francis

+0

http://ideone.com/I9sfXf –

Répondre

3

Puisque vous avez dit que vous travaillez depuis glm :: perspective, analysons votre code par rapport à celui-ci. Il y a une incongruité critique:

glm::perspective

assert(aspect != valType(0)); 
    assert(zFar != zNear); 

#ifdef GLM_FORCE_RADIANS 
    valType const rad = fovy; 
#else 
    valType const rad = glm::radians(fovy); 
#endif 

    valType tanHalfFovy = tan(rad/valType(2)); 
    detail::tmat4x4<valType> Result(valType(0)); 
    Result[0][0] = valType(1)/(aspect * tanHalfFovy); 
    Result[1][1] = valType(1)/(tanHalfFovy); 
    Result[2][2] = - (zFar + zNear)/(zFar - zNear); 
    Result[2][3] = - valType(1); 
    Result[3][2] = - (valType(2) * zFar * zNear)/(zFar - zNear); 
    return Result; 

Notez la ligne suivante:

Result[2][2] = - (zFar + zNear)/(zFar - zNear); 

Comparez à votre équivalent:

a_33 = (z_near + z_far)/(z_near - z_far) 

Notez qu'il ya un signe négatif (-) devant la déclaration entière. Votre version ne l'a pas.

+0

J'avais remarqué la différence entre les deux matrices et vérifié cela mais ce n'était pas le problème. Aussi après avoir changé le signe pour correspondre à mes coordonnées d'espace de clip, passez de (-1, + 1) à (+ 3, + 1). Je pense que le problème est ailleurs. – Francis

+0

Ok, c'était le problème, pour une raison quelconque, quand j'ai vérifié cela plus tôt, il n'y avait aucun effet visible. Je suppose que quelque chose d'autre était mauvais et j'ai changé cela en tripotant mon code (je ne sais toujours pas ce que c'était ou comment il l'a réparé). Les doigts croisés je ne le casse plus (ce sont des moments comme ceux-ci je suis reconnaissant j'ai git). – Francis

0

J'ai résolu le problème, en publiant des informations au cas où quelqu'un rencontrerait des problèmes similaires à l'avenir. Pendant la construction des matrices de modèle, de vue et de projection, j'ai introduit un mélange de matrices majeures et matricielles majeures. Celles-ci ont été introduites car numpy et OpenGL requièrent les matrices dans différents formats. En fonctionnant seuls ces matrices ont fonctionné parce qu'elles pourraient être transposées facilement avec numpy pour produire le résultat correct.

Le problème est survenu lors de la combinaison des matrices. L'effet était que les transformations étaient appliquées dans un ordre incohérent et sans signification et tous les points étaient retirés de l'écran. Cela a caché les erreurs dans la matrice de perspective et le débogage compliqué.

La solution consiste à s'assurer que toutes les matrices sont cohérentes dans la façon dont elles stockent les données (soit toutes les lignes majeures ou toutes les colonnes majeures) et la transposition se produit une fois avant l'envoi à OpenGL.