2 Copyright (C) 2003, 2010 - Wolfire Games
4 This file is part of Lugaru.
6 Lugaru is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 See the GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #ifndef _PHYSICSMATH_H_
23 #define _PHYSICSMATH_H_
27 #include "MacCompatibility.h"
29 //------------------------------------------------------------------------//
31 //------------------------------------------------------------------------//
33 float const pi = 3.14159265f;
34 float const g = -32.174f; // acceleration due to gravity, ft/s^2
35 float const rho = 0.0023769f; // desity of air at sea level, slugs/ft^3
36 float const tol = 0.0000000001f; // float type tolerance
39 //------------------------------------------------------------------------//
41 //------------------------------------------------------------------------//
42 inline float DegreesToRadians(float deg);
43 inline float RadiansToDegrees(float rad);
45 inline float DegreesToRadians(float deg)
47 return deg * pi / 180.0f;
50 inline float RadiansToDegrees(float rad)
52 return rad * 180.0f / pi;
55 //------------------------------------------------------------------------//
56 // Vector Class and vector functions
57 //------------------------------------------------------------------------//
66 Vector(float xi, float yi, float zi);
68 float Magnitude(void);
72 Vector& operator+=(Vector u); // vector addition
73 Vector& operator-=(Vector u); // vector subtraction
74 Vector& operator*=(float s); // scalar multiply
75 Vector& operator/=(float s); // scalar divide
77 Vector operator-(void);
81 inline Vector operator+(Vector u, Vector v);
82 inline Vector operator-(Vector u, Vector v);
83 inline Vector operator^(Vector u, Vector v);
84 inline float operator*(Vector u, Vector v);
85 inline Vector operator*(float s, Vector u);
86 inline Vector operator*(Vector u, float s);
87 inline Vector operator/(Vector u, float s);
88 inline float TripleScalarProduct(Vector u, Vector v, Vector w);
90 float fast_sqrt2 (register float arg);
91 float fast_sqrt2 (register float arg)
93 // Can replace with slower return std::sqrt(arg);
94 register float result;
96 if (arg == 0.0) return 0.0;
99 frsqrte result,arg // Calculate Square root
102 // Newton Rhapson iterations.
103 result = result + 0.5 * result * (1.0 - arg * result * result);
104 result = result + 0.5 * result * (1.0 - arg * result * result);
109 inline Vector::Vector(void)
116 inline Vector::Vector(float xi, float yi, float zi)
123 inline float Vector::Magnitude(void)
125 return (float) sqrt(x * x + y * y + z * z);
128 inline void Vector::Normalize(void)
130 float m = (float) sqrt(x * x + y * y + z * z);
136 if (fabs(x) < tol) x = 0.0f;
137 if (fabs(y) < tol) y = 0.0f;
138 if (fabs(z) < tol) z = 0.0f;
141 inline void Vector::Reverse(void)
148 inline Vector& Vector::operator+=(Vector u)
156 inline Vector& Vector::operator-=(Vector u)
164 inline Vector& Vector::operator*=(float s)
172 inline Vector& Vector::operator/=(float s)
180 inline Vector Vector::operator-(void)
182 return Vector(-x, -y, -z);
186 inline Vector operator+(Vector u, Vector v)
188 return Vector(u.x + v.x, u.y + v.y, u.z + v.z);
191 inline Vector operator-(Vector u, Vector v)
193 return Vector(u.x - v.x, u.y - v.y, u.z - v.z);
196 // Vector cross product (u cross v)
197 inline Vector operator^(Vector u, Vector v)
199 return Vector( u.y * v.z - u.z * v.y,
200 -u.x * v.z + u.z * v.x,
201 u.x * v.y - u.y * v.x );
204 // Vector dot product
205 inline float operator*(Vector u, Vector v)
207 return (u.x * v.x + u.y * v.y + u.z * v.z);
210 inline Vector operator*(float s, Vector u)
212 return Vector(u.x * s, u.y * s, u.z * s);
215 inline Vector operator*(Vector u, float s)
217 return Vector(u.x * s, u.y * s, u.z * s);
220 inline Vector operator/(Vector u, float s)
222 return Vector(u.x / s, u.y / s, u.z / s);
225 // triple scalar product (u dot (v cross w))
226 inline float TripleScalarProduct(Vector u, Vector v, Vector w)
228 return float( (u.x * (v.y * w.z - v.z * w.y)) +
229 (u.y * (-v.x * w.z + v.z * w.x)) +
230 (u.z * (v.x * w.y - v.y * w.x)) );
237 //------------------------------------------------------------------------//
238 // Matrix Class and matrix functions
239 //------------------------------------------------------------------------//
244 // elements eij: i -> row, j -> column
245 float e11, e12, e13, e21, e22, e23, e31, e32, e33;
248 Matrix3x3( float r1c1, float r1c2, float r1c3,
249 float r2c1, float r2c2, float r2c3,
250 float r3c1, float r3c2, float r3c3 );
253 Matrix3x3 Transpose(void);
254 Matrix3x3 Inverse(void);
256 Matrix3x3& operator+=(Matrix3x3 m);
257 Matrix3x3& operator-=(Matrix3x3 m);
258 Matrix3x3& operator*=(float s);
259 Matrix3x3& operator/=(float s);
262 inline Matrix3x3 operator+(Matrix3x3 m1, Matrix3x3 m2);
263 inline Matrix3x3 operator-(Matrix3x3 m1, Matrix3x3 m2);
264 inline Matrix3x3 operator/(Matrix3x3 m, float s);
265 inline Matrix3x3 operator*(Matrix3x3 m1, Matrix3x3 m2);
266 inline Matrix3x3 operator*(Matrix3x3 m, float s);
267 inline Matrix3x3 operator*(float s, Matrix3x3 m);
268 inline Vector operator*(Matrix3x3 m, Vector u);
269 inline Vector operator*(Vector u, Matrix3x3 m);
275 inline Matrix3x3::Matrix3x3(void)
288 inline Matrix3x3::Matrix3x3( float r1c1, float r1c2, float r1c3,
289 float r2c1, float r2c2, float r2c3,
290 float r3c1, float r3c2, float r3c3 )
303 inline float Matrix3x3::det(void)
305 return e11 * e22 * e33 -
313 inline Matrix3x3 Matrix3x3::Transpose(void)
315 return Matrix3x3(e11, e21, e31, e12, e22, e32, e13, e23, e33);
318 inline Matrix3x3 Matrix3x3::Inverse(void)
320 float d = e11 * e22 * e33 -
329 return Matrix3x3( (e22 * e33 - e23 * e32) / d,
330 -(e12 * e33 - e13 * e32) / d,
331 (e12 * e23 - e13 * e22) / d,
332 -(e21 * e33 - e23 * e31) / d,
333 (e11 * e33 - e13 * e31) / d,
334 -(e11 * e23 - e13 * e21) / d,
335 (e21 * e32 - e22 * e31) / d,
336 -(e11 * e32 - e12 * e31) / d,
337 (e11 * e22 - e12 * e21) / d );
340 inline Matrix3x3& Matrix3x3::operator+=(Matrix3x3 m)
354 inline Matrix3x3& Matrix3x3::operator-=(Matrix3x3 m)
368 inline Matrix3x3& Matrix3x3::operator*=(float s)
382 inline Matrix3x3& Matrix3x3::operator/=(float s)
396 inline Matrix3x3 operator+(Matrix3x3 m1, Matrix3x3 m2)
398 return Matrix3x3( m1.e11 + m2.e11,
409 inline Matrix3x3 operator-(Matrix3x3 m1, Matrix3x3 m2)
411 return Matrix3x3( m1.e11 - m2.e11,
422 inline Matrix3x3 operator/(Matrix3x3 m, float s)
424 return Matrix3x3( m.e11 / s,
435 inline Matrix3x3 operator*(Matrix3x3 m1, Matrix3x3 m2)
437 return Matrix3x3( m1.e11 * m2.e11 + m1.e12 * m2.e21 + m1.e13 * m2.e31,
438 m1.e11 * m2.e12 + m1.e12 * m2.e22 + m1.e13 * m2.e32,
439 m1.e11 * m2.e13 + m1.e12 * m2.e23 + m1.e13 * m2.e33,
440 m1.e21 * m2.e11 + m1.e22 * m2.e21 + m1.e23 * m2.e31,
441 m1.e21 * m2.e12 + m1.e22 * m2.e22 + m1.e23 * m2.e32,
442 m1.e21 * m2.e13 + m1.e22 * m2.e23 + m1.e23 * m2.e33,
443 m1.e31 * m2.e11 + m1.e32 * m2.e21 + m1.e33 * m2.e31,
444 m1.e31 * m2.e12 + m1.e32 * m2.e22 + m1.e33 * m2.e32,
445 m1.e31 * m2.e13 + m1.e32 * m2.e23 + m1.e33 * m2.e33 );
448 inline Matrix3x3 operator*(Matrix3x3 m, float s)
450 return Matrix3x3( m.e11 * s,
461 inline Matrix3x3 operator*(float s, Matrix3x3 m)
463 return Matrix3x3( m.e11 * s,
474 inline Vector operator*(Matrix3x3 m, Vector u)
476 return Vector( m.e11 * u.x + m.e12 * u.y + m.e13 * u.z,
477 m.e21 * u.x + m.e22 * u.y + m.e23 * u.z,
478 m.e31 * u.x + m.e32 * u.y + m.e33 * u.z);
481 inline Vector operator*(Vector u, Matrix3x3 m)
483 return Vector( u.x * m.e11 + u.y * m.e21 + u.z * m.e31,
484 u.x * m.e12 + u.y * m.e22 + u.z * m.e32,
485 u.x * m.e13 + u.y * m.e23 + u.z * m.e33);
488 //------------------------------------------------------------------------//
489 // Quaternion Class and Quaternion functions
490 //------------------------------------------------------------------------//
495 float n; // number (scalar) part
496 Vector v; // vector part: v.x, v.y, v.z
499 Quaternion(float e0, float e1, float e2, float e3);
501 float Magnitude(void);
502 Vector GetVector(void);
503 float GetScalar(void);
504 Quaternion operator+=(Quaternion q);
505 Quaternion operator-=(Quaternion q);
506 Quaternion operator*=(float s);
507 Quaternion operator/=(float s);
508 Quaternion operator~(void) const {
509 return Quaternion(n, -v.x, -v.y, -v.z);
513 inline Quaternion operator+(Quaternion q1, Quaternion q2);
514 inline Quaternion operator-(Quaternion q1, Quaternion q2);
515 inline Quaternion operator*(Quaternion q1, Quaternion q2);
516 inline Quaternion operator*(Quaternion q, float s);
517 inline Quaternion operator*(float s, Quaternion q);
518 inline Quaternion operator*(Quaternion q, Vector v);
519 inline Quaternion operator*(Vector v, Quaternion q);
520 inline Quaternion operator/(Quaternion q, float s);
521 inline float QGetAngle(Quaternion q);
522 inline Vector QGetAxis(Quaternion q);
523 inline Quaternion QRotate(Quaternion q1, Quaternion q2);
524 inline Vector QVRotate(Quaternion q, Vector v);
525 inline Quaternion MakeQFromEulerAngles(float x, float y, float z);
526 inline Vector MakeEulerAnglesFromQ(Quaternion q);
529 inline Quaternion::Quaternion(void)
537 inline Quaternion::Quaternion(float e0, float e1, float e2, float e3)
545 inline float Quaternion::Magnitude(void)
547 return (float) sqrt(n * n + v.x * v.x + v.y * v.y + v.z * v.z);
550 inline Vector Quaternion::GetVector(void)
552 return Vector(v.x, v.y, v.z);
555 inline float Quaternion::GetScalar(void)
560 inline Quaternion Quaternion::operator+=(Quaternion q)
569 inline Quaternion Quaternion::operator-=(Quaternion q)
578 inline Quaternion Quaternion::operator*=(float s)
587 inline Quaternion Quaternion::operator/=(float s)
596 /*inline Quaternion Quaternion::operator~()
598 return Quaternion(n, -v.x, -v.y, -v.z);
601 inline Quaternion operator+(Quaternion q1, Quaternion q2)
603 return Quaternion( q1.n + q2.n,
609 inline Quaternion operator-(Quaternion q1, Quaternion q2)
611 return Quaternion( q1.n - q2.n,
617 inline Quaternion operator*(Quaternion q1, Quaternion q2)
619 return Quaternion( q1.n * q2.n - q1.v.x * q2.v.x - q1.v.y * q2.v.y - q1.v.z * q2.v.z,
620 q1.n * q2.v.x + q1.v.x * q2.n + q1.v.y * q2.v.z - q1.v.z * q2.v.y,
621 q1.n * q2.v.y + q1.v.y * q2.n + q1.v.z * q2.v.x - q1.v.x * q2.v.z,
622 q1.n * q2.v.z + q1.v.z * q2.n + q1.v.x * q2.v.y - q1.v.y * q2.v.x);
625 inline Quaternion operator*(Quaternion q, float s)
627 return Quaternion(q.n * s, q.v.x * s, q.v.y * s, q.v.z * s);
630 inline Quaternion operator*(float s, Quaternion q)
632 return Quaternion(q.n * s, q.v.x * s, q.v.y * s, q.v.z * s);
635 inline Quaternion operator*(Quaternion q, Vector v)
637 return Quaternion( -(q.v.x * v.x + q.v.y * v.y + q.v.z * v.z),
638 q.n * v.x + q.v.y * v.z - q.v.z * v.y,
639 q.n * v.y + q.v.z * v.x - q.v.x * v.z,
640 q.n * v.z + q.v.x * v.y - q.v.y * v.x);
643 inline Quaternion operator*(Vector v, Quaternion q)
645 return Quaternion( -(q.v.x * v.x + q.v.y * v.y + q.v.z * v.z),
646 q.n * v.x + q.v.z * v.y - q.v.y * v.z,
647 q.n * v.y + q.v.x * v.z - q.v.z * v.x,
648 q.n * v.z + q.v.y * v.x - q.v.x * v.y);
651 inline Quaternion operator/(Quaternion q, float s)
653 return Quaternion(q.n / s, q.v.x / s, q.v.y / s, q.v.z / s);
656 inline float QGetAngle(Quaternion q)
658 return (float) (2 * acosf(q.n));
661 inline Vector QGetAxis(Quaternion q)
675 inline Quaternion QRotate(Quaternion q1, Quaternion q2)
677 return q1 * q2 * (~q1);
680 inline Vector QVRotate(Quaternion q, Vector v)
687 return t.GetVector();
690 inline Quaternion MakeQFromEulerAngles(float x, float y, float z)
693 double roll = DegreesToRadians(x);
694 double pitch = DegreesToRadians(y);
695 double yaw = DegreesToRadians(z);
697 double cyaw, cpitch, croll, syaw, spitch, sroll;
698 double cyawcpitch, syawspitch, cyawspitch, syawcpitch;
700 cyaw = cos(0.5f * yaw);
701 cpitch = cos(0.5f * pitch);
702 croll = cos(0.5f * roll);
703 syaw = sin(0.5f * yaw);
704 spitch = sin(0.5f * pitch);
705 sroll = sin(0.5f * roll);
707 cyawcpitch = cyaw * cpitch;
708 syawspitch = syaw * spitch;
709 cyawspitch = cyaw * spitch;
710 syawcpitch = syaw * cpitch;
712 q.n = (float) (cyawcpitch * croll + syawspitch * sroll);
713 q.v.x = (float) (cyawcpitch * sroll - syawspitch * croll);
714 q.v.y = (float) (cyawspitch * croll + syawcpitch * sroll);
715 q.v.z = (float) (syawcpitch * croll - cyawspitch * sroll);
720 inline Vector MakeEulerAnglesFromQ(Quaternion q)
722 double r11, r21, r31, r32, r33;
723 double q00, q11, q22, q33;
732 r11 = q00 + q11 - q22 - q33;
733 r21 = 2 * (q.v.x * q.v.y + q.n * q.v.z);
734 r31 = 2 * (q.v.x * q.v.z - q.n * q.v.y);
735 r32 = 2 * (q.v.y * q.v.z + q.n * q.v.x);
736 r33 = q00 - q11 - q22 + q33;
739 if (tmp > 0.999999) {
740 double r12 = 2 * (q.v.x * q.v.y - q.n * q.v.z);
741 double r13 = 2 * (q.v.x * q.v.z + q.n * q.v.y);
743 u.x = RadiansToDegrees(0.0f); //roll
744 u.y = RadiansToDegrees((float) (-(pi / 2) * r31 / tmp)); // pitch
745 u.z = RadiansToDegrees((float) atan2(-r12, -r31 * r13)); // yaw
749 u.x = RadiansToDegrees((float) atan2(r32, r33)); // roll
750 u.y = RadiansToDegrees((float) asinf(-r31)); // pitch
751 u.z = RadiansToDegrees((float) atan2(r21, r11)); // yaw