diff options
Diffstat (limited to 'dep/g3dlite/include/G3D/Quat.h')
-rw-r--r-- | dep/g3dlite/include/G3D/Quat.h | 105 |
1 files changed, 65 insertions, 40 deletions
diff --git a/dep/g3dlite/include/G3D/Quat.h b/dep/g3dlite/include/G3D/Quat.h index d8fdfafeca4..04e11e084a0 100644 --- a/dep/g3dlite/include/G3D/Quat.h +++ b/dep/g3dlite/include/G3D/Quat.h @@ -1,12 +1,12 @@ /** - @file Quat.h + \file G3D/Quat.h Quaternion - @maintainer Morgan McGuire, http://graphics.cs.williams.edu + \maintainer Morgan McGuire, http://graphics.cs.williams.edu - @created 2002-01-23 - @edited 2009-05-10 + \created 2002-01-23 + \edited 2011-05-10 */ #ifndef G3D_Quat_h @@ -21,9 +21,9 @@ namespace G3D { /** - Arbitrary quaternion (not necessarily unit) + Arbitrary quaternion (not necessarily unit). - Unit quaternions are used in computer graphics to represent + Unit quaternions (aka versors) are used in computer graphics to represent rotation about an axis. Any 3x3 rotation matrix can be stored as a quaternion. @@ -72,6 +72,8 @@ public: /** Expects "Quat(x,y,z,w)" or a Matrix3 constructor. */ Quat(const class Any& a); + Any toAny() const; + Quat(const Matrix3& rot); Quat(float _x, float _y, float _z, float _w) : @@ -81,6 +83,12 @@ public: Quat(const Vector3& v, float _w = 0) : x(v.x), y(v.y), z(v.z), w(_w) { } + /** True if the components are exactly equal. Note that two quaternations may + be unequal but map to the same rotation. */ + bool operator==(const Quat& q) const { + return x == q.x && y == q.y && z == q.z && w == q.w; + } + /** The real part of the quaternion. */ @@ -92,9 +100,9 @@ public: return w; } - Quat operator-() const { - return Quat(-x, -y, -z, -w); - } + Quat operator-() const { + return Quat(-x, -y, -z, -w); + } Quat operator-(const Quat& other) const { return Quat(x - other.x, y - other.y, z - other.z, w - other.w); @@ -148,7 +156,7 @@ public: } - /** @cite Based on Watt & Watt, page 360 */ + /** @cite Based on Watt & Watt, page 360 */ friend Quat operator* (float s, const Quat& q); inline Quat operator/(float s) const { @@ -196,36 +204,69 @@ public: void toAxisAngleRotation( Vector3& axis, float& angle) const { - double d; - toAxisAngleRotation(axis, d); - angle = (float)d; - } + double d; + toAxisAngleRotation(axis, d); + angle = (float)d; + } Matrix3 toRotationMatrix() const; void toRotationMatrix( Matrix3& rot) const; +private: + /** \param maxAngle Maximum angle of rotation allowed. If a larger rotation is required, the angle of rotation applied is clamped to maxAngle */ + Quat slerp + (const Quat& other, + float alpha, + float threshold, + float maxAngle) const; +public: + /** Spherical linear interpolation: linear interpolation along the shortest (3D) great-circle route between two quaternions. + Assumes that both arguments are unit quaternions. + Note: Correct rotations are expected between 0 and PI in the right order. - @cite Based on Game Physics -- David Eberly pg 538-540 - @param threshold Critical angle between between rotations at which - the algorithm switches to normalized lerp, which is more - numerically stable in those situations. 0.0 will always slerp. + \cite Based on Game Physics -- David Eberly pg 538-540 + + \param threshold Critical angle between between rotations (in radians) at which + the algorithm switches to normalized lerp, which is more + numerically stable in those situations. 0.0 will always slerp. + */ - Quat slerp( - const Quat& other, + Quat slerp + (const Quat& other, float alpha, - float threshold = 0.05f) const; + float threshold = 0.05f) const { + return slerp(other, alpha, threshold, finf()); + } - /** Normalized linear interpolation of quaternion components. */ - Quat nlerp(const Quat& other, float alpha) const; + /** Rotates towards \a other by at most \a maxAngle. */ + Quat movedTowards + (const Quat& other, + float maxAngle) const { + return slerp(other, 1.0f, 0.05f, maxAngle); + } + + /** Rotates towards \a other by at most \a maxAngle. */ + void moveTowards + (const Quat& other, + float maxAngle) { + *this = movedTowards(other, maxAngle); + } + /** Returns the angle in radians between this and other, assuming both are unit quaternions. + + \returns On the range [0, pif()]*/ + float angleBetween(const Quat& other) const; + /** Normalized linear interpolation of quaternion components. */ + Quat nlerp(const Quat& other, float alpha) const; + /** Note that q<SUP>-1</SUP> = q.conj() for a unit quaternion. @cite Dam99 page 13 */ @@ -274,22 +315,6 @@ public: return Quat(t * x, t * y, t * z, ::logf(len)); } } - /** log q = [Av, 0] where q = [sin(A) * v, cos(A)]. - Only for unit quaternions - debugAssertM(isUnit(), "Log only defined for unit quaternions"); - // Solve for A in q = [sin(A)*v, cos(A)] - Vector3 u(x, y, z); - double len = u.magnitude(); - - if (len == 0.0) { - return - } - double A = atan2((double)w, len); - Vector3 v = u / len; - - return Quat(v * A, 0); - } - */ /** exp q = [sin(A) * v, cos(A)] where q = [Av, 0]. Only defined for pure-vector quaternions */ @@ -348,7 +373,7 @@ public: float& operator[] (int i); /** Generate uniform random unit quaternion (i.e. random "direction") - @cite From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III. + @cite From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III. */ static Quat unitRandom(); |