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.