24 #include "quaternion.h" 
   37     const double epsilon = 1E-10f;
 
   42     if ((fromSqNorm < epsilon) || (toSqNorm < epsilon))
 
   49         Vec axis = cross(from, to);
 
   53         if (axisSqNorm < epsilon)
 
   56         double angle = asin(sqrt(axisSqNorm / (fromSqNorm * toSqNorm)));
 
   61         setAxisAngle(axis, angle);
 
   70     return inverse().rotate(v);
 
   78     const double q00 = 2.0l * q[0] * q[0];
 
   79     const double q11 = 2.0l * q[1] * q[1];
 
   80     const double q22 = 2.0l * q[2] * q[2];
 
   82     const double q01 = 2.0l * q[0] * q[1];
 
   83     const double q02 = 2.0l * q[0] * q[2];
 
   84     const double q03 = 2.0l * q[0] * q[3];
 
   86     const double q12 = 2.0l * q[1] * q[2];
 
   87     const double q13 = 2.0l * q[1] * q[3];
 
   89     const double q23 = 2.0l * q[2] * q[3];
 
   91     return Vec((1.0 - q11 - q22)*v[0] + (      q01 - q23)*v[1] + (      q02 + q13)*v[2],
 
   92             (      q01 + q23)*v[0] + (1.0 - q22 - q00)*v[1] + (      q12 - q03)*v[2],
 
   93             (      q02 - q13)*v[0] + (      q12 + q03)*v[1] + (1.0 - q11 - q00)*v[2] );
 
  104 void Quaternion::setFromRotationMatrix(
const double m[3][3])
 
  107     const double onePlusTrace = 1.0 + m[0][0] + m[1][1] + m[2][2];
 
  109     if (onePlusTrace > 1E-5)
 
  112         const double s = sqrt(onePlusTrace) * 2.0;
 
  113         q[0] = (m[2][1] - m[1][2]) / s;
 
  114         q[1] = (m[0][2] - m[2][0]) / s;
 
  115         q[2] = (m[1][0] - m[0][1]) / s;
 
  121         if ((m[0][0] > m[1][1])&(m[0][0] > m[2][2]))
 
  123             const double s = sqrt(1.0 + m[0][0] - m[1][1] - m[2][2]) * 2.0;
 
  125             q[1] = (m[0][1] + m[1][0]) / s;
 
  126             q[2] = (m[0][2] + m[2][0]) / s;
 
  127             q[3] = (m[1][2] - m[2][1]) / s;
 
  130             if (m[1][1] > m[2][2])
 
  132                 const double s = sqrt(1.0 + m[1][1] - m[0][0] - m[2][2]) * 2.0;
 
  133                 q[0] = (m[0][1] + m[1][0]) / s;
 
  135                 q[2] = (m[1][2] + m[2][1]) / s;
 
  136                 q[3] = (m[0][2] - m[2][0]) / s;
 
  140                 const double s = sqrt(1.0 + m[2][2] - m[0][0] - m[1][1]) * 2.0;
 
  141                 q[0] = (m[0][2] + m[2][0]) / s;
 
  142                 q[1] = (m[1][2] + m[2][1]) / s;
 
  144                 q[3] = (m[0][1] - m[1][0]) / s;
 
  151 void Quaternion::setFromRotationMatrix(
const float m[3][3])
 
  153     qWarning(
"setFromRotationMatrix now waits for a double[3][3] parameter");
 
  156     for (
int i=0; i<3; ++i)
 
  157         for (
int j=0; j<3; ++j)
 
  158             mat[i][j] = 
double(m[i][j]);
 
  160     setFromRotationMatrix(mat);
 
  163 void Quaternion::setFromRotatedBase(
const Vec& X, 
const Vec& Y, 
const Vec& Z)
 
  165     qWarning(
"setFromRotatedBase is deprecated, use setFromRotatedBasis instead");
 
  166     setFromRotatedBasis(X,Y,Z);
 
  185     double normX = X.
norm();
 
  186     double normY = Y.
norm();
 
  187     double normZ = Z.
