/* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright (c) 2000-2005 The OGRE Team Also see acknowledgements in Readme.html This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt. ----------------------------------------------------------------------------- */ // NOTE THAT THIS FILE IS BASED ON MATERIAL FROM: // Magic Software, Inc. // http://www.geometrictools.com/ // Copyright (c) 2000, All Rights Reserved // // Source code from Magic Software is supplied under the terms of a license // agreement and may not be copied or disclosed except in accordance with the // terms of that agreement. The various license agreements may be found at // the Magic Software web site. This file is subject to the license // // FREE SOURCE CODE // http://www.geometrictools.com/License/WildMagic3License.pdf #ifndef __Quaternion_H__ #define __Quaternion_H__ #include "OgrePrerequisites.h" #include "OgreMath.h" namespace Ogre { /** Implementation of a Quaternion, i.e. a rotation around an axis. */ class _OgreExport Quaternion { public: inline Quaternion ( Real fW = 1.0, Real fX = 0.0, Real fY = 0.0, Real fZ = 0.0) { w = fW; x = fX; y = fY; z = fZ; } inline Quaternion (const Quaternion& rkQ) { w = rkQ.w; x = rkQ.x; y = rkQ.y; z = rkQ.z; } /// Construct a quaternion from a rotation matrix inline Quaternion(const Matrix3& rot) { this->FromRotationMatrix(rot); } /// Construct a quaternion from an angle/axis inline Quaternion(const Radian& rfAngle, const Vector3& rkAxis) { this->FromAngleAxis(rfAngle, rkAxis); } #ifndef OGRE_FORCE_ANGLE_TYPES inline Quaternion(const Real& rfAngle, const Vector3& rkAxis) { this->FromAngleAxis(rfAngle, rkAxis); } #endif//OGRE_FORCE_ANGLE_TYPES /// Construct a quaternion from 3 orthonormal local axes inline Quaternion(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis) { this->FromAxes(xaxis, yaxis, zaxis); } /// Construct a quaternion from 3 orthonormal local axes inline Quaternion(const Vector3* akAxis) { this->FromAxes(akAxis); } /// Construct a quaternion from 4 manual w/x/y/z values inline Quaternion(Real* valptr) { memcpy(val, valptr, sizeof(Real)*4); } void FromRotationMatrix (const Matrix3& kRot); void ToRotationMatrix (Matrix3& kRot) const; void FromAngleAxis (const Radian& rfAngle, const Vector3& rkAxis); void ToAngleAxis (Radian& rfAngle, Vector3& rkAxis) const; inline void ToAngleAxis (Degree& dAngle, Vector3& rkAxis) const { Radian rAngle; ToAngleAxis ( rAngle, rkAxis ); dAngle = rAngle; } #ifndef OGRE_FORCE_ANGLE_TYPES inline void FromAngleAxis (const Real& rfAngle, const Vector3& rkAxis) { FromAngleAxis ( Angle(rfAngle), rkAxis ); } inline void ToAngleAxis (Real& rfAngle, Vector3& rkAxis) const { Radian r; ToAngleAxis ( r, rkAxis ); rfAngle = r.valueAngleUnits(); } #endif//OGRE_FORCE_ANGLE_TYPES void FromAxes (const Vector3* akAxis); void FromAxes (const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis); void ToAxes (Vector3* akAxis) const; void ToAxes (Vector3& xAxis, Vector3& yAxis, Vector3& zAxis) const; /// Get the local x-axis Vector3 xAxis(void) const; /// Get the local y-axis Vector3 yAxis(void) const; /// Get the local z-axis Vector3 zAxis(void) const; inline Quaternion& operator= (const Quaternion& rkQ) { w = rkQ.w; x = rkQ.x; y = rkQ.y; z = rkQ.z; return *this; } Quaternion operator+ (const Quaternion& rkQ) const; Quaternion operator- (const Quaternion& rkQ) const; Quaternion operator* (const Quaternion& rkQ) const; Quaternion operator* (Real fScalar) const; _OgreExport friend Quaternion operator* (Real fScalar, const Quaternion& rkQ); Quaternion operator- () const; inline bool operator== (const Quaternion& rhs) const { return (rhs.x == x) && (rhs.y == y) && (rhs.z == z) && (rhs.w == w); } inline bool operator!= (const Quaternion& rhs) const { return !operator==(rhs); } // functions of a quaternion Real Dot (const Quaternion& rkQ) const; // dot product Real Norm () const; // squared-length /// Normalises this quaternion, and returns the previous length Real normalise(void); Quaternion Inverse () const; // apply to non-zero quaternion Quaternion UnitInverse () const; // apply to unit-length quaternion Quaternion Exp () const; Quaternion Log () const; // rotation of a vector by a quaternion Vector3 operator* (const Vector3& rkVector) const; /// Calculate the local roll element of this quaternion Radian getRoll(void) const; /// Calculate the local pitch element of this quaternion Radian getPitch(void) const; /// Calculate the local yaw element of this quaternion Radian getYaw(void) const; /// Equality with tolerance (tolerance is max angle difference) bool equals(const Quaternion& rhs, const Radian& tolerance) const; // spherical linear interpolation static Quaternion Slerp (Real fT, const Quaternion& rkP, const Quaternion& rkQ, bool shortestPath = false); static Quaternion SlerpExtraSpins (Real fT, const Quaternion& rkP, const Quaternion& rkQ, int iExtraSpins); // setup for spherical quadratic interpolation static void Intermediate (const Quaternion& rkQ0, const Quaternion& rkQ1, const Quaternion& rkQ2, Quaternion& rka, Quaternion& rkB); // spherical quadratic interpolation static Quaternion Squad (Real fT, const Quaternion& rkP, const Quaternion& rkA, const Quaternion& rkB, const Quaternion& rkQ, bool shortestPath = false); // normalised linear interpolation - faster but less accurate (non-constant rotation velocity) static Quaternion nlerp(Real fT, const Quaternion& rkP, const Quaternion& rkQ, bool shortestPath = false); // cutoff for sine near zero static const Real ms_fEpsilon; // special values static const Quaternion ZERO; static const Quaternion IDENTITY; union { struct { Real w, x, y, z; }; Real val[4]; }; /** Function for writing to a stream. Outputs "Quaternion(w, x, y, z)" with w,x,y,z being the member values of the quaternion. */ inline _OgreExport friend std::ostream& operator << ( std::ostream& o, const Quaternion& q ) { o << "Quaternion(" << q.w << ", " << q.x << ", " << q.y << ", " << q.z << ")"; return o; } }; } #endif