123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824 |
- // David Eberly, Geometric Tools, Redmond WA 98052
- // Copyright (c) 1998-2020
- // Distributed under the Boost Software License, Version 1.0.
- // https://www.boost.org/LICENSE_1_0.txt
- // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
- // Version: 4.0.2020.01.10
- #pragma once
- #include <Mathematics/Logger.h>
- #include <Mathematics/Matrix3x3.h>
- #include <Mathematics/Matrix4x4.h>
- #include <Mathematics/Rotation.h>
- // Transforms when GTE_USE_MAT_VEC is defined in the preprocessor symbols.
- //
- // The transform is Y = M*X+T, where M is a 3-by-3 matrix and T is a 3x1
- // translation. In most cases, M = R, a rotation matrix, or M = R*S,
- // where R is a rotation matrix and S is a diagonal matrix whose diagonal
- // entries are positive scales. To support modeling packages that allow
- // general affine transforms, M can be any invertible 3x3 matrix. The vector
- // X is transformed in the "forward" direction to Y. The "inverse" direction
- // transforms Y to X, namely X = M^{-1}*(Y-T) in the general case. In the
- // special case of M = R*S, the inverse direction is X = S^{-1}*R^t*(Y-T),
- // where S^{-1} is the diagonal matrix whose diagonal entries are the
- // reciprocoals of those of S and where R^t is the transpose of R. For SIMD
- // support of matrix-vector and matrix-matrix multiplications, a homogeneous
- // matrix H = {{M,T},{0,1}} is stored by this class. The forward transform is
- // {Y,1} = H*{X,1} and the inverse transform is {X,1} = H^{-1}*{Y,1}.
- // Transforms when GTE_USE_MAT_VEC is NOT defined in the preprocessor symbols.
- //
- // The transform is Y = T + X*M, where M is a 3-by-3 matrix and T is a 1x3
- // translation. In most cases, M = R, a rotation matrix, or M = S*R,
- // where R is a rotation matrix and S is a diagonal matrix whose diagonal
- // entries are positive scales. To support modeling packages that allow
- // general affine transforms, M can be any invertible 3x3 matrix. The vector
- // X is transformed in the "forward" direction to Y. The "inverse" direction
- // transforms Y to X, namely X = (Y-T)*M^{-1} in the general case. In the
- // special case of M = S*R, the inverse direction is X = (Y-T)*R^t*S^{-1},
- // where S^{-1} is the diagonal matrix whose diagonal entries are the
- // reciprocoals of those of S and where R^t is the transpose of R. For SIMD
- // support of matrix-vector and matrix-matrix multiplications, a homogeneous
- // matrix H = {{M,0},{T,1}} is stored by this class. The forward transform is
- // {Y,1} = {X,1}*H and the inverse transform is {X,1} = {Y,1}*H^{-1}.
- // With either multiplication convention, a matrix M = R*S (GTE_USE_MAT_VEC)
- // or a matrix M = S*R (!GTE_USE_VEC_MAT) is referred to as an "RS-matrix".
- // The class does not provide a member function to compute the inverse of a
- // transform: 'Transform GetInverse() const'. If one were to add this,
- // be aware that the inverse of an RS-matrix is not generally an RS-matrix;
- // that is, the inverse of R*S is S^{-1}*R^t which cannot always be factored
- // as S^{-1} * R^t = R' * S'. You would need to SetMatrix using S^{-1}*R^t
- // as the input.
- namespace WwiseGTE
- {
- template <typename Real>
- class Transform
- {
- public:
- // The default constructor produces the identity transformation. The
- // default copy constructor and assignment operator are generated by
- // the compiler.
- Transform()
- :
- mTranslate{ (Real)0, (Real)0, (Real)0, (Real)1 },
- mScale{ (Real)1, (Real)1, (Real)1, (Real)1 },
- mIsIdentity(true),
- mIsRSMatrix(true),
- mIsUniformScale(true),
- mInverseNeedsUpdate(false)
- {
- mHMatrix.MakeIdentity();
- mInvHMatrix.MakeIdentity();
- mMatrix.MakeIdentity();
- }
- // Implicit conversion.
- inline operator Matrix4x4<Real> const& () const
- {
- return GetHMatrix();
- }
- // Set the transformation to the identity matrix.
- void MakeIdentity()
- {
- mMatrix.MakeIdentity();
- mTranslate = { (Real)0, (Real)0, (Real)0, (Real)1 };
- mScale = { (Real)1, (Real)1, (Real)1, (Real)1 };
- mIsIdentity = true;
- mIsRSMatrix = true;
- mIsUniformScale = true;
- UpdateHMatrix();
- }
- // Set the transformation to have scales of 1.
- void MakeUnitScale()
- {
- LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
- mScale = { (Real)1, (Real)1, (Real)1, (Real)1 };
- mIsUniformScale = true;
- UpdateHMatrix();
- }
- // Hints about the structure of the transformation.
- // M = I
- inline bool IsIdentity() const
- {
- return mIsIdentity;
- }
- // R*S (GTE_USE_MAT_VEC defined) or S*R (GTE_USE_MAT_VEC not defined)
- inline bool IsRSMatrix() const
- {
- return mIsRSMatrix;
- }
- // RS-matrix with S = c*I
- inline bool IsUniformScale() const
- {
- return mIsRSMatrix && mIsUniformScale;
- }
- // Member access.
- // (1) The Set* functions set the is-identity hint to false.
- // (2) The SetRotate function sets the is-rsmatrix hint to true. If this
- // hint is false, GetRotate triggers an assertion in debug mode.
- // (3) The SetMatrix function sets the is-rsmatrix and is-uniform-scale
- // hints to false.
- // (4) The SetScale function sets the is-uniform-scale hint to false.
- // The SetUniformScale function sets the is-uniform-scale hint to
- // true. If this hint is false, GetUniformScale triggers an assertion
- // in debug mode.
- // (5) All Set* functions set the inverse-needs-update to true. When
- // GetHInverse is called, the inverse must be computed in this case
- // and the inverse-needs-update is reset to false.
- // {{R,0},{0,1}}
- void SetRotation(Matrix4x4<Real> const& rotate)
- {
- mMatrix = rotate;
- mIsIdentity = false;
- mIsRSMatrix = true;
- UpdateHMatrix();
- }
- // {{M,0},{0,1}}
- void SetMatrix(Matrix4x4<Real> const& matrix)
- {
- mMatrix = matrix;
- mIsIdentity = false;
- mIsRSMatrix = false;
- mIsUniformScale = false;
- UpdateHMatrix();
- }
- void SetTranslation(Real x0, Real x1, Real x2)
- {
- mTranslate = Vector4<Real>{ x0, x1, x2, (Real)1 };
- mIsIdentity = false;
- UpdateHMatrix();
- }
- inline void SetTranslation(Vector3<Real> const& translate)
- {
- SetTranslation(translate[0], translate[1], translate[2]);
- }
- inline void SetTranslation(Vector4<Real> const& translate)
- {
- SetTranslation(translate[0], translate[1], translate[2]);
- }
- void SetScale(Real s0, Real s1, Real s2)
- {
- LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
- LogAssert(s0 != (Real)0 && s1 != (Real)0 && s2 != (Real)0, "Scales must be nonzero.");
- mScale = { s0, s1, s2, (Real)1 };
- mIsIdentity = false;
- mIsUniformScale = false;
- UpdateHMatrix();
- }
- inline void SetScale(Vector3<Real> const& scale)
- {
- SetScale(scale[0], scale[1], scale[2]);
- }
- inline void SetScale(Vector4<Real> const& scale)
- {
- SetScale(scale[0], scale[1], scale[2]);
- }
- void SetUniformScale(Real scale)
- {
- LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
- LogAssert(scale != (Real)0, "Scale must be nonzero.");
- mScale = { scale, scale, scale, (Real)1 };
- mIsIdentity = false;
- mIsUniformScale = true;
- UpdateHMatrix();
- }
- // {{R,0},{0,1}}
- Matrix4x4<Real> const& GetRotation() const
- {
- LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
- return mMatrix;
- }
- // {{M,0},{0,1}}
- inline Matrix4x4<Real> const& GetMatrix() const
- {
- return mMatrix;
- }
- // (x,y,z)
- inline Vector3<Real> GetTranslation() const
- {
- return Vector3<Real>{ mTranslate[0], mTranslate[1], mTranslate[2] };
- }
- // (x,y,z,0)
- inline Vector4<Real> GetTranslationW0() const
- {
- return Vector4<Real>{ mTranslate[0], mTranslate[1], mTranslate[2], (Real)0 };
- }
- // (x,y,z,1)
- inline Vector4<Real> GetTranslationW1() const
- {
- return Vector4<Real>{ mTranslate[0], mTranslate[1], mTranslate[2], (Real)1 };
- }
- // (s0,s1,s2)
- Vector3<Real> GetScale() const
- {
- LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
- return Vector3<Real>{ mScale[0], mScale[1], mScale[2] };
- }
- // (s0,s1,s2,1)
- Vector4<Real> GetScaleW1() const
- {
- LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
- return Vector4<Real>{ mScale[0], mScale[1], mScale[2], (Real)1 };
- }
- Real GetUniformScale() const
- {
- LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
- LogAssert(mIsUniformScale, "Transform is not uniform scale.");
- return mScale[0];
- }
- // Alternate representations to set/get the rotation.
- // Set/get from 3x3 matrices.
- void SetRotation(Matrix3x3<Real> const& rotate)
- {
- mMatrix.MakeIdentity();
- for (int r = 0; r < 3; ++r)
- {
- for (int c = 0; c < 3; ++c)
- {
- mMatrix(r, c) = rotate(r, c);
- }
- }
- mIsIdentity = false;
- mIsRSMatrix = true;
- UpdateHMatrix();
- }
- void GetRotation(Matrix3x3<Real>& rotate) const
- {
- LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
- for (int r = 0; r < 3; ++r)
- {
- for (int c = 0; c < 3; ++c)
- {
- rotate(r, c) = mMatrix(r, c);
- }
- }
- }
- // The quaternion is unit length.
- void SetRotation(Quaternion<Real> const& q)
- {
- mMatrix = Rotation<4, Real>(q);
- mIsIdentity = false;
- mIsRSMatrix = true;
- UpdateHMatrix();
- }
- void GetRotation(Quaternion<Real>& q) const
- {
- LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
- q = Rotation<4, Real>(mMatrix);
- }
- // The axis is unit length and the angle is in radians.
- void SetRotation(AxisAngle<3, Real> const& axisAngle)
- {
- AxisAngle<4, Real> aa4(HLift(axisAngle.axis, (Real)1), axisAngle.angle);
- mMatrix = Rotation<4, Real>(aa4);
- mIsIdentity = false;
- mIsRSMatrix = true;
- UpdateHMatrix();
- }
- void GetRotation(AxisAngle<3, Real>& axisAngle) const
- {
- LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
- AxisAngle<4, Real> aa4 = Rotation<4, Real>(mMatrix);
- axisAngle.axis = HProject(aa4.axis);
- axisAngle.angle = aa4.angle;
- }
- void SetRotation(AxisAngle<4, Real> const& axisAngle)
- {
- mMatrix = Rotation<4, Real>(axisAngle);
- mIsIdentity = false;
- mIsRSMatrix = true;
- UpdateHMatrix();
- }
- void GetRotation(AxisAngle<4, Real>& axisAngle) const
- {
- LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
- axisAngle = Rotation<4, Real>(mMatrix);
- }
- // The Euler angles are in radians. The GetEulerAngles function
- // expects the eulerAngles.axis[] values to be set to the axis order
- // you want.
- void SetRotation(EulerAngles<Real> const& eulerAngles)
- {
- mMatrix = Rotation<4, Real>(eulerAngles);
- mIsIdentity = false;
- mIsRSMatrix = true;
- UpdateHMatrix();
- }
- void GetRotation(EulerAngles<Real>& eulerAngles) const
- {
- LogAssert(mIsRSMatrix, "Transform is not rotation-scale.");
- eulerAngles = Rotation<4, Real>(mMatrix)(eulerAngles.axis[0],
- eulerAngles.axis[1], eulerAngles.axis[2]);
- }
- // For M = R*S or M = S*R, the largest value of S in absolute value is
- // returned. For general M, the max-row-sum norm is returned when
- // GTE_USE_MAT_VEC is defined or the max-col-sum norm is returned when
- // the GTE_USE_MAT_VEC is not defined, which is a reasonable measure
- // of maximum scale of the transformation.
- Real GetNorm() const
- {
- Real sum0, sum1, sum2;
- if (mIsRSMatrix)
- {
- // A RS matrix (GTE_USE_MAT_VEC defined) or an SR matrix
- // (GTE_USE_MAT_VEC is not defined).
- sum0 = std::fabs(mScale[0]);
- sum1 = std::fabs(mScale[1]);
- sum2 = std::fabs(mScale[2]);
- }
- else
- {
- // The spectral norm (the maximum absolute value of the
- // eigenvalues) is smaller or equal to this norm. Therefore,
- // this function returns an approximation to the maximum
- // scale.
- #if defined(GTE_USE_MAT_VEC)
- // Use the max-row-sum matrix norm.
- sum0 = std::fabs(mMatrix(0, 0)) + std::fabs(mMatrix(0, 1)) + std::fabs(mMatrix(0, 2));
- sum1 = std::fabs(mMatrix(1, 0)) + std::fabs(mMatrix(1, 1)) + std::fabs(mMatrix(1, 2));
- sum2 = std::fabs(mMatrix(2, 0)) + std::fabs(mMatrix(2, 1)) + std::fabs(mMatrix(2, 2));
- #else
- // Use the max-col-sum matrix norm.
- sum0 = std::fabs(mMatrix(0, 0)) + std::fabs(mMatrix(1, 0)) + std::fabs(mMatrix(2, 0));
- sum1 = std::fabs(mMatrix(0, 1)) + std::fabs(mMatrix(1, 1)) + std::fabs(mMatrix(2, 1));
- sum2 = std::fabs(mMatrix(0, 2)) + std::fabs(mMatrix(1, 2)) + std::fabs(mMatrix(2, 2));
- #endif
- }
- return std::max(std::max(sum0, sum1), sum2);
- }
- // Get the homogeneous matrix (composite of all channels).
- inline Matrix4x4<Real> const& GetHMatrix() const
- {
- return mHMatrix;
- }
- // Get the inverse homogeneous matrix, recomputing it when necessary.
- // GTE_USE_MAT_VEC
- // H = {{M,T},{0,1}}, then H^{-1} = {{M^{-1},-M^{-1}*T},{0,1}}
- // GTE_USE_VEC_MAT
- // H = {{M,0},{T,1}}, then H^{-1} = {{M^{-1},0},{-M^{-1}*T,1}}
- Matrix4x4<Real> const& GetHInverse() const
- {
- if (mInverseNeedsUpdate)
- {
- if (mIsIdentity)
- {
- mInvHMatrix.MakeIdentity();
- }
- else
- {
- if (mIsRSMatrix)
- {
- if (mIsUniformScale)
- {
- Real invScale = (Real)1 / mScale[0];
- #if defined(GTE_USE_MAT_VEC)
- mInvHMatrix(0, 0) = invScale * mMatrix(0, 0);
- mInvHMatrix(0, 1) = invScale * mMatrix(1, 0);
- mInvHMatrix(0, 2) = invScale * mMatrix(2, 0);
- mInvHMatrix(1, 0) = invScale * mMatrix(0, 1);
- mInvHMatrix(1, 1) = invScale * mMatrix(1, 1);
- mInvHMatrix(1, 2) = invScale * mMatrix(2, 1);
- mInvHMatrix(2, 0) = invScale * mMatrix(0, 2);
- mInvHMatrix(2, 1) = invScale * mMatrix(1, 2);
- mInvHMatrix(2, 2) = invScale * mMatrix(2, 2);
- #else
- mInvHMatrix(0, 0) = mMatrix(0, 0) * invScale;
- mInvHMatrix(0, 1) = mMatrix(1, 0) * invScale;
- mInvHMatrix(0, 2) = mMatrix(2, 0) * invScale;
- mInvHMatrix(1, 0) = mMatrix(0, 1) * invScale;
- mInvHMatrix(1, 1) = mMatrix(1, 1) * invScale;
- mInvHMatrix(1, 2) = mMatrix(2, 1) * invScale;
- mInvHMatrix(2, 0) = mMatrix(0, 2) * invScale;
- mInvHMatrix(2, 1) = mMatrix(1, 2) * invScale;
- mInvHMatrix(2, 2) = mMatrix(2, 2) * invScale;
- #endif
- }
- else
- {
- // Replace 3 reciprocals by 6 multiplies and
- // 1 reciprocal.
- Real s01 = mScale[0] * mScale[1];
- Real s02 = mScale[0] * mScale[2];
- Real s12 = mScale[1] * mScale[2];
- Real invs012 = (Real)1 / (s01 * mScale[2]);
- Real invS0 = s12 * invs012;
- Real invS1 = s02 * invs012;
- Real invS2 = s01 * invs012;
- #if defined(GTE_USE_MAT_VEC)
- mInvHMatrix(0, 0) = invS0 * mMatrix(0, 0);
- mInvHMatrix(0, 1) = invS0 * mMatrix(1, 0);
- mInvHMatrix(0, 2) = invS0 * mMatrix(2, 0);
- mInvHMatrix(1, 0) = invS1 * mMatrix(0, 1);
- mInvHMatrix(1, 1) = invS1 * mMatrix(1, 1);
- mInvHMatrix(1, 2) = invS1 * mMatrix(2, 1);
- mInvHMatrix(2, 0) = invS2 * mMatrix(0, 2);
- mInvHMatrix(2, 1) = invS2 * mMatrix(1, 2);
- mInvHMatrix(2, 2) = invS2 * mMatrix(2, 2);
- #else
- mInvHMatrix(0, 0) = mMatrix(0, 0) * invS0;
- mInvHMatrix(0, 1) = mMatrix(1, 0) * invS1;
- mInvHMatrix(0, 2) = mMatrix(2, 0) * invS2;
- mInvHMatrix(1, 0) = mMatrix(0, 1) * invS0;
- mInvHMatrix(1, 1) = mMatrix(1, 1) * invS1;
- mInvHMatrix(1, 2) = mMatrix(2, 1) * invS2;
- mInvHMatrix(2, 0) = mMatrix(0, 2) * invS0;
- mInvHMatrix(2, 1) = mMatrix(1, 2) * invS1;
- mInvHMatrix(2, 2) = mMatrix(2, 2) * invS2;
- #endif
- }
- }
- else
- {
- Invert3x3(mHMatrix, mInvHMatrix);
- }
- #if defined(GTE_USE_MAT_VEC)
- mInvHMatrix(0, 3) = -(
- mInvHMatrix(0, 0) * mTranslate[0] +
- mInvHMatrix(0, 1) * mTranslate[1] +
- mInvHMatrix(0, 2) * mTranslate[2]
- );
- mInvHMatrix(1, 3) = -(
- mInvHMatrix(1, 0) * mTranslate[0] +
- mInvHMatrix(1, 1) * mTranslate[1] +
- mInvHMatrix(1, 2) * mTranslate[2]
- );
- mInvHMatrix(2, 3) = -(
- mInvHMatrix(2, 0) * mTranslate[0] +
- mInvHMatrix(2, 1) * mTranslate[1] +
- mInvHMatrix(2, 2) * mTranslate[2]
- );
- // The last row of mHMatrix is always (0,0,0,1) for an
- // affine transformation, so it is set once in the
- // constructor. It is not necessary to reset it here.
- #else
- mInvHMatrix(3, 0) = -(
- mInvHMatrix(0, 0) * mTranslate[0] +
- mInvHMatrix(1, 0) * mTranslate[1] +
- mInvHMatrix(2, 0) * mTranslate[2]
- );
- mInvHMatrix(3, 1) = -(
- mInvHMatrix(0, 1) * mTranslate[0] +
- mInvHMatrix(1, 1) * mTranslate[1] +
- mInvHMatrix(2, 1) * mTranslate[2]
- );
- mInvHMatrix(3, 2) = -(
- mInvHMatrix(0, 2) * mTranslate[0] +
- mInvHMatrix(1, 2) * mTranslate[1] +
- mInvHMatrix(2, 2) * mTranslate[2]
- );
- // The last column of mHMatrix is always (0,0,0,1) for an
- // affine transformation, so it is set once in the
- // constructor. It is not necessary to reset it here.
- #endif
- }
- mInverseNeedsUpdate = false;
- }
- return mInvHMatrix;
- }
- // Invert the transform. If possible, the channels are properly
- // assigned. For example, if the input has mIsRSMatrix equal to
- // 'true', then the inverse also has mIsRSMatrix equal to 'true'
- // and the inverse's mMatrix is a rotation matrix and mScale is
- // set accordingly.
- Transform Inverse() const
- {
- Transform inverse;
- if (mIsIdentity)
- {
- inverse.MakeIdentity();
- }
- else
- {
- if (mIsRSMatrix && mIsUniformScale)
- {
- inverse.SetRotation(Transpose(GetRotation()));
- inverse.SetUniformScale(1.0f / GetUniformScale());
- }
- else
- {
- Matrix4x4<Real> invUpper;
- Invert3x3(GetMatrix(), invUpper);
- inverse.SetMatrix(invUpper);
- }
- Vector4<Real> trn = -GetTranslationW0();
- inverse.SetTranslation(inverse.GetMatrix() * trn);
- }
- mInverseNeedsUpdate = true;
- return inverse;
- }
- // The identity transformation.
- static Transform Identity()
- {
- static Transform identity;
- return identity;
- }
- private:
- // Fill in the entries of mHMatrix whenever one of the components
- // mMatrix, mTranslate, or mScale changes.
- void UpdateHMatrix()
- {
- if (mIsIdentity)
- {
- mHMatrix.MakeIdentity();
- }
- else
- {
- if (mIsRSMatrix)
- {
- #if defined(GTE_USE_MAT_VEC)
- mHMatrix(0, 0) = mMatrix(0, 0) * mScale[0];
- mHMatrix(0, 1) = mMatrix(0, 1) * mScale[1];
- mHMatrix(0, 2) = mMatrix(0, 2) * mScale[2];
- mHMatrix(1, 0) = mMatrix(1, 0) * mScale[0];
- mHMatrix(1, 1) = mMatrix(1, 1) * mScale[1];
- mHMatrix(1, 2) = mMatrix(1, 2) * mScale[2];
- mHMatrix(2, 0) = mMatrix(2, 0) * mScale[0];
- mHMatrix(2, 1) = mMatrix(2, 1) * mScale[1];
- mHMatrix(2, 2) = mMatrix(2, 2) * mScale[2];
- #else
- mHMatrix(0, 0) = mScale[0] * mMatrix(0, 0);
- mHMatrix(0, 1) = mScale[0] * mMatrix(0, 1);
- mHMatrix(0, 2) = mScale[0] * mMatrix(0, 2);
- mHMatrix(1, 0) = mScale[1] * mMatrix(1, 0);
- mHMatrix(1, 1) = mScale[1] * mMatrix(1, 1);
- mHMatrix(1, 2) = mScale[1] * mMatrix(1, 2);
- mHMatrix(2, 0) = mScale[2] * mMatrix(2, 0);
- mHMatrix(2, 1) = mScale[2] * mMatrix(2, 1);
- mHMatrix(2, 2) = mScale[2] * mMatrix(2, 2);
- #endif
- }
- else
- {
- mHMatrix(0, 0) = mMatrix(0, 0);
- mHMatrix(0, 1) = mMatrix(0, 1);
- mHMatrix(0, 2) = mMatrix(0, 2);
- mHMatrix(1, 0) = mMatrix(1, 0);
- mHMatrix(1, 1) = mMatrix(1, 1);
- mHMatrix(1, 2) = mMatrix(1, 2);
- mHMatrix(2, 0) = mMatrix(2, 0);
- mHMatrix(2, 1) = mMatrix(2, 1);
- mHMatrix(2, 2) = mMatrix(2, 2);
- }
- #if defined(GTE_USE_MAT_VEC)
- mHMatrix(0, 3) = mTranslate[0];
- mHMatrix(1, 3) = mTranslate[1];
- mHMatrix(2, 3) = mTranslate[2];
- // The last row of mHMatrix is always (0,0,0,1) for an affine
- // transformation, so it is set once in the constructor. It
- // is not necessary to reset it here.
- #else
- mHMatrix(3, 0) = mTranslate[0];
- mHMatrix(3, 1) = mTranslate[1];
- mHMatrix(3, 2) = mTranslate[2];
- // The last column of mHMatrix is always (0,0,0,1) for an
- // affine transformation, so it is set once in the
- // constructor. It is not necessary to reset it here.
- #endif
- }
- mInverseNeedsUpdate = true;
- }
- // Invert the 3x3 upper-left block of the input matrix.
- static void Invert3x3(Matrix4x4<Real> const& mat, Matrix4x4<Real>& invMat)
- {
- // Compute the adjoint of M (3x3).
- invMat(0, 0) = mat(1, 1) * mat(2, 2) - mat(1, 2) * mat(2, 1);
- invMat(0, 1) = mat(0, 2) * mat(2, 1) - mat(0, 1) * mat(2, 2);
- invMat(0, 2) = mat(0, 1) * mat(1, 2) - mat(0, 2) * mat(1, 1);
- invMat(0, 3) = 0.0f;
- invMat(1, 0) = mat(1, 2) * mat(2, 0) - mat(1, 0) * mat(2, 2);
- invMat(1, 1) = mat(0, 0) * mat(2, 2) - mat(0, 2) * mat(2, 0);
- invMat(1, 2) = mat(0, 2) * mat(1, 0) - mat(0, 0) * mat(1, 2);
- invMat(1, 3) = 0.0f;
- invMat(2, 0) = mat(1, 0) * mat(2, 1) - mat(1, 1) * mat(2, 0);
- invMat(2, 1) = mat(0, 1) * mat(2, 0) - mat(0, 0) * mat(2, 1);
- invMat(2, 2) = mat(0, 0) * mat(1, 1) - mat(0, 1) * mat(1, 0);
- invMat(2, 3) = 0.0f;
- invMat(3, 0) = 0.0f;
- invMat(3, 1) = 0.0f;
- invMat(3, 2) = 0.0f;
- invMat(3, 3) = 1.0f;
- // Compute the reciprocal of the determinant of M.
- Real invDet = (Real)1 / (
- mat(0, 0) * invMat(0, 0) +
- mat(0, 1) * invMat(1, 0) +
- mat(0, 2) * invMat(2, 0)
- );
- // inverse(M) = adjoint(M)/determinant(M).
- invMat(0, 0) *= invDet;
- invMat(0, 1) *= invDet;
- invMat(0, 2) *= invDet;
- invMat(1, 0) *= invDet;
- invMat(1, 1) *= invDet;
- invMat(1, 2) *= invDet;
- invMat(2, 0) *= invDet;
- invMat(2, 1) *= invDet;
- invMat(2, 2) *= invDet;
- }
- // The full 4x4 homogeneous matrix H and its inverse H^{-1}, stored
- // according to the conventions (see GetHInverse description). The
- // inverse is computed only on demand.
- Matrix4x4<Real> mHMatrix;
- mutable Matrix4x4<Real> mInvHMatrix;
- Matrix4x4<Real> mMatrix; // M (general) or R (rotation)
- Vector4<Real> mTranslate; // T
- Vector4<Real> mScale; // S
- bool mIsIdentity, mIsRSMatrix, mIsUniformScale;
- mutable bool mInverseNeedsUpdate;
- };
- // Compute M*V.
- template <typename Real>
- Vector4<Real> operator*(Transform<Real> const& M, Vector4<Real> const& V)
- {
- return M.GetHMatrix() * V;
- }
- // Compute V^T*M.
- template <typename Real>
- Vector4<Real> operator*(Vector4<Real> const& V, Transform<Real> const& M)
- {
- return V * M.GetHMatrix();
- }
- // Compute A*B.
- template <typename Real>
- Transform<Real> operator*(Transform<Real> const& A, Transform<Real> const& B)
- {
- if (A.IsIdentity())
- {
- return B;
- }
- if (B.IsIdentity())
- {
- return A;
- }
- Transform<Real> product;
- if (A.IsRSMatrix() && B.IsRSMatrix())
- {
- #if defined(GTE_USE_MAT_VEC)
- if (A.IsUniformScale())
- {
- product.SetRotation(A.GetRotation() * B.GetRotation());
- product.SetTranslation(A.GetUniformScale() * (
- A.GetRotation() * B.GetTranslationW0()) +
- A.GetTranslationW1());
- if (B.IsUniformScale())
- {
- product.SetUniformScale(A.GetUniformScale() * B.GetUniformScale());
- }
- else
- {
- product.SetScale(A.GetUniformScale() * B.GetScale());
- }
- return product;
- }
- #else
- if (B.IsUniformScale())
- {
- product.SetRotation(A.GetRotation() * B.GetRotation());
- product.SetTranslation(B.GetUniformScale() * (
- A.GetTranslationW0() * B.GetRotation()) +
- B.GetTranslationW1());
- if (A.IsUniformScale())
- {
- product.SetUniformScale(A.GetUniformScale() * B.GetUniformScale());
- }
- else
- {
- product.SetScale(A.GetScale() * B.GetUniformScale());
- }
- return product;
- }
- #endif
- }
- // In all remaining cases, the matrix cannot be written as R*S*X+T.
- Matrix4x4<Real> matMA;
- if (A.IsRSMatrix())
- {
- #if defined(GTE_USE_MAT_VEC)
- matMA = MultiplyMD(A.GetRotation(), A.GetScaleW1());
- #else
- matMA = MultiplyDM(A.GetScaleW1(), A.GetRotation());
- #endif
- }
- else
- {
- matMA = A.GetMatrix();
- }
- Matrix4x4<Real> matMB;
- if (B.IsRSMatrix())
- {
- #if defined(GTE_USE_MAT_VEC)
- matMB = MultiplyMD(B.GetRotation(), B.GetScaleW1());
- #else
- matMB = MultiplyDM(B.GetScaleW1(), B.GetRotation());
- #endif
- }
- else
- {
- matMB = B.GetMatrix();
- }
- product.SetMatrix(matMA * matMB);
- #if defined(GTE_USE_MAT_VEC)
- product.SetTranslation(matMA * B.GetTranslationW0() +
- A.GetTranslationW1());
- #else
- product.SetTranslation(A.GetTranslationW0() * matMB +
- B.GetTranslationW1());
- #endif
- return product;
- }
- template <typename Real>
- inline Matrix4x4<Real> operator*(Matrix4x4<Real> const& A, Transform<Real> const& B)
- {
- return A * B.GetHMatrix();
- }
- template <typename Real>
- inline Matrix4x4<Real> operator*(Transform<Real> const& A, Matrix4x4<Real> const& B)
- {
- return A.GetHMatrix()* B;
- }
- }
|