norm();
 
  189     for (
int i=0; i<3; ++i)
 
  191         m[i][0] = X[i] / normX;
 
  192         m[i][1] = Y[i] / normY;
 
  193         m[i][2] = Z[i] / normZ;
 
  196     setFromRotationMatrix(m);
 
  203     angle = 2.0*acos(q[3]);
 
  204     axis = 
Vec(q[0], q[1], q[2]);
 
  205     const double sinus = axis.
norm();
 
  211         angle = 2.0*M_PI - angle;
 
  221     Vec res = 
Vec(q[0], q[1], q[2]);
 
  222     const double sinus = res.
norm();
 
  225     return (acos(q[3]) <= M_PI/2.0) ? res : -res;
 
  236     const double angle = 2.0 * acos(q[3]);
 
  237     return (angle <= M_PI) ? angle : 2.0*M_PI - angle;
 
  258     QDomElement de = document.createElement(name);
 
  259     de.setAttribute(
"q0", QString::number(q[0]));
 
  260     de.setAttribute(
"q1", QString::number(q[1]));
 
  261     de.setAttribute(
"q2", QString::number(q[2]));
 
  262     de.setAttribute(
"q3", QString::number(q[3]));
 
  288     QStringList attribute;
 
  289     attribute << 
"q0" << 
"q1" << 
"q2" << 
"q3";
 
  290     for (
int i=0; i<attribute.size(); ++i)
 
  291         q[i] = DomUtils::doubleFromDom(element, attribute[i], ((i<3)?0.0f:1.0f));
 
  308     static GLdouble m[4][4];
 
  310     return (
const GLdouble*)(m);
 
  319     const double q00 = 2.0l * q[0] * q[0];
 
  320     const double q11 = 2.0l * q[1] * q[1];
 
  321     const double q22 = 2.0l * q[2] * q[2];
 
  323     const double q01 = 2.0l * q[0] * q[1];
 
  324     const double q02 = 2.0l * q[0] * q[2];
 
  325     const double q03 = 2.0l * q[0] * q[3];
 
  327     const double q12 = 2.0l * q[1] * q[2];
 
  328     const double q13 = 2.0l * q[1] * q[3];
 
  330     const double q23 = 2.0l * q[2] * q[3];
 
  332     m[0][0] = 1.0l - q11 - q22;
 
  337     m[1][1] = 1.0l - q22 - q00;
 
  342     m[2][2] = 1.0l - q11 - q00;
 
  357     static GLdouble mat[4][4];
 
  360     for (
int i=0; i<4; ++i)
 
  361         for (
int j=0; j<4; ++j)
 
  362             m[count++] = mat[i][j];
 
  373     static GLdouble mat[4][4];
 
  375     for (
int i=0; i<3; ++i)
 
  376         for (
int j=0; j<3; ++j)
 
  391     static GLdouble m[4][4];
 
  393     return (
const GLdouble*)(m);
 
  402     inverse().getMatrix(m);
 
  408     inverse().getMatrix(m);
 
  417     static GLdouble mat[4][4];
 
  418     getInverseMatrix(mat);
 
  419     for (
int i=0; i<3; ++i)
 
  420         for (
int j=0; j<3; ++j)
 
  439     if ((1.0 - fabs(cosAngle)) < 0.01)
 
  447         double angle    = acos(fabs(cosAngle));
 
  448         double sinAngle = sin(angle);
 
  449         c1 = sin(angle * (1.0 - t)) / sinAngle;
 
  450         c2 = sin(angle * t) / sinAngle;
 
  454     if (allowFlip && (cosAngle < 0.0))
 
  457     return Quaternion(c1*a[0] + c2*b[0], c1*a[1] + c2*b[1], c1*a[2] + c2*b[2], c1*a[3] + c2*b[3]);
 
  477     double len = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2]);
 
  483         double coef = acos(q[3]) / len;
 
  484         return Quaternion(q[0]*coef, q[1]*coef, q[2]*coef, 0.0);
 
  491     double theta = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2]);
 
  494         return Quaternion(q[0], q[1], q[2], cos(theta));
 
  497         double coef = sin(theta) / theta;
 
  498         return Quaternion(q[0]*coef, q[1]*coef, q[2]*coef, cos(theta));
 
  518     for (
int i=0; i<4; ++i)
 
  519         e.q[i] = -0.25 * (l1.q[i] + l2.q[i]);
 
  520     e = center*(e.
exp());
 
  528 ostream& operator<<(ostream& o, 
const Quaternion& Q)
 
  530     return o << Q[0] << 
'\t' << Q[1] << 
'\t' << Q[2] << 
'\t' << Q[3];
 
  546     double seed = rand()/(double)RAND_MAX;
 
  547     double r1 = sqrt(1.0 - seed);
 
  548     double r2 = sqrt(seed);
 
  549     double t1 = 2.0 * M_PI * (rand()/(double)RAND_MAX);
 
  550     double t2 = 2.0 * M_PI * (rand()/(double)RAND_MAX);
 
  551     return Quaternion(sin(t1)*r1, cos(t1)*r1, sin(t2)*r2, cos(t2)*r2);
 
const GLdouble * inverseMatrix() const 
Returns the associated 4x4 OpenGL inverse rotation matrix. 
 
Quaternion inverse() const 
Returns the inverse Quaternion (inverse rotation). 
 
double squaredNorm() const 
Returns the squared norm of the Vec. 
 
static double dot(const Quaternion &a, const Quaternion &b)
Returns the "dot" product of a and b: a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]. 
 
Quaternion log()
Returns the logarithm of the Quaternion. 
 
double norm() const 
Returns the norm of the vector. 
 
Vec orthogonalVec() const 
Returns a Vec orthogonal to the Vec. 
 
static Quaternion squadTangent(const Quaternion &before, const Quaternion ¢er, const Quaternion &after)
Returns a tangent Quaternion for center, defined by before and after Quaternions. ...
 
QDomElement domElement(const QString &name, QDomDocument &document) const 
Returns an XML QDomElement that represents the Quaternion. 
 
static Quaternion lnDif(const Quaternion &a, const Quaternion &b)
Returns log(a. 
 
static Quaternion squad(const Quaternion &a, const Quaternion &tgA, const Quaternion &tgB, const Quaternion &b, float t)
Returns the slerp interpolation of the two Quaternions a and b, at time t, using tangents tgA and tgB...
 
The Vec class represents 3D positions and 3D vectors. 
 
Quaternion exp()
Returns the exponential of the Quaternion. 
 
void getAxisAngle(Vec &axis, float &angle) const 
Returns the axis vector and the angle (in radians) of the rotation represented by the Quaternion...
 
static Quaternion slerp(const Quaternion &a, const Quaternion &b, float t, bool allowFlip=true)
Returns the slerp interpolation of Quaternions a and b, at time t. 
 
void setFromRotatedBasis(const Vec &X, const Vec &Y, const Vec &Z)
Sets the Quaternion from the three rotated vectors of an orthogonal basis. 
 
void getMatrix(GLdouble m[4][4]) const 
Fills m with the OpenGL representation of the Quaternion rotation. 
 
Vec inverseRotate(const Vec &v) const 
Returns the image of v by the Quaternion inverse() rotation. 
 
Quaternion()
Default constructor, builds an identity rotation. 
 
double angle() const 
Returns the angle (in radians) of the rotation represented by the Quaternion. 
 
The Quaternion class represents 3D rotations and orientations. 
 
static Quaternion randomQuaternion()
Returns a random unit Quaternion. 
 
Vec axis() const 
Returns the normalized axis direction of the rotation represented by the Quaternion. 
 
void getInverseRotationMatrix(float m[3][3]) const 
m is set to the 3x3 inverse rotation matrix associated with the Quaternion. 
 
Vec rotate(const Vec &v) const 
Returns the image of v by the Quaternion rotation. 
 
double normalize()
Normalizes the Quaternion coefficients. 
 
void initFromDOMElement(const QDomElement &element)
Restores the Quaternion state from a QDomElement created by domElement(). 
 
void getInverseMatrix(GLdouble m[4][4]) const 
Fills m with the OpenGL matrix corresponding to the inverse() rotation. 
 
const GLdouble * matrix() const 
Returns the Quaternion associated 4x4 OpenGL rotation matrix. 
 
void getRotationMatrix(float m[3][3]) const 
Fills m with the 3x3 rotation matrix associated with the Quaternion.