#ifndef _Orientation_h_ #define _Orientation_h_ ////////////////////////////////////////////////////////////////////////////// // // Orientation Value // ////////////////////////////////////////////////////////////////////////////// class Orientation { private: float m_r[3][3]; static const Orientation s_orientIdentity; friend class Matrix; public: Orientation(); Orientation(float r00, float r01, float r02, float r10, float r11, float r12, float r20, float r21, float r22) { m_r[0][0] = r00; m_r[0][1] = r01; m_r[0][2] = r02; m_r[1][0] = r10; m_r[1][1] = r11; m_r[1][2] = r12; m_r[2][0] = r20; m_r[2][1] = r21; m_r[2][2] = r22; } Orientation(const Orientation& o); Orientation(const float m[3][3]); Orientation& operator=(const float r[3][3]); Orientation(const Vector& vecForward); Orientation(const Vector& vecForward, const Vector& vecUp); Orientation(const Vector& axis, float angle); static const Orientation& GetIdentity() { return s_orientIdentity; } ~Orientation(); Orientation& operator=(const Orientation& o); Orientation& operator*=(const Orientation& o); Orientation operator*(const Orientation& o) const; bool operator==(const Orientation& o) const; // fuzzy equality test: forward & up axes within 1 degree or so // turn the forward axis of *this towards target (by yaw * pitch), turning <= maxTurn void TurnTo(const Vector& target); float TurnTo(const Vector& target, float maxTurn); //radians // invert the matrix by taking the transform Orientation& Invert(); // multiply a vector by the inverse (without actually creating the inverse matrix): xyz * (*this)^-1 // orientation o * (*this)^-1 //r = v * (o^-1) Vector TimesInverse(const Vector& vec) const; // r = this * (o^-1) Orientation TimesInverse(const Orientation& o) const; // Set the orientation equal to either the desired values void Reset(); bool Set(const Vector& vecForward); bool Set(const Vector& vecForward, const Vector& vecUp); // Get the forward, up & right axes of the orientation // in-lined and in the header file for efficiency Vector GetForward() const { return Vector(-m_r[2][0], -m_r[2][1],-m_r[2][2]); } const Vector& GetBackward() const { assert (&(((Vector*)&m_r[2][0])->z) == &m_r[2][2]); return *((Vector*)&m_r[2][0]); } const Vector& GetUp() const { assert (&(((Vector*)&m_r[1][0])->z) == &m_r[1][2]); return *((Vector*)&m_r[1][0]); } const Vector& GetRight() const { assert (&(((Vector*)&m_r[0][0])->z) == &m_r[0][2]); return *((Vector*)&m_r[0][0]); } void SetForward(const Vector& vec) { ZAssert(vec.LengthSquared() != 0); m_r[2][0] = -vec.x; m_r[2][1] = -vec.y; m_r[2][2] = -vec.z; } void SetUp(const Vector& vec) { ZAssert(vec.LengthSquared() != 0); m_r[1][0] = vec.x; m_r[1][1] = vec.y; m_r[1][2] = vec.z; } void SetRight(const Vector& vec) { ZAssert(vec.LengthSquared() != 0); m_r[0][0] = vec.x; m_r[0][1] = vec.y; m_r[0][2] = vec.z; } // Return the cosine of the angle between vec and the given axis, requires a sqrt() call float CosForward(const Vector& vec) const; float CosUp(const Vector& vec) const; float CosRight(const Vector& vec) const; // Fast versions of the above that don't take a square-root. // cosX == sqrt(abs(cosX2)) & sgn(cosX) == sgn(cosX2) float CosForward2(const Vector& vec) const; float CosUp2(const Vector& vec) const; float CosRight2(const Vector& vec) const; // Rotate the coordinate system about the given axis by theta Orientation& PostRoll(float theta); Orientation& PostPitch(float theta); Orientation& PostYaw(float theta); Orientation& Roll(float theta); Orientation& Pitch(float theta); Orientation& Yaw(float theta); void Renormalize(void) { Vector forward = GetForward(); Vector up = GetUp(); Set(forward, up); } // this = Orientation(axis, theta) * this Orientation& PreRotate(const Vector& axis, float theta); // this *= Orientation(axis, theta) Orientation& PostRotate(const Vector& axis, float theta); // Vector& operator*=(const Orientation& o); void Scale(const Vector& xyz) { m_r[0][0] *= xyz.x; m_r[0][1] *= xyz.y; m_r[0][2] *= xyz.z; m_r[1][0] *= xyz.x; m_r[1][1] *= xyz.y; m_r[1][2] *= xyz.z; m_r[2][0] *= xyz.x; m_r[2][1] *= xyz.y; m_r[2][2] *= xyz.z; } const float* operator[](int index) const { return m_r[index]; } friend Vector operator * (const Vector& v, const Orientation& o); }; inline Vector operator * (const Vector& v, const Orientation& o) { return Vector( v.x * o.m_r[0][0] + v.y * o.m_r[1][0] + v.z * o.m_r[2][0], v.x * o.m_r[0][1] + v.y * o.m_r[1][1] + v.z * o.m_r[2][1], v.x * o.m_r[0][2] + v.y * o.m_r[1][2] + v.z * o.m_r[2][2] ); } #endif