view include/Math.h @ 13:e00321d11fe1

to_string simplified. Added Vector constructors from smaller vectors. Added rotation and transform matrix calculation functions.
author Eris Caffee <discordia@eldalin.com>
date Wed, 08 May 2013 22:50:09 -0500
parents 1d2b25d4517f
children c029247daf0e
line source
1 #ifndef MATH_H_
2 #define MATH_H_
4 #include "Vector.h"
5 #include "Matrix.h"
7 ///////////////////////////////////////////////////////////////////////////////////
8 // Notes for improvement
9 //
10 // The angle related constants (PI, 2PI, etc) and functions (deg_to_rad, rad_to_deg)
11 // could be made faster by using #define's. In fact, this would turn them into
12 // compile time operations. But it would also put them, effectively, in the
13 // global namespace. Do I want that? For now I'm leaving things as const
14 // variables and inline functions. I can profile things later to see if changes
15 // are really needed.
17 namespace arda
18 {
20 ////////////////////////////////////////////////////////////////////////////////
21 // Angles
23 namespace Math
24 {
25 // This many decimals is enough to cover even IEEE quad precision (128 bit)
26 // reals. Run on PA-RISC lately? :)
27 long double const PI = 3.14159265358979323846264338327950288;
28 long double const TWO_PI = 6.28318530717958647692528676655900577;
29 long double const PI_DIV_180 = 0.01745329251994329576923690768488613;
30 long double const INV_PI_DIV_180 = 57.29577951308232087679815481410517033;
32 //////////////////////////////////////////////////////////////////////////
33 // Mixed Vector / Matrix operations.
34 // * *=
35 // Defined for Vector * Matrix and Matrix * Vector, but these
36 // operators are not part of the class. They are defined independently.
37 //
39 // Vector2 * Matrix22
40 template <typename T>
41 inline Vector2<T>& operator*=(Vector2<T> & v,
42 Matrix22<T> const & m)
43 {
44 Vector2<T> vres(0);
45 vres[0] = v[0]*m[0] + v[1]*m[1];
46 vres[1] = v[0]*m[2] + v[1]*m[3];
47 v = vres;
48 return v;
49 }
51 template <typename T>
52 inline Vector2<T> operator*(Vector2<T> const & v,
53 Matrix22<T> const & m)
54 { return Vector2<T>(v) *= m; }
56 // Note: can't define Matrix *= Vector since the result is a Vector.
57 template <typename T>
58 inline Vector2<T> operator*(Matrix22<T> const & m,
59 Vector2<T> const & v)
60 {
61 Vector2<T> vres(0);
62 vres[0] = m[0]*v[0] + m[2]*v[1];
63 vres[1] = m[1]*v[0] + m[3]*v[1];
64 return vres;
65 }
67 ////////////////////////////////////////
68 // Vector3 * Matrix33
69 template <typename T>
70 inline Vector3<T>& operator*=(Vector3<T> & v,
71 Matrix33<T> const & m)
72 {
73 Vector3<T> vres(0);
74 vres[0] = v[0]*m[0] + v[1]*m[1] + v[2]*m[2];
75 vres[1] = v[0]*m[3] + v[1]*m[4] + v[2]*m[5];
76 vres[2] = v[0]*m[6] + v[1]*m[7] + v[2]*m[8];
77 v = vres;
78 return v;
79 }
81 template <typename T>
82 inline Vector3<T> operator*(Vector3<T> const & v,
83 Matrix33<T> const & m)
84 { return Vector3<T>(v) *= m; }
86 // Matrix * Vector
87 // Note: can't define Matrix *= Vector since the result is a Vector.
88 template <typename T>
89 inline Vector3<T> operator*(Matrix33<T> const & m,
90 Vector3<T> const & v)
91 {
92 Vector3<T> vres(0);
93 vres[0] = m[0]*v[0] + m[3]*v[1] + m[6]*v[2];
94 vres[1] = m[1]*v[0] + m[4]*v[1] + m[7]*v[2];
95 vres[2] = m[2]*v[0] + m[5]*v[1] + m[8]*v[2];
96 return vres;
97 }
99 ////////////////////////////////////////
100 // Vector4 * Matrix44
101 template <typename T>
102 inline Vector4<T>& operator*=(Vector4<T> & v,
103 Matrix44<T> const & m)
104 {
105 Vector4<T> vres(0);
106 vres[0] = v[0]*m[0] + v[1]*m[1] + v[2]*m[2] + v[3]*m[3];
107 vres[1] = v[0]*m[4] + v[1]*m[5] + v[2]*m[6] + v[3]*m[7];
108 vres[2] = v[0]*m[8] + v[1]*m[9] + v[2]*m[10] + v[3]*m[11];
109 vres[3] = v[0]*m[12] + v[1]*m[13] + v[2]*m[14] + v[3]*m[15];
110 v = vres;
111 return v;
112 }
114 template <typename T>
115 inline Vector4<T> operator*(Vector4<T> const & v,
116 Matrix44<T> const & m)
117 { return Vector4<T>(v) *= m; }
119 // Matrix * Vector
120 // Note: can't define Matrix *= Vector since the result is a Vector.
121 template <typename T>
122 inline Vector4<T> operator*(Matrix44<T> const & m,
123 Vector4<T> const & v)
124 {
125 Vector4<T> vres(0);
126 vres[0] = m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3];
127 vres[1] = m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3];
128 vres[2] = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3];
129 vres[3] = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3];
130 return vres;
131 }
133 //////////////////////////////////////////////////////////////////////////
135 template <typename T>
136 void get_rot_mat33(Matrix33<T> & m, float angle, Vector3<T> v);
138 template <typename T>
139 void get_transform_mat44(Matrix33<T> & m, float angle, Vector3<T> v, Vector3<T> o);
142 //////////////////////////////////////////////////////////////////////////
144 inline double deg_to_rad(double deg) { return deg * PI_DIV_180; };
145 inline double rad_to_deg(double rad) { return rad * INV_PI_DIV_180; };
147 } // namespace Math
149 } // namespace arda
151 ////////////////////////////////////////////////////////////////////////////////
152 template <typename T>
153 void arda::Math::get_rot_mat33(arda::Math::Matrix33<T> & m, float angle, arda::Math::Vector3<T> v)
154 {
155 // TODO Replace == comparision of floating point number!
156 if (0.0 == v.length())
157 return;
159 // TODO: I should also immediately return identity if angle is a multiple of 2*PI but I'm not
160 // yet sure how I should I check for that (taking into account floating point imprecision).
163 v.normalize();
165 float c = cos(angle);
166 float s = sin(angle);
167 float one_minus_c = 1.0f - c;
169 m.assign(
170 c + one_minus_c * v.x * v.x , one_minus_c * v.x * v.y + s * v.z , one_minus_c * v.x * v.z - s * v.y ,
171 one_minus_c * v.x * v.y - s * v.z , c + one_minus_c * v.y * v.y , one_minus_c * v.y * v.z + s * v.x ,
172 one_minus_c * v.x * v.z + s * v.y , one_minus_c * v.y * v.z - s * v.x , c + one_minus_c * v.z * v.z
173 );
174 }
176 ////////////////////////////////////////////////////////////////////////////////
177 template <typename T>
178 void arda::Math::get_transform_mat44(arda::Math::Matrix44<T> & m,
179 float angle, arda::Math::Vector3<T> v,
180 arda::Math::Vector3<T> p)
181 {
182 arda::Math::Matrix33f m33(0);
183 get_rot_mat33(m33, angle, v);
184 arda::Math::Vector3f p1 = m33 * p;
186 m[0] = m33[0];
187 m[1] = m33[1];
188 m[2] = m33[2];
189 m[3] = 0.0f;
191 m[4] = m33[3];
192 m[5] = m33[4];
193 m[6] = m33[5];
194 m[7] = 0.0f;
196 m[8] = m33[6];
197 m[9] = m33[7];
198 m[10] = m33[8];
199 m[11] = 0.0f;
201 m[12] = p.x - p1.x;
202 m[13] = p.y - p1.y;
203 m[14] = p.z - p1.z;
204 m[15] = 1.0f;
205 }
207 #endif