Snapshotting and loading
[tecorrec.git] / maths / Matrix.h
blobb73c5fc42ad5cc3a1fcf0a63ac60efeb67e9e3fd
1 /***************************************************************************
2 * This file is part of Tecorrec. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
4 * *
5 * Tecorrec is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * Tecorrec is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with Tecorrec. If not, write to the Free Software Foundation, *
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
20 /**
21 * @file Matrix.h
22 * @brief Square matrix class.
23 * @author James Hogan (james@albanarts.com)
24 * @note Copyright (C) 2007
26 * @version 1 : From Computer Graphics and Visualisation Open Assessment.
29 #ifndef _maths_Matrix_h
30 #define _maths_Matrix_h
32 #include "Vector.h"
34 // For memcpy
35 #include <cstring>
37 namespace maths
39 // This isn't always used with matricies. include Quaternion.h if you wish to use it.
40 template <typename T>
41 class Quaternion;
43 template <int N, typename T>
44 class Matrix;
46 /// Get an arbitrary matrix where the z axis points in the direction of Z.
47 Matrix<3,float> getTbnMatrix(Vector<3, float> vZ);
49 Matrix<4,float> RotateRadMatrix44(char axis, float rad);
50 Matrix<4,float> RotateRadMatrix44(const maths::Vector<3,float> &axis, float rad);
51 Matrix<4,float> TranslateMatrix44(const maths::Vector<3,float> & v);
52 Matrix<4,float> ScaleMatrix44(const maths::Vector<4,float> & v);
53 inline Matrix<4,float> ScaleMatrix44(const maths::Vector<3,float> & v);
55 /// Square tranformation matrix.
56 /**
57 * The matrix is stored in a column major fashion so as to be directly.
58 * compatible with OpenGL
59 * @param N int Size of width and height of the matrix.
60 * @param T typename Type of the components of the matrix.
62 template <int N, typename T>
63 class Matrix
65 public:
66 /// Columns
67 Vector<N, T> col[N];
69 /// Default constructor (does not initialise values).
70 inline Matrix()
72 // let the vector constructor deal with the initialisation
75 /// Diagonal matrix constructor
76 inline explicit Matrix(T diagonal)
78 for (int i = 0; i < N; ++i) {
79 for (int j = 0; j < i; ++j) {
80 col[i][j] = col[j][i] = maths::zero<T>();
82 col[i][i] = diagonal;
86 /// Diagonal matrix constructor
87 inline explicit Matrix(Vector<N, T> diagonal)
89 for (int i = 0; i < N; ++i) {
90 for (int j = 0; j < i; ++j) {
91 col[i][j] = col[j][i] = maths::zero<T>();
93 col[i][i] = diagonal[i];
97 inline Matrix(Vector<N, T> x, Vector<N, T> y)
99 col[0] = x;
100 col[1] = y;
101 if (N > 2) {
102 for (int i = 2; i < N; ++i) {
103 col[i] = (Vector<N, T>)maths::zero<T>();
107 inline Matrix(Vector<N, T> x, Vector<N, T> y, Vector<N, T> z)
109 col[0] = x;
110 col[1] = y;
111 if (N > 2) {
112 col[2] = z;
113 if (N > 3) {
114 for (int i = 3; i < N; ++i) {
115 col[i] = (Vector<N, T>)maths::zero<T>();
120 inline Matrix(Vector<N, T> x, Vector<N, T> y, Vector<N, T> z, Vector<N, T> w)
122 col[0] = x;
123 col[1] = y;
124 if (N > 2) {
125 col[2] = z;
126 if (N > 3) {
127 col[3] = w;
128 if (N > 4) {
129 for (int i = 4; i < N; ++i) {
130 col[i] = (Vector<N, T>)maths::zero<T>();
137 /// Copy the matrix directly from an array.
139 * @param vec Pointer to array of values in column major format.
141 inline explicit Matrix(const T * vec)
143 std::memcpy(&col[0][0], vec, sizeof(T)*(N*N));
146 /// Copy the matrix from an array of vectors.
148 * @param columns Pointer to array of column vectors.
150 inline explicit Matrix(const Vector<N, T> * columns)
152 std::memcpy(col, columns.col, sizeof(T)*(N*N));
154 /// Convert quaternion to matrix
155 explicit Matrix(const Quaternion<T> &);
157 /// From something else
159 * Basically we want to prevent accidental double conversions between types.
161 template <typename U>
162 explicit Matrix(const U &);
164 /// Convert, downsize or upsize another matrix.
166 * If the matrix is being downsized, the extreme rows and columns are
167 * ignored.
168 * If the matrix is being upsized, the extreme rows and columns are filled
169 * with the identity matrix.
170 * @param copy The matrix object to construct from.
172 template <int M, typename U> inline explicit Matrix(const Matrix<M,U> & copy)
174 const int copyRange = (N < M ? N : M);
175 // Copy as many columns as possible from copy
176 int i = 0;
177 for (; i < copyRange; ++i) {
178 // Copy as many values as possible from the column
179 int j = 0;
180 for (; j < copyRange; ++j)
181 col[i][j] = (T)copy.col[i][j];
182 if (M < N) {
183 // Generate any remaining values from the identity matrix.
184 for (; j < N; ++j)
185 col[i][j] = (i==j ? (T)1 : maths::zero<T>());
188 if (M < N) {
189 // Generate any remaining columns from the identity matrix.
190 for (; i < N; ++i) {
191 for (int j = 0; j < N; ++j)
192 col[i][j] = (i==j ? (T)1 : maths::zero<T>());
197 /// Index a column in the matrix.
199 * @param columnIndex The index of the column starting at 0.
200 * @return The column as a vector.
202 inline Vector<N, T> & operator [] (int columnIndex)
204 return col[columnIndex];
206 /// Index a column in the matrix.
208 * @param columnIndex The index of the column starting at 0.
209 * @return The column as a vector.
211 inline const Vector<N, T> & operator [] (int columnIndex) const
213 return col[columnIndex];
216 /// Get a pointer to the values of the matrix.
218 * @return Pointer to the values of the array in column major format.
220 inline operator T * ()
222 return (T*)col;
224 /// Get a pointer to the values of the matrix.
226 * @return Pointer to the values of the array in column major format.
228 inline operator const T * () const
230 return (const T*)col;
233 inline Matrix & operator += (const Matrix & rhs)
235 for (int i = 0; i < N; ++i)
236 col[i] += rhs.col[i];
237 return *this;
239 inline Matrix operator + (const Matrix & rhs) const
241 Matrix ret = *this;
242 return ret += rhs;
245 inline Matrix & operator -= (const Matrix & rhs)
247 for (int i = 0; i < N; ++i)
248 col[i] -= rhs.col[i];
249 return *this;
251 inline Matrix operator - (const Matrix & rhs) const
253 Matrix ret = *this;
254 return ret -= rhs;
257 inline Matrix & operator *= (const T rhs)
259 for (int i = 0; i < N; ++i)
260 col[i] *= rhs;
261 return *this;
263 inline Matrix operator * (const T rhs) const
265 Matrix ret = *this;
266 return ret *= rhs;
269 inline friend Matrix operator * (const T lhs, const Matrix & rhs)
271 return rhs*lhs;
274 template <typename U>
275 inline friend Vector<N,U> operator * (const Matrix & lhs, const Vector<N,U> & rhs)
277 Vector<N,U> ret;
278 for (int row = 0; row < N; ++row) {
279 ret[row] = maths::zero<U>();
280 for (int i = 0; i < N; ++i) {
281 ret[row] += lhs[i][row] * rhs[i];
284 return ret;
286 template <typename U>
287 inline friend Vector<N,U> operator * (const Vector<N,U> & lhs, const Matrix & rhs)
289 Vector<N,U> ret;
290 for (int col = 0; col < N; ++col) {
291 ret[col] = maths::zero<T>();
292 for (int i = 0; i < N; ++i) {
293 ret[col] += lhs[i] * rhs[col][i];
296 return ret;
299 inline friend Matrix operator * (const Matrix & lhs, const Matrix & rhs)
301 Matrix ret;
302 for (int col = 0; col < N; ++col) {
303 for (int row = 0; row < N; ++row) {
304 T val = maths::zero<T>();
305 for (int i = 0; i < N; ++i) {
306 val += lhs[i][row] * rhs[col][i];
308 ret[col][row] = val;
311 return ret;
313 inline Matrix & operator *= (const Matrix & rhs)
315 return (*this = *this * rhs);
318 inline Matrix & operator /= (const T rhs)
320 for (int i = 0; i < N; ++i)
321 col[i] /= rhs;
322 return *this;
324 inline Matrix operator / (const T rhs) const
326 Matrix ret = *this;
327 return ret /= rhs;
330 /// Make the matrix an identity matrix.
331 inline Matrix & identity()
333 for (int i = 0; i < N; ++i) {
334 for (int j = 0; j < i; ++j) {
335 col[i][j] = col[j][i] = maths::zero<T>();
337 col[i][i] = 1;
339 return *this;
342 /// Transpose the matrix.
343 inline Matrix & transpose()
345 // go through lower left cells and swap with upper right
346 for (int i = 1; i < N; ++i) {
347 for (int j = 0; j < i; ++j) {
348 T temp = col[i][j];
349 col[i][j] = col[j][i];
350 col[j][i] = temp;
353 return *this;
356 /// Get the transposed matrix.
357 inline Matrix transposed() const
359 Matrix ret;
360 for (int i = 0; i < N; ++i) {
361 for (int j = 0; j < N; ++j) {
362 ret[j][i] = col[i][j];
365 return ret;
368 /// Invert the matrix.
369 Matrix & invert();
371 /// Get the inverted matrix.
372 inline Matrix inverted() const
374 Matrix ret = *this;
375 return ret.invert();
377 }; // ::maths::Matrix
379 inline Matrix<4,float> ScaleMatrix44(const maths::Vector<3,float> & v)
381 return ScaleMatrix44((v, 1.0f));
384 template <int N, typename T>
385 inline maths::Matrix<N,T> outer(const maths::Vector<N,T> & vertical, const maths::Vector<N,T> & horizontal)
387 maths::Matrix<N,T> result;
388 for (int i = 0; i < N; ++i) {
389 result[i] = horizontal[i] * vertical;
391 return result;
393 } // ::maths
395 #endif