1 //
2 // Copyright (c) 2010 Linaro Limited
3 //
4 // All rights reserved. This program and the accompanying materials
5 // are made available under the terms of the MIT License which accompanies
6 // this distribution, and is available at
7 // http://www.opensource.org/licenses/mit-license.php
8 //
9 // Contributors:
10 // Jesse Barker - original implementation.
11 //
12 #ifndef MAT_H_
13 #define MAT_H_
14 #include <stdexcept>
15 #include <iostream>
16 #include <iomanip>
17 #include "vec.h"
18 #ifndef USE_EXCEPTIONS
19 // If we're not throwing exceptions, we'll need the logger to make sure the
20 // caller is informed of errors.
21 #include "log.h"
22 #endif // USE_EXCEPTIONS
23
24 namespace LibMatrix
25 {
26 // Proxy class for providing the functionality of a doubly-dimensioned array
27 // representation of matrices. Each matrix class defines its operator[]
28 // to return an ArrayProxy. The ArrayProxy then returns the appropriate item
29 // from its operator[].
30 template<typename T, unsigned int dimension>
31 class ArrayProxy
32 {
33 public:
ArrayProxy(T * data)34 ArrayProxy(T* data) { data_ = data; }
~ArrayProxy()35 ~ArrayProxy() { data_ = 0; }
36 T& operator[](int index)
37 {
38 return data_[index * dimension];
39 }
40 const T& operator[](int index) const
41 {
42 return data_[index * dimension];
43 }
44 private:
45 T* data_;
46 };
47
48
49 // Programming interfaces to all matrix objects are represented row-centric
50 // (i.e. C/C++ style references to the data appear as matrix[row][column]).
51 // However, the internal data representation is column-major, so when using
52 // the raw data access member to treat the data as a singly-dimensioned array,
53 // it does not have to be transposed.
54 //
55 // A template class for creating, managing and operating on a 2x2 matrix
56 // of any type you like (intended for built-in types, but as long as it
57 // supports the basic arithmetic and assignment operators, any type should
58 // work).
59 template<typename T>
60 class tmat2
61 {
62 public:
tmat2()63 tmat2()
64 {
65 setIdentity();
66 }
tmat2(const tmat2 & m)67 tmat2(const tmat2& m)
68 {
69 m_[0] = m.m_[0];
70 m_[1] = m.m_[1];
71 m_[2] = m.m_[2];
72 m_[3] = m.m_[3];
73 }
tmat2(const T & c0r0,const T & c0r1,const T & c1r0,const T & c1r1)74 tmat2(const T& c0r0, const T& c0r1, const T& c1r0, const T& c1r1)
75 {
76 m_[0] = c0r0;
77 m_[1] = c0r1;
78 m_[2] = c1r0;
79 m_[3] = c1r1;
80 }
~tmat2()81 ~tmat2() {}
82
83 // Reset this to the identity matrix.
setIdentity()84 void setIdentity()
85 {
86 m_[0] = 1;
87 m_[1] = 0;
88 m_[2] = 0;
89 m_[3] = 1;
90 }
91
92 // Transpose this. Return a reference to this.
transpose()93 tmat2& transpose()
94 {
95 T tmp_val = m_[1];
96 m_[1] = m_[2];
97 m_[2] = tmp_val;
98 return *this;
99 }
100
101 // Compute the determinant of this and return it.
determinant()102 T determinant()
103 {
104 return (m_[0] * m_[3]) - (m_[2] * m_[1]);
105 }
106
107 // Invert this. Return a reference to this.
108 //
109 // NOTE: If this is non-invertible, we will
110 // throw to avoid undefined behavior.
inverse()111 tmat2& inverse()
112 {
113 T d(determinant());
114 if (d == static_cast<T>(0))
115 {
116 #ifdef USE_EXCEPTIONS
117 throw std::runtime_error("Matrix is noninvertible!!!!");
118 #else // !USE_EXCEPTIONS
119 Log::error("Matrix is noninvertible!!!!\n");
120 return *this;
121 #endif // USE_EXCEPTIONS
122 }
123 T c0r0(m_[3] / d);
124 T c0r1(-m_[1] / d);
125 T c1r0(-m_[2] / d);
126 T c1r1(m_[0] / d);
127 m_[0] = c0r0;
128 m_[1] = c0r1;
129 m_[2] = c1r0;
130 m_[3] = c1r1;
131 return *this;
132 }
133
134 // Print the elements of the matrix to standard out.
135 // Really only useful for debug and test.
print()136 void print() const
137 {
138 static const int precision(6);
139 // row 0
140 std::cout << "| ";
141 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[0];
142 std::cout << " ";
143 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[2];
144 std::cout << " |" << std::endl;
145 // row 1
146 std::cout << "| ";
147 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[1];
148 std::cout << " ";
149 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[3];
150 std::cout << " |" << std::endl;
151 }
152
153 // Allow raw data access for API calls and the like.
154 // For example, it is valid to pass a tmat2<float> into a call to
155 // the OpenGL command "glUniformMatrix2fv()".
156 operator const T*() const { return &m_[0];}
157
158 // Test if 'rhs' is equal to this.
159 bool operator==(const tmat2& rhs) const
160 {
161 return m_[0] == rhs.m_[0] &&
162 m_[1] == rhs.m_[1] &&
163 m_[2] == rhs.m_[2] &&
164 m_[3] == rhs.m_[3];
165 }
166
167 // Test if 'rhs' is not equal to this.
168 bool operator!=(const tmat2& rhs) const
169 {
170 return !(*this == rhs);
171 }
172
173 // A direct assignment of 'rhs' to this. Return a reference to this.
174 tmat2& operator=(const tmat2& rhs)
175 {
176 if (this != &rhs)
177 {
178 m_[0] = rhs.m_[0];
179 m_[1] = rhs.m_[1];
180 m_[2] = rhs.m_[2];
181 m_[3] = rhs.m_[3];
182 }
183 return *this;
184 }
185
186 // Add another matrix to this. Return a reference to this.
187 tmat2& operator+=(const tmat2& rhs)
188 {
189 m_[0] += rhs.m_[0];
190 m_[1] += rhs.m_[1];
191 m_[2] += rhs.m_[2];
192 m_[3] += rhs.m_[3];
193 return *this;
194 }
195
196 // Add another matrix to a copy of this. Return the copy.
197 const tmat2 operator+(const tmat2& rhs)
198 {
199 return tmat2(*this) += rhs;
200 }
201
202 // Subtract another matrix from this. Return a reference to this.
203 tmat2& operator-=(const tmat2& rhs)
204 {
205 m_[0] -= rhs.m_[0];
206 m_[1] -= rhs.m_[1];
207 m_[2] -= rhs.m_[2];
208 m_[3] -= rhs.m_[3];
209 return *this;
210 }
211
212 // Subtract another matrix from a copy of this. Return the copy.
213 const tmat2 operator-(const tmat2& rhs)
214 {
215 return tmat2(*this) += rhs;
216 }
217
218 // Multiply this by another matrix. Return a reference to this.
219 tmat2& operator*=(const tmat2& rhs)
220 {
221 T c0r0((m_[0] * rhs.m_[0]) + (m_[2] * rhs.m_[1]));
222 T c0r1((m_[1] * rhs.m_[0]) + (m_[3] * rhs.m_[1]));
223 T c1r0((m_[0] * rhs.m_[2]) + (m_[2] * rhs.m_[3]));
224 T c1r1((m_[1] * rhs.m_[2]) + (m_[3] * rhs.m_[3]));
225 m_[0] = c0r0;
226 m_[1] = c0r1;
227 m_[2] = c1r0;
228 m_[3] = c1r1;
229 return *this;
230 }
231
232 // Multiply a copy of this by another matrix. Return the copy.
233 const tmat2 operator*(const tmat2& rhs)
234 {
235 return tmat2(*this) *= rhs;
236 }
237
238 // Multiply this by a scalar. Return a reference to this.
239 tmat2& operator*=(const T& rhs)
240 {
241 m_[0] *= rhs;
242 m_[1] *= rhs;
243 m_[2] *= rhs;
244 m_[3] *= rhs;
245 return *this;
246 }
247
248 // Multiply a copy of this by a scalar. Return the copy.
249 const tmat2 operator*(const T& rhs)
250 {
251 return tmat2(*this) *= rhs;
252 }
253
254 // Divide this by a scalar. Return a reference to this.
255 tmat2& operator/=(const T& rhs)
256 {
257 m_[0] /= rhs;
258 m_[1] /= rhs;
259 m_[2] /= rhs;
260 m_[3] /= rhs;
261 return *this;
262 }
263
264 // Divide a copy of this by a scalar. Return the copy.
265 const tmat2 operator/(const T& rhs)
266 {
267 return tmat2(*this) /= rhs;
268 }
269
270 // Use an instance of the ArrayProxy class to support double-indexed
271 // references to a matrix (i.e., m[1][1]). See comments above the
272 // ArrayProxy definition for more details.
273 ArrayProxy<T, 2> operator[](int index)
274 {
275 return ArrayProxy<T, 2>(&m_[index]);
276 }
277 const ArrayProxy<T, 2> operator[](int index) const
278 {
279 return ArrayProxy<T, 2>(const_cast<T*>(&m_[index]));
280 }
281
282 private:
283 T m_[4];
284 };
285
286 // Multiply a scalar and a matrix just like the member operator, but allow
287 // the scalar to be the left-hand operand.
288 template<typename T>
289 const tmat2<T> operator*(const T& lhs, const tmat2<T>& rhs)
290 {
291 return tmat2<T>(rhs) * lhs;
292 }
293
294 // Multiply a copy of a vector and a matrix (matrix is right-hand operand).
295 // Return the copy.
296 template<typename T>
297 const tvec2<T> operator*(const tvec2<T>& lhs, const tmat2<T>& rhs)
298 {
299 T x((lhs.x() * rhs[0][0]) + (lhs.y() * rhs[1][0]));
300 T y((lhs.x() * rhs[0][1]) + (lhs.y() * rhs[1][1]));
301 return tvec2<T>(x,y);
302 }
303
304 // Multiply a copy of a vector and a matrix (matrix is left-hand operand).
305 // Return the copy.
306 template<typename T>
307 const tvec2<T> operator*(const tmat2<T>& lhs, const tvec2<T>& rhs)
308 {
309 T x((lhs[0][0] * rhs.x()) + (lhs[0][1] * rhs.y()));
310 T y((lhs[1][0] * rhs.x()) + (lhs[1][1] * rhs.y()));
311 return tvec2<T>(x, y);
312 }
313
314 // Compute the outer product of two vectors. Return the resultant matrix.
315 template<typename T>
outer(const tvec2<T> & a,const tvec2<T> & b)316 const tmat2<T> outer(const tvec2<T>& a, const tvec2<T>& b)
317 {
318 tmat2<T> product;
319 product[0][0] = a.x() * b.x();
320 product[0][1] = a.x() * b.y();
321 product[1][0] = a.y() * b.x();
322 product[1][1] = a.y() * b.y();
323 return product;
324 }
325
326 // A template class for creating, managing and operating on a 3x3 matrix
327 // of any type you like (intended for built-in types, but as long as it
328 // supports the basic arithmetic and assignment operators, any type should
329 // work).
330 template<typename T>
331 class tmat3
332 {
333 public:
tmat3()334 tmat3()
335 {
336 setIdentity();
337 }
tmat3(const tmat3 & m)338 tmat3(const tmat3& m)
339 {
340 m_[0] = m.m_[0];
341 m_[1] = m.m_[1];
342 m_[2] = m.m_[2];
343 m_[3] = m.m_[3];
344 m_[4] = m.m_[4];
345 m_[5] = m.m_[5];
346 m_[6] = m.m_[6];
347 m_[7] = m.m_[7];
348 m_[8] = m.m_[8];
349 }
tmat3(const T & c0r0,const T & c0r1,const T & c0r2,const T & c1r0,const T & c1r1,const T & c1r2,const T & c2r0,const T & c2r1,const T & c2r2)350 tmat3(const T& c0r0, const T& c0r1, const T& c0r2,
351 const T& c1r0, const T& c1r1, const T& c1r2,
352 const T& c2r0, const T& c2r1, const T& c2r2)
353 {
354 m_[0] = c0r0;
355 m_[1] = c0r1;
356 m_[2] = c0r2;
357 m_[3] = c1r0;
358 m_[4] = c1r1;
359 m_[5] = c1r2;
360 m_[6] = c2r0;
361 m_[7] = c2r1;
362 m_[8] = c2r2;
363 }
~tmat3()364 ~tmat3() {}
365
366 // Reset this to the identity matrix.
setIdentity()367 void setIdentity()
368 {
369 m_[0] = 1;
370 m_[1] = 0;
371 m_[2] = 0;
372 m_[3] = 0;
373 m_[4] = 1;
374 m_[5] = 0;
375 m_[6] = 0;
376 m_[7] = 0;
377 m_[8] = 1;
378 }
379
380 // Transpose this. Return a reference to this.
transpose()381 tmat3& transpose()
382 {
383 T tmp_val = m_[1];
384 m_[1] = m_[3];
385 m_[3] = tmp_val;
386 tmp_val = m_[2];
387 m_[2] = m_[6];
388 m_[6] = tmp_val;
389 tmp_val = m_[5];
390 m_[5] = m_[7];
391 m_[7] = tmp_val;
392 return *this;
393 }
394
395 // Compute the determinant of this and return it.
determinant()396 T determinant()
397 {
398 tmat2<T> minor0(m_[4], m_[5], m_[7], m_[8]);
399 tmat2<T> minor3(m_[1], m_[2], m_[7], m_[8]);
400 tmat2<T> minor6(m_[1], m_[2], m_[4], m_[5]);
401 return (m_[0] * minor0.determinant()) -
402 (m_[3] * minor3.determinant()) +
403 (m_[6] * minor6.determinant());
404 }
405
406 // Invert this. Return a reference to this.
407 //
408 // NOTE: If this is non-invertible, we will
409 // throw to avoid undefined behavior.
inverse()410 tmat3& inverse()
411 {
412 T d(determinant());
413 if (d == static_cast<T>(0))
414 {
415 #ifdef USE_EXCEPTIONS
416 throw std::runtime_error("Matrix is noninvertible!!!!");
417 #else // !USE_EXCEPTIONS
418 Log::error("Matrix is noninvertible!!!!\n");
419 return *this;
420 #endif // USE_EXCEPTIONS
421 }
422 tmat2<T> minor0(m_[4], m_[5], m_[7], m_[8]);
423 tmat2<T> minor1(m_[7], m_[8], m_[1], m_[2]);
424 tmat2<T> minor2(m_[1], m_[2], m_[4], m_[5]);
425 tmat2<T> minor3(m_[6], m_[8], m_[3], m_[5]);
426 tmat2<T> minor4(m_[0], m_[2], m_[6], m_[8]);
427 tmat2<T> minor5(m_[3], m_[5], m_[0], m_[2]);
428 tmat2<T> minor6(m_[3], m_[4], m_[6], m_[7]);
429 tmat2<T> minor7(m_[6], m_[7], m_[0], m_[1]);
430 tmat2<T> minor8(m_[0], m_[1], m_[3], m_[4]);
431 m_[0] = minor0.determinant() / d;
432 m_[1] = minor1.determinant() / d;
433 m_[2] = minor2.determinant() / d;
434 m_[3] = minor3.determinant() / d;
435 m_[4] = minor4.determinant() / d;
436 m_[5] = minor5.determinant() / d;
437 m_[6] = minor6.determinant() / d;
438 m_[7] = minor7.determinant() / d;
439 m_[8] = minor8.determinant() / d;
440 return *this;
441 }
442
443 // Print the elements of the matrix to standard out.
444 // Really only useful for debug and test.
print()445 void print() const
446 {
447 static const int precision(6);
448 // row 0
449 std::cout << "| ";
450 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[0];
451 std::cout << " ";
452 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[3];
453 std::cout << " ";
454 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[6];
455 std::cout << " |" << std::endl;
456 // row 1
457 std::cout << "| ";
458 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[1];
459 std::cout << " ";
460 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[4];
461 std::cout << " ";
462 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[7];
463 std::cout << " |" << std::endl;
464 // row 2
465 std::cout << "| ";
466 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[2];
467 std::cout << " ";
468 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[5];
469 std::cout << " ";
470 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[8];
471 std::cout << " |" << std::endl;
472 }
473
474 // Allow raw data access for API calls and the like.
475 // For example, it is valid to pass a tmat3<float> into a call to
476 // the OpenGL command "glUniformMatrix3fv()".
477 operator const T*() const { return &m_[0];}
478
479 // Test if 'rhs' is equal to this.
480 bool operator==(const tmat3& rhs) const
481 {
482 return m_[0] == rhs.m_[0] &&
483 m_[1] == rhs.m_[1] &&
484 m_[2] == rhs.m_[2] &&
485 m_[3] == rhs.m_[3] &&
486 m_[4] == rhs.m_[4] &&
487 m_[5] == rhs.m_[5] &&
488 m_[6] == rhs.m_[6] &&
489 m_[7] == rhs.m_[7] &&
490 m_[8] == rhs.m_[8];
491 }
492
493 // Test if 'rhs' is not equal to this.
494 bool operator!=(const tmat3& rhs) const
495 {
496 return !(*this == rhs);
497 }
498
499 // A direct assignment of 'rhs' to this. Return a reference to this.
500 tmat3& operator=(const tmat3& rhs)
501 {
502 if (this != &rhs)
503 {
504 m_[0] = rhs.m_[0];
505 m_[1] = rhs.m_[1];
506 m_[2] = rhs.m_[2];
507 m_[3] = rhs.m_[3];
508 m_[4] = rhs.m_[4];
509 m_[5] = rhs.m_[5];
510 m_[6] = rhs.m_[6];
511 m_[7] = rhs.m_[7];
512 m_[8] = rhs.m_[8];
513 }
514 return *this;
515 }
516
517 // Add another matrix to this. Return a reference to this.
518 tmat3& operator+=(const tmat3& rhs)
519 {
520 m_[0] += rhs.m_[0];
521 m_[1] += rhs.m_[1];
522 m_[2] += rhs.m_[2];
523 m_[3] += rhs.m_[3];
524 m_[4] += rhs.m_[4];
525 m_[5] += rhs.m_[5];
526 m_[6] += rhs.m_[6];
527 m_[7] += rhs.m_[7];
528 m_[8] += rhs.m_[8];
529 return *this;
530 }
531
532 // Add another matrix to a copy of this. Return the copy.
533 const tmat3 operator+(const tmat3& rhs)
534 {
535 return tmat3(*this) += rhs;
536 }
537
538 // Subtract another matrix from this. Return a reference to this.
539 tmat3& operator-=(const tmat3& rhs)
540 {
541 m_[0] -= rhs.m_[0];
542 m_[1] -= rhs.m_[1];
543 m_[2] -= rhs.m_[2];
544 m_[3] -= rhs.m_[3];
545 m_[4] -= rhs.m_[4];
546 m_[5] -= rhs.m_[5];
547 m_[6] -= rhs.m_[6];
548 m_[7] -= rhs.m_[7];
549 m_[8] -= rhs.m_[8];
550 return *this;
551 }
552
553 // Subtract another matrix from a copy of this. Return the copy.
554 const tmat3 operator-(const tmat3& rhs)
555 {
556 return tmat3(*this) -= rhs;
557 }
558
559 // Multiply this by another matrix. Return a reference to this.
560 tmat3& operator*=(const tmat3& rhs)
561 {
562 T c0r0((m_[0] * rhs.m_[0]) + (m_[3] * rhs.m_[1]) + (m_[6] * rhs.m_[2]));
563 T c0r1((m_[1] * rhs.m_[0]) + (m_[4] * rhs.m_[1]) + (m_[7] * rhs.m_[2]));
564 T c0r2((m_[2] * rhs.m_[0]) + (m_[5] * rhs.m_[1]) + (m_[8] * rhs.m_[2]));
565 T c1r0((m_[0] * rhs.m_[3]) + (m_[3] * rhs.m_[4]) + (m_[6] * rhs.m_[5]));
566 T c1r1((m_[1] * rhs.m_[3]) + (m_[4] * rhs.m_[4]) + (m_[7] * rhs.m_[5]));
567 T c1r2((m_[2] * rhs.m_[3]) + (m_[5] * rhs.m_[4]) + (m_[8] * rhs.m_[5]));
568 T c2r0((m_[0] * rhs.m_[6]) + (m_[3] * rhs.m_[7]) + (m_[6] * rhs.m_[8]));
569 T c2r1((m_[1] * rhs.m_[6]) + (m_[4] * rhs.m_[7]) + (m_[7] * rhs.m_[8]));
570 T c2r2((m_[2] * rhs.m_[6]) + (m_[5] * rhs.m_[7]) + (m_[8] * rhs.m_[8]));
571 m_[0] = c0r0;
572 m_[1] = c0r1;
573 m_[2] = c0r2;
574 m_[3] = c1r0;
575 m_[4] = c1r1;
576 m_[5] = c1r2;
577 m_[6] = c2r0;
578 m_[7] = c2r1;
579 m_[8] = c2r2;
580 return *this;
581 }
582
583 // Multiply a copy of this by another matrix. Return the copy.
584 const tmat3 operator*(const tmat3& rhs)
585 {
586 return tmat3(*this) *= rhs;
587 }
588
589 // Multiply this by a scalar. Return a reference to this.
590 tmat3& operator*=(const T& rhs)
591 {
592 m_[0] *= rhs;
593 m_[1] *= rhs;
594 m_[2] *= rhs;
595 m_[3] *= rhs;
596 m_[4] *= rhs;
597 m_[5] *= rhs;
598 m_[6] *= rhs;
599 m_[7] *= rhs;
600 m_[8] *= rhs;
601 return *this;
602 }
603
604 // Multiply a copy of this by a scalar. Return the copy.
605 const tmat3 operator*(const T& rhs)
606 {
607 return tmat3(*this) *= rhs;
608 }
609
610 // Divide this by a scalar. Return a reference to this.
611 tmat3& operator/=(const T& rhs)
612 {
613 m_[0] /= rhs;
614 m_[1] /= rhs;
615 m_[2] /= rhs;
616 m_[3] /= rhs;
617 m_[4] /= rhs;
618 m_[5] /= rhs;
619 m_[6] /= rhs;
620 m_[7] /= rhs;
621 m_[8] /= rhs;
622 return *this;
623 }
624
625 // Divide a copy of this by a scalar. Return the copy.
626 const tmat3 operator/(const T& rhs)
627 {
628 return tmat3(*this) /= rhs;
629 }
630
631 // Use an instance of the ArrayProxy class to support double-indexed
632 // references to a matrix (i.e., m[1][1]). See comments above the
633 // ArrayProxy definition for more details.
634 ArrayProxy<T, 3> operator[](int index)
635 {
636 return ArrayProxy<T, 3>(&m_[index]);
637 }
638 const ArrayProxy<T, 3> operator[](int index) const
639 {
640 return ArrayProxy<T, 3>(const_cast<T*>(&m_[index]));
641 }
642
643 private:
644 T m_[9];
645 };
646
647 // Multiply a scalar and a matrix just like the member operator, but allow
648 // the scalar to be the left-hand operand.
649 template<typename T>
650 const tmat3<T> operator*(const T& lhs, const tmat3<T>& rhs)
651 {
652 return tmat3<T>(rhs) * lhs;
653 }
654
655 // Multiply a copy of a vector and a matrix (matrix is right-hand operand).
656 // Return the copy.
657 template<typename T>
658 const tvec3<T> operator*(const tvec3<T>& lhs, const tmat3<T>& rhs)
659 {
660 T x((lhs.x() * rhs[0][0]) + (lhs.y() * rhs[1][0]) + (lhs.z() * rhs[2][0]));
661 T y((lhs.x() * rhs[0][1]) + (lhs.y() * rhs[1][1]) + (lhs.z() * rhs[2][1]));
662 T z((lhs.x() * rhs[0][2]) + (lhs.y() * rhs[1][2]) + (lhs.z() * rhs[2][2]));
663 return tvec3<T>(x, y, z);
664 }
665
666 // Multiply a copy of a vector and a matrix (matrix is left-hand operand).
667 // Return the copy.
668 template<typename T>
669 const tvec3<T> operator*(const tmat3<T>& lhs, const tvec3<T>& rhs)
670 {
671 T x((lhs[0][0] * rhs.x()) + (lhs[0][1] * rhs.y()) + (lhs[0][2] * rhs.z()));
672 T y((lhs[1][0] * rhs.x()) + (lhs[1][1] * rhs.y()) + (lhs[1][2] * rhs.z()));
673 T z((lhs[2][0] * rhs.x()) + (lhs[2][1] * rhs.y()) + (lhs[2][2] * rhs.z()));
674 return tvec3<T>(x, y, z);
675 }
676
677 // Compute the outer product of two vectors. Return the resultant matrix.
678 template<typename T>
outer(const tvec3<T> & a,const tvec3<T> & b)679 const tmat3<T> outer(const tvec3<T>& a, const tvec3<T>& b)
680 {
681 tmat3<T> product;
682 product[0][0] = a.x() * b.x();
683 product[0][1] = a.x() * b.y();
684 product[0][2] = a.x() * b.z();
685 product[1][0] = a.y() * b.x();
686 product[1][1] = a.y() * b.y();
687 product[1][2] = a.y() * b.z();
688 product[2][0] = a.z() * b.x();
689 product[2][1] = a.z() * b.y();
690 product[2][2] = a.z() * b.z();
691 return product;
692 }
693
694 // A template class for creating, managing and operating on a 4x4 matrix
695 // of any type you like (intended for built-in types, but as long as it
696 // supports the basic arithmetic and assignment operators, any type should
697 // work).
698 template<typename T>
699 class tmat4
700 {
701 public:
tmat4()702 tmat4()
703 {
704 setIdentity();
705 }
tmat4(const tmat4 & m)706 tmat4(const tmat4& m)
707 {
708 m_[0] = m.m_[0];
709 m_[1] = m.m_[1];
710 m_[2] = m.m_[2];
711 m_[3] = m.m_[3];
712 m_[4] = m.m_[4];
713 m_[5] = m.m_[5];
714 m_[6] = m.m_[6];
715 m_[7] = m.m_[7];
716 m_[8] = m.m_[8];
717 m_[9] = m.m_[9];
718 m_[10] = m.m_[10];
719 m_[11] = m.m_[11];
720 m_[12] = m.m_[12];
721 m_[13] = m.m_[13];
722 m_[14] = m.m_[14];
723 m_[15] = m.m_[15];
724 }
~tmat4()725 ~tmat4() {}
726
727 // Reset this to the identity matrix.
setIdentity()728 void setIdentity()
729 {
730 m_[0] = 1;
731 m_[1] = 0;
732 m_[2] = 0;
733 m_[3] = 0;
734 m_[4] = 0;
735 m_[5] = 1;
736 m_[6] = 0;
737 m_[7] = 0;
738 m_[8] = 0;
739 m_[9] = 0;
740 m_[10] = 1;
741 m_[11] = 0;
742 m_[12] = 0;
743 m_[13] = 0;
744 m_[14] = 0;
745 m_[15] = 1;
746 }
747
748 // Transpose this. Return a reference to this.
transpose()749 tmat4& transpose()
750 {
751 T tmp_val = m_[1];
752 m_[1] = m_[4];
753 m_[4] = tmp_val;
754 tmp_val = m_[2];
755 m_[2] = m_[8];
756 m_[8] = tmp_val;
757 tmp_val = m_[3];
758 m_[3] = m_[12];
759 m_[12] = tmp_val;
760 tmp_val = m_[6];
761 m_[6] = m_[9];
762 m_[9] = tmp_val;
763 tmp_val = m_[7];
764 m_[7] = m_[13];
765 m_[13] = tmp_val;
766 tmp_val = m_[11];
767 m_[11] = m_[14];
768 m_[14] = tmp_val;
769 return *this;
770 }
771
772 // Compute the determinant of this and return it.
determinant()773 T determinant()
774 {
775 tmat3<T> minor0(m_[5], m_[6], m_[7], m_[9], m_[10], m_[11], m_[13], m_[14], m_[15]);
776 tmat3<T> minor4(m_[1], m_[2], m_[3], m_[9], m_[10], m_[11], m_[13], m_[14], m_[15]);
777 tmat3<T> minor8(m_[1], m_[2], m_[3], m_[5], m_[6], m_[7], m_[13], m_[14], m_[15]);
778 tmat3<T> minor12(m_[1], m_[2], m_[3], m_[5], m_[6], m_[7], m_[9], m_[10], m_[11]);
779 return (m_[0] * minor0.determinant()) -
780 (m_[4] * minor4.determinant()) +
781 (m_[8] * minor8.determinant()) -
782 (m_[12] * minor12.determinant());
783 }
784
785 // Invert this. Return a reference to this.
786 //
787 // NOTE: If this is non-invertible, we will
788 // throw to avoid undefined behavior.
inverse()789 tmat4& inverse()
790 {
791 T d(determinant());
792 if (d == static_cast<T>(0))
793 {
794 #ifdef USE_EXCEPTIONS
795 throw std::runtime_error("Matrix is noninvertible!!!!");
796 #else // !USE_EXCEPTIONS
797 Log::error("Matrix is noninvertible!!!!\n");
798 return *this;
799 #endif // USE_EXCEPTIONS
800 }
801 tmat3<T> minor0(m_[5], m_[6], m_[7], m_[9], m_[10], m_[11], m_[13], m_[14], m_[15]);
802 tmat3<T> minor1(m_[1], m_[2], m_[3], m_[13], m_[14], m_[15], m_[9], m_[10], m_[11]);
803 tmat3<T> minor2(m_[1], m_[2], m_[3], m_[5], m_[6], m_[7], m_[13], m_[14], m_[15]);
804 tmat3<T> minor3(m_[1], m_[2], m_[3], m_[9], m_[10], m_[11], m_[5], m_[6], m_[7]);
805
806 tmat3<T> minor4(m_[4], m_[6], m_[7], m_[12], m_[14], m_[15], m_[8], m_[10], m_[11]);
807 tmat3<T> minor5(m_[0], m_[2], m_[3], m_[8], m_[10], m_[11], m_[12], m_[14], m_[15]);
808 tmat3<T> minor6(m_[0], m_[2], m_[3], m_[12], m_[14], m_[15], m_[4], m_[6], m_[7]);
809 tmat3<T> minor7(m_[0], m_[2], m_[3], m_[4], m_[6], m_[7], m_[8], m_[10], m_[11]);
810
811 tmat3<T> minor8(m_[4], m_[5], m_[7], m_[8], m_[9], m_[11], m_[12], m_[13], m_[15]);
812 tmat3<T> minor9(m_[0], m_[1], m_[3], m_[12], m_[13], m_[15], m_[8], m_[9], m_[11]);
813 tmat3<T> minor10(m_[0], m_[1], m_[3], m_[4], m_[5], m_[7], m_[12], m_[13], m_[15]);
814 tmat3<T> minor11(m_[0], m_[1], m_[3], m_[8], m_[9], m_[11], m_[4], m_[5], m_[7]);
815
816 tmat3<T> minor12(m_[4], m_[5], m_[6], m_[12], m_[13], m_[14], m_[8], m_[9], m_[10]);
817 tmat3<T> minor13(m_[0], m_[1], m_[2], m_[8], m_[9], m_[10], m_[12], m_[13], m_[14]);
818 tmat3<T> minor14(m_[0], m_[1], m_[2], m_[12], m_[13], m_[14], m_[4], m_[5], m_[6]);
819 tmat3<T> minor15(m_[0], m_[1], m_[2], m_[4], m_[5], m_[6], m_[8], m_[9], m_[10]);
820 m_[0] = minor0.determinant() / d;
821 m_[1] = minor1.determinant() / d;
822 m_[2] = minor2.determinant() / d;
823 m_[3] = minor3.determinant() / d;
824 m_[4] = minor4.determinant() / d;
825 m_[5] = minor5.determinant() / d;
826 m_[6] = minor6.determinant() / d;
827 m_[7] = minor7.determinant() / d;
828 m_[8] = minor8.determinant() / d;
829 m_[9] = minor9.determinant() / d;
830 m_[10] = minor10.determinant() / d;
831 m_[11] = minor11.determinant() / d;
832 m_[12] = minor12.determinant() / d;
833 m_[13] = minor13.determinant() / d;
834 m_[14] = minor14.determinant() / d;
835 m_[15] = minor15.determinant() / d;
836 return *this;
837 }
838
839 // Print the elements of the matrix to standard out.
840 // Really only useful for debug and test.
print()841 void print() const
842 {
843 static const int precision(6);
844 // row 0
845 std::cout << "| ";
846 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[0];
847 std::cout << " ";
848 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[4];
849 std::cout << " ";
850 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[8];
851 std::cout << " ";
852 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[12];
853 std::cout << " |" << std::endl;
854 // row 1
855 std::cout << "| ";
856 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[1];
857 std::cout << " ";
858 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[5];
859 std::cout << " ";
860 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[9];
861 std::cout << " ";
862 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[13];
863 std::cout << " |" << std::endl;
864 // row 2
865 std::cout << "| ";
866 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[2];
867 std::cout << " ";
868 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[6];
869 std::cout << " ";
870 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[10];
871 std::cout << " ";
872 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[14];
873 std::cout << " |" << std::endl;
874 // row 3
875 std::cout << "| ";
876 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[3];
877 std::cout << " ";
878 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[7];
879 std::cout << " ";
880 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[11];
881 std::cout << " ";
882 std::cout << std::fixed << std::showpoint << std::setprecision(precision) << m_[15];
883 std::cout << " |" << std::endl;
884 }
885
886 // Allow raw data access for API calls and the like.
887 // For example, it is valid to pass a tmat4<float> into a call to
888 // the OpenGL command "glUniformMatrix4fv()".
889 operator const T*() const { return &m_[0];}
890
891 // Test if 'rhs' is equal to this.
892 bool operator==(const tmat4& rhs) const
893 {
894 return m_[0] == rhs.m_[0] &&
895 m_[1] == rhs.m_[1] &&
896 m_[2] == rhs.m_[2] &&
897 m_[3] == rhs.m_[3] &&
898 m_[4] == rhs.m_[4] &&
899 m_[5] == rhs.m_[5] &&
900 m_[6] == rhs.m_[6] &&
901 m_[7] == rhs.m_[7] &&
902 m_[8] == rhs.m_[8] &&
903 m_[9] == rhs.m_[9] &&
904 m_[10] == rhs.m_[10] &&
905 m_[11] == rhs.m_[11] &&
906 m_[12] == rhs.m_[12] &&
907 m_[13] == rhs.m_[13] &&
908 m_[14] == rhs.m_[14] &&
909 m_[15] == rhs.m_[15];
910 }
911
912 // Test if 'rhs' is not equal to this.
913 bool operator!=(const tmat4& rhs) const
914 {
915 return !(*this == rhs);
916 }
917
918 // A direct assignment of 'rhs' to this. Return a reference to this.
919 tmat4& operator=(const tmat4& rhs)
920 {
921 if (this != &rhs)
922 {
923 m_[0] = rhs.m_[0];
924 m_[1] = rhs.m_[1];
925 m_[2] = rhs.m_[2];
926 m_[3] = rhs.m_[3];
927 m_[4] = rhs.m_[4];
928 m_[5] = rhs.m_[5];
929 m_[6] = rhs.m_[6];
930 m_[7] = rhs.m_[7];
931 m_[8] = rhs.m_[8];
932 m_[9] = rhs.m_[9];
933 m_[10] = rhs.m_[10];
934 m_[11] = rhs.m_[11];
935 m_[12] = rhs.m_[12];
936 m_[13] = rhs.m_[13];
937 m_[14] = rhs.m_[14];
938 m_[15] = rhs.m_[15];
939 }
940 return *this;
941 }
942
943 // Add another matrix to this. Return a reference to this.
944 tmat4& operator+=(const tmat4& rhs)
945 {
946 m_[0] += rhs.m_[0];
947 m_[1] += rhs.m_[1];
948 m_[2] += rhs.m_[2];
949 m_[3] += rhs.m_[3];
950 m_[4] += rhs.m_[4];
951 m_[5] += rhs.m_[5];
952 m_[6] += rhs.m_[6];
953 m_[7] += rhs.m_[7];
954 m_[8] += rhs.m_[8];
955 m_[9] += rhs.m_[9];
956 m_[10] += rhs.m_[10];
957 m_[11] += rhs.m_[11];
958 m_[12] += rhs.m_[12];
959 m_[13] += rhs.m_[13];
960 m_[14] += rhs.m_[14];
961 m_[15] += rhs.m_[15];
962 return *this;
963 }
964
965 // Add another matrix to a copy of this. Return the copy.
966 const tmat4 operator+(const tmat4& rhs)
967 {
968 return tmat4(*this) += rhs;
969 }
970
971 // Subtract another matrix from this. Return a reference to this.
972 tmat4& operator-=(const tmat4& rhs)
973 {
974 m_[0] -= rhs.m_[0];
975 m_[1] -= rhs.m_[1];
976 m_[2] -= rhs.m_[2];
977 m_[3] -= rhs.m_[3];
978 m_[4] -= rhs.m_[4];
979 m_[5] -= rhs.m_[5];
980 m_[6] -= rhs.m_[6];
981 m_[7] -= rhs.m_[7];
982 m_[8] -= rhs.m_[8];
983 m_[9] -= rhs.m_[9];
984 m_[10] -= rhs.m_[10];
985 m_[11] -= rhs.m_[11];
986 m_[12] -= rhs.m_[12];
987 m_[13] -= rhs.m_[13];
988 m_[14] -= rhs.m_[14];
989 m_[15] -= rhs.m_[15];
990 return *this;
991 }
992
993 // Subtract another matrix from a copy of this. Return the copy.
994 const tmat4 operator-(const tmat4& rhs)
995 {
996 return tmat4(*this) -= rhs;
997 }
998
999 // Multiply this by another matrix. Return a reference to this.
1000 tmat4& operator*=(const tmat4& rhs)
1001 {
1002 T c0r0((m_[0] * rhs.m_[0]) + (m_[4] * rhs.m_[1]) + (m_[8] * rhs.m_[2]) + (m_[12] * rhs.m_[3]));
1003 T c0r1((m_[1] * rhs.m_[0]) + (m_[5] * rhs.m_[1]) + (m_[9] * rhs.m_[2]) + (m_[13] * rhs.m_[3]));
1004 T c0r2((m_[2] * rhs.m_[0]) + (m_[6] * rhs.m_[1]) + (m_[10] * rhs.m_[2]) + (m_[14] * rhs.m_[3]));
1005 T c0r3((m_[3] * rhs.m_[0]) + (m_[7] * rhs.m_[1]) + (m_[11] * rhs.m_[2]) + (m_[15] * rhs.m_[3]));
1006 T c1r0((m_[0] * rhs.m_[4]) + (m_[4] * rhs.m_[5]) + (m_[8] * rhs.m_[6]) + (m_[12] * rhs.m_[7]));
1007 T c1r1((m_[1] * rhs.m_[4]) + (m_[5] * rhs.m_[5]) + (m_[9] * rhs.m_[6]) + (m_[13] * rhs.m_[7]));
1008 T c1r2((m_[2] * rhs.m_[4]) + (m_[6] * rhs.m_[5]) + (m_[10] * rhs.m_[6]) + (m_[14] * rhs.m_[7]));
1009 T c1r3((m_[3] * rhs.m_[4]) + (m_[7] * rhs.m_[5]) + (m_[11] * rhs.m_[6]) + (m_[15] * rhs.m_[7]));
1010 T c2r0((m_[0] * rhs.m_[8]) + (m_[4] * rhs.m_[9]) + (m_[8] * rhs.m_[10]) + (m_[12] * rhs.m_[11]));
1011 T c2r1((m_[1] * rhs.m_[8]) + (m_[5] * rhs.m_[9]) + (m_[9] * rhs.m_[10]) + (m_[13] * rhs.m_[11]));
1012 T c2r2((m_[2] * rhs.m_[8]) + (m_[6] * rhs.m_[9]) + (m_[10] * rhs.m_[10]) + (m_[14] * rhs.m_[11]));
1013 T c2r3((m_[3] * rhs.m_[8]) + (m_[7] * rhs.m_[9]) + (m_[11] * rhs.m_[10]) + (m_[15] * rhs.m_[11]));
1014 T c3r0((m_[0] * rhs.m_[12]) + (m_[4] * rhs.m_[13]) + (m_[8] * rhs.m_[14]) + (m_[12] * rhs.m_[15]));
1015 T c3r1((m_[1] * rhs.m_[12]) + (m_[5] * rhs.m_[13]) + (m_[9] * rhs.m_[14]) + (m_[13] * rhs.m_[15]));
1016 T c3r2((m_[2] * rhs.m_[12]) + (m_[6] * rhs.m_[13]) + (m_[10] * rhs.m_[14]) + (m_[14] * rhs.m_[15]));
1017 T c3r3((m_[3] * rhs.m_[12]) + (m_[7] * rhs.m_[13]) + (m_[11] * rhs.m_[14]) + (m_[15] * rhs.m_[15]));
1018 m_[0] = c0r0;
1019 m_[1] = c0r1;
1020 m_[2] = c0r2;
1021 m_[3] = c0r3;
1022 m_[4] = c1r0;
1023 m_[5] = c1r1;
1024 m_[6] = c1r2;
1025 m_[7] = c1r3;
1026 m_[8] = c2r0;
1027 m_[9] = c2r1;
1028 m_[10] = c2r2;
1029 m_[11] = c2r3;
1030 m_[12] = c3r0;
1031 m_[13] = c3r1;
1032 m_[14] = c3r2;
1033 m_[15] = c3r3;
1034 return *this;
1035 }
1036
1037 // Multiply a copy of this by another matrix. Return the copy.
1038 const tmat4 operator*(const tmat4& rhs)
1039 {
1040 return tmat4(*this) *= rhs;
1041 }
1042
1043 // Multiply this by a scalar. Return a reference to this.
1044 tmat4& operator*=(const T& rhs)
1045 {
1046 m_[0] *= rhs;
1047 m_[1] *= rhs;
1048 m_[2] *= rhs;
1049 m_[3] *= rhs;
1050 m_[4] *= rhs;
1051 m_[5] *= rhs;
1052 m_[6] *= rhs;
1053 m_[7] *= rhs;
1054 m_[8] *= rhs;
1055 m_[9] *= rhs;
1056 m_[10] *= rhs;
1057 m_[11] *= rhs;
1058 m_[12] *= rhs;
1059 m_[13] *= rhs;
1060 m_[14] *= rhs;
1061 m_[15] *= rhs;
1062 return *this;
1063 }
1064
1065 // Multiply a copy of this by a scalar. Return the copy.
1066 const tmat4 operator*(const T& rhs)
1067 {
1068 return tmat4(*this) *= rhs;
1069 }
1070
1071 // Divide this by a scalar. Return a reference to this.
1072 tmat4& operator/=(const T& rhs)
1073 {
1074 m_[0] /= rhs;
1075 m_[1] /= rhs;
1076 m_[2] /= rhs;
1077 m_[3] /= rhs;
1078 m_[4] /= rhs;
1079 m_[5] /= rhs;
1080 m_[6] /= rhs;
1081 m_[7] /= rhs;
1082 m_[8] /= rhs;
1083 m_[9] /= rhs;
1084 m_[10] /= rhs;
1085 m_[11] /= rhs;
1086 m_[12] /= rhs;
1087 m_[13] /= rhs;
1088 m_[14] /= rhs;
1089 m_[15] /= rhs;
1090 return *this;
1091 }
1092
1093 // Divide a copy of this by a scalar. Return the copy.
1094 const tmat4 operator/(const T& rhs)
1095 {
1096 return tmat4(*this) /= rhs;
1097 }
1098
1099 // Use an instance of the ArrayProxy class to support double-indexed
1100 // references to a matrix (i.e., m[1][1]). See comments above the
1101 // ArrayProxy definition for more details.
1102 ArrayProxy<T, 4> operator[](int index)
1103 {
1104 return ArrayProxy<T, 4>(&m_[index]);
1105 }
1106 const ArrayProxy<T, 4> operator[](int index) const
1107 {
1108 return ArrayProxy<T, 4>(const_cast<T*>(&m_[index]));
1109 }
1110
1111 private:
1112 T m_[16];
1113 };
1114
1115 // Multiply a scalar and a matrix just like the member operator, but allow
1116 // the scalar to be the left-hand operand.
1117 template<typename T>
1118 const tmat4<T> operator*(const T& lhs, const tmat4<T>& rhs)
1119 {
1120 return tmat4<T>(rhs) * lhs;
1121 }
1122
1123 // Multiply a copy of a vector and a matrix (matrix is right-hand operand).
1124 // Return the copy.
1125 template<typename T>
1126 const tvec4<T> operator*(const tvec4<T>& lhs, const tmat4<T>& rhs)
1127 {
1128 T x((lhs.x() * rhs[0][0]) + (lhs.y() * rhs[1][0]) + (lhs.z() * rhs[2][0]) + (lhs.w() * rhs[3][0]));
1129 T y((lhs.x() * rhs[0][1]) + (lhs.y() * rhs[1][1]) + (lhs.z() * rhs[2][1]) + (lhs.w() * rhs[3][1]));
1130 T z((lhs.x() * rhs[0][2]) + (lhs.y() * rhs[1][2]) + (lhs.z() * rhs[2][2]) + (lhs.w() * rhs[3][2]));
1131 T w((lhs.x() * rhs[0][3]) + (lhs.y() * rhs[1][3]) + (lhs.z() * rhs[2][3]) + (lhs.w() * rhs[3][3]));
1132 return tvec4<T>(x, y, z, w);
1133 }
1134
1135 // Multiply a copy of a vector and a matrix (matrix is left-hand operand).
1136 // Return the copy.
1137 template<typename T>
1138 const tvec4<T> operator*(const tmat4<T>& lhs, const tvec4<T>& rhs)
1139 {
1140 T x((lhs[0][0] * rhs.x()) + (lhs[0][1] * rhs.y()) + (lhs[0][2] * rhs.z()) + (lhs[0][3] * rhs.w()));
1141 T y((lhs[1][0] * rhs.x()) + (lhs[1][1] * rhs.y()) + (lhs[1][2] * rhs.z()) + (lhs[1][3] * rhs.w()));
1142 T z((lhs[2][0] * rhs.x()) + (lhs[2][1] * rhs.y()) + (lhs[2][2] * rhs.z()) + (lhs[2][3] * rhs.w()));
1143 T w((lhs[3][0] * rhs.x()) + (lhs[3][1] * rhs.y()) + (lhs[3][2] * rhs.z()) + (lhs[3][3] * rhs.w()));
1144 return tvec4<T>(x, y, z, w);
1145 }
1146
1147 // Compute the outer product of two vectors. Return the resultant matrix.
1148 template<typename T>
outer(const tvec4<T> & a,const tvec4<T> & b)1149 const tmat4<T> outer(const tvec4<T>& a, const tvec4<T>& b)
1150 {
1151 tmat4<T> product;
1152 product[0][0] = a.x() * b.x();
1153 product[0][1] = a.x() * b.y();
1154 product[0][2] = a.x() * b.z();
1155 product[0][3] = a.x() * b.w();
1156 product[1][0] = a.y() * b.x();
1157 product[1][1] = a.y() * b.y();
1158 product[1][2] = a.y() * b.z();
1159 product[1][3] = a.y() * b.w();
1160 product[2][0] = a.z() * b.x();
1161 product[2][1] = a.z() * b.y();
1162 product[2][2] = a.z() * b.z();
1163 product[2][3] = a.z() * b.w();
1164 product[3][0] = a.w() * b.x();
1165 product[3][1] = a.w() * b.y();
1166 product[3][2] = a.w() * b.z();
1167 product[3][3] = a.w() * b.w();
1168 return product;
1169 }
1170
1171 //
1172 // Convenience typedefs. These are here to present a homogeneous view of these
1173 // objects with respect to shader source.
1174 //
1175 typedef tmat2<float> mat2;
1176 typedef tmat3<float> mat3;
1177 typedef tmat4<float> mat4;
1178
1179 typedef tmat2<double> dmat2;
1180 typedef tmat3<double> dmat3;
1181 typedef tmat4<double> dmat4;
1182
1183 typedef tmat2<int> imat2;
1184 typedef tmat3<int> imat3;
1185 typedef tmat4<int> imat4;
1186
1187 typedef tmat2<unsigned int> umat2;
1188 typedef tmat3<unsigned int> umat3;
1189 typedef tmat4<unsigned int> umat4;
1190
1191 typedef tmat2<bool> bmat2;
1192 typedef tmat3<bool> bmat3;
1193 typedef tmat4<bool> bmat4;
1194
1195 namespace Mat4
1196 {
1197
1198 //
1199 // Some functions to generate transformation matrices that used to be provided
1200 // by OpenGL.
1201 //
1202 mat4 translate(float x, float y, float z);
1203 mat4 scale(float x, float y, float z);
1204 mat4 rotate(float angle, float x, float y, float z);
1205 mat4 frustum(float left, float right, float bottom, float top, float near, float far);
1206 mat4 ortho(float left, float right, float bottom, float top, float near, float far);
1207 mat4 perspective(float fovy, float aspect, float zNear, float zFar);
1208 mat4 lookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ);
1209
1210 } // namespace Mat4
1211 } // namespace LibMatrix
1212 #endif // MAT_H_
1213