IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

OpenGL et rotation


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 212
    Points : 93
    Points
    93
    Par défaut OpenGL et rotation
    Bonjour à tous,

    Je viens vers vous car j'ai un petit soucis de rotation d'objet sous OpenGL en cpp. Pour info je suis sous windows 7 et je code via l'IDE Code::Blocks.

    Pour faire simple, je veux faire tourner un objet dans mon espace. Cet objet est une série de triangles, soit un modèle de reconstruction (Marching Cube) 3D utilisé en imagerie médicale pour avoir la structure externe de l'objet notamment.

    J'ai essayé d'implémenter cette rotation de deux manières différentes, et bien sur les deux ont encore des soucis que je n'arrive plus à résoudre :

    - La première via les touches z, s, q et d :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
    void Clavier(GLubyte touche, GLint x, GLint y)
    {
    	switch(touche){
    	case 'z' : ;
    	{
    		if (save_rotation == 1){
    			rotateAngle = 1;
    			rotatex = 1;
    			rotatey = 0;
    		}
    		else{
    			rotateAngle ++;
    			rotatex = 1;
    		}
    		save_rotation = 0;
    		break;
    	}
     
    	case 's' : ;
    	{
    		if (save_rotation == 1){
    			rotateAngle = -1;
    			rotatex = 1;
    			rotatey = 0;
    		}
    		else{
    			rotateAngle --;
    			rotatex = 1;
    		}
    		save_rotation = 0;
    		break;
    	}
     
    	case 'q' : ;
    	{
    		if (save_rotation == 0){
    			rotateAngle = -1;
    			rotatex = 0;
    			rotatey = 1;
    		}
    		else{
    			rotateAngle --;
    			rotatey = 1;
    		}
     
    		save_rotation = 1;
    		break;
    	}
     
    	case 'd' : ;
    	{
    		if (save_rotation == 0){
    			rotateAngle = 1;
    			rotatex = 0;
    			rotatey = 1;
    		}
    		else{
    			rotateAngle ++;
    			rotatey = 1;
    		}
    		save_rotation = 1;
    		break;
    	}
     
    	default : break;
      }
     
      //strength display a new time
    	glutPostRedisplay();
    }
    Sur cette solution, lorsque je passe de z à s (soit sur le même axe) je n'ai aucun problème. Par contre lorsque je passe de z à q (d'un axe à l'autre) mon objet reprend sa position initiale avant d'effectuer la rotation q ... Or j'aimerais qu'il reste en place et je ne sais pas vraiment comment faire. La fonction du dessin est plus bas.

    - la deuxième solution, via la souris :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
     
    void ClicSouris (int bouton, int etat, int x, int y)
    {
    	save_pos_x = x;
    	save_pos_y = y;
    	save_bouton = bouton;
    	save_etat = etat;
    }
     
     
    void MouvementSourisAvecClic(int x, int y)
    {
    	//initialize
    	float d0, d1, d2, v0, v1, v2, angle_horizontal, angle_vertical, t0, t1, t2;
     
    	int deplacement_x = x - save_pos_x;
    	int deplacement_y = y - save_pos_y;
     
    	save_pos_x = x;
    	save_pos_y = y;
     
    	angle_horizontal = deplacement_x * (Pi/1000);
    	angle_vertical = deplacement_y * (Pi/1000);
     
    	switch (save_bouton){
                   case GLUT_MIDDLE_BUTTON :
                        if (deplacement_y != 0 and deplacement_x == 0)
                        {
    		          rotateAngle += deplacement_y;
                              rotatex = 1;
    			  rotatey = 0;
                         }
    		     else if (deplacement_y != 0 )
                         {
    			  rotateAngle += deplacement_y;
    			  rotatex = 1;
    		     }
    		     if (deplacement_x != 0 and deplacement_y == 0)
                        {
                              rotateAngle += deplacement_x;
                              rotatex = 0;
    			   rotatey = 1;
                        }
    		     else if (deplacement_x != 0)
                        {
    			  rotateAngle += deplacement_x;
    			  rotatey = 1;
    		     }
                        break;
    	}
    	glutPostRedisplay();
     
    }
    Ici le problème est que la rotation fonctionne mais elle n'est pas tout à fait comme on l'attendrait au déplacement de la souris ... J'ai cherché un moment, j'ai supposé un problème d'angle mais je n'ai pas trouvé la solution.

    Voici la fonction dessin de ma scène
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    void Dessiner(){
    	//clear the buffer and Z-buffer
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        //choose the MODELVIEW matrix
        glMatrixMode(GL_MODELVIEW);
        //initialize a new time the matrix
        glLoadIdentity();
     
        //background color
        glClearColor(0,200,255, 0);
     
    	//initial location of us view
        gluLookAt(obs.position[0], obs.position[1], obs.position[2],
    	obs.position[0] + obs.direction[0],
    	obs.position[1] + obs.direction[1],
    	obs.position[2] + obs.direction[2],
    	obs.verticale[0], obs.verticale[1],obs.verticale[2]);
     
        //landmark
        glBegin(GL_LINES);
            glColor3f(1.0,0.0,0.0);
            glVertex2i(0,0);glVertex2i(50,0);//red
            glColor3f(0.0,1.0,0.0);
            glVertex2i(0,0);glVertex2i(0,50);//green
            glColor3f(0.0,0.0,1.0);
            glVertex2i(0,0);glVertex3i(0,0,50);//blue
        glEnd();
     
           //application de la rotation qu'a mon objet
    	if (rotateAngle != 0){
    		glTranslatef(moyx, moyy, moyz);
    		glRotatef(rotateAngle, rotatex, rotatey, rotatez);
    		glTranslatef(-moyx, -moyy, -moyz);
    	}
     
           //triangle de mon objet (Marching Cube)
    	for (int i=0;i<ntri;i++) {
              glBegin(GL_TRIANGLES);
               for (int k=0;k<3;k++)  {
    			glColor3ub(tri[i].ndg, tri[i].ndg, tri[i].ndg);
    			glVertex3d(tri[i].p[k].x, tri[i].p[k].y, tri[i].p[k].z);
               }
               glEnd();
    	}
     
        glutSwapBuffers();
        //calculation a new time the picture
        glutPostRedisplay();
    }
    Autre point non mentionné, les variables non déclarées au long de ce code, sont en réalité des variables globales (d'où le fait que vous les retrouviez dans plusieurs fonctions).
    Je crois n'avoir rien oublié, merci à ceux qui ont eu le courage de me lire en tout cas

  2. #2
    Membre émérite Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 047
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 047
    Points : 2 251
    Points
    2 251
    Par défaut
    Bonjour,
    Avec ce que tu as dis, et le peu de code que l'on vois, je dirais que tu accumule les rotations sur un axe uniquement au lieu de les accumuler sur les 3 axes. Comment est ta matrice de transformation? Fais tu bien une rotation sur les 3 axes et pas uniquement sur le dernier que tu demandes?

  3. #3
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 212
    Points : 93
    Points
    93
    Par défaut
    Bonsoir,

    J'ai pensé à ce point d'accumulation à un moment et j'avoue que j'ai cherché un peu dans cette direction mais je ne voyais pas comment faire dans mon cas avec les glRotatef.
    Sinon je n'ai pas vraiment de matrice de transformation, on la retrouve dans cette fonction Opengl spécifique (choix par simplicité, je l'avoue). Par contre pour appliquer cette rotation, je déplace mon objet en 0,0,0 (translation), j'applique ma rotation d'angle "rotateAngle" et je refais une translation inverse derrière.
    Et pour ta dernière question, à mon avis non du coup, elle revient au point que tu soulèves au début, du coup ça doit certainement venir de là, mais la question est comment faire ... ? ^^ (je m'y penche de mon côté même si les idées n'affluent pas ^^')

  4. #4
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Santé

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Bonjour,

    Je pense qu'il faut que tu sépares les angles en fonction des axes sinon tu risques de réinitialiser les angles pour les axes que tu ne souhaites pas.

    Tu aurais quelque chose du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    int deplacement_x = x - save_pos_x;
    int deplacement_y = y - save_pos_y;
     
    save_pos_x = x;
    save_pos_y = y;
     
    rotateX = (deplacement_x > 0) ? 1 : 0;
    rotateY = (deplacement_y > 0) ? 1 : 0;
     
    switch (save_bouton){
          case GLUT_MIDDLE_BUTTON :
          if(rotateX)
          {
             angleX++; 
          }
          if (rotateY)
          {
             angleY++;
          }
          break;
    }
     
    /// Dans ta fonction dessin:
    glTranslatef(moyx, moyy, moyz);
    glRotatef(angleX, 1, 0, 0);
    glRotatef(angleY, 0, 1, 0);
    glTranslatef(-moyx, -moyy, -moyz);

  5. #5
    Membre émérite Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 047
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 047
    Points : 2 251
    Points
    2 251
    Par défaut
    Et bien, vois ton objet comme un ensemble (un classe).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Geomtery
    {
         Transformation m_t; //rotation (Matrix ou quaternion si tu connais + vecteur de translation + vecteur de scale)
         Geometry m_g; //ensemble de vertice + indice
    };
    class Transformation
    {
        Vector3f m_position;
        Vector3f m_scale;
        Quaternion m_orientation; /* OU */ Vector3f m_orientation; //Angle sur x y et z.    
    };
    Avec un organisation aussi simple, tu peux facilement lier ta transformation avec ta geometry et ainsi facilement debugger. Utilise une matrice de transformation et UNE seule que tu modifies et utilises pour appliquer la transformation.
    Si tu es à l'aise avec les matrices, utilises les quaternions pour l'orientation de ton objet. note que si tu utilises autre chose que les quaternions tu auras du gimbal lock (perte d'un axe)

  6. #6
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 212
    Points : 93
    Points
    93
    Par défaut
    Bonsoir,

    Merci ton idée est vraiment sympa, assez simple en plus, j'ai implémenté ta solution en modifiant juste ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    if (rotateX){
    	rotateAngleX += 5;
    }
    else{
    	rotateAngleX -= 5;
    }
    if (rotateY){
    	rotateAngleY += 5;
    }
    else{
    	rotateAngleY -= 5;
    }
    Par contre ça ne marche pas, j'ai toujours ce problème de visualisation qui n'est pas vraiment celle attendu (même si elle est mieux). Du coup je pars sur cette piste ^^ si vous avez d'autres recommandations je ne dis pas non

  7. #7
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 212
    Points : 93
    Points
    93
    Par défaut
    Désolé je n'ai répondu qu'à un, je pensais avoir confirmé le message et en le faisant quelques heures après je me suis aperçut du second ...
    J'avoue que la notion de quaternions m'est quasi inconnue (en gros j'ai entendu le mot 2 3 fois ...). Et j'utilise les fonctions de gl pour éviter de me prendre la tête là dessus puisque je suis en manque de temps. Après si je vois que ce que je voulais faire au début ne me mène à rien, je passerais sur ta solution, même si en la lisant à tête reposée j'ai un peu de mal ^^'

  8. #8
    Membre régulier
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 212
    Points : 93
    Points
    93
    Par défaut
    j'ai réussi à appliquer ta méthode darkman19320 sur les touches Merci à toi, un très gros merci même ^^ j'avais besoin de faire marcher un des deux minimum, je vais passer à mes specs suivantes et si j'ai le temps je verrais à corriger le problème de la souris.

    Si certains ont le même problèmes, voici le code qui au final est simple ^^' :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    void Clavier(GLubyte touche, GLint x, GLint y)
    {
        switch(touche){
    	case 'z' : ;
    	{
    		rotateAngleX += 5;
    		break;
    	}
     
    	case 's' : ;
    	{
    		rotateAngleX -= 5;
    		break;
    	}
     
    	case 'q' : ;
    	{
    		rotateAngleY -= 5;
    		break;
    	}
     
    	case 'd' : ;
    	{
    		rotateAngleY += 5;
    		break;
    	}
     
    	default : break;
      }
     
      //strength display a new time
    	glutPostRedisplay();
    }
     
    // pour le reste cf plus haut, c'est la même chose ^^

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [OpenGL] la rotation ?
    Par swo.line dans le forum OpenGL
    Réponses: 10
    Dernier message: 12/08/2008, 14h07
  2. [OpenGL] probleme rotations/ translations
    Par Daemonkii dans le forum Windows
    Réponses: 4
    Dernier message: 16/12/2007, 17h42
  3. Réponses: 2
    Dernier message: 15/06/2007, 08h49
  4. [OpenGl] Problème rotation d'un rectangle
    Par dib258 dans le forum SDL
    Réponses: 2
    Dernier message: 20/12/2006, 17h02
  5. [OpenGL] problème de rotation 3D
    Par ReiVon dans le forum OpenGL
    Réponses: 3
    Dernier message: 11/04/2005, 09h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo