37 const qreal epsilon = 1E-10;
42 if ((fromSqNorm < epsilon) || (toSqNorm < epsilon))
49 Vec axis = cross(from, to);
53 if (axisSqNorm < epsilon)
56 qreal angle = asin(sqrt(axisSqNorm / (fromSqNorm * toSqNorm)));
61 setAxisAngle(axis, angle);
70 return inverse().rotate(v);
78 const qreal q00 = 2.0 * q[0] * q[0];
79 const qreal q11 = 2.0 * q[1] * q[1];
80 const qreal q22 = 2.0 * q[2] * q[2];
82 const qreal q01 = 2.0 * q[0] * q[1];
83 const qreal q02 = 2.0 * q[0] * q[2];
84 const qreal q03 = 2.0 * q[0] * q[3];
86 const qreal q12 = 2.0 * q[1] * q[2];
87 const qreal q13 = 2.0 * q[1] * q[3];
89 const qreal q23 = 2.0 * 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] );
107 const qreal onePlusTrace = 1.0 + m[0][0] + m[1][1] + m[2][2];
109 if (onePlusTrace > 1E-5)
112 const qreal 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 qreal 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 qreal 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 qreal 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;
153 qWarning(
"setFromRotationMatrix now expects 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] = qreal(m[i][j]);
160 setFromRotationMatrix(mat);
165 qWarning(
"setFromRotatedBase is deprecated, use setFromRotatedBasis instead");
166 setFromRotatedBasis(X,Y,Z);
185 qreal normX = X.
norm();
186 qreal normY = Y.
norm();
187 qreal 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 qreal sinus = axis.
norm();
211 angle = 2.0 * qreal(
M_PI) - angle;
221 Vec res =
Vec(q[0], q[1], q[2]);
222 const qreal sinus = res.
norm();
225 return (acos(q[3]) <=
M_PI/2.0) ? res : -res;
236 const qreal 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)
308 static GLdouble m[4][4];
310 return (
const GLdouble*)(m);
319 const qreal q00 = 2.0 * q[0] * q[0];
320 const qreal q11 = 2.0 * q[1] * q[1];
321 const qreal q22 = 2.0 * q[2] * q[2];
323 const qreal q01 = 2.0 * q[0] * q[1];
324 const qreal q02 = 2.0 * q[0] * q[2];
325 const qreal q03 = 2.0 * q[0] * q[3];
327 const qreal q12 = 2.0 * q[1] * q[2];
328 const qreal q13 = 2.0 * q[1] * q[3];
330 const qreal q23 = 2.0 * q[2] * q[3];
332 m[0][0] = 1.0 - q11 - q22;
337 m[1][1] = 1.0 - q22 - q00;
342 m[2][2] = 1.0 - 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)
378 m[i][j] = qreal(mat[j][i]);
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)
422 m[i][j] = qreal(mat[j][i]);
439 if ((1.0 - fabs(cosAngle)) < 0.01)
447 qreal angle = acos(fabs(cosAngle));
448 qreal 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 qreal len = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2]);
483 qreal coef = acos(q[3]) / len;
484 return Quaternion(q[0]*coef, q[1]*coef, q[2]*coef, 0.0);
491 qreal 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 qreal 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());
530 return o << Q[0] <<
'\t' << Q[1] <<
'\t' << Q[2] <<
'\t' << Q[3];
546 qreal seed = rand()/(qreal)RAND_MAX;
547 qreal r1 = sqrt(1.0 - seed);
548 qreal r2 = sqrt(seed);
549 qreal t1 = 2.0 *
M_PI * (rand()/(qreal)RAND_MAX);
550 qreal t2 = 2.0 *
M_PI * (rand()/(qreal)RAND_MAX);
551 return Quaternion(sin(t1)*r1, cos(t1)*r1, sin(t2)*r2, cos(t2)*r2);
Quaternion inverse() const
void getAxisAngle(Vec &axis, qreal &angle) const
static Quaternion randomQuaternion()
void setFromRotatedBase(const Vec &X, const Vec &Y, const Vec &Z)
static Quaternion squad(const Quaternion &a, const Quaternion &tgA, const Quaternion &tgB, const Quaternion &b, qreal t)
Vec orthogonalVec() const
qreal squaredNorm() const
Vec rotate(const Vec &v) const
static Quaternion squadTangent(const Quaternion &before, const Quaternion ¢er, const Quaternion &after)
Vec inverseRotate(const Vec &v) const
void setFromRotationMatrix(const float m[3][3])
const GLdouble * inverseMatrix() const
ostream & operator<<(ostream &o, const Quaternion &Q)
The Vec class represents 3D positions and 3D vectors.
void initFromDOMElement(const QDomElement &element)
static qreal dot(const Quaternion &a, const Quaternion &b)
void getInverseRotationMatrix(qreal m[3][3]) const
void getRotationMatrix(qreal m[3][3]) const
static qreal qrealFromDom(const QDomElement &e, const QString &attribute, qreal defValue)
static Quaternion lnDif(const Quaternion &a, const Quaternion &b)
const GLdouble * matrix() const
The Quaternion class represents 3D rotations and orientations.
void setFromRotatedBasis(const Vec &X, const Vec &Y, const Vec &Z)
static Quaternion slerp(const Quaternion &a, const Quaternion &b, qreal t, bool allowFlip=true)
QDomElement domElement(const QString &name, QDomDocument &document) const
void getMatrix(GLdouble m[4][4]) const
void getInverseMatrix(GLdouble m[4][4]) const