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

OpenGL Discussion :

probleme de rotation axes fixes


Sujet :

OpenGL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 27
    Par défaut probleme de rotation axes fixes
    Faisant suite à ce sujet que plus grand monde ne doit regarder vu qu'il a été résolu, je me permet de recréer un topic.

    J'applique la méthode qui a permie de resoudre le probleme de jmb462, à savoir utiliser les quaternions, mais rien à faire, celà ne veux pas fonctionner chez moi.
    Je me suis basé sur le code du tuto de NeHe et de la FAQ puis du code de jmb462 pour faire le mien, pas grand chose ne change, et pourtant ....

    Berf le voici :

    Code de ma classe Quaternion, il ne devrait pas poser de souci, étant purement et simplement implenté à partir de la FAQ ou de NeHe. Aucunes difficultées particulières a priori : 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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
     
    #include "Quaternion.h"
     
    Quaternion::Quaternion(){
      x = y = z = 0;
      w = 1;
    };
     
    void 
    Quaternion::createFromAxisAngle(float _x, float _y, float _z, float angle) {
      // Convert degrees to radians
      angle = float((angle / 180.0) * M_PI);
     
      // Here we calculate the sin( theta / 2) once for optimization
      float result = (float)sin( angle / 2.0 );
     
      // Calcualte the w value by cos( theta / 2 )
      w = (float)cos( angle / 2.0 );
      // Calculate the x, y and z of the quaternion
      x = float(_x * result);
      y = float(_y * result);
      z = float(_z * result);
     
      normalise();
    };
     
    void 
    Quaternion::createFromMatrix(float* m){
      float t = m[0] + m[5] + m[10];
      float s;
     
      if(t>0){
        s = 1/(2*sqrt(t));
        x = (m[9]-m[6])*s;
        y = (m[2]-m[8])*s;
        z = (m[4]-m[1])*s;
        w = 1/(4*s);
      }else if(m[0]>m[5] && m[0]>m[10]){
        s = sqrt(1+m[0]-m[5]-m[10])*2;
        x = 1/(2*s);
        y = (m[1]-m[4])/s;
        z = (m[2]-m[8])/s;
        w = (m[6]-m[9])/s;
      }else if(m[5]>m[0] && m[5]>m[10]){
        s = sqrt(1-m[0]+m[5]-m[10])*2;
        x = (m[1]-m[4])/s;
        y = 1/(2*s);
        z = (m[6]-m[9])/s;
        w = (m[2]-m[8])/s;
      }else {
        s = sqrt(1-m[0]-m[5]+m[10])*2;
        x = (m[2]-m[8])/s;
        y = (m[6]-m[9])/s;
        z = 1/(2*s);
        w = (m[1]-m[4])/s;
      }
      normalise();
    };
     
    void
    Quaternion::createFromEuler(float ax, float ay, float az){
      double eulerX, eulerY, eulerZ;		
     
      eulerX = ax/180*M_PI/ 2.0;
      eulerY = ay/180*M_PI/ 2.0;
      eulerZ = az/180*M_PI/ 2.0;
     
     
      //on calcule les 4 valeurs du quaternion :
     
      w = float(cos(eulerX) * cos(eulerY)*cos(eulerZ) + sin(eulerX) * sin(eulerY)*sin(eulerZ));
     
      x = float(sin(eulerX) * cos(eulerY)*cos(eulerZ) - cos(eulerX) * sin(eulerY)*sin(eulerZ));
      y = float(cos(eulerX) * sin(eulerY) * cos(eulerZ) + sin(eulerX) * cos(eulerY) * sin(eulerZ));
      z = float(cos(eulerX) * cos(eulerY) * sin(eulerZ) - sin(eulerX) * sin(eulerY) * cos(eulerZ));
     
      normalise(); // ici tu appelles la fonction membre qui normalise ton quaternion (Normalize() ?)
     
      return;
     
    };
     
    Quaternion 
    Quaternion::operator *(Quaternion q){
      Quaternion r;
      r.w = w*q.w - x*q.x - y*q.y - z*q.z;
      r.x = w*q.x + x*q.w + y*q.z - z*q.y;
      r.y = w*q.y + y*q.w + z*q.x - x*q.z;
      r.z = w*q.z + z*q.w + x*q.y - y*q.x;
     
      r.normalise();
      return r;
    };
     
    Quaternion 
    Quaternion::conjugate(Quaternion q){
      Quaternion r;
      r.x = -q.x;
      r.y = -q.y;
      r.z = -q.z;
      r.w = q.w;
     
      return r;
    };
     
    float 
    Quaternion:: magnitude(){
      return sqrt(w * w + x * x + y * y + z * z);
    };
     
    void 
    Quaternion::normalise(){
      float m = magnitude();
      if(m>0){
        x /= m;
        y /= m;
        z /= m;
        w /= m;
      }
    };
     
    void 
    Quaternion::createMatrix(float* matrix){
      // Make sure the matrix has allocated memory to store the rotation data
      if(!matrix) return;
      // First row
      matrix[0] = 1.0 - 2.0 * ( y * y + z * z ); 
      matrix[1] = 2.0 * (x * y + z * w);
      matrix[2] = 2.0 * (x * z - y * w);
      matrix[3] = 0.0;  
      // Second row
      matrix[4] = 2.0 * ( x * y - z * w );  
      matrix[5] = 1.0 - 2.0 * ( x * x + z * z ); 
      matrix[6] = 2.0 * (z * y + x * w );  
      matrix[7] = 0.0;  
      // Third row
      matrix[8] = 2.0 * ( x * z + y * w );
      matrix[9] = 2.0 * ( y * z - x * w );
      matrix[10] = 1.0 - 2.0 * ( x * x + y * y );  
      matrix[11] = 0.0;  
      // Fourth row
      matrix[12] = 0.0;  
      matrix[13] = 0.0;  
      matrix[14] = 0.0;  
      matrix[15] = 1.0;
      // Now matrix[] is a 4x4 homogeneous matrix that can be applied to an OpenGL Matrix
    };
     
    void 
    Quaternion::createAxisAngle(float &_x, float &_y, float &_z, float &angle){
      float scale = sqrt(x*x + y*y + z*z); ;
      if(scale == 0)
        scale = 1;
      normalise();
      angle = acos(w) * 2 * 180 / M_PI;
      _x = x/scale;
      _y = y/scale;
      _z = z/scale; 
    };

    J'ai essaye les différentes fonctions pour créer les quaternions et pour les retransfomer en matrices ou angle/axe, cela donne à chaque fois le même résultats

    Code perso, la ou doit se trouver l'erreur ... Il est appelé à chaque fois que la scène doit être redessinée : 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
     
    void MaClasse::draw(){
      float matrix[16];
      Quaternion q0, qrotx, qroty;
     
      // Initialisation   
      if (!valid()) {
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
        glViewport(0,0,w(),h());
        gluPerspective(70,(double)w()/h(),1,1000);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_BLEND);						// Activate transparency
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);		// Activate transparency
     
        glMatrixMode( GL_MODELVIEW );
      }
     
      glClearColor(1,1,1,1);					
      glClearDepth(1.0);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      glLoadIdentity();
      gluLookAt(0,0,10,0,0,0,0,1,0);				// Place the camera
     
      if(size < 0)
        size = 0;
      glScalef((float)(size),(float)(size),(float)(size));		// Change size (zoom)
      glTranslatef(hshift, vshift, 0);				// Translate (user's movements)
     
      //Make the Quaternions that will represent our rotations
      qrotx.createFromEuler(vAng,0,0);
      qroty.createFromEuler(0,hAng,0);
      q0 = qroty * qrotx;		// Combine the both rotation and store the result in q0
      q0.createMatrix(matrix);
      glMultMatrixf(matrix);
     
      // dessiner le repere  	
      glBegin(GL_LINES);
      glColor3f(1,0,0);
      glVertex3f(0,0,0);
      glVertex3f(1,0,0);
      glColor3f(0,1,0);
      glVertex3f(0,0,0);
      glVertex3f(0,1,0);
      glColor3f(0,0,1);
      glVertex3f(0,0,0);
      glVertex3f(0,0,1);
      glEnd();
    };

    J'utilise fltk, d'où la syntaxe d'initialisation.

    Le probleme est donc ici que la rotation suivant y (donc la deuxième) se fait autour de l'axe x local, celui-là meme qui a tourné correctement autour de l'axe y global avec la première rotation. Bien entendu si j'inverse l'ordre des rotations, c'est le contraire qui se passe.

    Je ne comprend vraiment pas pourquoi j'obtient cela, et n'arrive absolument pas à trouver le problème.

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 8
    Par défaut
    Bon je ne vais pas te resoudre ton probleme juste te donner le code que j'utilise pour ma trackball sous osg.
    Si ca t'interesse c facilement transformable pour gl
    dx dy sont mes décalage en x et y de ma souris pour toi ca doit etre ton angle sur x et sur y

    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
    72
    73
    74
    75
    76
    77
    78
    osg::Vec3d MyTrackBall::makeRotatePointXY(osg::Vec3d vPointVue,float dx, float dy,osg::Vec3d vPointVise)
    {
    		osg::Vec3d res;
    		osg::Vec3d vecVisionCam;
    		osg::Vec3d vecNormalVision;
    		float fAngleDy = dy*45;
    		float fAngleDx = dx*45;
    		float fAngleOzVecVision,cosfAngleOzVecVision;
    		float fAngleOyVecVision,cosfAngleOyVecVision;
    		float fLongueur;
    		float fRayonCercle;
    		float fRapport;
    		float fTest;
     
    		//res=vPointVue;
    		fLongueur = vPointVue.length();
    		vecVisionCam._v[0]=vPointVue._v[0]-vPointVise._v[0];
    		vecVisionCam._v[1]=vPointVue._v[1]-vPointVise._v[1];
    		vecVisionCam._v[2]=vPointVue._v[2]-vPointVise._v[2];
    		fLongueur = vecVisionCam.length();
    		fRayonCercle = sqrt(vecVisionCam._v[0]*vecVisionCam._v[0]+vecVisionCam._v[1]*vecVisionCam._v[1]);
     
    		if(fRayonCercle < 0.01) // le point de vue est sur l'axe oz 
    		{
    			if ( vecVisionCam._v[2]>0 && fAngleDy<0)
    				return vPointVue;
    			if ( vecVisionCam._v[2]<0 && fAngleDy>0 )
    				return vPointVue;
    		}	
    		vecNormalVision._v[0]=vecVisionCam._v[1];
    		vecNormalVision._v[1]=-vecVisionCam._v[0];
    		vecNormalVision._v[2]=vPointVise._v[2];
     
    		osg::Vec3d oz(0.0,0.0,1.0);
    		cosfAngleOzVecVision = produitScalaire(oz,vecVisionCam);
    		fAngleOzVecVision = acos(cosfAngleOzVecVision);
    		fAngleOzVecVision = osg::RadiansToDegrees(fAngleOzVecVision);
     
    		osg::Vec3d oy(0.0,1.0,0.0);
    		vecVisionCam._v[2] = 0;
    		cosfAngleOyVecVision = produitScalaire(vecVisionCam,oy);
    		fAngleOyVecVision = acos(cosfAngleOyVecVision);
    		fAngleOyVecVision = osg::RadiansToDegrees(fAngleOyVecVision);
     
    		if(vecVisionCam._v[0]<0)
    			fAngleOyVecVision = -fAngleOyVecVision;
     
    		res._v[0] = 0.0;
    		res._v[1] = 0.0;
    		res._v[2] = fLongueur;
     
    		// recupere le z et y grace a la rotation d'angle fAngleOzVecVision - fAngleDy autour de x sur le point (0,0,fLongueur)
     
    		fAngleOzVecVision = fAngleOzVecVision + fAngleDy;
    		// si l'angle est négatif on stop
    		if (fAngleOzVecVision < 0.5 || fAngleOzVecVision > 179.5)
    			return vPointVue;
    		fAngleOzVecVision = osg::DegreesToRadians(fAngleOzVecVision);
     
    		res._v[0] = res._v[0];
    		res._v[1] = sin(fAngleOzVecVision)*fLongueur;
    		res._v[2] = cos(fAngleOzVecVision)*fLongueur;
     
    		// calcul du rayon du nouveau cercle
    		fRayonCercle = sqrt(res._v[1]*res._v[1]);
     
    		// calcul le y et x grace a la rotation d'angle fAngleOyVecVision + fAngleDx
    		fAngleOyVecVision = fAngleOyVecVision + fAngleDx;
    		fAngleOyVecVision = osg::DegreesToRadians(fAngleOyVecVision);
    		res._v[0] = sin(fAngleOyVecVision)*fRayonCercle;
    		res._v[1] = cos(fAngleOyVecVision)*fRayonCercle;
    		res._v[2] = res._v[2];
     
    		res._v[0] = res._v[0] + vPointVise._v[0];
    		res._v[1] = res._v[1] + vPointVise._v[1];
    		res._v[2] = res._v[2] + vPointVise._v[2];
    		return res;
    }
    et res est la nouvelle position de l'obs

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 27
    Par défaut
    Merci de vouloir m'aider, mais disons que ce n'est pas vraiment d'une nouvelle methode dont j'ai besoin, c'est de savoir pourquoi une qui marche et que j'applique ne fonctionne pas chez moi. A fortiori si c'est un code que je dois adapter, je ferais les meme erreurs.
    J'ai deja retraivailler mon code plusieur fois pour changer de methode, cela ne m'a pas vraiment aide. J'en conclu que mon probleme n'est surement pas das la methode en elle meme, mais dans ce qu'il y a autour.

    De plus je ne suis pas sur que le code que tu me donne fasse ce que je veux, pour exemple le code de la trackball possede exactement la meme faiblesse que le mien, qui dans leur cas est favorable, dans le mien non.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 27
    Par défaut
    ^ up ^

    Si quelqu'un à une autre idée ?

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 27
    Par défaut
    Toujours pas ?

Discussions similaires

  1. Réponses: 5
    Dernier message: 13/09/2013, 08h13
  2. Rotation d'une sphère avec axes fixes
    Par jmb462 dans le forum OpenGL
    Réponses: 10
    Dernier message: 09/05/2007, 10h44
  3. Probleme de rotation de bannieres
    Par bug33 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 06/09/2005, 20h30

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