diff options
Diffstat (limited to 'dep/include/g3dlite/G3D/Quat.h')
-rw-r--r-- | dep/include/g3dlite/G3D/Quat.h | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/dep/include/g3dlite/G3D/Quat.h b/dep/include/g3dlite/G3D/Quat.h index 2c7fe68353e..f53d70be909 100644 --- a/dep/include/g3dlite/G3D/Quat.h +++ b/dep/include/g3dlite/G3D/Quat.h @@ -1,34 +1,46 @@ /** @file Quat.h + Quaternion + @maintainer Morgan McGuire, matrix@graphics3d.com + @created 2002-01-23 @edited 2006-05-10 */ + #ifndef G3D_QUAT_H #define G3D_QUAT_H + #include "G3D/platform.h" #include "G3D/g3dmath.h" #include "G3D/Vector3.h" #include "G3D/Matrix3.h" #include <string> + namespace G3D { + /** Unit quaternions are used in computer graphics to represent rotation about an axis. Any 3x3 rotation matrix can be stored as a quaternion. + A quaternion represents the sum of a real scalar and an imaginary vector: ix + jy + kz + w. A unit quaternion representing a rotation by A about axis v has the form [sin(A/2)*v, cos(A/2)]. For a unit quaternion, q.conj() == q.inverse() is a rotation by -A about v. -q is the same rotation as q (negate both the axis and angle). + A non-unit quaterion q represents the same rotation as q.unitize() (Dam98 pg 28). + Although quaternion-vector operations (eg. Quat + Vector3) are well defined, they are not supported by this class because they typically are bugs when they appear in code. + Do not subclass. + <B>BETA API -- subject to change</B> @cite Erik B. Dam, Martin Koch, Martin Lillholm, Quaternions, Interpolation and Animation. Technical Report DIKU-TR-98/5, Department of Computer Science, University of Copenhagen, Denmark. 1998. */ @@ -39,64 +51,81 @@ private: bool operator>(const Quat&) const; bool operator<=(const Quat&) const; bool operator>=(const Quat&) const; + public: + /** q = [sin(angle / 2) * axis, cos(angle / 2)] + In Watt & Watt's notation, s = w, v = (x, y, z) In the Real-Time Rendering notation, u = (x, y, z), w = w */ float x, y, z, w; + /** Initializes to a zero degree rotation. */ inline Quat() : x(0), y(0), z(0), w(1) {} + Quat( const Matrix3& rot); + inline Quat(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) {} + /** Defaults to a pure vector quaternion */ inline Quat(const Vector3& v, float _w = 0) : x(v.x), y(v.y), z(v.z), w(_w) { } + /** The real part of the quaternion. */ inline const float& real() const { return w; } + inline float& real() { return w; } + /** Note: two quats can represent the Quat::sameRotation and not be equal. */ bool fuzzyEq(const Quat& q) { return G3D::fuzzyEq(x, q.x) && G3D::fuzzyEq(y, q.y) && G3D::fuzzyEq(z, q.z) && G3D::fuzzyEq(w, q.w); } + /** True if these quaternions represent the same rotation (note that every rotation is represented by two values; q and -q). */ bool sameRotation(const Quat& q) { return fuzzyEq(q) || fuzzyEq(-q); } + inline Quat operator-() const { return Quat(-x, -y, -z, -w); } + /** Returns the imaginary part (x, y, z) */ inline const Vector3& imag() const { return *(reinterpret_cast<const Vector3*>(this)); } + inline Vector3& imag() { return *(reinterpret_cast<Vector3*>(this)); } + /** q = [sin(angle/2)*axis, cos(angle/2)] */ static Quat fromAxisAngleRotation( const Vector3& axis, float angle); + /** Returns the axis and angle of rotation represented by this quaternion (i.e. q = [sin(angle/2)*axis, cos(angle/2)]) */ void toAxisAngleRotation( Vector3& axis, double& angle) const; + void toAxisAngleRotation( Vector3& axis, float& angle) const { @@ -104,13 +133,18 @@ public: toAxisAngleRotation(axis, d); angle = (float)d; } + Matrix3 toRotationMatrix() const; + void toRotationMatrix( Matrix3& rot) const; + /** Spherical linear interpolation: linear interpolation along the shortest (3D) great-circle route between two 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 @@ -120,56 +154,72 @@ public: const Quat& other, float alpha, float threshold = 0.05f) const; + /** Normalized linear interpolation of quaternion components. */ Quat nlerp(const Quat& other, float alpha) const; + /** Negates the imaginary part. */ inline Quat conj() const { return Quat(-x, -y, -z, w); } + inline float sum() const { return x + y + z + w; } + inline float average() const { return sum() / 4.0f; } + inline Quat operator*(float s) const { return Quat(x * s, y * s, z * s, w * s); } + /** @cite Based on Watt & Watt, page 360 */ friend Quat operator* (float s, const Quat& q); + inline Quat operator/(float s) const { return Quat(x / s, y / s, z / s, w / s); } + inline float dot(const Quat& other) const { return (x * other.x) + (y * other.y) + (z * other.z) + (w * other.w); } + /** Note that q<SUP>-1</SUP> = q.conj() for a unit quaternion. @cite Dam99 page 13 */ inline Quat inverse() const { return conj() / dot(*this); } + Quat operator-(const Quat& other) const; + Quat operator+(const Quat& other) const; + /** Quaternion multiplication (composition of rotations). Note that this does not commute. */ Quat operator*(const Quat& other) const; + /* (*this) * other.inverse() */ Quat operator/(const Quat& other) const { return (*this) * other.inverse(); } + /** Is the magnitude nearly 1.0? */ inline bool isUnit(float tolerance = 1e-5) const { return abs(dot(*this) - 1.0f) < tolerance; } + inline float magnitude() const { return sqrtf(dot(*this)); } + inline Quat log() const { if ((x == 0) && (y == 0) && (z == 0)) { if (w > 0) { @@ -197,14 +247,17 @@ public: // 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 */ inline Quat exp() const { @@ -215,10 +268,12 @@ public: return Quat(sinf(A) * v, cosf(A)); } + /** Raise this quaternion to a power. For a rotation, this is the effect of rotating x times as much as the original quaterion. + Note that q.pow(a).pow(b) == q.pow(a + b) @cite Dam98 pg 21 */ @@ -226,6 +281,7 @@ public: return (log() * x).exp(); } + /** @deprecated Use toUnit() @@ -238,6 +294,7 @@ public: return *this / sqrtf(mag2); } } + /** Returns a unit quaterion obtained by dividing through by the magnitude. @@ -245,6 +302,7 @@ public: inline Quat toUnit() const { return unitize(); } + /** The linear algebra 2-norm, sqrt(q dot q). This matches the value used in Dam's 1998 tech report but differs from the @@ -254,6 +312,7 @@ public: inline float norm() const { return magnitude(); } + // access quaternion as q[0] = q.x, q[1] = q.y, q[2] = q.z, q[3] = q.w // // WARNING. These member functions rely on @@ -261,11 +320,14 @@ public: // (2) the data packed in a 4*sizeof(float) memory block const float& operator[] (int i) const; float& operator[] (int i); + /** Generate uniform random unit quaternion (i.e. random "direction") @cite From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III. */ static Quat unitRandom(); + // 2-char swizzles + Vector2 xx() const; Vector2 yx() const; Vector2 zx() const; @@ -282,7 +344,9 @@ public: Vector2 yw() const; Vector2 zw() const; Vector2 ww() const; + // 3-char swizzles + Vector3 xxx() const; Vector3 yxx() const; Vector3 zxx() const; @@ -347,7 +411,9 @@ public: Vector3 yww() const; Vector3 zww() const; Vector3 www() const; + // 4-char swizzles + Vector4 xxxx() const; Vector4 yxxx() const; Vector4 zxxx() const; @@ -605,24 +671,33 @@ public: Vector4 zwww() const; Vector4 wwww() const; }; + inline Quat exp(const Quat& q) { return q.exp(); } + inline Quat log(const Quat& q) { return q.log(); } + inline G3D::Quat operator*(double s, const G3D::Quat& q) { return q * (float)s; } + inline G3D::Quat operator*(float s, const G3D::Quat& q) { return q * s; } + } // Namespace G3D + // Outside the namespace to avoid overloading confusion for C++ inline G3D::Quat pow(const G3D::Quat& q, double x) { return q.pow((float)x); } + + #include "Quat.inl" + #endif |