Browse Source

Merge branch 'RotationFPR_Cleaned' of https://github.com/Areloch/Torque3D into development

Areloch 9 years ago
parent
commit
9bc87709ab

+ 2 - 0
Engine/source/console/consoleTypes.h

@@ -74,6 +74,8 @@ DefineConsoleType( TypeCommand, String )
 DefineConsoleType( TypeFilename, const char * )
 DefineConsoleType( TypeStringFilename, String )
 
+DefineConsoleType(TypeRotationF, RotationF)
+
 /// A universally unique identifier.
 DefineConsoleType( TypeUUID, Torque::UUID )
 

+ 2 - 1
Engine/source/gui/editor/inspector/field.cpp

@@ -284,7 +284,8 @@ void GuiInspectorField::setData( const char* data, bool callbacks )
                   || type == TypeMatrixPosition
                   || type == TypeMatrixRotation
                   || type == TypeBox3F
-                  || type == TypeRectUV )
+                  || type == TypeRectUV
+                  || type == TypeRotationF)
          {
             //TODO: we should actually take strings into account and not chop things up between quotes
 

+ 299 - 0
Engine/source/math/mRotation.cpp

@@ -0,0 +1,299 @@
+//-----------------------------------------------------------------------------
+// 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"
+
+#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);
+}
+
+//========================================================
+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)
+   {
+      returnMat.set(EulerF(x, y, z));
+   }
+   else
+   {
+      AngAxisF aa;
+      aa.set(Point3F(x, y, z), w);
+
+      aa.setMatrix(&returnMat);
+   }
+
+   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);
+   }
+}
+
+//Testing
+#ifdef TORQUE_TESTS_ENABLED
+TEST(Maths, RotationF_Calculations)
+{
+   //TODO: implement unit test
+};
+#endif

+ 465 - 0
Engine/source/math/mRotation.h

