La 3ième dimension - les bases sous OpenGL pour Windows
Ca y est, vous avez les bases pour pouvoir attaquer la 3D !
La 3ième dimension
Les objets primitifs sont dessinés via des vertice. Sauf que vous ne passez que 2 dimensions.
Donc, pour passer la 3ième dimension : gl vertex 3 d(x, y, z) (cf. fonctions polyformes)
Et Voilà, vous pouvez modifier le code. Vous n'allez donc plus afficher un point, une droite, mais trois faces pour faire un classeur en 3D. Le cube, exemple souvent donné, c'est trop facile !

Les couvertures du classeur sont bleu devant, rose derrière, et vert sur le coté.
Le z-buffer
Le résultat de l'exemple précédent est le suivant:
La partie rose se superpose sur la partie bleue. En fait, en regardant d'un peu plus près le code, le dessin commence d'abord avec la couverture le bleu, puis le rose. Par défaut, OpenGL va donc dessiner la surface rose au-dessus de la surface précédemment dessiner...la bleue. Une solution pourrait être d'ordonner le dessin, mais ce n'est pas la meilleure solution. A oublier donc !
La meilleure solution sera d'activer le z-buffer. C'est par cette méthode que les faces s'afficheront comme il faut. En fait, il n'y aura affichage que des points les plus proches de celui qui regarde.
Le z-buffer n'est pas actif par défaut dans OpenGL. Il faut donc l'activer. Ne surtout pas oublier d'effacer le contenu du z-buffer surtout si vous faîtes une animation avant chaque calcule de nouvelles images !
Pour activer le z-buffer, il faudra utilisez une fonction : glEnable() (qui permet d'activer pas mal de chose, on pourra alors utiliser le | pour activer plusieurs choses en une fois).
Ici glEnable (GL_DEPTH_TEST) que je vais mettre dans une fonction EnableOpenGL().
Pour désactiver
de nouveau le z-buffer: glDisable (GL_DEPTH_TEST);
Comme indiqué précédemment, il faut effacer le contenu du z-buffer. Il sera à faire systématiquement au début de la procédure de gestion du message WM_PAINT. Vous aviez déjà glClear( GL_COLOR_BUFFER_BIT). Vous allez lui ajouter le z-buffer: glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Le culling
Le résultat
sans z-buffer donne donc ceci. Pour essayer d'éviter
ce problème, vous pouvez aussi utiliser le culling.
Comme déjà vu, OpenGL découpe tous les objets en triangle. Le culling va permettre d'indiquer que l'on veut ne dessiner que les triangles dont les points sont dans le sens des aiguilles d’une montre (« clockwise ») ou dans l’autre sens (« counter-clockwise »).
L’intérêt par rapport au z-buffer est la vitesse. Le but étant de supprimer la face non visible d'un seul coup et non pas de vérifier chaucun des points comme dans le z-buffer.
La méthode consiste donc à regarder dans quel sens les points des triangles sont dessinés: dans le sens des aiguilles d’une montre ou dans l’autre sens:il suffit de regarder le signe du produit scalaire de deux cotés d’un triangle.
La seule contrainte pour le programmeur est de dessiner dans le bon sens les
points.
Par défaut, le test se fait dans le sens inverse des aiguilles d'une
montre (counter-clockwise)
Les fonctions sont:
Activation/désactivation du culling via les classiques glEnable / glDisable avec la valeur GL_CULL_FACE
void glCullFace( GLenum mode )
En entrée:
mode prenant les valeurs GL_FRONT, GL_BACK ou GL_FRONT_AND_BACK, pour indiquer quel coté doit être éliminé au culling.
void glFrontFace( GLenum mode )
En entrée:
mode prenant les valeurs GL_CW ou GL_CCW pour indiquer quelles sont les faces de devant.
Voici un exemple de culling que je fais avec ce classeur, tout ça pour voir un petit problème du culling par rapport au z-buffer...
Les modifications concernent donc l'activation du culling, ainsi que la modification sur la manière d'afficher le classeur (sens anti-horaire respecté)
Le résultat montre que la fonction culling fonctionne très bien, mais le soucis, c'est que la surface est entièrement effacée, y compris la partie encore visible. Ce genre de fonction est très bien pour dessiner des cubes, où les surfaces à l'arrière sont toutes cachées, mais bien moins intéressant dans notre cas !
Annexes
OpenGL pour Linux, Windows, Android...