24 #ifndef _USE_MATH_DEFINES
25 #define _USE_MATH_DEFINES
35 template<
typename Real,
typename Vec3Real>
43 { q[0]=q[1]=q[2]=0.0; q[3]=1.0; }
51 TQuaternion(
const Vec3Real& from,
const Vec3Real& to)
53 const Real epsilon = 1E-10f;
55 const Real fromSqNorm = from.squaredNorm();
56 const Real toSqNorm = to.squaredNorm();
58 if ((fromSqNorm < epsilon) || (toSqNorm < epsilon))
65 Vec3Real axis =
cross(from, to);
66 const Real axisSqNorm = axis.squaredNorm();
69 if (axisSqNorm < epsilon)
71 axis = Vec3Real(1.0, 0.0, 0.0);
72 if (axis*from < 0.1*sqrt(fromSqNorm))
73 axis = Vec3Real(0.0, 1.0, 0.0);
76 Real angle = asin(sqrt(axisSqNorm / (fromSqNorm * toSqNorm)));
91 { q[0]=q0; q[1]=q1; q[2]=q2; q[3]=q3; }
95 {
for (
int i=0; i<4; ++i) q[i] = Q.q[i]; }
100 for (
int i=0; i<4; ++i)
107 for (
int i = 0; i < 4; ++i)
118 const Real norm =
length(axis);
129 const Real sin_half_angle = sin(angle / 2.0);
130 q[0] = sin_half_angle*axis.x/norm;
131 q[1] = sin_half_angle*axis.y/norm;
132 q[2] = sin_half_angle*axis.z/norm;
133 q[3] = cos(angle / 2.0);
139 { q[0]=q0; q[1]=q1; q[2]=q2; q[3]=q3; }
142 template<
typename MAT>
143 void setFromRotationMatrix(
const MAT& m)
147 if (m[0][0] > m[1][1])
149 if (m[0][0] > m[2][2])
156 if (m[1][1] > m[2][2])
162 if (m[0][0]+m[1][1]+m[2][2] > m[i][i])
165 q[3] = sqrt(m[0][0]+m[1][1]+m[2][2]+1.0)/2.0;
167 q[0] = (m[2][1]-m[1][2])/(4.0*q[3]);
168 q[1] = (m[0][2]-m[2][0])/(4.0*q[3]);
169 q[2] = (m[1][0]-m[0][1])/(4.0*q[3]);
178 q[i] = sqrt(m[i][i]-m[j][j]-m[k][k]+1.0)/2.0;
181 q[j] = (m[i][j]+m[j][i])/(4.0*q[i]);
182 q[k] = (m[i][k]+m[k][i])/(4.0*q[i]);
184 q[3] = (m[k][j]-m[j][k])/(4.0*q[i]);
188 void setFromRotatedBase(
const Vec3Real& X,
const Vec3Real& Y,
const Vec3Real& Z)
191 Real normX = X.norm();
192 Real normY = Y.norm();
193 Real normZ = Z.norm();
195 for (
int i=0; i<3; ++i)
197 m[i][0] = X[i] / normX;
198 m[i][1] = Y[i] / normY;
199 m[i][2] = Z[i] / normZ;
201 setFromRotationMatrix(m);
209 Vec3Real axis()
const
211 Vec3Real res = Vec3Real(q[0], q[1], q[2]);
212 const Real sinus = res.norm();
215 return (acos(q[3]) <= M_PI/2.0) ? res : -res;
221 const Real angle = 2.0 * acos(q[3]);
222 return (angle <= M_PI) ? angle : 2.0*M_PI - angle;
226 void getAxisAngle(Vec3Real& axis, Real& angle)
const
228 angle = 2.0*acos(q[3]);
229 axis = Vec3Real(q[0], q[1], q[2]);
230 const Real sinus = axis.norm();
236 angle = 2.0*M_PI - angle;
270 return TQuaternion(a.q[3]*b.q[0] + b.q[3]*a.q[0] + a.q[1]*b.q[2] - a.q[2]*b.q[1],
271 a.q[3]*b.q[1] + b.q[3]*a.q[1] + a.q[2]*b.q[0] - a.q[0]*b.q[2],
272 a.q[3]*b.q[2] + b.q[3]*a.q[2] + a.q[0]*b.q[1] - a.q[1]*b.q[0],
273 a.q[3]*b.q[3] - b.q[0]*a.q[0] - a.q[1]*b.q[1] - a.q[2]*b.q[2]);
298 Vec3Real rotate(
const Vec3Real& v)
const
300 const Real q00 = 2.0l * q[0] * q[0];
301 const Real q11 = 2.0l * q[1] * q[1];
302 const Real q22 = 2.0l * q[2] * q[2];
304 const Real q01 = 2.0l * q[0] * q[1];
305 const Real q02 = 2.0l * q[0] * q[2];
306 const Real q03 = 2.0l * q[0] * q[3];
308 const Real q12 = 2.0l * q[1] * q[2];
309 const Real q13 = 2.0l * q[1] * q[3];
311 const Real q23 = 2.0l * q[2] * q[3];
313 return Vec3Real((1.0 - q11 - q22)*v.x + ( q01 - q23)*v.y + ( q02 + q13)*v.z,
314 ( q01 + q23)*v.x + (1.0 - q22 - q00)*v.y + ( q12 - q03)*v.z,
315 ( q02 - q13)*v.x + ( q12 + q03)*v.y + (1.0 - q11 - q00)*v.z );
319 Vec3Real inverseRotate(
const Vec3Real& v)
const
342 void invert() { q[0] = -q[0]; q[1] = -q[1]; q[2] = -q[2]; }
360 const Real norm = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
361 for (
int i=0; i<4; ++i)
385 return (
const Real*)(m);
394 template<
typename MAT>
397 const Real q00 = 2.0l * q[0] * q[0];
398 const Real q11 = 2.0l * q[1] * q[1];
399 const Real q22 = 2.0l * q[2] * q[2];
401 const Real q01 = 2.0l * q[0] * q[1];
402 const Real q02 = 2.0l * q[0] * q[2];
403 const Real q03 = 2.0l * q[0] * q[3];
405 const Real q12 = 2.0l * q[1] * q[2];
406 const Real q13 = 2.0l * q[1] * q[3];
408 const Real q23 = 2.0l * q[2] * q[3];
410 m[0][0] = 1.0l - q11 - q22;
415 m[1][1] = 1.0l - q22 - q00;
420 m[2][2] = 1.0l - q11 - q00;
437 template<
typename MAT>
440 const Real q00 = 2.0l * q[0] * q[0];
441 const Real q11 = 2.0l * q[1] * q[1];
442 const Real q22 = 2.0l * q[2] * q[2];
444 const Real q01 = 2.0l * q[0] * q[1];
445 const Real q02 = 2.0l * q[0] * q[2];
446 const Real q03 = 2.0l * q[0] * q[3];
448 const Real q12 = 2.0l * q[1] * q[2];
449 const Real q13 = 2.0l * q[1] * q[3];
451 const Real q23 = 2.0l * q[2] * q[3];
453 m[0][0] = 1.0l - q11 - q22;
458 m[1][1] = 1.0l - q22 - q00;
463 m[2][2] = 1.0l - q11 - q00;
466 void getMatrix16(Real m[16])
const
468 static Real mat[4][4];
471 for (
int i=0; i<4; ++i)
472 for (
int j=0; j<4; ++j)
473 m[count++] = mat[i][j];
483 static Real mat[4][4];
485 for (
int i=0; i<3; ++i)
486 for (
int j=0; j<3; ++j)
501 return (
const Real*)(m);
526 static Real mat[4][4];
528 for (
int i=0; i<3; ++i)
529 for (
int j=0; j<3; ++j)
544 if ((1.0 - fabs(cosAngle)) < 0.01)
552 Real angle = acos(fabs(cosAngle));
553 Real sinAngle = sin(angle);
554 c1 = sin(angle * (1.0 - t)) / sinAngle;
555 c2 = sin(angle * t) / sinAngle;
559 if (allowFlip && (cosAngle < 0.0))
562 return TQuaternion(c1*a[0] + c2*b[0], c1*a[1] + c2*b[1], c1*a[2] + c2*b[2], c1*a[3] + c2*b[3]);
569 TQuaternion tg = TQuaternion::slerp(tgA, tgB, t,
false);
570 return TQuaternion::slerp(ab, tg, 2.0*t*(1.0-t),
false);
580 Real len = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2]);
586 Real coef = acos(q[3]) / len;
587 return TQuaternion(q[0]*coef, q[1]*coef, q[2]*coef, 0.0);
594 Real theta = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2]);
600 Real coef = sin(theta) / theta;
601 return TQuaternion(q[0]*coef, q[1]*coef, q[2]*coef, cos(theta));
619 for (
int i=0; i<4; ++i)
620 e.q[i] = -0.25 * (l1.q[i] + l2.q[i]);
636 Real seed = rand()/(Real)RAND_MAX;
637 Real r1 = sqrt(1.0 - seed);
638 Real r2 = sqrt(seed);
639 Real t1 = 2.0 * M_PI * (rand()/(Real)RAND_MAX);
640 Real t2 = 2.0 * M_PI * (rand()/(Real)RAND_MAX);
641 return TQuaternion(sin(t1)*r1, cos(t1)*r1, sin(t2)*r2, cos(t2)*r2);
660 inline std::ostream& operator<<(std::ostream& o,
const qglviewer::Vec&);
665 friend inline std::ostream& operator<<(std::ostream& o,
const TQuaternion& Q)
667 o <<
"(" << Q[0] <<
',' << Q[1] <<
',' << Q[2] <<
',' << Q[3] <<
")";
void getInverseMatrix(Real m[4][4]) const
Real operator[](int i) const
TQuaternion(const TQuaternion &Q)
void getMatrix33(MAT &m) const
void setAxisAngle(const Vec3Real &axis, const Real angle)
static Real dot(const TQuaternion &a, const TQuaternion &b)
friend Vec3Real operator*(const TQuaternion &q, const Vec3Real &v)
friend TQuaternion operator*(const TQuaternion &a, const TQuaternion &b)
void getRotationMatrix(Real m[3][3]) const
TQuaternion & operator=(const TQuaternion &Q)
void getMatrix44(MAT &m) const
TQuaternion & operator*=(const TQuaternion &q)
TQuaternion inverse() const
TQuaternion(Real q0, Real q1, Real q2, Real q3)
const Real * matrix() const
friend TQuaternion operator*(const Real a, const TQuaternion &b)
TQuaternion(const Vec3Real &axis, const Real angle)
void setValue(Real q0, Real q1, Real q2, Real q3)
void getInverseRotationMatrix(Real m[3][3]) const
const Real * inverseMatrix() const
Point center(const Point &a, const Point &b)
renvoie le milieu du segment ab.
float length(const Vector &v)
renvoie la longueur d'un vecteur.
Vector cross(const Vector &u, const Vector &v)
renvoie le produit vectoriel de 2 vecteurs.