| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 | //-----------------------------------------------------------------------------// Copyright (c) 2012 GarageGames, LLC//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to// deal in the Software without restriction, including without limitation the// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or// sell copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in// all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS// IN THE SOFTWARE.//-----------------------------------------------------------------------------#include "math/mRotation.h"#include "console/console.h"#include "console/engineAPI.h"#include "math/mathUtils.h"//#ifdef TORQUE_TESTS_ENABLED//#include "testing/unitTesting.h"//#endif//====================================================================//Eulers setup//====================================================================RotationF::RotationF(EulerF _euler, UnitFormat format){   set(_euler.x, _euler.y, _euler.z, format);}RotationF::RotationF(F32 _x, F32 _y, F32 _z, UnitFormat format){   set(_x, _y, _z, format);}void RotationF::set(EulerF _euler, UnitFormat format){   x = format == Degrees ? mDegToRad(_euler.x) : _euler.x;   y = format == Degrees ? mDegToRad(_euler.y) : _euler.y;   z = format == Degrees ? mDegToRad(_euler.z) : _euler.z;   mRotationType = Euler;}void RotationF::set(F32 _x, F32 _y, F32 _z, UnitFormat format){   EulerF tempEul;   if (format == Degrees)   {      tempEul.set(mDegToRad(_x), mDegToRad(_y), mDegToRad(_z));   }   else   {      tempEul.set(_x, _y, _z);   }   set(tempEul);}//====================================================================//AxisAngle setup//====================================================================RotationF::RotationF(AngAxisF _aa, UnitFormat format){   set(_aa, format);}void RotationF::set(AngAxisF _aa, UnitFormat format){   x = _aa.axis.x;   y = _aa.axis.y;   z = _aa.axis.z;   w = format == Degrees ? mDegToRad(_aa.angle) : _aa.angle;   mRotationType = AxisAngle;}//====================================================================//QuatF setup//====================================================================RotationF::RotationF(QuatF _quat){   set(_quat);}void RotationF::set(QuatF _quat){   AngAxisF tmpAA;   tmpAA.set(_quat);   set(tmpAA);}//====================================================================//MatrixF setup//====================================================================RotationF::RotationF(MatrixF _mat){   set(_mat);}void RotationF::set(MatrixF _mat){   set(_mat.toEuler());}//inline F32 RotationF::len() const{   return asEulerF().len();}inline void RotationF::interpolate(const RotationF& _from, const RotationF& _to, F32 _factor){   QuatF tmpQuat;   tmpQuat.interpolate(_from.asQuatF(), _to.asQuatF(), _factor);   set(tmpQuat);}void RotationF::lookAt(const Point3F& _origin, const Point3F& _target, const Point3F& _up){   MatrixF mat;   VectorF newForward = _target - _origin;   newForward.normalize();   VectorF up(0.0f, 0.0f, 1.0f);   VectorF axisX;   VectorF axisY = newForward;   VectorF axisZ;   if (_up != VectorF::Zero)      up = _up;   // Validate and normalize input:     F32 lenSq;   lenSq = axisY.lenSquared();   if (lenSq < 0.000001f)   {      //degenerate forward vector      axisY.set(0.0f, 1.0f, 0.0f);   }   else   {      axisY /= mSqrt(lenSq);   }   lenSq = up.lenSquared();   if (lenSq < 0.000001f)   {      //degenerate up vector - too small      up.set(0.0f, 0.0f, 1.0f);   }   else   {      up /= mSqrt(lenSq);   }   if (fabsf(mDot(up, axisY)) > 0.9999f)   {      //degenerate up vector - same as forward      F32 tmp = up.x;      up.x = -up.y;      up.y = up.z;      up.z = tmp;   }   // construct the remaining axes:     mCross(axisY, up, &axisX);   mCross(axisX, axisY, &axisZ);   mat.setColumn(0, axisX);   mat.setColumn(1, axisY);   mat.setColumn(2, axisZ);   set(mat);}VectorF RotationF::getDirection(){   VectorF dir;   EulerF angles = asEulerF();   MathUtils::getVectorFromAngles(dir, angles.z, angles.x);   return dir;}//========================================================EulerF RotationF::asEulerF(UnitFormat _format) const{   if (mRotationType == Euler)   {      if (_format == Degrees)      {         return EulerF(mRadToDeg(x), mRadToDeg(y), mRadToDeg(z));      }      else      {         return EulerF(x, y, z);      }   }   else   {      EulerF returnEuler = asMatrixF().toEuler();      if (_format == Degrees)      {         returnEuler.x = mRadToDeg(returnEuler.x);         returnEuler.y = mRadToDeg(returnEuler.y);         returnEuler.z = mRadToDeg(returnEuler.z);      }      return returnEuler;   }}AngAxisF RotationF::asAxisAngle(UnitFormat format) const{   AngAxisF returnAA;   if (mRotationType == Euler)   {      returnAA.set(EulerF(x, y, z));   }   else   {      returnAA.set(Point3F(x, y, z), w);   }   if (format == Radians)   {      returnAA.angle = mDegToRad(returnAA.angle);   }   return returnAA;}MatrixF RotationF::asMatrixF() const{   MatrixF returnMat;   if (mRotationType == Euler)   {      MatrixF imat, xmat, ymat, zmat;      xmat.set(EulerF(x, 0, 0));      ymat.set(EulerF(0.0f, y, 0.0f));      zmat.set(EulerF(0, 0, z));      imat.mul(zmat, xmat);      returnMat.mul(imat, ymat);   }   else   {      AngAxisF aa;      aa.set(Point3F(x, y, z), w);      MatrixF tempMat;      aa.setMatrix(&tempMat);      EulerF eul = tempMat.toEuler();      MatrixF imat, xmat, ymat, zmat;      xmat.set(EulerF(eul.x, 0, 0));      ymat.set(EulerF(0.0f, eul.y, 0.0f));      zmat.set(EulerF(0, 0, eul.z));      imat.mul(zmat, xmat);      returnMat.mul(imat, ymat);   }   return returnMat;}QuatF RotationF::asQuatF() const{   QuatF returnQuat;   if (mRotationType == Euler)   {      returnQuat.set(EulerF(x, y, z));   }   else   {      AngAxisF aa;      aa.set(Point3F(x, y, z), w);      returnQuat.set(aa);   }   return returnQuat;}void RotationF::normalize(){   if (mRotationType == Euler)   {      EulerF eul = EulerF(x, y, z);      eul.normalize();      set(eul);   }   else   {      QuatF quat;      quat.set(Point3F(x, y, z), w);      quat.normalize();      set(quat);   }}DefineEngineFunction(AddRotation, RotationF, (RotationF a, RotationF b, const char* returnType), ("Euler"),   "Adds two rotations together.\n"   "@param a Rotation one."   "@param b Rotation two."   "@returns v sum of both rotations."   "@ingroup Math"){   RotationF ret;   RotationF sum = a + b;   if (String(returnType) == String("Euler"))      ret.set(sum.asEulerF());   else      ret.set(sum.asAxisAngle());   return ret;} DefineEngineFunction(SubtractRotation, RotationF, (RotationF a, RotationF b), ,   "Subtracts two rotations.\n"   "@param a Rotation one."   "@param b Rotation two."   "@returns v difference of both rotations."   "@ingroup Math"){   return a - b;} DefineEngineFunction(InterpolateRotation, RotationF, (RotationF a, RotationF b, F32 factor), ,   "Interpolates between two rotations.\n"   "@param a Rotation one."   "@param b Rotation two."   "@param factor The amount to interpolate between the two."   "@returns v, interpolated result."   "@ingroup Math"){   RotationF result;   result.interpolate(a, b, factor);   return result;} DefineEngineFunction(RotationLookAt, RotationF, (Point3F origin, Point3F target, Point3F up),   (Point3F(0, 0, 0), Point3F(0, 0, 0), Point3F(0, 0, 1)),   "Provides a rotation orientation to look at a target from a given position.\n"   "@param origin Position of the object doing the looking."   "@param target Position to be looked at."   "@param up The up angle to orient the rotation."   "@returns v orientation result."   "@ingroup Math"){   RotationF result;   result.lookAt(origin, target, up);   return result;}DefineEngineFunction(setRotationRightVector, RotationF, (RotationF rot, VectorF rightVec), ,   "Sets the right vector of the rotation.\n"   "@param Starting rotation."   "@param New up vector."   "@returns New rotation with the set right vector."   "@ingroup Math"){   rot.asMatrixF().setColumn(0, rightVec);   return rot;}DefineEngineFunction(setRotationUpVector, RotationF, (RotationF rot, VectorF upVec), ,   "Sets the up vector of the rotation.\n"   "@param Starting rotation."   "@param New up vector."   "@returns New rotation with the set up vector."   "@ingroup Math"){   rot.asMatrixF().setColumn(2, upVec);   return rot;}DefineEngineFunction(getRotationForwardVector, VectorF, (RotationF rot), ,   "Get the forward vector of a rotation.\n"   "@ingroup Math"){   return rot.asMatrixF().getForwardVector();}DefineEngineFunction(getRotationRightVector, VectorF, (RotationF rot), ,   "Gets the right vector of a rotation.\n"   "@param Our rotation."   "@ingroup Math"){   return rot.asMatrixF().getRightVector();}DefineEngineFunction(getRotationUpVector, VectorF, (RotationF rot), ,   "Gets the up vector of a rotation.\n"   "@param Our rotation."   "@ingroup Math"){   return rot.asMatrixF().getUpVector();}DefineEngineFunction(getRotationDirection, Point3F, (RotationF rot),,   "Gets the direction from the rotation's angles.\n"   "@param Our rotation."   "@ingroup Math"){   return rot.getDirection();}
 |