@@ -0,0 +1,465 @@
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+
+#ifndef MROTATION_H
+#define MROTATION_H
+
+#ifndef _MMATHFN_H_
+#include "math/mMathFn.h"
+#endif
+
+#ifndef _MPOINT3_H_
+#include "math/mPoint3.h"
+#endif
+
+#ifndef _MQUAT_H_
+#include "math/mQuat.h"
+#endif
+
+#ifndef _MMATRIX_H_
+#include "math/mMatrix.h"
+#endif
+
+#ifndef _MANGAXIS_H_
+#include "math/mAngAxis.h"
+#endif
+
+//------------------------------------------------------------------------------
+/// Rotation Interop Utility class
+///
+/// Useful for easily handling rotations/orientations in transforms while manipulating or converting between formats.
+class RotationF
+{
+   //-------------------------------------- Public data
+public:
+   F32 x;   ///< X co-ordinate.
+   F32 y;   ///< Y co-ordinate.
+   F32 z;   ///< Z co-ordinate.
+   F32 w;   ///< W co-ordinate.
+
+   enum RotationTypes
+   {
+      Euler = 0,
+      AxisAngle
+   };
+   RotationTypes mRotationType;
+
+   enum UnitFormat
+   {
+      Radians = 0,
+      Degrees
+   };
+
+   RotationF();               ///< Create an uninitialized point.
+   RotationF(const RotationF&); ///< Copy constructor.
+
+   //
+   //Eulers
+   RotationF(EulerF euler, UnitFormat format = Radians);
+   RotationF(F32 _x, F32 _y, F32 _z, UnitFormat format = Radians);
+
+   void set(EulerF euler, UnitFormat format = Radians);
+   void set(F32 _x, F32 _y, F32 _z, UnitFormat format = Radians);
+
+   //As with AxisAngles, we make the assumption here that if not told otherwise, inbound rotations are in Degrees.
+   RotationF operator=(const EulerF&);
+   RotationF operator-(const EulerF&) const;
+   RotationF operator+(const EulerF&) const;
+   RotationF& operator-=(const EulerF&);
+   RotationF& operator+=(const EulerF&);
+   S32 operator==(const EulerF&) const;
+   S32 operator!=(const EulerF&) const;
+
+   //
+   //AxisAngle
+   RotationF(AngAxisF aa, UnitFormat format = Radians);
+   void set(AngAxisF aa, UnitFormat format = Radians);
+
+   //As with Eulers, we make the assumption here that if not told otherwise, inbound rotations are in Degrees.
+   RotationF operator=(const AngAxisF&);
+   RotationF operator-(const AngAxisF&) const;
+   RotationF operator+(const AngAxisF&) const;
+   RotationF& operator-=(const AngAxisF&);
+   RotationF& operator+=(const AngAxisF&);
+   S32 operator==(const AngAxisF&) const;
+   S32 operator!=(const AngAxisF&) const;
+
+   //
+   //Quat
+   RotationF(QuatF quat);
+   void set(QuatF _quat);
+
+   RotationF operator=(const QuatF&);
+   RotationF operator-(const QuatF&) const;
+   RotationF operator+(const QuatF&) const;
+   RotationF& operator-=(const QuatF&);
+   RotationF& operator+=(const QuatF&);
+   S32 operator==(const QuatF&) const;
+   S32 operator!=(const QuatF&) const;
+
+   //
+   //Matrix
+   RotationF(MatrixF mat);
+   void set(MatrixF _mat);
+
+   RotationF operator=(const MatrixF&);
+   RotationF operator-(const MatrixF&) const;
+   RotationF operator+(const MatrixF&) const;
+   RotationF& operator-=(const MatrixF&);
+   RotationF& operator+=(const MatrixF&);
+   S32 operator==(const MatrixF&) const;
+   S32 operator!=(const MatrixF&) const;
+
+   //
+   void interpolate(const RotationF& _pt1, const RotationF& _pt2, F32 _factor);
+   void lookAt(const Point3F& _origin, const Point3F& _target, const Point3F& _up = Point3F(0, 0, 1));
+
+   F32 len() const;
+
+   void normalize();
+
+   //Non-converting operators
+   S32 operator ==(const RotationF &) const;
+   S32 operator !=(const RotationF &) const;
+
+   RotationF  operator+(const RotationF&) const;
+   RotationF& operator+=(const RotationF&);
+   RotationF  operator-(const RotationF&) const;
+   RotationF&  operator-=(const RotationF&);
+
+   RotationF& operator=(const RotationF&);
+
+   //Conversion stuffs
+   EulerF asEulerF(UnitFormat format = Radians) const;
+   AngAxisF asAxisAngle(UnitFormat format = Radians) const;
+   MatrixF asMatrixF() const;
+   QuatF asQuatF() const;
+};
+
+inline RotationF::RotationF()
+{
+   x = 0;
+   y = 0;
+   z = 0;
+   w = 0;
+
+   mRotationType = AxisAngle;
+}
+
+inline RotationF::RotationF(const RotationF& _copy)
+   : x(_copy.x), y(_copy.y), z(_copy.z), w(_copy.w), mRotationType(_copy.mRotationType)
+{}
+
+inline int RotationF::operator ==(const RotationF& _rotation) const
+{
+   return (x == _rotation.x && y == _rotation.y && z == _rotation.z && w == _rotation.w);
+}
+
+inline int RotationF::operator !=(const RotationF& _rotation) const
+{
+   return (x != _rotation.x || y != _rotation.y || z != _rotation.z || w != _rotation.w);
+}
+
+//When it comes to actually trying to add rotations, we, in fact, actually multiply their data together.
+//Since we're specifically operating on usability for RotationF, we'll operate on this, rather than the literal addition of the values
+inline RotationF& RotationF::operator +=(const RotationF& _rotation)
+{
+   if (mRotationType == Euler)
+   {
+      x += _rotation.x;
+      y += _rotation.y;
+      z += _rotation.z;
+   }
+   else
+   {
+      MatrixF tempMat = asMatrixF();
+      MatrixF tempMatAdd = _rotation.asMatrixF();
+
+      tempMat.mul(tempMatAdd);
+
+      this->set(tempMat);
+   }
+
+   return *this;
+}
+
+inline RotationF RotationF::operator +(const RotationF& _rotation) const
+{
+   RotationF result = *this;
+
+   if (mRotationType == Euler)
+   {
+      result.x += _rotation.x;
+      result.y += _rotation.y;
+      result.z += _rotation.z;
+   }
+   else
+   {
+      MatrixF tempMat = asMatrixF();
+      MatrixF tempMatAdd = _rotation.asMatrixF();
+
+      tempMat.mul(tempMatAdd);
+
+      result.set(tempMat);
+   }
+
+   return result;
+}
+
+//Much like addition, when subtracting, we're not literally subtracting the values, but infact multiplying the inverse.
+//This subtracts the rotation angles to get the difference
+inline RotationF& RotationF::operator -=(const RotationF& _rotation)
+{
+   if (mRotationType == Euler)
+   {
+      x -= _rotation.x;
+      y -= _rotation.y;
+      z -= _rotation.z;
+   }
+   else
+   {
+      MatrixF tempMat = asMatrixF();
+      MatrixF tempMatAdd = _rotation.asMatrixF();
+
+      tempMatAdd.inverse();
+
+      tempMat.mul(tempMatAdd);
+
+      this->set(tempMat);
+   }
+
+   return *this;
+}
+
+inline RotationF RotationF::operator -(const RotationF& _rotation) const
+{
+   RotationF result = *this;
+
+   if (mRotationType == Euler)
+   {
+      result.x += _rotation.x;
+      result.y += _rotation.y;
+      result.z += _rotation.z;
+   }
+   else
+   {
+      MatrixF tempMat = asMatrixF();
+      MatrixF tempMatAdd = _rotation.asMatrixF();
+      tempMatAdd.inverse();
+
+      tempMat.mul(tempMatAdd);
+
+      result.set(tempMat);
+   }
+
+   return result;
+}
+
+inline RotationF& RotationF::operator =(const RotationF& _rotation)
+{
+   x = _rotation.x;
+   y = _rotation.y;
+   z = _rotation.z;
+   w = _rotation.w;
+
+   mRotationType = _rotation.mRotationType;
+
+   return *this;
+}
+
+//====================================================================
+// Euler operators
+//====================================================================
+inline RotationF RotationF::operator=(const EulerF& _euler)
+{
+   return RotationF(_euler, Radians);
+}
+
+inline RotationF RotationF::operator-(const EulerF& _euler) const
+{
+   RotationF temp = *this;
+   temp -= RotationF(_euler, Radians);
+   return temp;
+}
+
+inline RotationF RotationF::operator+(const EulerF& _euler) const
+{
+   RotationF temp = *this;
+   temp += RotationF(_euler, Radians);
+   return temp;
+}
+
+inline RotationF& RotationF::operator-=(const EulerF& _euler)
+{
+   *this -= RotationF(_euler, Radians);
+   return *this;
+}
+
+inline RotationF& RotationF::operator+=(const EulerF& _euler)
+{
+   *this += RotationF(_euler, Radians);
+   return *this;
+}
+
+inline S32 RotationF::operator==(const EulerF& _euler) const
+{
+   return *this == RotationF(_euler);
+}
+
+inline S32 RotationF::operator!=(const EulerF& _euler) const
+{
+   return *this != RotationF(_euler);
+}
+
+//====================================================================
+// AxisAngle operators
+//====================================================================
+inline RotationF RotationF::operator=(const AngAxisF& _aa)
+{
+   return RotationF(_aa, Radians);
+}
+
+inline RotationF RotationF::operator-(const AngAxisF& _aa) const
+{
+   RotationF temp = *this;
+   temp -= RotationF(_aa, Radians);
+   return temp;
+}
+
+inline RotationF RotationF::operator+(const AngAxisF& _aa) const
+{
+   RotationF temp = *this;
+   temp += RotationF(_aa, Radians);
+   return temp;
+}
+
+inline RotationF& RotationF::operator-=(const AngAxisF& _aa)
+{
+   *this -= RotationF(_aa, Radians);
+   return *this;
+}
+
+inline RotationF& RotationF::operator+=(const AngAxisF& _aa)
+{
+   *this += RotationF(_aa, Radians);
+   return *this;
+}
+
+inline S32 RotationF::operator==(const AngAxisF& _aa) const
+{
+   return *this == RotationF(_aa);
+}
+
+inline S32 RotationF::operator!=(const AngAxisF& _aa) const
+{
+   return *this != RotationF(_aa);
+}
+
+//====================================================================
+// QuatF operators
+//====================================================================
+inline RotationF RotationF::operator=(const QuatF& _quat)
+{
+   return RotationF(_quat);
+}
+
+inline RotationF RotationF::operator-(const QuatF& _quat) const
+{
+   RotationF temp = *this;
+   temp -= RotationF(_quat);
+   return temp;
+}
+
+inline RotationF RotationF::operator+(const QuatF& _quat) const
+{
+   RotationF temp = *this;
+   temp += RotationF(_quat);
+   return temp;
+}
+
+inline RotationF& RotationF::operator-=(const QuatF& _quat)
+{
+   *this -= RotationF(_quat);
+   return *this;
+}
+
+inline RotationF& RotationF::operator+=(const QuatF& _quat)
+{
+   *this += RotationF(_quat);
+   return *this;
+}
+
+inline S32 RotationF::operator==(const QuatF& _quat) const
+{
+   return *this == RotationF(_quat);
+}
+
+inline S32 RotationF::operator!=(const QuatF& _quat) const
+{
+   return *this != RotationF(_quat);
+}
+
+//====================================================================
+// MatrixF operators
+//====================================================================
+inline RotationF RotationF::operator=(const MatrixF& _mat)
+{
+   return RotationF(_mat);
+}
+
+inline RotationF RotationF::operator-(const MatrixF& _mat) const
+{
+   RotationF temp = *this;
+   temp -= RotationF(_mat);
+   return temp;
+}
+
+inline RotationF RotationF::operator+(const MatrixF& _mat) const
+{
+   RotationF temp = *this;
+   temp += RotationF(_mat);
+   return temp;
+}
+
+inline RotationF& RotationF::operator-=(const MatrixF& _mat)
+{
+   *this -= RotationF(_mat);
+   return *this;
+}
+
+inline RotationF& RotationF::operator+=(const MatrixF& _mat)
+{
+   *this += RotationF(_mat);
+   return *this;
+}
+
+inline S32 RotationF::operator==(const MatrixF& _mat) const
+{
+   return *this == RotationF(_mat);
+}
+
+inline S32 RotationF::operator!=(const MatrixF& _mat) const
+{
+   return *this != RotationF(_mat);
+}
+
+#endif // MROTATION_H

