Pour réaliser une animation, on pourrait simplement mettre le "renduScene()" en boucle,
et changer progressivement certaines valeurs de positions, ou d'angles.
Cette méthode possède l'inconvénient de pousser la carte graphique à 100% de ses capacités.
J'utiliserai plutôt un timer (un genre de chronomètre) qui décidera quand le rendu devra
être réactualisé. Cette façon de faire est plus économe en énergie, et donne aussi de
très bon résultats.
La déclaration du timer se fait avec la fonction :
glutTimerFunc(40, onRelance, 1);
• Le premier argument correspond au temps d'attente qui est ici de 40ms.
• Le deuxième argument est le nom de la fonction qui sera appelée lorsque le temps
sera écoulé.
• le dernier argument est juste un indice dans le cas d'utilisation de plusieurs
timers. On le laisse ici à 1.
Cette fonction sera à placer juste avant "glutMainLoop()" appartenant à la fonction "main()".
Ecrivons maintenant la fonction "onRelance()" :
void
onRelance(int
i)
{
glutPostRedisplay();
glutTimerFunc(40,
onRelance,
i);
}
Au déclenchement du timer, la fonction "glutTimerFunc()" transmet en argument l'indice du
timer, à la fonction "onRelance()". On aura donc ici : i = 1.
La fonction "glutPostRedisplay()" lance un nouveau rendu en réactivant la fonction
"glutDisplayFunc(renduScene)" se trouvant dans "main()".
C'est justement ce que nous souhaitions !
Pour terminer on relance le même timer avec la même durée que précédemment.
Vous remarquerez surement la façon astucieuse de transmettre l'indice.
A l'issue du temps écoulé, on recommence et ainsi de suite ...
Juste avant de dessiner notre triangle, nous ajoutons :
glLoadIdentity();
Elle permet une réinitialisation de la matrice de projection.
Nous ajoutons également à suivre :
gluLookAt(0.0,
0.0,
6.0,
0.0,
0.0,
0.0,
0.0,
1.0,
0.0);
Cette nouvelle fonction permet de positionner la caméra qui visionne la scène.
Découvrons maintenant la signification de ces arguments :
• Les trois premier indique la position (x1, y1, z1) de la caméra.
Avec le choix z1 = 6.0, on voit que nous avons éloigné la caméra de 6 unité, de la
position du triangle.
• Les trois arguments suivants (x2, y2, z2) indique le point vers où la caméra regarde.
C'est donc ici le centre de notre scène.
• Les trois derniers (x3, y3, z3) permettent d'incliner la caméra autour de son axe de vision.
Ces coordonnées représente en fait un vecteur P traversant de part en part la caméra de bas en haut.
Incliner ce vecteur conduit donc a incliner la caméra. Le fait d'écrire
(x3 = 0, y3 = 1, et z3 = 0),
force la caméra à rester debout bien droite.
L'animation arrive maintenant grace à la fonction :
glRotatef(angle, 0.0, 1.0, 0.0);
Cette fonction entraine la rotation de notre scène de la valeur donnée par la variable
"angle". Cette variable est en degrès. Vous l'avez surement compris, c'est en faisant évoluer
cette variable que nous allons animer notre triangle.
On parle ici de rotation, mais une rotation autour de quel axe ?
Bonne question ! En fait ce sont les trois derniers paramètres qui vont définir un vecteur
autour duquel se fera la rotation.
Comme nous avons choisi y = 1, c'est donc un vecteur vertical que nous aurons.
Il reste le sens. Avec le choix d'une valeur positive pour "angle" on aura donc
forcément un sens trigonométrique, ce qui donnera lorsque nous regarderons la scène par
le dessus, un sens de rotation inverse des aiguilles d'une montre.
Nous avons terminé, il ne reste plus qu'à incrémenter notre variable "angle" et de tester
notre programme.
angle += 5.0; // En degrès
En tête de programme il ne faudra pas oublier de déclarer la variable "angle" de cette façon :
float angle = 0.0; // En degrès
#include <GL/glut.h>
float
angle =
0.0;
// En degrès
void renduScene()
{
glClearColor(1.0,
0.8,
0.4,
1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// Réinitialisation de la matrice
// Positionnement de la caméra
gluLookAt(0.0,
0.0,
6.0,
0.0,
0.0,
0.0,
0.0,
1.0,
0.0);
glRotatef(angle,
0.0,
1.0,
0.0);
// On applique une rotation
glBegin(GL_TRIANGLES);
glColor3f(1.0,
0.0,
0.0);
// De la couleur
// Coordonnées des vertex (des points)
glVertex3f(-1.5,
-1.5,
0.0);
glVertex3f(1.5,
0.0,
0.0);
glVertex3f(0.0,
1.5,
0.0);
glEnd();
angle +=
5.0;
// En degrès
glutSwapBuffers();
}
void changeDimensions(int
w,
int h)
{
// On se protège d'une division par zéro,
et on calcul le rapport W/H.
// W = Width = Largeur de la fenêtre,
h = hauteur de la fenêtre
if(h
==
0)
h =
1;
float
rapportWsurH =
1.0 *
w / h;
// Choix d'une matrice de calcul pour la projection des points
glMatrixMode(GL_PROJECTION);
// Remplacement de la matrice actuelle par la matrice unité.
glLoadIdentity();
// Paramétrage de la fenêtre d'affichage
glViewport(0,
0,
w,
h);
// Paramétrage de l'observation, perspective, ...
gluPerspective(45,
rapportWsurH,
1,
50);
// Retour à la vue initiale
glMatrixMode(GL_MODELVIEW);
}
void
onRelance(int
i)
{
glutPostRedisplay();
glutTimerFunc(40,
onRelance,
i);
}
int main(int
argc,
char** argv)
{
glutInit(&argc,
argv);
glutInitDisplayMode(GLUT_RGBA |
GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(100,
100);
glutInitWindowSize(300,
200);
glutCreateWindow("Triangle en rotation");
glutDisplayFunc(renduScene);
glutReshapeFunc(changeDimensions);
glutTimerFunc(40,
onRelance,
1);
glutMainLoop();
return
0;
}