[OpenGL] faire une rotation d'une scene proprement selon MSDN

faire une rotation d'une scene proprement selon MSDN [OpenGL] - Programmation

Marsh Posté le 13-01-2001 à 00:07:09    

Hi 'vrybody !
 
Juste une petitte question d'un chti debutant en OpenGL:
Pour l'instant, j'utilise GLUT pour afficher une pauvre scene et la faire tourner.
Pour cela, j'ai défini une variable globale, mon angle, que j'incrémente à chaque passage dans ma fonction d'affichage.
Voici la partie interressante du code:
GLfloat angle = 0;
 
void display (void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix ();
 glRotatef(angle, 0.0, 1.0, 0.0);
 angle+=0.1;
 
 glBegin(GL_LINES);ss//le boulot commence ici pour OpenGL !

 
 
 
Or, en parcourant MSDN, je suis tombé là dessus, je cite:"Do not make extensive changes to a single matrix. For example, do not animate a rotation by continually calling glRotate with an incremental angle. Rather, use glLoadIdentity to initialize the given matrix for each frame, and then call glRotate with the desired complete angle for that frame."
Le probleme, c'est que je ne saisi pas trop bien ce qu'ils veulent dire ! Moi, ce que je fais, c'est bien ou pas ? Je débute donc je voudrais pas prendre de mauvaises habitudes !!!

Reply

Marsh Posté le 13-01-2001 à 00:07:09   

Reply

Marsh Posté le 13-01-2001 à 00:28:43    

Je pense que c'est à cause des erreurs de calculs. Si tu fais 360 rotations de 1° de manière incrémentale tu risque de ne pas avoir fais un vrai tour complet.
Tandis que si à chaque fois tu part de la position initiale et fait une rotation de n x 1°, t'es sûr que pour n=360, le tour sera complet.

Reply

Marsh Posté le 13-01-2001 à 00:51:30    

En gros, tu as 2 solution pour faire un animation de rotation:
 
void display (void)  {  glClearColor (0.0, 0.0, 0.0, 0.0);  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  glRotatef(angle, 0.0, 1.0, 0.0); //avec un angle qui ne change pas et qui représente la pas de ta rotation
glBegin(GL_LINES);  //le boulot commence ici pour OpenGL !  ...
}
ou alors
 
void display (void)  {  glClearColor (0.0, 0.0, 0.0, 0.0);  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
 
glRotatef(angle, 0.0, 1.0, 0.0); //avec un angle qui change  (c'est l'angle globale de ta rotation)
glBegin(GL_LINES);  //le boulot commence ici pour OpenGL !  ...
}
 
Le problème, quand tu utilise la première méthode, c'est que tu va faire des multiplications de matrice qui contiennent de + en + d'erreurs d'arrondis... Il vaut donc mieux avoir un angle globale, qui tu incrémente entre chaque frame, et repartir d'une matrice vide avant chaque dessin .
 
J'espère que j'ai été sufisemment explicatif (je ne suis pas un super pro en OpenGL, je débute aussi).

 

--Message édité par Pitounet--

Reply

Marsh Posté le 14-01-2001 à 00:32:47    

Merci de vos réponse !
Juste pour vérifier que j'ai bien compris: c'est donc le bout de code que j'ai mis au début qui est "le meilleur", non ? (V'z'avez vus comment que j'suis fort, j'avais trouvé la bonne réponse des le debut :D !)

Reply

Marsh Posté le 14-01-2001 à 00:41:26    

Euh non faut faire comme dit dans la MSDN.

Reply

Marsh Posté le 14-01-2001 à 11:35:47    

Tu avais bon mais il fallait pas oublier de mettress
glMatrixMode(GL_MODELVIEW);ss
glLoadIdentity();

Reply

Marsh Posté le 14-01-2001 à 17:30:57    

Ces 2 instructions là, je les ai mises à la toute fin de la fonction reshape (placee en parametre de glutReshapeFunc). Donc c'est bon alors finalement, non ?
 
Pour vous remercier de vos reponse, je pourrais vous envoyer le prog ou mes cubes tournent autour d'un axe... ca vous ferait plaisir, heinss:D ?!

Reply

Marsh Posté le 14-01-2001 à 23:07:57    

Top moumoute !

Reply

Marsh Posté le 15-01-2001 à 00:02:43    

Effectivement, je pense aussi que c'est pour les erreurs d'arrondis...
 
au fait, tu as un glPushMatrix sans un glPopMatrix ?

Reply

Marsh Posté le 15-01-2001 à 12:25:22    

Je dirais pas seulement pour les erreurs
d'arrondis, mais aussi pour savoir ou l'on en est.
 
en multipliant regulierement la matrice de rotation d'angles petits,
c'est sale parce que a la fin tu ne sais plus de combien tu as tourne et dans quel sens. Si tu veux garder une trace des rotations sous forme d'une decomposition sous forme d'angles d'Euler(theta, phi, psi) ou d'angles aeronautiques(roulis, tangage et lacet), et bien ta methode ne marche pas.
 
C'est sur que quand tu ne tournes que suivant un seul axe
ca pose pas trop de probleme (a part peut-etre les arrondis,
mais tu peux regler ca en chargeant l'identite quand tu
atteins 360 ou 0 degres)
 
De plus quand tu as une structure hierarchique
(quand ton push et pop marchent et servent a quelque chose)
et bien quand tu reviens a ton objet, tu n'as plus
de souvenir du contexte precedent, sauf en stockant explicitement la matrice, ce qui est un peu lourd puisqu'une rotation c'est trois flottants au max (voir moins, suivant le degre de liberte par rapport au niveau superieur).
Donc de toute facon il faut reappliquer les rotations depuis
le debut, donc je te laisse tirer les conclusions.
(mais pas recharger l'identite, evidemment)
 
Legreg

 

--Message édité par legreg--

Reply

Marsh Posté le 15-01-2001 à 12:25:22   

Reply

Marsh Posté le 15-01-2001 à 16:33:12    

De plus la méthode "j'incremente de 1° a chaque frame" est daubique a point: entre une TNT1 et une GeForce2 Ultra tu auras une sacré difference de vitesse de rotation!
 
Donc la méthode de la rotation fixe + incrémentation de l'angle par un timer, avec glut tu as le choix entre un timer (po terrible) ou de faire ca dans la fonction idle avec lecture du temps, dans ce cas tu ne fait pas un redisplay a la fin de la trame mais plutot a chaque update dans la fonction idle (si tu veux un framerate fixe). De cette facon tu peux fixer le framerate ET la vitesse de rotation de facon independante...

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed