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.
30 #include "Quaternion.h"
35 Matrix
<3,float>::Matrix(const Quaternion
<float> & q
)
44 setVector3(col
[0].v
, 1-2*(yy
+zz
), 2*(xy
+zw
), 2*(xz
-yw
));
48 setVector3(col
[1].v
, 2*(xy
-zw
), 1-2*(xx
+zz
), 2*(yz
+xw
));
49 setVector3(col
[2].v
, 2*(xz
+yw
), 2*(yz
-xw
), 1-2*(xx
+yy
));
52 /// Get an arbitrary matrix where the z axis points in the direction of Z.
53 Matrix
<3,float> getTbnMatrix(Vector
<3, float> vZ
)
55 Vector
<3,float> vY(0, 0, -1);
56 Vector
<3,float> vX(cross(vY
, vZ
));
63 return Matrix
<3,float>(vX
, vY
, vZ
);
66 // Invert the 3x3 matrix
69 Matrix
<3,float> & Matrix
<3,float>::invert()
77 unsigned int rowMax
; // Points to max abs value row in this column
83 // Find the row with max value in this column
85 for (r
=c
+1; r
<3; r
++) {
86 if (fabs(a
[c
][r
]) > fabs(a
[c
][rowMax
])) {
91 // If the max value here is 0, we can't invert. Return identity.
92 if (a
[rowMax
][c
] == 0.0F
)
95 // Swap row "rowMax" with row "c"
96 for (cc
=0; cc
<3; cc
++)
99 a
[cc
][c
] = a
[cc
][rowMax
];
102 b
[cc
][c
] = b
[cc
][rowMax
];
106 // Now everything we do is on row "c".
107 // Set the max cell to 1 by dividing the entire row by that value
109 for (cc
=0; cc
<3; cc
++) {
114 // Now do the other rows, so that this column only has a 1 and 0's
115 for (row
= 0; row
< 3; row
++) {
118 for (cc
=0; cc
<3; cc
++) {
119 a
[cc
][row
] -= a
[cc
][c
] * tmp
;
120 b
[cc
][row
] -= b
[cc
][c
] * tmp
;
132 // Invert the Matrix<4,float>
134 Matrix
<4,float> & Matrix
<4,float>::invert()
136 Matrix
<4,float> a(*this);
142 unsigned int rowMax
; // Points to max abs value row in this column
146 // Go through columns
147 for (c
=0; c
<4; c
++) {
148 // Find the row with max value in this column
150 for (r
=c
+1; r
<4; r
++) {
151 if (fabs(a
[c
][r
]) > fabs(a
[c
][rowMax
])) {
156 // If the max value here is 0, we can't invert. Return identity.
157 //if (a[rowMax][c] == 0.0F)
158 // return(identity());
160 // Swap row "rowMax" with row "c"
161 for (cc
=0; cc
<4; cc
++) {
163 a
[cc
][c
] = a
[cc
][rowMax
];
166 b
[cc
][c
] = b
[cc
][rowMax
];
170 // Now everything we do is on row "c".
171 // Set the max cell to 1 by dividing the entire row by that value
173 for (cc
=0; cc
<4; cc
++) {
178 // Now do the other rows, so that this column only has a 1 and 0's
179 for (row
= 0; row
< 4; row
++) {
182 for (cc
=0; cc
<4; cc
++) {
183 a
[cc
][row
] -= a
[cc
][c
] * tmp
;
184 b
[cc
][row
] -= b
[cc
][c
] * tmp
;
196 // Return a 3D axis-rotation maths::Matrix<4,float>
197 // Pass in 'x', 'y', or 'z' for the axis.
198 Matrix
<4,float> RotateRadMatrix44(char axis
, float rad
)
210 ret
[0][0] = 1.0F
; ret
[1][0] = 0.0F
; ret
[2][0] = 0.0F
;
211 ret
[0][1] = 0.0F
; ret
[1][1] = cosA
; ret
[2][1] = -sinA
;
212 ret
[0][2] = 0.0F
; ret
[1][2] = sinA
; ret
[2][2] = cosA
;
217 ret
[0][0] = cosA
; ret
[1][0] = 0.0F
; ret
[2][0] = sinA
;
218 ret
[0][1] = 0.0F
; ret
[1][1] = 1.0F
; ret
[2][1] = 0.0F
;
219 ret
[0][2] = -sinA
; ret
[1][2] = 0.0F
; ret
[2][2] = cosA
;
224 ret
[0][0] = cosA
; ret
[1][0] = -sinA
; ret
[2][0] = 0.0F
;
225 ret
[0][1] = sinA
; ret
[1][1] = cosA
; ret
[2][1] = 0.0F
;
226 ret
[0][2] = 0.0F
; ret
[1][2] = 0.0F
; ret
[2][2] = 1.0F
;
230 ret
[0][3] = 0.0F
; ret
[1][3] = 0.0F
; ret
[2][3] = 0.0F
;
239 // Return a 3D axis-rotation maths::Matrix<4,float>
240 // Pass in an arbitrary maths::Vector<3,float> axis.
241 Matrix
<4,float> RotateRadMatrix44(const Vector
<3,float> &axis
, float rad
)
246 Vector
<3,float> nrm
= axis
;
253 invCosA
= 1.0F
- cosA
;
263 ret
[0][0] = (invCosA
* xSq
) + (cosA
);
264 ret
[1][0] = (invCosA
* x
* y
) - (sinA
* z
);
265 ret
[2][0] = (invCosA
* x
* z
) + (sinA
* y
);
268 ret
[0][1] = (invCosA
* x
* y
) + (sinA
* z
);
269 ret
[1][1] = (invCosA
* ySq
) + (cosA
);
270 ret
[2][1] = (invCosA
* y
* z
) - (sinA
* x
);
273 ret
[0][2] = (invCosA
* x
* z
) - (sinA
* y
);
274 ret
[1][2] = (invCosA
* y
* z
) + (sinA
* x
);
275 ret
[2][2] = (invCosA
* zSq
) + (cosA
);
286 // Return a 3D translation Matrix<4,float>
287 Matrix
<4,float> TranslateMatrix44(const maths::Vector
<3,float> & v
)
292 ret
[3].slice
<0,3>() = v
;
297 // Return a 3D/4D scale Matrix<4,float>
298 Matrix
<4,float> ScaleMatrix44(const maths::Vector
<4,float> & v
)
303 for (int i
= 0; i
< 4; ++i
) {