HowTo: Matrice de Projection Perspective en OpenGL

Maths...



Je viens de tomber sur ce post de Xavier Gouchet qui avait besoin d’une routine pour initialiser la matrice de projection de la caméra en OpenGL. Vu qu’il ne pouvait pas utiliser les fonctions de la glu/glut car non supportées sous Android, il a du trouver une routine avec juste deux fonctions de base d’OpenGL: glMatrixMode et glFrustum. C’est bien! Mais on peut mieux faire: rendre le calcul de la matrice totalement indépendant d’OpenGL. En gros, recoder la fonction glFrustum.

Gros intéret de la méthode: la routine peut être utilisée aussi bien avec Direct3D qu’avec avec le futur Larrabee

Okay mes amis, voici le code extrait de mes routines 3D (et légèrement modifié pour les besoins de ce post):

void BuildPerspProjMat(float *m, float fov, float aspect, 
float znear, float zfar)
{
  float xymax = znear * tan(fov * PI_OVER_360);
  float ymin = -ymax;
  float xmin = -xmax;

  float width = xymax - xmin;
  float height = xymax - ymin;

  float depth = zfar - znear;
  float q = -(zfar + znear) / depth;
  float qn = -2 * (zfar * znear) / depth;

  float w = 2 * znear / width;
  w = w / aspect;
  float h = 2 * znear / height;

  m[0]  = w;
  m[1]  = 0;
  m[2]  = 0;
  m[3]  = 0;

  m[4]  = 0;
  m[5]  = h;
  m[6]  = 0;
  m[7]  = 0;

  m[8]  = 0;
  m[9]  = 0;
  m[10] = q;
  m[11] = -1;

  m[12] = 0;
  m[13] = 0;
  m[14] = qn;
  m[15] = 0;
}

et voici son utilisation:

float m[16] = {0};
float fov=60.0f; // en degrés
float aspect=1.3333f;
float znear=1.0f;
float zfar=1000.0f;
BuildPerspProjMat(m, fov, aspect, znear, zfar);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(m);

// et hop on repasse en modelview pour le reste des matrices
glMatrixMode(GL_MODELVIEW);
...

Pour finir et juste pour optimiser un peu, la fonction glLoadIdentity dans le code de Xavier n’est pas nécessaire car la fonction glFrustum remplace complétement la matrice…