#ifndef _PHYSICSMATH_H_ #define _PHYSICSMATH_H_ #include #include "Quaternions.h" //------------------------------------------------------------------------// // Misc. Constants //------------------------------------------------------------------------// float const pi = 3.14159265f; float const g = -32.174f; // acceleration due to gravity, ft/s^2 float const rho = 0.0023769f; // desity of air at sea level, slugs/ft^3 float const tol = 0.0000000001f; // float type tolerance //------------------------------------------------------------------------// // Misc. Functions //------------------------------------------------------------------------// inline float DegreesToRadians(float deg); inline float RadiansToDegrees(float rad); inline float DegreesToRadians(float deg) { return deg * pi / 180.0f; } inline float RadiansToDegrees(float rad) { return rad * 180.0f / pi; } //------------------------------------------------------------------------// // Vector Class and vector functions //------------------------------------------------------------------------// class Vector { public: float x; float y; float z; Vector(void); Vector(float xi, float yi, float zi); float Magnitude(void); void Normalize(void); void Reverse(void); Vector& operator+=(Vector u); // vector addition Vector& operator-=(Vector u); // vector subtraction Vector& operator*=(float s); // scalar multiply Vector& operator/=(float s); // scalar divide Vector operator-(void); }; inline Vector operator+(Vector u, Vector v); inline Vector operator-(Vector u, Vector v); inline Vector operator^(Vector u, Vector v); inline float operator*(Vector u, Vector v); inline Vector operator*(float s, Vector u); inline Vector operator*(Vector u, float s); inline Vector operator/(Vector u, float s); inline float TripleScalarProduct(Vector u, Vector v, Vector w); inline Vector::Vector(void) { x = 0; y = 0; z = 0; } inline Vector::Vector(float xi, float yi, float zi) { x = xi; y = yi; z = zi; } inline float Vector::Magnitude(void) { return (float) sqrt(x*x + y*y + z*z); } inline void Vector::Normalize(void) { float m = (float) sqrt(x*x + y*y + z*z); if(m <= tol) m = 1; x /= m; y /= m; z /= m; if (fabs(x) < tol) x = 0.0f; if (fabs(y) < tol) y = 0.0f; if (fabs(z) < tol) z = 0.0f; } inline void Vector::Reverse(void) { x = -x; y = -y; z = -z; } inline Vector& Vector::operator+=(Vector u) { x += u.x; y += u.y; z += u.z; return *this; } inline Vector& Vector::operator-=(Vector u) { x -= u.x; y -= u.y; z -= u.z; return *this; } inline Vector& Vector::operator*=(float s) { x *= s; y *= s; z *= s; return *this; } inline Vector& Vector::operator/=(float s) { x /= s; y /= s; z /= s; return *this; } inline Vector Vector::operator-(void) { return Vector(-x, -y, -z); } inline Vector operator+(Vector u, Vector v) { return Vector(u.x + v.x, u.y + v.y, u.z + v.z); } inline Vector operator-(Vector u, Vector v) { return Vector(u.x - v.x, u.y - v.y, u.z - v.z); } // Vector cross product (u cross v) inline Vector operator^(Vector u, Vector v) { return Vector( u.y*v.z - u.z*v.y, -u.x*v.z + u.z*v.x, u.x*v.y - u.y*v.x ); } // Vector dot product inline float operator*(Vector u, Vector v) { return (u.x*v.x + u.y*v.y + u.z*v.z); } inline Vector operator*(float s, Vector u) { return Vector(u.x*s, u.y*s, u.z*s); } inline Vector operator*(Vector u, float s) { return Vector(u.x*s, u.y*s, u.z*s); } inline Vector operator/(Vector u, float s) { return Vector(u.x/s, u.y/s, u.z/s); } // triple scalar product (u dot (v cross w)) inline float TripleScalarProduct(Vector u, Vector v, Vector w) { return float( (u.x * (v.y*w.z - v.z*w.y)) + (u.y * (-v.x*w.z + v.z*w.x)) + (u.z * (v.x*w.y - v.y*w.x)) ); //return u*(v^w); } //------------------------------------------------------------------------// // Matrix Class and matrix functions //------------------------------------------------------------------------// class Matrix3x3 { public: // elements eij: i -> row, j -> column float e11, e12, e13, e21, e22, e23, e31, e32, e33; Matrix3x3(void); Matrix3x3( float r1c1, float r1c2, float r1c3, float r2c1, float r2c2, float r2c3, float r3c1, float r3c2, float r3c3 ); float det(void); Matrix3x3 Transpose(void); Matrix3x3 Inverse(void); Matrix3x3& operator+=(Matrix3x3 m); Matrix3x3& operator-=(Matrix3x3 m); Matrix3x3& operator*=(float s); Matrix3x3& operator/=(float s); }; inline Matrix3x3 operator+(Matrix3x3 m1, Matrix3x3 m2); inline Matrix3x3 operator-(Matrix3x3 m1, Matrix3x3 m2); inline Matrix3x3 operator/(Matrix3x3 m, float s); inline Matrix3x3 operator*(Matrix3x3 m1, Matrix3x3 m2); inline Matrix3x3 operator*(Matrix3x3 m, float s); inline Matrix3x3 operator*(float s, Matrix3x3 m); inline Vector operator*(Matrix3x3 m, Vector u); inline Vector operator*(Vector u, Matrix3x3 m); inline Matrix3x3::Matrix3x3(void) { e11 = 0; e12 = 0; e13 = 0; e21 = 0; e22 = 0; e23 = 0; e31 = 0; e32 = 0; e33 = 0; } inline Matrix3x3::Matrix3x3( float r1c1, float r1c2, float r1c3, float r2c1, float r2c2, float r2c3, float r3c1, float r3c2, float r3c3 ) { e11 = r1c1; e12 = r1c2; e13 = r1c3; e21 = r2c1; e22 = r2c2; e23 = r2c3; e31 = r3c1; e32 = r3c2; e33 = r3c3; } inline float Matrix3x3::det(void) { return e11*e22*e33 - e11*e32*e23 + e21*e32*e13 - e21*e12*e33 + e31*e12*e23 - e31*e22*e13; } inline Matrix3x3 Matrix3x3::Transpose(void) { return Matrix3x3(e11,e21,e31,e12,e22,e32,e13,e23,e33); } inline Matrix3x3 Matrix3x3::Inverse(void) { float d = e11*e22*e33 - e11*e32*e23 + e21*e32*e13 - e21*e12*e33 + e31*e12*e23 - e31*e22*e13; if (d == 0) d = 1; return Matrix3x3( (e22*e33-e23*e32)/d, -(e12*e33-e13*e32)/d, (e12*e23-e13*e22)/d, -(e21*e33-e23*e31)/d, (e11*e33-e13*e31)/d, -(e11*e23-e13*e21)/d, (e21*e32-e22*e31)/d, -(e11*e32-e12*e31)/d, (e11*e22-e12*e21)/d ); } inline Matrix3x3& Matrix3x3::operator+=(Matrix3x3 m) { e11 += m.e11; e12 += m.e12; e13 += m.e13; e21 += m.e21; e22 += m.e22; e23 += m.e23; e31 += m.e31; e32 += m.e32; e33 += m.e33; return *this; } inline Matrix3x3& Matrix3x3::operator-=(Matrix3x3 m) { e11 -= m.e11; e12 -= m.e12; e13 -= m.e13; e21 -= m.e21; e22 -= m.e22; e23 -= m.e23; e31 -= m.e31; e32 -= m.e32; e33 -= m.e33; return *this; } inline Matrix3x3& Matrix3x3::operator*=(float s) { e11 *= s; e12 *= s; e13 *= s; e21 *= s; e22 *= s; e23 *= s; e31 *= s; e32 *= s; e33 *= s; return *this; } inline Matrix3x3& Matrix3x3::operator/=(float s) { e11 /= s; e12 /= s; e13 /= s; e21 /= s; e22 /= s; e23 /= s; e31 /= s; e32 /= s; e33 /= s; return *this; } inline Matrix3x3 operator+(Matrix3x3 m1, Matrix3x3 m2) { return Matrix3x3( m1.e11+m2.e11, m1.e12+m2.e12, m1.e13+m2.e13, m1.e21+m2.e21, m1.e22+m2.e22, m1.e23+m2.e23, m1.e31+m2.e31, m1.e32+m2.e32, m1.e33+m2.e33); } inline Matrix3x3 operator-(Matrix3x3 m1, Matrix3x3 m2) { return Matrix3x3( m1.e11-m2.e11, m1.e12-m2.e12, m1.e13-m2.e13, m1.e21-m2.e21, m1.e22-m2.e22, m1.e23-m2.e23, m1.e31-m2.e31, m1.e32-m2.e32, m1.e33-m2.e33); } inline Matrix3x3 operator/(Matrix3x3 m, float s) { return Matrix3x3( m.e11/s, m.e12/s, m.e13/s, m.e21/s, m.e22/s, m.e23/s, m.e31/s, m.e32/s, m.e33/s); } inline Matrix3x3 operator*(Matrix3x3 m1, Matrix3x3 m2) { return Matrix3x3( m1.e11*m2.e11 + m1.e12*m2.e21 + m1.e13*m2.e31, m1.e11*m2.e12 + m1.e12*m2.e22 + m1.e13*m2.e32, m1.e11*m2.e13 + m1.e12*m2.e23 + m1.e13*m2.e33, m1.e21*m2.e11 + m1.e22*m2.e21 + m1.e23*m2.e31, m1.e21*m2.e12 + m1.e22*m2.e22 + m1.e23*m2.e32, m1.e21*m2.e13 + m1.e22*m2.e23 + m1.e23*m2.e33, m1.e31*m2.e11 + m1.e32*m2.e21 + m1.e33*m2.e31, m1.e31*m2.e12 + m1.e32*m2.e22 + m1.e33*m2.e32, m1.e31*m2.e13 + m1.e32*m2.e23 + m1.e33*m2.e33 ); } inline Matrix3x3 operator*(Matrix3x3 m, float s) { return Matrix3x3( m.e11*s, m.e12*s, m.e13*s, m.e21*s, m.e22*s, m.e23*s, m.e31*s, m.e32*s, m.e33*s); } inline Matrix3x3 operator*(float s, Matrix3x3 m) { return Matrix3x3( m.e11*s, m.e12*s, m.e13*s, m.e21*s, m.e22*s, m.e23*s, m.e31*s, m.e32*s, m.e33*s); } inline Vector operator*(Matrix3x3 m, Vector u) { return Vector( m.e11*u.x + m.e12*u.y + m.e13*u.z, m.e21*u.x + m.e22*u.y + m.e23*u.z, m.e31*u.x + m.e32*u.y + m.e33*u.z); } inline Vector operator*(Vector u, Matrix3x3 m) { return Vector( u.x*m.e11 + u.y*m.e21 + u.z*m.e31, u.x*m.e12 + u.y*m.e22 + u.z*m.e32, u.x*m.e13 + u.y*m.e23 + u.z*m.e33); } //------------------------------------------------------------------------// // Quaternion Class and Quaternion functions //------------------------------------------------------------------------// class Quaternion { public: float n; // number (scalar) part Vector v; // vector part: v.x, v.y, v.z Quaternion(void); Quaternion(float e0, float e1, float e2, float e3); float Magnitude(void); Vector GetVector(void); float GetScalar(void); Quaternion operator+=(Quaternion q); Quaternion operator-=(Quaternion q); Quaternion operator*=(float s); Quaternion operator/=(float s); Quaternion operator~(void) const { return Quaternion(n, -v.x, -v.y, -v.z);} }; inline Quaternion operator+(Quaternion q1, Quaternion q2); inline Quaternion operator-(Quaternion q1, Quaternion q2); inline Quaternion operator*(Quaternion q1, Quaternion q2); inline Quaternion operator*(Quaternion q, float s); inline Quaternion operator*(float s, Quaternion q); inline Quaternion operator*(Quaternion q, Vector v); inline Quaternion operator*(Vector v, Quaternion q); inline Quaternion operator/(Quaternion q, float s); inline float QGetAngle(Quaternion q); inline Vector QGetAxis(Quaternion q); inline Quaternion QRotate(Quaternion q1, Quaternion q2); inline Vector QVRotate(Quaternion q, Vector v); inline Quaternion MakeQFromEulerAngles(float x, float y, float z); inline Vector MakeEulerAnglesFromQ(Quaternion q); inline Quaternion::Quaternion(void) { n = 0; v.x = 0; v.y = 0; v.z = 0; } inline Quaternion::Quaternion(float e0, float e1, float e2, float e3) { n = e0; v.x = e1; v.y = e2; v.z = e3; } inline float Quaternion::Magnitude(void) { return (float) sqrt(n*n + v.x*v.x + v.y*v.y + v.z*v.z); } inline Vector Quaternion::GetVector(void) { return Vector(v.x, v.y, v.z); } inline float Quaternion::GetScalar(void) { return n; } inline Quaternion Quaternion::operator+=(Quaternion q) { n += q.n; v.x += q.v.x; v.y += q.v.y; v.z += q.v.z; return *this; } inline Quaternion Quaternion::operator-=(Quaternion q) { n -= q.n; v.x -= q.v.x; v.y -= q.v.y; v.z -= q.v.z; return *this; } inline Quaternion Quaternion::operator*=(float s) { n *= s; v.x *= s; v.y *= s; v.z *= s; return *this; } inline Quaternion Quaternion::operator/=(float s) { n /= s; v.x /= s; v.y /= s; v.z /= s; return *this; } /*inline Quaternion Quaternion::operator~() { return Quaternion(n, -v.x, -v.y, -v.z); }*/ inline Quaternion operator+(Quaternion q1, Quaternion q2) { return Quaternion( q1.n + q2.n, q1.v.x + q2.v.x, q1.v.y + q2.v.y, q1.v.z + q2.v.z); } inline Quaternion operator-(Quaternion q1, Quaternion q2) { return Quaternion( q1.n - q2.n, q1.v.x - q2.v.x, q1.v.y - q2.v.y, q1.v.z - q2.v.z); } inline Quaternion operator*(Quaternion q1, Quaternion q2) { return Quaternion( q1.n*q2.n - q1.v.x*q2.v.x - q1.v.y*q2.v.y - q1.v.z*q2.v.z, q1.n*q2.v.x + q1.v.x*q2.n + q1.v.y*q2.v.z - q1.v.z*q2.v.y, q1.n*q2.v.y + q1.v.y*q2.n + q1.v.z*q2.v.x - q1.v.x*q2.v.z, q1.n*q2.v.z + q1.v.z*q2.n + q1.v.x*q2.v.y - q1.v.y*q2.v.x); } inline Quaternion operator*(Quaternion q, float s) { return Quaternion(q.n*s, q.v.x*s, q.v.y*s, q.v.z*s); } inline Quaternion operator*(float s, Quaternion q) { return Quaternion(q.n*s, q.v.x*s, q.v.y*s, q.v.z*s); } inline Quaternion operator*(Quaternion q, Vector v) { return Quaternion( -(q.v.x*v.x + q.v.y*v.y + q.v.z*v.z), q.n*v.x + q.v.y*v.z - q.v.z*v.y, q.n*v.y + q.v.z*v.x - q.v.x*v.z, q.n*v.z + q.v.x*v.y - q.v.y*v.x); } inline Quaternion operator*(Vector v, Quaternion q) { return Quaternion( -(q.v.x*v.x + q.v.y*v.y + q.v.z*v.z), q.n*v.x + q.v.z*v.y - q.v.y*v.z, q.n*v.y + q.v.x*v.z - q.v.z*v.x, q.n*v.z + q.v.y*v.x - q.v.x*v.y); } inline Quaternion operator/(Quaternion q, float s) { return Quaternion(q.n/s, q.v.x/s, q.v.y/s, q.v.z/s); } inline float QGetAngle(Quaternion q) { return (float) (2*acos(q.n)); } inline Vector QGetAxis(Quaternion q) { Vector v; float m; v = q.GetVector(); m = v.Magnitude(); if (m <= tol) return Vector(); else return v/m; } inline Quaternion QRotate(Quaternion q1, Quaternion q2) { return q1*q2*(~q1); } inline Vector QVRotate(Quaternion q, Vector v) { Quaternion t; t = q*v*(~q); return t.GetVector(); } inline Quaternion MakeQFromEulerAngles(float x, float y, float z) { Quaternion q; double roll = DegreesToRadians(x); double pitch = DegreesToRadians(y); double yaw = DegreesToRadians(z); double cyaw, cpitch, croll, syaw, spitch, sroll; double cyawcpitch, syawspitch, cyawspitch, syawcpitch; cyaw = cos(0.5f * yaw); cpitch = cos(0.5f * pitch); croll = cos(0.5f * roll); syaw = sin(0.5f * yaw); spitch = sin(0.5f * pitch); sroll = sin(0.5f * roll); cyawcpitch = cyaw*cpitch; syawspitch = syaw*spitch; cyawspitch = cyaw*spitch; syawcpitch = syaw*cpitch; q.n = (float) (cyawcpitch * croll + syawspitch * sroll); q.v.x = (float) (cyawcpitch * sroll - syawspitch * croll); q.v.y = (float) (cyawspitch * croll + syawcpitch * sroll); q.v.z = (float) (syawcpitch * croll - cyawspitch * sroll); return q; } inline Vector MakeEulerAnglesFromQ(Quaternion q) { double r11, r21, r31, r32, r33, r12, r13; double q00, q11, q22, q33; double tmp; Vector u; q00 = q.n * q.n; q11 = q.v.x * q.v.x; q22 = q.v.y * q.v.y; q33 = q.v.z * q.v.z; r11 = q00 + q11 - q22 - q33; r21 = 2 * (q.v.x*q.v.y + q.n*q.v.z); r31 = 2 * (q.v.x*q.v.z - q.n*q.v.y); r32 = 2 * (q.v.y*q.v.z + q.n*q.v.x); r33 = q00 - q11 - q22 + q33; tmp = fabs(r31); if(tmp > 0.999999) { r12 = 2 * (q.v.x*q.v.y - q.n*q.v.z); r13 = 2 * (q.v.x*q.v.z + q.n*q.v.y); u.x = RadiansToDegrees(0.0f); //roll u.y = RadiansToDegrees((float) (-(pi/2) * r31/tmp)); // pitch u.z = RadiansToDegrees((float) atan2(-r12, -r31*r13)); // yaw return u; } u.x = RadiansToDegrees((float) atan2(r32, r33)); // roll u.y = RadiansToDegrees((float) asin(-r31)); // pitch u.z = RadiansToDegrees((float) atan2(r21, r11)); // yaw return u; } #endif