Mercurial > fife-parpg
comparison engine/core/util/math/matrix.h @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children | 90005975cdbb |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4a0efb7baf70 |
---|---|
1 /*************************************************************************** | |
2 * Copyright (C) 2005-2008 by the FIFE team * | |
3 * http://www.fifengine.de * | |
4 * This file is part of FIFE. * | |
5 * * | |
6 * FIFE is free software; you can redistribute it and/or modify * | |
7 * it under the terms of the GNU General Public License as published by * | |
8 * the Free Software Foundation; either version 2 of the License, or * | |
9 * (at your option) any later version. * | |
10 * * | |
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. See the * | |
14 * GNU General Public License for more details. * | |
15 * * | |
16 * You should have received a copy of the GNU General Public License * | |
17 * along with this program; if not, write to the * | |
18 * Free Software Foundation, Inc., * | |
19 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * | |
20 ***************************************************************************/ | |
21 /*************************************************************************** | |
22 * Includes some heavy copying from mathgl-pp project * | |
23 * (http://sourceforge.net/projects/mathgl-pp/) * | |
24 ***************************************************************************/ | |
25 | |
26 #ifndef FIFE_UTIL_MATRIX_H | |
27 #define FIFE_UTIL_MATRIX_H | |
28 | |
29 // Standard C++ library includes | |
30 #include <cassert> | |
31 #include <iostream> | |
32 | |
33 // Platform specific includes | |
34 | |
35 // 3rd party library includes | |
36 | |
37 // FIFE includes | |
38 // These includes are split up in two parts, separated by one empty line | |
39 // First block: files included from the FIFE root src directory | |
40 // Second block: files included from the same folder | |
41 #include "util/base/fife_stdint.h" | |
42 #include "util/structures/point.h" | |
43 | |
44 #include "fife_math.h" | |
45 | |
46 namespace FIFE { | |
47 | |
48 | |
49 /** Minimal matrix class to assist in view 3d calculations | |
50 */ | |
51 template <typename T> | |
52 class Matrix { | |
53 public: | |
54 Matrix<T>() {} | |
55 template <typename U> friend class Matrix; | |
56 template <typename U> Matrix<T>(const Matrix<U>& mat) { | |
57 memmove(m, mat.m, 16*sizeof(T)); | |
58 } | |
59 ~Matrix() {} | |
60 | |
61 /** Adjoint method inverse, constant time inversion implementation | |
62 */ | |
63 Matrix inverse() const { | |
64 Matrix ret(adjoint()); | |
65 | |
66 T determinant = m0*ret[0] + m1*ret[4] + m2*ret[8] + m3*ret[12]; | |
67 assert(determinant!=0 && "Singular matrix has no inverse"); | |
68 | |
69 ret/=determinant; | |
70 return ret; | |
71 } | |
72 | |
73 /** Divide this matrix by a scalar | |
74 */ | |
75 inline Matrix& operator/= (T val) { | |
76 for (register unsigned i = 0; i < 16; ++i) | |
77 m[i] /= val; | |
78 return *this; | |
79 } | |
80 | |
81 /** Get the adjoint matrix | |
82 */ | |
83 Matrix adjoint() const { | |
84 Matrix ret; | |
85 | |
86 ret[0] = cofactorm0(); | |
87 ret[1] = -cofactorm4(); | |
88 ret[2] = cofactorm8(); | |
89 ret[3] = -cofactorm12(); | |
90 | |
91 ret[4] = -cofactorm1(); | |
92 ret[5] = cofactorm5(); | |
93 ret[6] = -cofactorm9(); | |
94 ret[7] = cofactorm13(); | |
95 | |
96 ret[8] = cofactorm2(); | |
97 ret[9] = -cofactorm6(); | |
98 ret[10] = cofactorm10(); | |
99 ret[11] = -cofactorm14(); | |
100 | |
101 ret[12] = -cofactorm3(); | |
102 ret[13] = cofactorm7(); | |
103 ret[14] = -cofactorm11(); | |
104 ret[15] = cofactorm15(); | |
105 | |
106 return ret; | |
107 } | |
108 | |
109 | |
110 /** Make this a rotation matrix | |
111 */ | |
112 | |
113 inline Matrix& loadRotate(T angle, T x, T y, T z) { | |
114 register T magSqr = x*x + y*y + z*z; | |
115 if (magSqr != 1.0) { | |
116 register T mag = sqrt(magSqr); | |
117 x/=mag; | |
118 y/=mag; | |
119 z/=mag; | |
120 } | |
121 T c = cos(angle*M_PI/180); | |
122 T s = sin(angle*M_PI/180); | |
123 m0 = x*x*(1-c)+c; | |
124 m1 = y*x*(1-c)+z*s; | |
125 m2 = z*x*(1-c)-y*s; | |
126 m3 = 0; | |
127 | |
128 m4 = x*y*(1-c)-z*s; | |
129 m5 = y*y*(1-c)+c; | |
130 m6 = z*y*(1-c)+x*s; | |
131 m7 = 0; | |
132 | |
133 m8 = x*z*(1-c)+y*s; | |
134 m9 = y*z*(1-c)-x*s; | |
135 m10 = z*z*(1-c)+c; | |
136 m11 = 0; | |
137 | |
138 m12 = 0; | |
139 m13 = 0; | |
140 m14 = 0; | |
141 m15 = 1; | |
142 | |
143 return *this; | |
144 } | |
145 | |
146 /** Apply scale into this matrix | |
147 */ | |
148 inline Matrix& applyScale(T x, T y, T z) { | |
149 static Matrix<T> temp; | |
150 temp.loadScale(x,y,z); | |
151 *this = temp.mult4by4(*this); | |
152 return *this; | |
153 } | |
154 | |
155 /** Make this a scale matrix | |
156 */ | |
157 inline Matrix& loadScale(T x, T y, T z = 1) { | |
158 m0 = x; | |
159 m4 = 0; | |
160 m8 = 0; | |
161 m12 = 0; | |
162 m1 = 0; | |
163 m5 = y; | |
164 m9 = 0; | |
165 m13 = 0; | |
166 m2 = 0; | |
167 m6 = 0; | |
168 m10 = z; | |
169 m14 = 0; | |
170 m3 = 0; | |
171 m7 = 0; | |
172 m11 = 0; | |
173 m15 = 1; | |
174 | |
175 return *this; | |
176 } | |
177 | |
178 /** Apply translation into this matrix | |
179 */ | |
180 inline Matrix& applyTranslate(T x, T y, T z) { | |
181 static Matrix<T> temp; | |
182 temp.loadTranslate(x,y,z); | |
183 *this = temp.mult4by4(*this); | |
184 return *this; | |
185 } | |
186 | |
187 /** Make this a translation matrix | |
188 */ | |
189 inline Matrix& loadTranslate( const T x, const T y, const T z) { | |
190 m0 = 1; | |
191 m4 = 0; | |
192 m8 = 0; | |
193 m12 = x; | |
194 m1 = 0; | |
195 m5 = 1; | |
196 m9 = 0; | |
197 m13 = y; | |
198 m2 = 0; | |
199 m6 = 0; | |
200 m10 = 1; | |
201 m14 = z; | |
202 m3 = 0; | |
203 m7 = 0; | |
204 m11 = 0; | |
205 m15 = 1; | |
206 | |
207 return *this; | |
208 } | |
209 | |
210 /** Transform given point using this matrix | |
211 */ | |
212 inline PointType3D<T> operator* (const PointType3D<T>& vec) { | |
213 PointType3D<T> ret(T(0)); | |
214 for (register unsigned j = 0; j < 3; ++j) | |
215 for (register unsigned i = 0; i < 3; ++i) | |
216 ret.val[j] += vec.val[i]*m[j+i*4]; //scale and rotate disregarding w scaling | |
217 | |
218 for (register unsigned i = 0; i < 3; ++i) | |
219 ret.val[i] += m[i+3*4]; //translate | |
220 | |
221 //do w scaling | |
222 T w = m[15]; | |
223 for (register unsigned i = 0; i < 3; ++i) | |
224 w += vec.val[i]*m[3+i*4]; | |
225 | |
226 register T resip = 1/w; | |
227 | |
228 for (register unsigned i = 0; i < 3; ++i) | |
229 ret[i] *= resip; | |
230 | |
231 return ret; | |
232 } | |
233 | |
234 /** Direct access to the matrix elements, just remember they are in column major format!! | |
235 */ | |
236 inline T& operator[] (int ind) { | |
237 assert(ind > -1 && ind < 16); | |
238 return m[ind]; | |
239 } | |
240 | |
241 /** Apply the matrix dot product to this matrix | |
242 */ | |
243 inline Matrix& mult3by3(const Matrix& mat) { | |
244 Matrix temp(*this); | |
245 m0 = temp.m0*mat.m0+temp.m4*mat.m1+temp.m8*mat.m2; | |
246 m4 = temp.m0*mat.m4+temp.m4*mat.m5+temp.m8*mat.m6; | |
247 m8 = temp.m0*mat.m8+temp.m4*mat.m9+temp.m8*mat.m10; | |
248 | |
249 m1 = temp.m1*mat.m0+temp.m5*mat.m1+temp.m9*mat.m2; | |
250 m5 = temp.m1*mat.m4+temp.m5*mat.m5+temp.m9*mat.m6; | |
251 m9 = temp.m1*mat.m8+temp.m5*mat.m9+temp.m9*mat.m10; | |
252 | |
253 m2 = temp.m2*mat.m0+temp.m6*mat.m1+temp.m10*mat.m2; | |
254 m6 = temp.m2*mat.m4+temp.m6*mat.m5+temp.m10*mat.m6; | |
255 m10 = temp.m2*mat.m8+temp.m6*mat.m9+temp.m10*mat.m10; | |
256 | |
257 m3 = temp.m3*mat.m0+temp.m7*mat.m1+temp.m11*mat.m2; | |
258 m7 = temp.m3*mat.m4+temp.m7*mat.m5+temp.m11*mat.m6; | |
259 m11 = temp.m3*mat.m8+temp.m7*mat.m9+temp.m11*mat.m10; | |
260 return *this; | |
261 } | |
262 | |
263 /** this->Rmult4by4(temp) == [temp] X [*this] **/ | |
264 /** also equal to temp->mult4by4(*this) **/ | |
265 inline Matrix<T>& Rmult4by4(const Matrix<T>& mat) { | |
266 Matrix temp(*this); | |
267 | |
268 m0 = mat.m0*temp.m0+mat.m4*temp.m1+mat.m8*temp.m2+mat.m12*temp.m3; | |
269 m4 = mat.m0*temp.m4+mat.m4*temp.m5+mat.m8*temp.m6+mat.m12*temp.m7; | |
270 m8 = mat.m0*temp.m8+mat.m4*temp.m9+mat.m8*temp.m10+mat.m12*temp.m11; | |
271 m12 = mat.m0*temp.m12+mat.m4*temp.m13+mat.m8*temp.m14+mat.m12*temp.m15; | |
272 | |
273 m1 = mat.m1*temp.m0 + mat.m5*temp.m1 + mat.m9*temp.m2+mat.m13*temp.m3; | |
274 m5 = mat.m1*temp.m4 + mat.m5*temp.m5 + mat.m9*temp.m6+mat.m13*temp.m7; | |
275 m9 = mat.m1*temp.m8 + mat.m5*temp.m9 + mat.m9*temp.m10+mat.m13*temp.m11; | |
276 m13 = mat.m1*temp.m12+ mat.m5*temp.m13 + mat.m9*temp.m14+mat.m13*temp.m15; | |
277 | |
278 m2 = mat.m2*temp.m0+mat.m6*temp.m1+mat.m10*temp.m2+mat.m14*temp.m3; | |
279 m6 = mat.m2*temp.m4+mat.m6*temp.m5+mat.m10*temp.m6+mat.m14*temp.m7; | |
280 m10 = mat.m2*temp.m8+mat.m6*temp.m9+mat.m10*temp.m10+mat.m14*temp.m11; | |
281 m14 = mat.m2*temp.m12+mat.m6*temp.m13+mat.m10*temp.m14+mat.m14*temp.m15; | |
282 | |
283 m3 = mat.m3*temp.m0+mat.m7*temp.m1+mat.m11*temp.m2+mat.m15*temp.m3; | |
284 m7 = mat.m3*temp.m4+mat.m7*temp.m5+mat.m11*temp.m6+mat.m15*temp.m7; | |
285 m11 = mat.m3*temp.m8+mat.m7*temp.m9+mat.m11*temp.m10+mat.m15*temp.m11; | |
286 m15 = mat.m3*temp.m12+mat.m7*temp.m13+mat.m11*temp.m14+mat.m15*temp.m15; | |
287 return *this; | |
288 } | |
289 | |
290 | |
291 inline Matrix<T>& mult4by4(const Matrix<T>& mat) { | |
292 Matrix temp(*this); | |
293 | |
294 m0 = temp.m0*mat.m0+temp.m4*mat.m1+temp.m8*mat.m2+temp.m12*mat.m3; | |
295 m4 = temp.m0*mat.m4+temp.m4*mat.m5+temp.m8*mat.m6+temp.m12*mat.m7; | |
296 m8 = temp.m0*mat.m8+temp.m4*mat.m9+temp.m8*mat.m10+temp.m12*mat.m11; | |
297 m12 = temp.m0*mat.m12+temp.m4*mat.m13+temp.m8*mat.m14+temp.m12*mat.m15; | |
298 | |
299 m1 = temp.m1*mat.m0 + temp.m5*mat.m1 + temp.m9*mat.m2+temp.m13*mat.m3; | |
300 m5 = temp.m1*mat.m4 + temp.m5*mat.m5 + temp.m9*mat.m6+temp.m13*mat.m7; | |
301 m9 = temp.m1*mat.m8 + temp.m5*mat.m9 + temp.m9*mat.m10+temp.m13*mat.m11; | |
302 m13 = temp.m1*mat.m12+ temp.m5*mat.m13 + temp.m9*mat.m14+temp.m13*mat.m15; | |
303 | |
304 m2 = temp.m2*mat.m0+temp.m6*mat.m1+temp.m10*mat.m2+temp.m14*mat.m3; | |
305 m6 = temp.m2*mat.m4+temp.m6*mat.m5+temp.m10*mat.m6+temp.m14*mat.m7; | |
306 m10 = temp.m2*mat.m8+temp.m6*mat.m9+temp.m10*mat.m10+temp.m14*mat.m11; | |
307 m14 = temp.m2*mat.m12+temp.m6*mat.m13+temp.m10*mat.m14+temp.m14*mat.m15; | |
308 | |
309 m3 = temp.m3*mat.m0+temp.m7*mat.m1+temp.m11*mat.m2+temp.m15*mat.m3; | |
310 m7 = temp.m3*mat.m4+temp.m7*mat.m5+temp.m11*mat.m6+temp.m15*mat.m7; | |
311 m11 = temp.m3*mat.m8+temp.m7*mat.m9+temp.m11*mat.m10+temp.m15*mat.m11; | |
312 m15 = temp.m3*mat.m12+temp.m7*mat.m13+temp.m11*mat.m14+temp.m15*mat.m15; | |
313 return *this; | |
314 } | |
315 | |
316 Matrix& applyRotate(T angle, T x, T y, T z) { | |
317 static Matrix<T> temp; | |
318 temp.loadRotate(angle,x,y,z); | |
319 *this = temp.mult4by4(*this); | |
320 return *this; | |
321 } | |
322 | |
323 | |
324 private: | |
325 #define cofactor_maker(f1,mj1,mi1, f2,mj2,mi2, f3,mj3,mi3) \ | |
326 f1*(mj1*mi1-mj2*mi3) + f2*(mj2*mi2-mj3*mi1) + f3*(mj3*mi3-mj1*mi2) | |
327 | |
328 inline T cofactorm0() const { | |
329 return cofactor_maker(m5,m10,m15, m6,m11,m13, m7,m9,m14); | |
330 } | |
331 inline T cofactorm1() const { | |
332 return cofactor_maker(m6,m11,m12, m7,m8,m14, m4,m10,m15); | |
333 } | |
334 inline T cofactorm2() const { | |
335 return cofactor_maker(m7,m8,m13, m4,m9,m15, m5,m11,m12); | |
336 } | |
337 inline T cofactorm3() const { | |
338 return cofactor_maker(m4,m9,m14, m5,m10,m12, m6,m8,m13); | |
339 } | |
340 inline T cofactorm4() const { | |
341 return cofactor_maker(m9,m14,m3, m10,m15,m1, m11,m13,m2); | |
342 } | |
343 inline T cofactorm5() const { | |
344 return cofactor_maker(m10,m15,m0, m11,m12,m2, m8,m14,m3); | |
345 } | |
346 inline T cofactorm6() const { | |
347 return cofactor_maker(m11,m12,m1, m8,m13,m3, m9,m15,m0); | |
348 } | |
349 inline T cofactorm7() const { | |
350 return cofactor_maker(m8,m13,m2, m9,m14,m0, m10,m12,m1); | |
351 } | |
352 inline T cofactorm8() const { | |
353 return cofactor_maker(m13,m2,m7, m14,m3,m5, m15,m1,m6); | |
354 } | |
355 inline T cofactorm9() const { | |
356 return cofactor_maker(m14,m13,m4, m15,m0,m6, m12,m2,m7); | |
357 } | |
358 inline T cofactorm10() const { | |
359 return cofactor_maker(m15,m0,m5, m12,m1,m7, m13,m3,m4); | |
360 } | |
361 inline T cofactorm11() const { | |
362 return cofactor_maker(m12,m1,m6, m13,m2,m4, m14,m0,m5); | |
363 } | |
364 inline T cofactorm12() const { | |
365 return cofactor_maker(m1,m6,m11, m2,m7,m9, m3,m5,m10); | |
366 } | |
367 inline T cofactorm13() const { | |
368 return cofactor_maker(m2,m7,m8, m3,m4,m10, m10,m6,m11); | |
369 } | |
370 inline T cofactorm14() const { | |
371 return cofactor_maker(m3,m4,m9, m0,m5,m11, m1,m7,m8); | |
372 } | |
373 inline T cofactorm15() const { | |
374 return cofactor_maker(m0,m5,m10, m1,m6,m8, m2,m4,m9); | |
375 } | |
376 | |
377 union { | |
378 T m[16]; | |
379 struct { | |
380 T m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,m13,m14,m15; | |
381 }; | |
382 }; | |
383 }; | |
384 | |
385 typedef Matrix<double> DoubleMatrix; | |
386 typedef Matrix<int> IntMatrix; | |
387 | |
388 /** Print coords of the Matrix to a stream | |
389 */ | |
390 template<typename T> | |
391 std::ostream& operator<<(std::ostream& os, Matrix<T>& m) { | |
392 return os << "\n|" << m[0] << "," << m[4] << "," << m[8] << "," << m[12] << "|\n" << \ | |
393 "|" << m[1] << "," << m[5] << "," << m[9] << "," << m[13] << "|\n" << \ | |
394 "|" << m[2] << "," << m[6] << "," << m[10] << "," << m[14] << "|\n" << \ | |
395 "|" << m[3] << "," << m[7] << "," << m[11] << "," << m[15] << "|\n"; | |
396 } | |
397 | |
398 | |
399 } | |
400 | |
401 #endif |