1 /***************************************************************************
2 * This file is part of Tecorrec. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
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. *
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. *
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 ***************************************************************************/
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
39 // This isn't always used with matricies. include Quaternion.h if you wish to use it.
43 template <int N
, typename T
>
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.
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
>
69 /// Default constructor (does not initialise values).
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
>();
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
)
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
)
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
)
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
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
177 for (; i
< copyRange
; ++i
) {
178 // Copy as many values as possible from the column
180 for (; j
< copyRange
; ++j
)
181 col
[i
][j
] = (T
)copy
.col
[i
][j
];
183 // Generate any remaining values from the identity matrix.
185 col
[i
][j
] = (i
==j
? (T
)1 : maths::zero
<T
>());
189 // Generate any remaining columns from the identity matrix.
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
* ()
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
];
239 inline Matrix
operator + (const Matrix
& rhs
) const
245 inline Matrix
& operator -= (const Matrix
& rhs
)
247 for (int i
= 0; i
< N
; ++i
)
248 col
[i
] -= rhs
.col
[i
];
251 inline Matrix
operator - (const Matrix
& rhs
) const
257 inline Matrix
& operator *= (const T rhs
)
259 for (int i
= 0; i
< N
; ++i
)
263 inline Matrix
operator * (const T rhs
) const
269 inline friend Matrix
operator * (const T lhs
, const Matrix
& rhs
)
274 template <typename U
>
275 inline friend Vector
<N
,U
> operator * (const Matrix
& lhs
, const Vector
<N
,U
> & rhs
)
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
];
286 template <typename U
>
287 inline friend Vector
<N
,U
> operator * (const Vector
<N
,U
> & lhs
, const Matrix
& rhs
)
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
];
299 inline friend Matrix
operator * (const Matrix
& lhs
, const Matrix
& rhs
)
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
];
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
)
324 inline Matrix
operator / (const T rhs
) const
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
>();
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
) {
349 col
[i
][j
] = col
[j
][i
];
356 /// Get the transposed matrix.
357 inline Matrix
transposed() const
360 for (int i
= 0; i
< N
; ++i
) {
361 for (int j
= 0; j
< N
; ++j
) {
362 ret
[j
][i
] = col
[i
][j
];
368 /// Invert the matrix.
371 /// Get the inverted matrix.
372 inline Matrix
inverted() const
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
;