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