123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829 |
- #pragma once
- #include <Mathematics/AxisAngle.h>
- #include <Mathematics/EulerAngles.h>
- #include <Mathematics/Matrix.h>
- #include <Mathematics/Quaternion.h>
- namespace WwiseGTE
- {
-
-
-
-
-
-
- template <int N, typename Real>
- class Rotation
- {
- public:
-
- Rotation(Matrix<N, N, Real> const& matrix)
- :
- mType(IS_MATRIX),
- mMatrix(matrix)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- }
- Rotation(Quaternion<Real> const& quaternion)
- :
- mType(IS_QUATERNION),
- mQuaternion(quaternion)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- }
- Rotation(AxisAngle<N, Real> const& axisAngle)
- :
- mType(IS_AXIS_ANGLE),
- mAxisAngle(axisAngle)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- }
- Rotation(EulerAngles<Real> const& eulerAngles)
- :
- mType(IS_EULER_ANGLES),
- mEulerAngles(eulerAngles)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- }
-
- operator Matrix<N, N, Real>() const
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- switch (mType)
- {
- case IS_MATRIX:
- break;
- case IS_QUATERNION:
- Convert(mQuaternion, mMatrix);
- break;
- case IS_AXIS_ANGLE:
- Convert(mAxisAngle, mMatrix);
- break;
- case IS_EULER_ANGLES:
- Convert(mEulerAngles, mMatrix);
- break;
- }
- return mMatrix;
- }
- operator Quaternion<Real>() const
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- switch (mType)
- {
- case IS_MATRIX:
- Convert(mMatrix, mQuaternion);
- break;
- case IS_QUATERNION:
- break;
- case IS_AXIS_ANGLE:
- Convert(mAxisAngle, mQuaternion);
- break;
- case IS_EULER_ANGLES:
- Convert(mEulerAngles, mQuaternion);
- break;
- }
- return mQuaternion;
- }
- operator AxisAngle<N, Real>() const
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- switch (mType)
- {
- case IS_MATRIX:
- Convert(mMatrix, mAxisAngle);
- break;
- case IS_QUATERNION:
- Convert(mQuaternion, mAxisAngle);
- break;
- case IS_AXIS_ANGLE:
- break;
- case IS_EULER_ANGLES:
- Convert(mEulerAngles, mAxisAngle);
- break;
- }
- return mAxisAngle;
- }
- EulerAngles<Real> const& operator()(int i0, int i1, int i2) const
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- mEulerAngles.axis[0] = i0;
- mEulerAngles.axis[1] = i1;
- mEulerAngles.axis[2] = i2;
- switch (mType)
- {
- case IS_MATRIX:
- Convert(mMatrix, mEulerAngles);
- break;
- case IS_QUATERNION:
- Convert(mQuaternion, mEulerAngles);
- break;
- case IS_AXIS_ANGLE:
- Convert(mAxisAngle, mEulerAngles);
- break;
- case IS_EULER_ANGLES:
- break;
- }
- return mEulerAngles;
- }
- private:
- enum RepresentationType
- {
- IS_MATRIX,
- IS_QUATERNION,
- IS_AXIS_ANGLE,
- IS_EULER_ANGLES
- };
- RepresentationType mType;
- mutable Matrix<N, N, Real> mMatrix;
- mutable Quaternion<Real> mQuaternion;
- mutable AxisAngle<N, Real> mAxisAngle;
- mutable EulerAngles<Real> mEulerAngles;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- static void Convert(Matrix<N, N, Real> const& r, Quaternion<Real>& q)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- Real r22 = r(2, 2);
- if (r22 <= (Real)0)
- {
- Real dif10 = r(1, 1) - r(0, 0);
- Real omr22 = (Real)1 - r22;
- if (dif10 <= (Real)0)
- {
- Real fourXSqr = omr22 - dif10;
- Real inv4x = ((Real)0.5) / std::sqrt(fourXSqr);
- q[0] = fourXSqr * inv4x;
- q[1] = (r(0, 1) + r(1, 0)) * inv4x;
- q[2] = (r(0, 2) + r(2, 0)) * inv4x;
- #if defined(GTE_USE_MAT_VEC)
- q[3] = (r(2, 1) - r(1, 2)) * inv4x;
- #else
- q[3] = (r(1, 2) - r(2, 1)) * inv4x;
- #endif
- }
- else
- {
- Real fourYSqr = omr22 + dif10;
- Real inv4y = ((Real)0.5) / std::sqrt(fourYSqr);
- q[0] = (r(0, 1) + r(1, 0)) * inv4y;
- q[1] = fourYSqr * inv4y;
- q[2] = (r(1, 2) + r(2, 1)) * inv4y;
- #if defined(GTE_USE_MAT_VEC)
- q[3] = (r(0, 2) - r(2, 0)) * inv4y;
- #else
- q[3] = (r(2, 0) - r(0, 2)) * inv4y;
- #endif
- }
- }
- else
- {
- Real sum10 = r(1, 1) + r(0, 0);
- Real opr22 = (Real)1 + r22;
- if (sum10 <= (Real)0)
- {
- Real fourZSqr = opr22 - sum10;
- Real inv4z = ((Real)0.5) / std::sqrt(fourZSqr);
- q[0] = (r(0, 2) + r(2, 0)) * inv4z;
- q[1] = (r(1, 2) + r(2, 1)) * inv4z;
- q[2] = fourZSqr * inv4z;
- #if defined(GTE_USE_MAT_VEC)
- q[3] = (r(1, 0) - r(0, 1)) * inv4z;
- #else
- q[3] = (r(0, 1) - r(1, 0)) * inv4z;
- #endif
- }
- else
- {
- Real fourWSqr = opr22 + sum10;
- Real inv4w = ((Real)0.5) / std::sqrt(fourWSqr);
- #if defined(GTE_USE_MAT_VEC)
- q[0] = (r(2, 1) - r(1, 2)) * inv4w;
- q[1] = (r(0, 2) - r(2, 0)) * inv4w;
- q[2] = (r(1, 0) - r(0, 1)) * inv4w;
- #else
- q[0] = (r(1, 2) - r(2, 1)) * inv4w;
- q[1] = (r(2, 0) - r(0, 2)) * inv4w;
- q[2] = (r(0, 1) - r(1, 0)) * inv4w;
- #endif
- q[3] = fourWSqr * inv4w;
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- static void Convert(Quaternion<Real> const& q, Matrix<N, N, Real>& r)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- r.MakeIdentity();
- Real twoX = ((Real)2) * q[0];
- Real twoY = ((Real)2) * q[1];
- Real twoZ = ((Real)2) * q[2];
- Real twoXX = twoX * q[0];
- Real twoXY = twoX * q[1];
- Real twoXZ = twoX * q[2];
- Real twoXW = twoX * q[3];
- Real twoYY = twoY * q[1];
- Real twoYZ = twoY * q[2];
- Real twoYW = twoY * q[3];
- Real twoZZ = twoZ * q[2];
- Real twoZW = twoZ * q[3];
- #if defined(GTE_USE_MAT_VEC)
- r(0, 0) = (Real)1 - twoYY - twoZZ;
- r(0, 1) = twoXY - twoZW;
- r(0, 2) = twoXZ + twoYW;
- r(1, 0) = twoXY + twoZW;
- r(1, 1) = (Real)1 - twoXX - twoZZ;
- r(1, 2) = twoYZ - twoXW;
- r(2, 0) = twoXZ - twoYW;
- r(2, 1) = twoYZ + twoXW;
- r(2, 2) = (Real)1 - twoXX - twoYY;
- #else
- r(0, 0) = (Real)1 - twoYY - twoZZ;
- r(1, 0) = twoXY - twoZW;
- r(2, 0) = twoXZ + twoYW;
- r(0, 1) = twoXY + twoZW;
- r(1, 1) = (Real)1 - twoXX - twoZZ;
- r(2, 1) = twoYZ - twoXW;
- r(0, 2) = twoXZ - twoYW;
- r(1, 2) = twoYZ + twoXW;
- r(2, 2) = (Real)1 - twoXX - twoYY;
- #endif
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- static void Convert(Matrix<N, N, Real> const& r, AxisAngle<N, Real>& a)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- Real trace = r(0, 0) + r(1, 1) + r(2, 2);
- Real half = (Real)0.5;
- Real cs = half * (trace - (Real)1);
- cs = std::max(std::min(cs, (Real)1), (Real)-1);
- a.angle = std::acos(cs);
- a.axis.MakeZero();
- if (a.angle > (Real)0)
- {
- if (a.angle < (Real)GTE_C_PI)
- {
-
- #if defined(GTE_USE_MAT_VEC)
- a.axis[0] = r(2, 1) - r(1, 2);
- a.axis[1] = r(0, 2) - r(2, 0);
- a.axis[2] = r(1, 0) - r(0, 1);
- Normalize(a.axis);
- #else
- a.axis[0] = r(1, 2) - r(2, 1);
- a.axis[1] = r(2, 0) - r(0, 2);
- a.axis[2] = r(0, 1) - r(1, 0);
- Normalize(a.axis);
- #endif
- }
- else
- {
-
-
-
-
-
-
-
- Real one = (Real)1;
- if (r(0, 0) >= r(1, 1))
- {
- if (r(0, 0) >= r(2, 2))
- {
-
- a.axis[0] = r(0, 0) + one;
- a.axis[1] = half * (r(0, 1) + r(1, 0));
- a.axis[2] = half * (r(0, 2) + r(2, 0));
- }
- else
- {
-
- a.axis[0] = half * (r(2, 0) + r(0, 2));
- a.axis[1] = half * (r(2, 1) + r(1, 2));
- a.axis[2] = r(2, 2) + one;
- }
- }
- else
- {
- if (r(1, 1) >= r(2, 2))
- {
-
- a.axis[0] = half * (r(1, 0) + r(0, 1));
- a.axis[1] = r(1, 1) + one;
- a.axis[2] = half * (r(1, 2) + r(2, 1));
- }
- else
- {
-
- a.axis[0] = half * (r(2, 0) + r(0, 2));
- a.axis[1] = half * (r(2, 1) + r(1, 2));
- a.axis[2] = r(2, 2) + one;
- }
- }
- Normalize(a.axis);
- }
- }
- else
- {
-
-
- a.axis[0] = (Real)1;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- static void Convert(AxisAngle<N, Real> const& a, Matrix<N, N, Real>& r)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- r.MakeIdentity();
- Real cs = std::cos(a.angle);
- Real sn = std::sin(a.angle);
- Real oneMinusCos = ((Real)1) - cs;
- Real x0sqr = a.axis[0] * a.axis[0];
- Real x1sqr = a.axis[1] * a.axis[1];
- Real x2sqr = a.axis[2] * a.axis[2];
- Real x0x1m = a.axis[0] * a.axis[1] * oneMinusCos;
- Real x0x2m = a.axis[0] * a.axis[2] * oneMinusCos;
- Real x1x2m = a.axis[1] * a.axis[2] * oneMinusCos;
- Real x0Sin = a.axis[0] * sn;
- Real x1Sin = a.axis[1] * sn;
- Real x2Sin = a.axis[2] * sn;
- #if defined(GTE_USE_MAT_VEC)
- r(0, 0) = x0sqr * oneMinusCos + cs;
- r(0, 1) = x0x1m - x2Sin;
- r(0, 2) = x0x2m + x1Sin;
- r(1, 0) = x0x1m + x2Sin;
- r(1, 1) = x1sqr * oneMinusCos + cs;
- r(1, 2) = x1x2m - x0Sin;
- r(2, 0) = x0x2m - x1Sin;
- r(2, 1) = x1x2m + x0Sin;
- r(2, 2) = x2sqr * oneMinusCos + cs;
- #else
- r(0, 0) = x0sqr * oneMinusCos + cs;
- r(1, 0) = x0x1m - x2Sin;
- r(2, 0) = x0x2m + x1Sin;
- r(0, 1) = x0x1m + x2Sin;
- r(1, 1) = x1sqr * oneMinusCos + cs;
- r(2, 1) = x1x2m - x0Sin;
- r(0, 2) = x0x2m - x1Sin;
- r(1, 2) = x1x2m + x0Sin;
- r(2, 2) = x2sqr * oneMinusCos + cs;
- #endif
- }
-
-
-
-
-
-
-
- static void Convert(Matrix<N, N, Real> const& r, EulerAngles<Real>& e)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- if (0 <= e.axis[0] && e.axis[0] < 3
- && 0 <= e.axis[1] && e.axis[1] < 3
- && 0 <= e.axis[2] && e.axis[2] < 3
- && e.axis[1] != e.axis[0]
- && e.axis[1] != e.axis[2])
- {
- if (e.axis[0] != e.axis[2])
- {
- #if defined(GTE_USE_MAT_VEC)
-
-
- int parity = (((e.axis[2] | (e.axis[1] << 2)) >> e.axis[0]) & 1);
- Real const sgn = (parity & 1 ? (Real)-1 : (Real)+1);
- if (r(e.axis[2], e.axis[0]) < (Real)1)
- {
- if (r(e.axis[2], e.axis[0]) > (Real)-1)
- {
- e.angle[2] = std::atan2(sgn * r(e.axis[1], e.axis[0]),
- r(e.axis[0], e.axis[0]));
- e.angle[1] = std::asin(-sgn * r(e.axis[2], e.axis[0]));
- e.angle[0] = std::atan2(sgn * r(e.axis[2], e.axis[1]),
- r(e.axis[2], e.axis[2]));
- e.result = ER_UNIQUE;
- }
- else
- {
- e.angle[2] = (Real)0;
- e.angle[1] = sgn * (Real)GTE_C_HALF_PI;
- e.angle[0] = std::atan2(-sgn * r(e.axis[1], e.axis[2]),
- r(e.axis[1], e.axis[1]));
- e.result = ER_NOT_UNIQUE_DIF;
- }
- }
- else
- {
- e.angle[2] = (Real)0;
- e.angle[1] = -sgn * (Real)GTE_C_HALF_PI;
- e.angle[0] = std::atan2(-sgn * r(e.axis[1], e.axis[2]),
- r(e.axis[1], e.axis[1]));
- e.result = ER_NOT_UNIQUE_SUM;
- }
- #else
-
-
- int parity = (((e.axis[0] | (e.axis[1] << 2)) >> e.axis[2]) & 1);
- Real const sgn = (parity & 1 ? (Real)+1 : (Real)-1);
- if (r(e.axis[0], e.axis[2]) < (Real)1)
- {
- if (r(e.axis[0], e.axis[2]) > (Real)-1)
- {
- e.angle[0] = std::atan2(sgn * r(e.axis[1], e.axis[2]),
- r(e.axis[2], e.axis[2]));
- e.angle[1] = std::asin(-sgn * r(e.axis[0], e.axis[2]));
- e.angle[2] = std::atan2(sgn * r(e.axis[0], e.axis[1]),
- r(e.axis[0], e.axis[0]));
- e.result = ER_UNIQUE;
- }
- else
- {
- e.angle[0] = (Real)0;
- e.angle[1] = sgn * (Real)GTE_C_HALF_PI;
- e.angle[2] = std::atan2(-sgn * r(e.axis[1], e.axis[0]),
- r(e.axis[1], e.axis[1]));
- e.result = ER_NOT_UNIQUE_DIF;
- }
- }
- else
- {
- e.angle[0] = (Real)0;
- e.angle[1] = -sgn * (Real)GTE_C_HALF_PI;
- e.angle[2] = std::atan2(-sgn * r(e.axis[1], e.axis[0]),
- r(e.axis[1], e.axis[1]));
- e.result = ER_NOT_UNIQUE_SUM;
- }
- #endif
- }
- else
- {
- #if defined(GTE_USE_MAT_VEC)
-
-
- int b0 = 3 - e.axis[1] - e.axis[2];
- int parity = (((b0 | (e.axis[1] << 2)) >> e.axis[2]) & 1);
- Real const sgn = (parity & 1 ? (Real)+1 : (Real)-1);
- if (r(e.axis[2], e.axis[2]) < (Real)1)
- {
- if (r(e.axis[2], e.axis[2]) > (Real)-1)
- {
- e.angle[2] = std::atan2(r(e.axis[1], e.axis[2]),
- sgn * r(b0, e.axis[2]));
- e.angle[1] = std::acos(r(e.axis[2], e.axis[2]));
- e.angle[0] = std::atan2(r(e.axis[2], e.axis[1]),
- -sgn * r(e.axis[2], b0));
- e.result = ER_UNIQUE;
- }
- else
- {
- e.angle[2] = (Real)0;
- e.angle[1] = (Real)GTE_C_PI;
- e.angle[0] = std::atan2(sgn * r(e.axis[1], b0),
- r(e.axis[1], e.axis[1]));
- e.result = ER_NOT_UNIQUE_DIF;
- }
- }
- else
- {
- e.angle[2] = (Real)0;
- e.angle[1] = (Real)0;
- e.angle[0] = std::atan2(sgn * r(e.axis[1], b0),
- r(e.axis[1], e.axis[1]));
- e.result = ER_NOT_UNIQUE_SUM;
- }
- #else
-
-
- int b2 = 3 - e.axis[0] - e.axis[1];
- int parity = (((b2 | (e.axis[1] << 2)) >> e.axis[0]) & 1);
- Real const sgn = (parity & 1 ? (Real)-1 : (Real)+1);
- if (r(e.axis[0], e.axis[0]) < (Real)1)
- {
- if (r(e.axis[0], e.axis[0]) > (Real)-1)
- {
- e.angle[0] = std::atan2(r(e.axis[1], e.axis[0]),
- sgn * r(b2, e.axis[0]));
- e.angle[1] = std::acos(r(e.axis[0], e.axis[0]));
- e.angle[2] = std::atan2(r(e.axis[0], e.axis[1]),
- -sgn * r(e.axis[0], b2));
- e.result = ER_UNIQUE;
- }
- else
- {
- e.angle[0] = (Real)0;
- e.angle[1] = (Real)GTE_C_PI;
- e.angle[2] = std::atan2(sgn * r(e.axis[1], b2),
- r(e.axis[1], e.axis[1]));
- e.result = ER_NOT_UNIQUE_DIF;
- }
- }
- else
- {
- e.angle[0] = (Real)0;
- e.angle[1] = (Real)0;
- e.angle[2] = std::atan2(sgn * r(e.axis[1], b2),
- r(e.axis[1], e.axis[1]));
- e.result = ER_NOT_UNIQUE_SUM;
- }
- #endif
- }
- }
- else
- {
-
- e.angle[0] = (Real)0;
- e.angle[1] = (Real)0;
- e.angle[2] = (Real)0;
- e.result = ER_INVALID;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- static void Convert(EulerAngles<Real> const& e, Matrix<N, N, Real>& r)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- if (0 <= e.axis[0] && e.axis[0] < 3
- && 0 <= e.axis[1] && e.axis[1] < 3
- && 0 <= e.axis[2] && e.axis[2] < 3
- && e.axis[1] != e.axis[0]
- && e.axis[1] != e.axis[2])
- {
- Matrix<N, N, Real> r0, r1, r2;
- Convert(AxisAngle<N, Real>(Vector<N, Real>::Unit(e.axis[0]),
- e.angle[0]), r0);
- Convert(AxisAngle<N, Real>(Vector<N, Real>::Unit(e.axis[1]),
- e.angle[1]), r1);
- Convert(AxisAngle<N, Real>(Vector<N, Real>::Unit(e.axis[2]),
- e.angle[2]), r2);
- #if defined(GTE_USE_MAT_VEC)
- r = r2 * r1 * r0;
- #else
- r = r0 * r1 * r2;
- #endif
- }
- else
- {
-
- r.MakeIdentity();
- }
- }
-
-
- static void Convert(Quaternion<Real> const& q, AxisAngle<N, Real>& a)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- a.axis.MakeZero();
- Real axisSqrLen = q[0] * q[0] + q[1] * q[1] + q[2] * q[2];
- if (axisSqrLen > (Real)0)
- {
- #if defined(GTE_USE_MAT_VEC)
- Real adjust = ((Real)1) / std::sqrt(axisSqrLen);
- #else
- Real adjust = ((Real)-1) / std::sqrt(axisSqrLen);
- #endif
- a.axis[0] = q[0] * adjust;
- a.axis[1] = q[1] * adjust;
- a.axis[2] = q[2] * adjust;
- Real cs = std::max(std::min(q[3], (Real)1), (Real)-1);
- a.angle = (Real)2 * std::acos(cs);
- }
- else
- {
-
-
- a.axis[0] = (Real)1;
- a.angle = (Real)0;
- }
- }
-
-
- static void Convert(AxisAngle<N, Real> const& a, Quaternion<Real>& q)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- #if defined(GTE_USE_MAT_VEC)
- Real halfAngle = (Real)0.5 * a.angle;
- #else
- Real halfAngle = (Real)-0.5 * a.angle;
- #endif
- Real sn = std::sin(halfAngle);
- q[0] = sn * a.axis[0];
- q[1] = sn * a.axis[1];
- q[2] = sn * a.axis[2];
- q[3] = std::cos(halfAngle);
- }
-
-
- static void Convert(Quaternion<Real> const& q, EulerAngles<Real>& e)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- Matrix<N, N, Real> r;
- Convert(q, r);
- Convert(r, e);
- }
-
-
- static void Convert(EulerAngles<Real> const& e, Quaternion<Real>& q)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- Matrix<N, N, Real> r;
- Convert(e, r);
- Convert(r, q);
- }
-
-
-
- static void Convert(AxisAngle<N, Real> const& a, EulerAngles<Real>& e)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- Quaternion<Real> q;
- Convert(a, q);
- Convert(q, e);
- }
-
-
-
- static void Convert(EulerAngles<Real> const& e, AxisAngle<N, Real>& a)
- {
- static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
- Quaternion<Real> q;
- Convert(e, q);
- Convert(q, a);
- }
- };
- }
|