+ 24 - 0
Engine/source/math/mathIO.h

@@ -149,6 +149,20 @@ inline bool mathRead(Stream& stream, EaseF* e)
    return success;
 }
 
+inline bool mathRead(Stream& stream, RotationF* e)
+{
+   bool success = stream.read(&e->x);
+   success &= stream.read(&e->y);
+   success &= stream.read(&e->z);
+   success &= stream.read(&e->w);
+
+   U32 rotType;
+   success &= stream.read(&rotType);
+   e->mRotationType = (RotationF::RotationTypes)rotType;
+
+   return success;
+}
+
 //------------------------------------------------------------------------------
 //-------------------------------------- WRITING
 //
@@ -263,5 +277,15 @@ inline bool mathWrite(Stream& stream, const EaseF& e)
    return success;
 }
 
+inline bool mathWrite(Stream& stream, const RotationF& e)
+{
+   bool success = stream.write(e.x);
+   success &= stream.write(e.y);
+   success &= stream.write(e.z);
+   success &= stream.write(e.w);
+   success &= stream.write(e.mRotationType);
+   return success;;
+}
+
 #endif //_MATHIO_H_
 

+ 58 - 2
Engine/source/math/mathTypes.cpp

@@ -36,7 +36,7 @@
 #include "math/mRandom.h"
 #include "math/mEase.h"
 #include "math/mathUtils.h"
-
+#include "math/mRotation.h"
 #include "core/strings/stringUnit.h"
 
 IMPLEMENT_SCOPE( MathTypes, Math,, "" );
@@ -113,7 +113,14 @@ IMPLEMENT_STRUCT( EaseF,
    EaseF, MathTypes,
    "" )
 END_IMPLEMENT_STRUCT;
-
+IMPLEMENT_STRUCT(RotationF,
+   RotationF, MathTypes,
+   "")
+   FIELD(x, x, 1, "X coordinate.")
+   FIELD(y, y, 1, "Y coordinate.")
+   FIELD(z, z, 1, "Z coordinate.")
+   FIELD(w, w, 1, "W coordinate.")
+END_IMPLEMENT_STRUCT;
 
 //-----------------------------------------------------------------------------
 // TypePoint2I
@@ -572,6 +579,55 @@ ConsoleSetType( TypeEaseF )
    }
 }
 
+//-----------------------------------------------------------------------------
+// TypeRotationF
+//-----------------------------------------------------------------------------
+ConsoleType(RotationF, TypeRotationF, RotationF, "")
+//ImplementConsoleTypeCasters( TypeRotationF, RotationF )
+
+ConsoleGetType(TypeRotationF)
+{
+   RotationF *pt = (RotationF *)dptr;
+   static const U32 bufSize = 256;
+   char* returnBuffer = Con::getReturnBuffer(bufSize);
+
+   EulerF out = pt->asEulerF(RotationF::Degrees);
+   dSprintf(returnBuffer, bufSize, "%g %g %g", out.x, out.y, out.z);
+
+   return returnBuffer;
+}
+
+ConsoleSetType(TypeRotationF)
+{
+   if (argc == 1)
+   {
+      U32 elements = StringUnit::getUnitCount(argv[0], " \t\n");
+      if (elements == 3)
+      {
+         EulerF in;
+         dSscanf(argv[0], "%g %g %g", &in.x, &in.y, &in.z);
+         ((RotationF *)dptr)->set(in, RotationF::Degrees);
+      }
+      else
+      {
+         AngAxisF in;
+         dSscanf(argv[0], "%g %g %g %g", &in.axis.x, &in.axis.y, &in.axis.z, &in.angle);
+         ((RotationF *)dptr)->set(in, RotationF::Degrees);
+      }
+   }
+   else if (argc == 3)
+   {
+      EulerF in(dAtof(argv[0]), dAtof(argv[1]), dAtof(argv[2]));
+      ((RotationF *)dptr)->set(in, RotationF::Degrees);
+   }
+   else if (argc == 4)
+   {
+      AngAxisF in(Point3F(dAtof(argv[0]), dAtof(argv[1]), dAtof(argv[2])), dAtof(argv[3]));
+      ((RotationF *)dptr)->set(in, RotationF::Degrees);
+   }
+   else
+      Con::printf("RotationF must be set as { x, y, z, w } or \"x y z w\"");
+}
 
 //-----------------------------------------------------------------------------
 

+ 3 - 2
Engine/source/math/mathTypes.h

@@ -43,7 +43,7 @@ class Box3F;
 class EaseF;
 class AngAxisF;
 class TransformF;
-
+class RotationF;
 
 DECLARE_SCOPE( MathTypes );
 
@@ -60,6 +60,7 @@ DECLARE_STRUCT( AngAxisF );
 DECLARE_STRUCT( TransformF );
 DECLARE_STRUCT( Box3F );
 DECLARE_STRUCT( EaseF );
+DECLARE_STRUCT(RotationF);
 
 
 // Legacy console types.
@@ -77,6 +78,6 @@ DefineConsoleType( TypeAngAxisF, AngAxisF )
 DefineConsoleType( TypeTransformF, TransformF )
 DefineConsoleType( TypeBox3F, Box3F )
 DefineConsoleType( TypeEaseF, EaseF )
-
+DefineConsoleType(TypeRotationF, RotationF)
 
 #endif