rev |
line source |
nuclear@10
|
1 /*
|
nuclear@10
|
2 libvmath - a vector math library
|
nuclear@10
|
3 Copyright (C) 2004-2015 John Tsiombikas <nuclear@member.fsf.org>
|
nuclear@10
|
4
|
nuclear@10
|
5 This program is free software: you can redistribute it and/or modify
|
nuclear@10
|
6 it under the terms of the GNU Lesser General Public License as published
|
nuclear@10
|
7 by the Free Software Foundation, either version 3 of the License, or
|
nuclear@10
|
8 (at your option) any later version.
|
nuclear@10
|
9
|
nuclear@10
|
10 This program is distributed in the hope that it will be useful,
|
nuclear@10
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nuclear@10
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nuclear@10
|
13 GNU Lesser General Public License for more details.
|
nuclear@10
|
14
|
nuclear@10
|
15 You should have received a copy of the GNU Lesser General Public License
|
nuclear@10
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
nuclear@10
|
17 */
|
nuclear@10
|
18 #include <cstdio>
|
nuclear@10
|
19 #include <cmath>
|
nuclear@10
|
20 #include "matrix.h"
|
nuclear@10
|
21 #include "vector.h"
|
nuclear@10
|
22 #include "quat.h"
|
nuclear@10
|
23
|
nuclear@10
|
24 using namespace std;
|
nuclear@10
|
25
|
nuclear@10
|
26 // ----------- Matrix3x3 --------------
|
nuclear@10
|
27
|
nuclear@10
|
28 Matrix3x3 Matrix3x3::identity = Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
|
nuclear@10
|
29
|
nuclear@10
|
30 Matrix3x3::Matrix3x3()
|
nuclear@10
|
31 {
|
nuclear@10
|
32 *this = Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
|
nuclear@10
|
33 }
|
nuclear@10
|
34
|
nuclear@10
|
35 Matrix3x3::Matrix3x3( scalar_t m11, scalar_t m12, scalar_t m13,
|
nuclear@10
|
36 scalar_t m21, scalar_t m22, scalar_t m23,
|
nuclear@10
|
37 scalar_t m31, scalar_t m32, scalar_t m33)
|
nuclear@10
|
38 {
|
nuclear@10
|
39 m[0][0] = m11; m[0][1] = m12; m[0][2] = m13;
|
nuclear@10
|
40 m[1][0] = m21; m[1][1] = m22; m[1][2] = m23;
|
nuclear@10
|
41 m[2][0] = m31; m[2][1] = m32; m[2][2] = m33;
|
nuclear@10
|
42 }
|
nuclear@10
|
43
|
nuclear@10
|
44 Matrix3x3::Matrix3x3(const Vector3 &ivec, const Vector3 &jvec, const Vector3 &kvec)
|
nuclear@10
|
45 {
|
nuclear@10
|
46 set_row_vector(ivec, 0);
|
nuclear@10
|
47 set_row_vector(jvec, 1);
|
nuclear@10
|
48 set_row_vector(kvec, 2);
|
nuclear@10
|
49 }
|
nuclear@10
|
50
|
nuclear@10
|
51 Matrix3x3::Matrix3x3(const mat3_t cmat)
|
nuclear@10
|
52 {
|
nuclear@10
|
53 memcpy(m, cmat, sizeof(mat3_t));
|
nuclear@10
|
54 }
|
nuclear@10
|
55
|
nuclear@10
|
56 Matrix3x3::Matrix3x3(const Matrix4x4 &mat4x4)
|
nuclear@10
|
57 {
|
nuclear@10
|
58 for(int i=0; i<3; i++) {
|
nuclear@10
|
59 for(int j=0; j<3; j++) {
|
nuclear@10
|
60 m[i][j] = mat4x4[i][j];
|
nuclear@10
|
61 }
|
nuclear@10
|
62 }
|
nuclear@10
|
63 }
|
nuclear@10
|
64
|
nuclear@10
|
65 Matrix3x3 operator +(const Matrix3x3 &m1, const Matrix3x3 &m2)
|
nuclear@10
|
66 {
|
nuclear@10
|
67 Matrix3x3 res;
|
nuclear@10
|
68 const scalar_t *op1 = m1.m[0], *op2 = m2.m[0];
|
nuclear@10
|
69 scalar_t *dest = res.m[0];
|
nuclear@10
|
70
|
nuclear@10
|
71 for(int i=0; i<9; i++) {
|
nuclear@10
|
72 *dest++ = *op1++ + *op2++;
|
nuclear@10
|
73 }
|
nuclear@10
|
74 return res;
|
nuclear@10
|
75 }
|
nuclear@10
|
76
|
nuclear@10
|
77 Matrix3x3 operator -(const Matrix3x3 &m1, const Matrix3x3 &m2)
|
nuclear@10
|
78 {
|
nuclear@10
|
79 Matrix3x3 res;
|
nuclear@10
|
80 const scalar_t *op1 = m1.m[0], *op2 = m2.m[0];
|
nuclear@10
|
81 scalar_t *dest = res.m[0];
|
nuclear@10
|
82
|
nuclear@10
|
83 for(int i=0; i<9; i++) {
|
nuclear@10
|
84 *dest++ = *op1++ - *op2++;
|
nuclear@10
|
85 }
|
nuclear@10
|
86 return res;
|
nuclear@10
|
87 }
|
nuclear@10
|
88
|
nuclear@10
|
89 Matrix3x3 operator *(const Matrix3x3 &m1, const Matrix3x3 &m2)
|
nuclear@10
|
90 {
|
nuclear@10
|
91 Matrix3x3 res;
|
nuclear@10
|
92 for(int i=0; i<3; i++) {
|
nuclear@10
|
93 for(int j=0; j<3; j++) {
|
nuclear@10
|
94 res.m[i][j] = m1.m[i][0] * m2.m[0][j] + m1.m[i][1] * m2.m[1][j] + m1.m[i][2] * m2.m[2][j];
|
nuclear@10
|
95 }
|
nuclear@10
|
96 }
|
nuclear@10
|
97 return res;
|
nuclear@10
|
98 }
|
nuclear@10
|
99
|
nuclear@10
|
100 void operator +=(Matrix3x3 &m1, const Matrix3x3 &m2)
|
nuclear@10
|
101 {
|
nuclear@10
|
102 scalar_t *op1 = m1.m[0];
|
nuclear@10
|
103 const scalar_t *op2 = m2.m[0];
|
nuclear@10
|
104
|
nuclear@10
|
105 for(int i=0; i<9; i++) {
|
nuclear@10
|
106 *op1++ += *op2++;
|
nuclear@10
|
107 }
|
nuclear@10
|
108 }
|
nuclear@10
|
109
|
nuclear@10
|
110 void operator -=(Matrix3x3 &m1, const Matrix3x3 &m2)
|
nuclear@10
|
111 {
|
nuclear@10
|
112 scalar_t *op1 = m1.m[0];
|
nuclear@10
|
113 const scalar_t *op2 = m2.m[0];
|
nuclear@10
|
114
|
nuclear@10
|
115 for(int i=0; i<9; i++) {
|
nuclear@10
|
116 *op1++ -= *op2++;
|
nuclear@10
|
117 }
|
nuclear@10
|
118 }
|
nuclear@10
|
119
|
nuclear@10
|
120 void operator *=(Matrix3x3 &m1, const Matrix3x3 &m2)
|
nuclear@10
|
121 {
|
nuclear@10
|
122 Matrix3x3 res;
|
nuclear@10
|
123 for(int i=0; i<3; i++) {
|
nuclear@10
|
124 for(int j=0; j<3; j++) {
|
nuclear@10
|
125 res.m[i][j] = m1.m[i][0] * m2.m[0][j] + m1.m[i][1] * m2.m[1][j] + m1.m[i][2] * m2.m[2][j];
|
nuclear@10
|
126 }
|
nuclear@10
|
127 }
|
nuclear@10
|
128 memcpy(m1.m, res.m, 9 * sizeof(scalar_t));
|
nuclear@10
|
129 }
|
nuclear@10
|
130
|
nuclear@10
|
131 Matrix3x3 operator *(const Matrix3x3 &mat, scalar_t scalar)
|
nuclear@10
|
132 {
|
nuclear@10
|
133 Matrix3x3 res;
|
nuclear@10
|
134 const scalar_t *mptr = mat.m[0];
|
nuclear@10
|
135 scalar_t *dptr = res.m[0];
|
nuclear@10
|
136
|
nuclear@10
|
137 for(int i=0; i<9; i++) {
|
nuclear@10
|
138 *dptr++ = *mptr++ * scalar;
|
nuclear@10
|
139 }
|
nuclear@10
|
140 return res;
|
nuclear@10
|
141 }
|
nuclear@10
|
142
|
nuclear@10
|
143 Matrix3x3 operator *(scalar_t scalar, const Matrix3x3 &mat)
|
nuclear@10
|
144 {
|
nuclear@10
|
145 Matrix3x3 res;
|
nuclear@10
|
146 const scalar_t *mptr = mat.m[0];
|
nuclear@10
|
147 scalar_t *dptr = res.m[0];
|
nuclear@10
|
148
|
nuclear@10
|
149 for(int i=0; i<9; i++) {
|
nuclear@10
|
150 *dptr++ = *mptr++ * scalar;
|
nuclear@10
|
151 }
|
nuclear@10
|
152 return res;
|
nuclear@10
|
153 }
|
nuclear@10
|
154
|
nuclear@10
|
155 void operator *=(Matrix3x3 &mat, scalar_t scalar)
|
nuclear@10
|
156 {
|
nuclear@10
|
157 scalar_t *mptr = mat.m[0];
|
nuclear@10
|
158
|
nuclear@10
|
159 for(int i=0; i<9; i++) {
|
nuclear@10
|
160 *mptr++ *= scalar;
|
nuclear@10
|
161 }
|
nuclear@10
|
162 }
|
nuclear@10
|
163
|
nuclear@10
|
164 void Matrix3x3::translate(const Vector2 &trans)
|
nuclear@10
|
165 {
|
nuclear@10
|
166 Matrix3x3 tmat(1, 0, trans.x, 0, 1, trans.y, 0, 0, 1);
|
nuclear@10
|
167 *this *= tmat;
|
nuclear@10
|
168 }
|
nuclear@10
|
169
|
nuclear@10
|
170 void Matrix3x3::set_translation(const Vector2 &trans)
|
nuclear@10
|
171 {
|
nuclear@10
|
172 *this = Matrix3x3(1, 0, trans.x, 0, 1, trans.y, 0, 0, 1);
|
nuclear@10
|
173 }
|
nuclear@10
|
174
|
nuclear@10
|
175 void Matrix3x3::rotate(scalar_t angle)
|
nuclear@10
|
176 {
|
nuclear@10
|
177 scalar_t cos_a = cos(angle);
|
nuclear@10
|
178 scalar_t sin_a = sin(angle);
|
nuclear@10
|
179 Matrix3x3 rmat( cos_a, -sin_a, 0,
|
nuclear@10
|
180 sin_a, cos_a, 0,
|
nuclear@10
|
181 0, 0, 1);
|
nuclear@10
|
182 *this *= rmat;
|
nuclear@10
|
183 }
|
nuclear@10
|
184
|
nuclear@10
|
185 void Matrix3x3::set_rotation(scalar_t angle)
|
nuclear@10
|
186 {
|
nuclear@10
|
187 scalar_t cos_a = cos(angle);
|
nuclear@10
|
188 scalar_t sin_a = sin(angle);
|
nuclear@10
|
189 *this = Matrix3x3(cos_a, -sin_a, 0, sin_a, cos_a, 0, 0, 0, 1);
|
nuclear@10
|
190 }
|
nuclear@10
|
191
|
nuclear@10
|
192 void Matrix3x3::rotate(const Vector3 &euler_angles)
|
nuclear@10
|
193 {
|
nuclear@10
|
194 Matrix3x3 xrot, yrot, zrot;
|
nuclear@10
|
195
|
nuclear@10
|
196 xrot = Matrix3x3( 1, 0, 0,
|
nuclear@10
|
197 0, cos(euler_angles.x), -sin(euler_angles.x),
|
nuclear@10
|
198 0, sin(euler_angles.x), cos(euler_angles.x));
|
nuclear@10
|
199
|
nuclear@10
|
200 yrot = Matrix3x3( cos(euler_angles.y), 0, sin(euler_angles.y),
|
nuclear@10
|
201 0, 1, 0,
|
nuclear@10
|
202 -sin(euler_angles.y), 0, cos(euler_angles.y));
|
nuclear@10
|
203
|
nuclear@10
|
204 zrot = Matrix3x3( cos(euler_angles.z), -sin(euler_angles.z), 0,
|
nuclear@10
|
205 sin(euler_angles.z), cos(euler_angles.z), 0,
|
nuclear@10
|
206 0, 0, 1);
|
nuclear@10
|
207
|
nuclear@10
|
208 *this *= xrot * yrot * zrot;
|
nuclear@10
|
209 }
|
nuclear@10
|
210
|
nuclear@10
|
211 void Matrix3x3::set_rotation(const Vector3 &euler_angles)
|
nuclear@10
|
212 {
|
nuclear@10
|
213 Matrix3x3 xrot, yrot, zrot;
|
nuclear@10
|
214
|
nuclear@10
|
215 xrot = Matrix3x3( 1, 0, 0,
|
nuclear@10
|
216 0, cos(euler_angles.x), -sin(euler_angles.x),
|
nuclear@10
|
217 0, sin(euler_angles.x), cos(euler_angles.x));
|
nuclear@10
|
218
|
nuclear@10
|
219 yrot = Matrix3x3( cos(euler_angles.y), 0, sin(euler_angles.y),
|
nuclear@10
|
220 0, 1, 0,
|
nuclear@10
|
221 -sin(euler_angles.y), 0, cos(euler_angles.y));
|
nuclear@10
|
222
|
nuclear@10
|
223 zrot = Matrix3x3( cos(euler_angles.z), -sin(euler_angles.z), 0,
|
nuclear@10
|
224 sin(euler_angles.z), cos(euler_angles.z), 0,
|
nuclear@10
|
225 0, 0, 1);
|
nuclear@10
|
226
|
nuclear@10
|
227 *this = xrot * yrot * zrot;
|
nuclear@10
|
228 }
|
nuclear@10
|
229
|
nuclear@10
|
230 void Matrix3x3::rotate(const Vector3 &axis, scalar_t angle)
|
nuclear@10
|
231 {
|
nuclear@10
|
232 scalar_t sina = (scalar_t)sin(angle);
|
nuclear@10
|
233 scalar_t cosa = (scalar_t)cos(angle);
|
nuclear@10
|
234 scalar_t invcosa = 1-cosa;
|
nuclear@10
|
235 scalar_t nxsq = axis.x * axis.x;
|
nuclear@10
|
236 scalar_t nysq = axis.y * axis.y;
|
nuclear@10
|
237 scalar_t nzsq = axis.z * axis.z;
|
nuclear@10
|
238
|
nuclear@10
|
239 Matrix3x3 xform;
|
nuclear@10
|
240 xform.m[0][0] = nxsq + (1-nxsq) * cosa;
|
nuclear@10
|
241 xform.m[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
|
nuclear@10
|
242 xform.m[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
|
nuclear@10
|
243
|
nuclear@10
|
244 xform.m[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
|
nuclear@10
|
245 xform.m[1][1] = nysq + (1-nysq) * cosa;
|
nuclear@10
|
246 xform.m[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
|
nuclear@10
|
247
|
nuclear@10
|
248 xform.m[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
|
nuclear@10
|
249 xform.m[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
|
nuclear@10
|
250 xform.m[2][2] = nzsq + (1-nzsq) * cosa;
|
nuclear@10
|
251
|
nuclear@10
|
252 *this *= xform;
|
nuclear@10
|
253 }
|
nuclear@10
|
254
|
nuclear@10
|
255 void Matrix3x3::set_rotation(const Vector3 &axis, scalar_t angle)
|
nuclear@10
|
256 {
|
nuclear@10
|
257 scalar_t sina = (scalar_t)sin(angle);
|
nuclear@10
|
258 scalar_t cosa = (scalar_t)cos(angle);
|
nuclear@10
|
259 scalar_t invcosa = 1-cosa;
|
nuclear@10
|
260 scalar_t nxsq = axis.x * axis.x;
|
nuclear@10
|
261 scalar_t nysq = axis.y * axis.y;
|
nuclear@10
|
262 scalar_t nzsq = axis.z * axis.z;
|
nuclear@10
|
263
|
nuclear@10
|
264 reset_identity();
|
nuclear@10
|
265 m[0][0] = nxsq + (1-nxsq) * cosa;
|
nuclear@10
|
266 m[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
|
nuclear@10
|
267 m[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
|
nuclear@10
|
268 m[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
|
nuclear@10
|
269 m[1][1] = nysq + (1-nysq) * cosa;
|
nuclear@10
|
270 m[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
|
nuclear@10
|
271 m[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
|
nuclear@10
|
272 m[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
|
nuclear@10
|
273 m[2][2] = nzsq + (1-nzsq) * cosa;
|
nuclear@10
|
274 }
|
nuclear@10
|
275
|
nuclear@10
|
276 // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
|
nuclear@10
|
277 // article "Quaternion Calculus and Fast Animation".
|
nuclear@10
|
278 // adapted from: http://www.geometrictools.com/LibMathematics/Algebra/Wm5Quaternion.inl
|
nuclear@10
|
279 Quaternion Matrix3x3::get_rotation_quat() const
|
nuclear@10
|
280 {
|
nuclear@10
|
281 static const int next[3] = {1, 2, 0};
|
nuclear@10
|
282
|
nuclear@10
|
283 float quat[4];
|
nuclear@10
|
284
|
nuclear@10
|
285 scalar_t trace = m[0][0] + m[1][1] + m[2][2];
|
nuclear@10
|
286 scalar_t root;
|
nuclear@10
|
287
|
nuclear@10
|
288 if(trace > 0.0f) {
|
nuclear@10
|
289 // |w| > 1/2
|
nuclear@10
|
290 root = sqrt(trace + 1.0f); // 2w
|
nuclear@10
|
291 quat[0] = 0.5f * root;
|
nuclear@10
|
292 root = 0.5f / root; // 1 / 4w
|
nuclear@10
|
293 quat[1] = (m[2][1] - m[1][2]) * root;
|
nuclear@10
|
294 quat[2] = (m[0][2] - m[2][0]) * root;
|
nuclear@10
|
295 quat[3] = (m[1][0] - m[0][1]) * root;
|
nuclear@10
|
296 } else {
|
nuclear@10
|
297 // |w| <= 1/2
|
nuclear@10
|
298 int i = 0;
|
nuclear@10
|
299 if(m[1][1] > m[0][0]) {
|
nuclear@10
|
300 i = 1;
|
nuclear@10
|
301 }
|
nuclear@10
|
302 if(m[2][2] > m[i][i]) {
|
nuclear@10
|
303 i = 2;
|
nuclear@10
|
304 }
|
nuclear@10
|
305 int j = next[i];
|
nuclear@10
|
306 int k = next[j];
|
nuclear@10
|
307
|
nuclear@10
|
308 root = sqrt(m[i][i] - m[j][j] - m[k][k] + 1.0f);
|
nuclear@10
|
309 quat[i + 1] = 0.5f * root;
|
nuclear@10
|
310 root = 0.5f / root;
|
nuclear@10
|
311 quat[0] = (m[k][j] - m[j][k]) * root;
|
nuclear@10
|
312 quat[j + 1] = (m[j][i] - m[i][j]) * root;
|
nuclear@10
|
313 quat[k + 1] = (m[k][i] - m[i][k]) * root;
|
nuclear@10
|
314 }
|
nuclear@10
|
315 return Quaternion(quat[0], quat[1], quat[2], quat[3]);
|
nuclear@10
|
316 }
|
nuclear@10
|
317
|
nuclear@10
|
318 void Matrix3x3::scale(const Vector3 &scale_vec)
|
nuclear@10
|
319 {
|
nuclear@10
|
320 Matrix3x3 smat( scale_vec.x, 0, 0,
|
nuclear@10
|
321 0, scale_vec.y, 0,
|
nuclear@10
|
322 0, 0, scale_vec.z);
|
nuclear@10
|
323 *this *= smat;
|
nuclear@10
|
324 }
|
nuclear@10
|
325
|
nuclear@10
|
326 void Matrix3x3::set_scaling(const Vector3 &scale_vec)
|
nuclear@10
|
327 {
|
nuclear@10
|
328 *this = Matrix3x3( scale_vec.x, 0, 0,
|
nuclear@10
|
329 0, scale_vec.y, 0,
|
nuclear@10
|
330 0, 0, scale_vec.z);
|
nuclear@10
|
331 }
|
nuclear@10
|
332
|
nuclear@10
|
333 void Matrix3x3::set_column_vector(const Vector3 &vec, unsigned int col_index)
|
nuclear@10
|
334 {
|
nuclear@10
|
335 m[0][col_index] = vec.x;
|
nuclear@10
|
336 m[1][col_index] = vec.y;
|
nuclear@10
|
337 m[2][col_index] = vec.z;
|
nuclear@10
|
338 }
|
nuclear@10
|
339
|
nuclear@10
|
340 void Matrix3x3::set_row_vector(const Vector3 &vec, unsigned int row_index)
|
nuclear@10
|
341 {
|
nuclear@10
|
342 m[row_index][0] = vec.x;
|
nuclear@10
|
343 m[row_index][1] = vec.y;
|
nuclear@10
|
344 m[row_index][2] = vec.z;
|
nuclear@10
|
345 }
|
nuclear@10
|
346
|
nuclear@10
|
347 Vector3 Matrix3x3::get_column_vector(unsigned int col_index) const
|
nuclear@10
|
348 {
|
nuclear@10
|
349 return Vector3(m[0][col_index], m[1][col_index], m[2][col_index]);
|
nuclear@10
|
350 }
|
nuclear@10
|
351
|
nuclear@10
|
352 Vector3 Matrix3x3::get_row_vector(unsigned int row_index) const
|
nuclear@10
|
353 {
|
nuclear@10
|
354 return Vector3(m[row_index][0], m[row_index][1], m[row_index][2]);
|
nuclear@10
|
355 }
|
nuclear@10
|
356
|
nuclear@10
|
357 void Matrix3x3::transpose()
|
nuclear@10
|
358 {
|
nuclear@10
|
359 Matrix3x3 tmp = *this;
|
nuclear@10
|
360 for(int i=0; i<3; i++) {
|
nuclear@10
|
361 for(int j=0; j<3; j++) {
|
nuclear@10
|
362 m[i][j] = tmp[j][i];
|
nuclear@10
|
363 }
|
nuclear@10
|
364 }
|
nuclear@10
|
365 }
|
nuclear@10
|
366
|
nuclear@10
|
367 Matrix3x3 Matrix3x3::transposed() const
|
nuclear@10
|
368 {
|
nuclear@10
|
369 Matrix3x3 res;
|
nuclear@10
|
370 for(int i=0; i<3; i++) {
|
nuclear@10
|
371 for(int j=0; j<3; j++) {
|
nuclear@10
|
372 res[i][j] = m[j][i];
|
nuclear@10
|
373 }
|
nuclear@10
|
374 }
|
nuclear@10
|
375 return res;
|
nuclear@10
|
376 }
|
nuclear@10
|
377
|
nuclear@10
|
378 scalar_t Matrix3x3::determinant() const
|
nuclear@10
|
379 {
|
nuclear@10
|
380 return m[0][0] * (m[1][1]*m[2][2] - m[1][2]*m[2][1]) -
|
nuclear@10
|
381 m[0][1] * (m[1][0]*m[2][2] - m[1][2]*m[2][0]) +
|
nuclear@10
|
382 m[0][2] * (m[1][0]*m[2][1] - m[1][1]*m[2][0]);
|
nuclear@10
|
383 }
|
nuclear@10
|
384
|
nuclear@10
|
385 Matrix3x3 Matrix3x3::inverse() const
|
nuclear@10
|
386 {
|
nuclear@10
|
387 // TODO: implement 3x3 inverse
|
nuclear@10
|
388 return *this;
|
nuclear@10
|
389 }
|
nuclear@10
|
390
|
nuclear@10
|
391 /*ostream &operator <<(ostream &out, const Matrix3x3 &mat)
|
nuclear@10
|
392 {
|
nuclear@10
|
393 for(int i=0; i<3; i++) {
|
nuclear@10
|
394 char str[100];
|
nuclear@10
|
395 sprintf(str, "[ %12.5f %12.5f %12.5f ]\n", (float)mat.m[i][0], (float)mat.m[i][1], (float)mat.m[i][2]);
|
nuclear@10
|
396 out << str;
|
nuclear@10
|
397 }
|
nuclear@10
|
398 return out;
|
nuclear@10
|
399 }*/
|
nuclear@10
|
400
|
nuclear@10
|
401
|
nuclear@10
|
402
|
nuclear@10
|
403 /* ----------------- Matrix4x4 implementation --------------- */
|
nuclear@10
|
404
|
nuclear@10
|
405 Matrix4x4 Matrix4x4::identity = Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
nuclear@10
|
406
|
nuclear@10
|
407 Matrix4x4::Matrix4x4()
|
nuclear@10
|
408 {
|
nuclear@10
|
409 *this = Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
nuclear@10
|
410 }
|
nuclear@10
|
411
|
nuclear@10
|
412 Matrix4x4::Matrix4x4( scalar_t m11, scalar_t m12, scalar_t m13, scalar_t m14,
|
nuclear@10
|
413 scalar_t m21, scalar_t m22, scalar_t m23, scalar_t m24,
|
nuclear@10
|
414 scalar_t m31, scalar_t m32, scalar_t m33, scalar_t m34,
|
nuclear@10
|
415 scalar_t m41, scalar_t m42, scalar_t m43, scalar_t m44)
|
nuclear@10
|
416 {
|
nuclear@10
|
417 m[0][0] = m11; m[0][1] = m12; m[0][2] = m13; m[0][3] = m14;
|
nuclear@10
|
418 m[1][0] = m21; m[1][1] = m22; m[1][2] = m23; m[1][3] = m24;
|
nuclear@10
|
419 m[2][0] = m31; m[2][1] = m32; m[2][2] = m33; m[2][3] = m34;
|
nuclear@10
|
420 m[3][0] = m41; m[3][1] = m42; m[3][2] = m43; m[3][3] = m44;
|
nuclear@10
|
421 }
|
nuclear@10
|
422
|
nuclear@10
|
423 Matrix4x4::Matrix4x4(const mat4_t cmat)
|
nuclear@10
|
424 {
|
nuclear@10
|
425 memcpy(m, cmat, sizeof(mat4_t));
|
nuclear@10
|
426 }
|
nuclear@10
|
427
|
nuclear@10
|
428 Matrix4x4::Matrix4x4(const Matrix3x3 &mat3x3)
|
nuclear@10
|
429 {
|
nuclear@10
|
430 reset_identity();
|
nuclear@10
|
431 for(int i=0; i<3; i++) {
|
nuclear@10
|
432 for(int j=0; j<3; j++) {
|
nuclear@10
|
433 m[i][j] = mat3x3[i][j];
|
nuclear@10
|
434 }
|
nuclear@10
|
435 }
|
nuclear@10
|
436 }
|
nuclear@10
|
437
|
nuclear@10
|
438 Matrix4x4 operator +(const Matrix4x4 &m1, const Matrix4x4 &m2)
|
nuclear@10
|
439 {
|
nuclear@10
|
440 Matrix4x4 res;
|
nuclear@10
|
441 const scalar_t *op1 = m1.m[0], *op2 = m2.m[0];
|
nuclear@10
|
442 scalar_t *dest = res.m[0];
|
nuclear@10
|
443
|
nuclear@10
|
444 for(int i=0; i<16; i++) {
|
nuclear@10
|
445 *dest++ = *op1++ + *op2++;
|
nuclear@10
|
446 }
|
nuclear@10
|
447 return res;
|
nuclear@10
|
448 }
|
nuclear@10
|
449
|
nuclear@10
|
450 Matrix4x4 operator -(const Matrix4x4 &m1, const Matrix4x4 &m2)
|
nuclear@10
|
451 {
|
nuclear@10
|
452 Matrix4x4 res;
|
nuclear@10
|
453 const scalar_t *op1 = m1.m[0], *op2 = m2.m[0];
|
nuclear@10
|
454 scalar_t *dest = res.m[0];
|
nuclear@10
|
455
|
nuclear@10
|
456 for(int i=0; i<16; i++) {
|
nuclear@10
|
457 *dest++ = *op1++ - *op2++;
|
nuclear@10
|
458 }
|
nuclear@10
|
459 return res;
|
nuclear@10
|
460 }
|
nuclear@10
|
461
|
nuclear@10
|
462 void operator +=(Matrix4x4 &m1, const Matrix4x4 &m2)
|
nuclear@10
|
463 {
|
nuclear@10
|
464 scalar_t *op1 = m1.m[0];
|
nuclear@10
|
465 const scalar_t *op2 = m2.m[0];
|
nuclear@10
|
466
|
nuclear@10
|
467 for(int i=0; i<16; i++) {
|
nuclear@10
|
468 *op1++ += *op2++;
|
nuclear@10
|
469 }
|
nuclear@10
|
470 }
|
nuclear@10
|
471
|
nuclear@10
|
472 void operator -=(Matrix4x4 &m1, const Matrix4x4 &m2)
|
nuclear@10
|
473 {
|
nuclear@10
|
474 scalar_t *op1 = m1.m[0];
|
nuclear@10
|
475 const scalar_t *op2 = m2.m[0];
|
nuclear@10
|
476
|
nuclear@10
|
477 for(int i=0; i<16; i++) {
|
nuclear@10
|
478 *op1++ -= *op2++;
|
nuclear@10
|
479 }
|
nuclear@10
|
480 }
|
nuclear@10
|
481
|
nuclear@10
|
482 Matrix4x4 operator *(const Matrix4x4 &mat, scalar_t scalar)
|
nuclear@10
|
483 {
|
nuclear@10
|
484 Matrix4x4 res;
|
nuclear@10
|
485 const scalar_t *mptr = mat.m[0];
|
nuclear@10
|
486 scalar_t *dptr = res.m[0];
|
nuclear@10
|
487
|
nuclear@10
|
488 for(int i=0; i<16; i++) {
|
nuclear@10
|
489 *dptr++ = *mptr++ * scalar;
|
nuclear@10
|
490 }
|
nuclear@10
|
491 return res;
|
nuclear@10
|
492 }
|
nuclear@10
|
493
|
nuclear@10
|
494 Matrix4x4 operator *(scalar_t scalar, const Matrix4x4 &mat)
|
nuclear@10
|
495 {
|
nuclear@10
|
496 Matrix4x4 res;
|
nuclear@10
|
497 const scalar_t *mptr = mat.m[0];
|
nuclear@10
|
498 scalar_t *dptr = res.m[0];
|
nuclear@10
|
499
|
nuclear@10
|
500 for(int i=0; i<16; i++) {
|
nuclear@10
|
501 *dptr++ = *mptr++ * scalar;
|
nuclear@10
|
502 }
|
nuclear@10
|
503 return res;
|
nuclear@10
|
504 }
|
nuclear@10
|
505
|
nuclear@10
|
506 void operator *=(Matrix4x4 &mat, scalar_t scalar)
|
nuclear@10
|
507 {
|
nuclear@10
|
508 scalar_t *mptr = mat.m[0];
|
nuclear@10
|
509
|
nuclear@10
|
510 for(int i=0; i<16; i++) {
|
nuclear@10
|
511 *mptr++ *= scalar;
|
nuclear@10
|
512 }
|
nuclear@10
|
513 }
|
nuclear@10
|
514
|
nuclear@10
|
515 void Matrix4x4::translate(const Vector3 &trans)
|
nuclear@10
|
516 {
|
nuclear@10
|
517 Matrix4x4 tmat(1, 0, 0, trans.x, 0, 1, 0, trans.y, 0, 0, 1, trans.z, 0, 0, 0, 1);
|
nuclear@10
|
518 *this *= tmat;
|
nuclear@10
|
519 }
|
nuclear@10
|
520
|
nuclear@10
|
521 void Matrix4x4::set_translation(const Vector3 &trans)
|
nuclear@10
|
522 {
|
nuclear@10
|
523 *this = Matrix4x4(1, 0, 0, trans.x, 0, 1, 0, trans.y, 0, 0, 1, trans.z, 0, 0, 0, 1);
|
nuclear@10
|
524 }
|
nuclear@10
|
525
|
nuclear@10
|
526 Vector3 Matrix4x4::get_translation() const
|
nuclear@10
|
527 {
|
nuclear@10
|
528 return Vector3(m[0][3], m[1][3], m[2][3]);
|
nuclear@10
|
529 }
|
nuclear@10
|
530
|
nuclear@10
|
531 void Matrix4x4::rotate(const Vector3 &euler_angles)
|
nuclear@10
|
532 {
|
nuclear@10
|
533 Matrix3x3 xrot, yrot, zrot;
|
nuclear@10
|
534
|
nuclear@10
|
535 xrot = Matrix3x3( 1, 0, 0,
|
nuclear@10
|
536 0, cos(euler_angles.x), -sin(euler_angles.x),
|
nuclear@10
|
537 0, sin(euler_angles.x), cos(euler_angles.x));
|
nuclear@10
|
538
|
nuclear@10
|
539 yrot = Matrix3x3( cos(euler_angles.y), 0, sin(euler_angles.y),
|
nuclear@10
|
540 0, 1, 0,
|
nuclear@10
|
541 -sin(euler_angles.y), 0, cos(euler_angles.y));
|
nuclear@10
|
542
|
nuclear@10
|
543 zrot = Matrix3x3( cos(euler_angles.z), -sin(euler_angles.z), 0,
|
nuclear@10
|
544 sin(euler_angles.z), cos(euler_angles.z), 0,
|
nuclear@10
|
545 0, 0, 1);
|
nuclear@10
|
546
|
nuclear@10
|
547 *this *= Matrix4x4(xrot * yrot * zrot);
|
nuclear@10
|
548 }
|
nuclear@10
|
549
|
nuclear@10
|
550 void Matrix4x4::set_rotation(const Vector3 &euler_angles)
|
nuclear@10
|
551 {
|
nuclear@10
|
552 Matrix3x3 xrot, yrot, zrot;
|
nuclear@10
|
553
|
nuclear@10
|
554 xrot = Matrix3x3( 1, 0, 0,
|
nuclear@10
|
555 0, cos(euler_angles.x), -sin(euler_angles.x),
|
nuclear@10
|
556 0, sin(euler_angles.x), cos(euler_angles.x));
|
nuclear@10
|
557
|
nuclear@10
|
558 yrot = Matrix3x3( cos(euler_angles.y), 0, sin(euler_angles.y),
|
nuclear@10
|
559 0, 1, 0,
|
nuclear@10
|
560 -sin(euler_angles.y), 0, cos(euler_angles.y));
|
nuclear@10
|
561
|
nuclear@10
|
562 zrot = Matrix3x3( cos(euler_angles.z), -sin(euler_angles.z), 0,
|
nuclear@10
|
563 sin(euler_angles.z), cos(euler_angles.z), 0,
|
nuclear@10
|
564 0, 0, 1);
|
nuclear@10
|
565
|
nuclear@10
|
566 *this = Matrix4x4(xrot * yrot * zrot);
|
nuclear@10
|
567 }
|
nuclear@10
|
568
|
nuclear@10
|
569 void Matrix4x4::rotate(const Vector3 &axis, scalar_t angle)
|
nuclear@10
|
570 {
|
nuclear@10
|
571 scalar_t sina = (scalar_t)sin(angle);
|
nuclear@10
|
572 scalar_t cosa = (scalar_t)cos(angle);
|
nuclear@10
|
573 scalar_t invcosa = 1-cosa;
|
nuclear@10
|
574 scalar_t nxsq = axis.x * axis.x;
|
nuclear@10
|
575 scalar_t nysq = axis.y * axis.y;
|
nuclear@10
|
576 scalar_t nzsq = axis.z * axis.z;
|
nuclear@10
|
577
|
nuclear@10
|
578 Matrix4x4 xform;
|
nuclear@10
|
579 xform[0][0] = nxsq + (1-nxsq) * cosa;
|
nuclear@10
|
580 xform[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
|
nuclear@10
|
581 xform[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
|
nuclear@10
|
582 xform[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
|
nuclear@10
|
583 xform[1][1] = nysq + (1-nysq) * cosa;
|
nuclear@10
|
584 xform[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
|
nuclear@10
|
585 xform[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
|
nuclear@10
|
586 xform[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
|
nuclear@10
|
587 xform[2][2] = nzsq + (1-nzsq) * cosa;
|
nuclear@10
|
588
|
nuclear@10
|
589 *this *= xform;
|
nuclear@10
|
590 }
|
nuclear@10
|
591
|
nuclear@10
|
592 void Matrix4x4::set_rotation(const Vector3 &axis, scalar_t angle)
|
nuclear@10
|
593 {
|
nuclear@10
|
594 scalar_t sina = (scalar_t)sin(angle);
|
nuclear@10
|
595 scalar_t cosa = (scalar_t)cos(angle);
|
nuclear@10
|
596 scalar_t invcosa = 1-cosa;
|
nuclear@10
|
597 scalar_t nxsq = axis.x * axis.x;
|
nuclear@10
|
598 scalar_t nysq = axis.y * axis.y;
|
nuclear@10
|
599 scalar_t nzsq = axis.z * axis.z;
|
nuclear@10
|
600
|
nuclear@10
|
601 reset_identity();
|
nuclear@10
|
602 m[0][0] = nxsq + (1-nxsq) * cosa;
|
nuclear@10
|
603 m[0][1] = axis.x * axis.y * invcosa - axis.z * sina;
|
nuclear@10
|
604 m[0][2] = axis.x * axis.z * invcosa + axis.y * sina;
|
nuclear@10
|
605 m[1][0] = axis.x * axis.y * invcosa + axis.z * sina;
|
nuclear@10
|
606 m[1][1] = nysq + (1-nysq) * cosa;
|
nuclear@10
|
607 m[1][2] = axis.y * axis.z * invcosa - axis.x * sina;
|
nuclear@10
|
608 m[2][0] = axis.x * axis.z * invcosa - axis.y * sina;
|
nuclear@10
|
609 m[2][1] = axis.y * axis.z * invcosa + axis.x * sina;
|
nuclear@10
|
610 m[2][2] = nzsq + (1-nzsq) * cosa;
|
nuclear@10
|
611 }
|
nuclear@10
|
612
|
nuclear@10
|
613 void Matrix4x4::rotate(const Quaternion &quat)
|
nuclear@10
|
614 {
|
nuclear@10
|
615 *this *= quat.get_rotation_matrix();
|
nuclear@10
|
616 }
|
nuclear@10
|
617
|
nuclear@10
|
618 void Matrix4x4::set_rotation(const Quaternion &quat)
|
nuclear@10
|
619 {
|
nuclear@10
|
620 *this = quat.get_rotation_matrix();
|
nuclear@10
|
621 }
|
nuclear@10
|
622
|
nuclear@10
|
623 Quaternion Matrix4x4::get_rotation_quat() const
|
nuclear@10
|
624 {
|
nuclear@10
|
625 Matrix3x3 mat3 = *this;
|
nuclear@10
|
626 return mat3.get_rotation_quat();
|
nuclear@10
|
627 }
|
nuclear@10
|
628
|
nuclear@10
|
629 void Matrix4x4::scale(const Vector4 &scale_vec)
|
nuclear@10
|
630 {
|
nuclear@10
|
631 Matrix4x4 smat( scale_vec.x, 0, 0, 0,
|
nuclear@10
|
632 0, scale_vec.y, 0, 0,
|
nuclear@10
|
633 0, 0, scale_vec.z, 0,
|
nuclear@10
|
634 0, 0, 0, scale_vec.w);
|
nuclear@10
|
635 *this *= smat;
|
nuclear@10
|
636 }
|
nuclear@10
|
637
|
nuclear@10
|
638 void Matrix4x4::set_scaling(const Vector4 &scale_vec)
|
nuclear@10
|
639 {
|
nuclear@10
|
640 *this = Matrix4x4( scale_vec.x, 0, 0, 0,
|
nuclear@10
|
641 0, scale_vec.y, 0, 0,
|
nuclear@10
|
642 0, 0, scale_vec.z, 0,
|
nuclear@10
|
643 0, 0, 0, scale_vec.w);
|
nuclear@10
|
644 }
|
nuclear@10
|
645
|
nuclear@10
|
646 Vector3 Matrix4x4::get_scaling() const
|
nuclear@10
|
647 {
|
nuclear@10
|
648 Vector3 vi = get_row_vector(0);
|
nuclear@10
|
649 Vector3 vj = get_row_vector(1);
|
nuclear@10
|
650 Vector3 vk = get_row_vector(2);
|
nuclear@10
|
651
|
nuclear@10
|
652 return Vector3(vi.length(), vj.length(), vk.length());
|
nuclear@10
|
653 }
|
nuclear@10
|
654
|
nuclear@10
|
655 void Matrix4x4::set_frustum(float left, float right, float bottom, float top, float znear, float zfar)
|
nuclear@10
|
656 {
|
nuclear@10
|
657 float dx = right - left;
|
nuclear@10
|
658 float dy = top - bottom;
|
nuclear@10
|
659 float dz = zfar - znear;
|
nuclear@10
|
660
|
nuclear@10
|
661 float a = (right + left) / dx;
|
nuclear@10
|
662 float b = (top + bottom) / dy;
|
nuclear@10
|
663 float c = -(zfar + znear) / dz;
|
nuclear@10
|
664 float d = -2.0 * zfar * znear / dz;
|
nuclear@10
|
665
|
nuclear@10
|
666 *this = Matrix4x4(2.0 * znear / dx, 0, a, 0,
|
nuclear@10
|
667 0, 2.0 * znear / dy, b, 0,
|
nuclear@10
|
668 0, 0, c, d,
|
nuclear@10
|
669 0, 0, -1, 0);
|
nuclear@10
|
670 }
|
nuclear@10
|
671
|
nuclear@10
|
672 void Matrix4x4::set_perspective(float vfov, float aspect, float znear, float zfar)
|
nuclear@10
|
673 {
|
nuclear@10
|
674 float f = 1.0f / tan(vfov * 0.5f);
|
nuclear@10
|
675 float dz = znear - zfar;
|
nuclear@10
|
676
|
nuclear@10
|
677 reset_identity();
|
nuclear@10
|
678
|
nuclear@10
|
679 m[0][0] = f / aspect;
|
nuclear@10
|
680 m[1][1] = f;
|
nuclear@10
|
681 m[2][2] = (zfar + znear) / dz;
|
nuclear@10
|
682 m[3][2] = -1.0f;
|
nuclear@10
|
683 m[2][3] = 2.0f * zfar * znear / dz;
|
nuclear@10
|
684 m[3][3] = 0.0f;
|
nuclear@10
|
685 }
|
nuclear@10
|
686
|
nuclear@10
|
687 void Matrix4x4::set_orthographic(float left, float right, float bottom, float top, float znear, float zfar)
|
nuclear@10
|
688 {
|
nuclear@10
|
689 float dx = right - left;
|
nuclear@10
|
690 float dy = top - bottom;
|
nuclear@10
|
691 float dz = zfar - znear;
|
nuclear@10
|
692
|
nuclear@10
|
693 reset_identity();
|
nuclear@10
|
694
|
nuclear@10
|
695 m[0][0] = 2.0 / dx;
|
nuclear@10
|
696 m[1][1] = 2.0 / dy;
|
nuclear@10
|
697 m[2][2] = -2.0 / dz;
|
nuclear@10
|
698 m[0][3] = -(right + left) / dx;
|
nuclear@10
|
699 m[1][3] = -(top + bottom) / dy;
|
nuclear@10
|
700 m[2][3] = -(zfar + znear) / dz;
|
nuclear@10
|
701 }
|
nuclear@10
|
702
|
nuclear@10
|
703 void Matrix4x4::set_lookat(const Vector3 &pos, const Vector3 &targ, const Vector3 &up)
|
nuclear@10
|
704 {
|
nuclear@10
|
705 Vector3 vk = (targ - pos).normalized();
|
nuclear@10
|
706 Vector3 vj = up.normalized();
|
nuclear@10
|
707 Vector3 vi = cross_product(vk, vj).normalized();
|
nuclear@10
|
708 vj = cross_product(vi, vk);
|
nuclear@10
|
709
|
nuclear@10
|
710 *this = Matrix4x4(
|
nuclear@10
|
711 vi.x, vi.y, vi.z, 0,
|
nuclear@10
|
712 vj.x, vj.y, vj.z, 0,
|
nuclear@10
|
713 -vk.x, -vk.y, -vk.z, 0,
|
nuclear@10
|
714 0, 0, 0, 1);
|
nuclear@10
|
715 translate(-pos);
|
nuclear@10
|
716 }
|
nuclear@10
|
717
|
nuclear@10
|
718 void Matrix4x4::set_column_vector(const Vector4 &vec, unsigned int col_index)
|
nuclear@10
|
719 {
|
nuclear@10
|
720 m[0][col_index] = vec.x;
|
nuclear@10
|
721 m[1][col_index] = vec.y;
|
nuclear@10
|
722 m[2][col_index] = vec.z;
|
nuclear@10
|
723 m[3][col_index] = vec.w;
|
nuclear@10
|
724 }
|
nuclear@10
|
725
|
nuclear@10
|
726 void Matrix4x4::set_row_vector(const Vector4 &vec, unsigned int row_index)
|
nuclear@10
|
727 {
|
nuclear@10
|
728 m[row_index][0] = vec.x;
|
nuclear@10
|
729 m[row_index][1] = vec.y;
|
nuclear@10
|
730 m[row_index][2] = vec.z;
|
nuclear@10
|
731 m[row_index][3] = vec.w;
|
nuclear@10
|
732 }
|
nuclear@10
|
733
|
nuclear@10
|
734 Vector4 Matrix4x4::get_column_vector(unsigned int col_index) const
|
nuclear@10
|
735 {
|
nuclear@10
|
736 return Vector4(m[0][col_index], m[1][col_index], m[2][col_index], m[3][col_index]);
|
nuclear@10
|
737 }
|
nuclear@10
|
738
|
nuclear@10
|
739 Vector4 Matrix4x4::get_row_vector(unsigned int row_index) const
|
nuclear@10
|
740 {
|
nuclear@10
|
741 return Vector4(m[row_index][0], m[row_index][1], m[row_index][2], m[row_index][3]);
|
nuclear@10
|
742 }
|
nuclear@10
|
743
|
nuclear@10
|
744 void Matrix4x4::transpose()
|
nuclear@10
|
745 {
|
nuclear@10
|
746 Matrix4x4 tmp = *this;
|
nuclear@10
|
747 for(int i=0; i<4; i++) {
|
nuclear@10
|
748 for(int j=0; j<4; j++) {
|
nuclear@10
|
749 m[i][j] = tmp[j][i];
|
nuclear@10
|
750 }
|
nuclear@10
|
751 }
|
nuclear@10
|
752 }
|
nuclear@10
|
753
|
nuclear@10
|
754 Matrix4x4 Matrix4x4::transposed() const
|
nuclear@10
|
755 {
|
nuclear@10
|
756 Matrix4x4 res;
|
nuclear@10
|
757 for(int i=0; i<4; i++) {
|
nuclear@10
|
758 for(int j=0; j<4; j++) {
|
nuclear@10
|
759 res[i][j] = m[j][i];
|
nuclear@10
|
760 }
|
nuclear@10
|
761 }
|
nuclear@10
|
762 return res;
|
nuclear@10
|
763 }
|
nuclear@10
|
764
|
nuclear@10
|
765 scalar_t Matrix4x4::determinant() const
|
nuclear@10
|
766 {
|
nuclear@10
|
767 scalar_t det11 = (m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
|
nuclear@10
|
768 (m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
|
nuclear@10
|
769 (m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
|
nuclear@10
|
770
|
nuclear@10
|
771 scalar_t det12 = (m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
|
nuclear@10
|
772 (m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
|
nuclear@10
|
773 (m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
|
nuclear@10
|
774
|
nuclear@10
|
775 scalar_t det13 = (m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
|
nuclear@10
|
776 (m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
|
nuclear@10
|
777 (m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
|
nuclear@10
|
778
|
nuclear@10
|
779 scalar_t det14 = (m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
|
nuclear@10
|
780 (m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
|
nuclear@10
|
781 (m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
|
nuclear@10
|
782
|
nuclear@10
|
783 return m[0][0] * det11 - m[0][1] * det12 + m[0][2] * det13 - m[0][3] * det14;
|
nuclear@10
|
784 }
|
nuclear@10
|
785
|
nuclear@10
|
786
|
nuclear@10
|
787 Matrix4x4 Matrix4x4::adjoint() const
|
nuclear@10
|
788 {
|
nuclear@10
|
789 Matrix4x4 coef;
|
nuclear@10
|
790
|
nuclear@10
|
791 coef.m[0][0] = (m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
|
nuclear@10
|
792 (m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
|
nuclear@10
|
793 (m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
|
nuclear@10
|
794 coef.m[0][1] = (m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
|
nuclear@10
|
795 (m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
|
nuclear@10
|
796 (m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
|
nuclear@10
|
797 coef.m[0][2] = (m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
|
nuclear@10
|
798 (m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
|
nuclear@10
|
799 (m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
|
nuclear@10
|
800 coef.m[0][3] = (m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
|
nuclear@10
|
801 (m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
|
nuclear@10
|
802 (m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
|
nuclear@10
|
803
|
nuclear@10
|
804 coef.m[1][0] = (m[0][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
|
nuclear@10
|
805 (m[0][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) +
|
nuclear@10
|
806 (m[0][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2]));
|
nuclear@10
|
807 coef.m[1][1] = (m[0][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) -
|
nuclear@10
|
808 (m[0][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
|
nuclear@10
|
809 (m[0][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2]));
|
nuclear@10
|
810 coef.m[1][2] = (m[0][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) -
|
nuclear@10
|
811 (m[0][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) +
|
nuclear@10
|
812 (m[0][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
|
nuclear@10
|
813 coef.m[1][3] = (m[0][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) -
|
nuclear@10
|
814 (m[0][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) +
|
nuclear@10
|
815 (m[0][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1]));
|
nuclear@10
|
816
|
nuclear@10
|
817 coef.m[2][0] = (m[0][1] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) -
|
nuclear@10
|
818 (m[0][2] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) +
|
nuclear@10
|
819 (m[0][3] * (m[1][1] * m[3][2] - m[3][1] * m[1][2]));
|
nuclear@10
|
820 coef.m[2][1] = (m[0][0] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) -
|
nuclear@10
|
821 (m[0][2] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) +
|
nuclear@10
|
822 (m[0][3] * (m[1][0] * m[3][2] - m[3][0] * m[1][2]));
|
nuclear@10
|
823 coef.m[2][2] = (m[0][0] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) -
|
nuclear@10
|
824 (m[0][1] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) +
|
nuclear@10
|
825 (m[0][3] * (m[1][0] * m[3][1] - m[3][0] * m[1][1]));
|
nuclear@10
|
826 coef.m[2][3] = (m[0][0] * (m[1][1] * m[3][2] - m[3][1] * m[1][2])) -
|
nuclear@10
|
827 (m[0][1] * (m[1][0] * m[3][2] - m[3][0] * m[1][2])) +
|
nuclear@10
|
828 (m[0][2] * (m[1][0] * m[3][1] - m[3][0] * m[1][1]));
|
nuclear@10
|
829
|
nuclear@10
|
830 coef.m[3][0] = (m[0][1] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) -
|
nuclear@10
|
831 (m[0][2] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) +
|
nuclear@10
|
832 (m[0][3] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]));
|
nuclear@10
|
833 coef.m[3][1] = (m[0][0] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) -
|
nuclear@10
|
834 (m[0][2] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) +
|
nuclear@10
|
835 (m[0][3] * (m[1][0] * m[2][2] - m[2][0] * m[1][2]));
|
nuclear@10
|
836 coef.m[3][2] = (m[0][0] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) -
|
nuclear@10
|
837 (m[0][1] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) +
|
nuclear@10
|
838 (m[0][3] * (m[1][0] * m[2][1] - m[2][0] * m[1][1]));
|
nuclear@10
|
839 coef.m[3][3] = (m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])) -
|
nuclear@10
|
840 (m[0][1] * (m[1][0] * m[2][2] - m[2][0] * m[1][2])) +
|
nuclear@10
|
841 (m[0][2] * (m[1][0] * m[2][1] - m[2][0] * m[1][1]));
|
nuclear@10
|
842
|
nuclear@10
|
843 coef.transpose();
|
nuclear@10
|
844
|
nuclear@10
|
845 for(int i=0; i<4; i++) {
|
nuclear@10
|
846 for(int j=0; j<4; j++) {
|
nuclear@10
|
847 coef.m[i][j] = j%2 ? -coef.m[i][j] : coef.m[i][j];
|
nuclear@10
|
848 if(i%2) coef.m[i][j] = -coef.m[i][j];
|
nuclear@10
|
849 }
|
nuclear@10
|
850 }
|
nuclear@10
|
851
|
nuclear@10
|
852 return coef;
|
nuclear@10
|
853 }
|
nuclear@10
|
854
|
nuclear@10
|
855 Matrix4x4 Matrix4x4::inverse() const
|
nuclear@10
|
856 {
|
nuclear@10
|
857 Matrix4x4 adj = adjoint();
|
nuclear@10
|
858
|
nuclear@10
|
859 return adj * (1.0f / determinant());
|
nuclear@10
|
860 }
|
nuclear@10
|
861
|
nuclear@10
|
862 /*
|
nuclear@10
|
863 ostream &operator <<(ostream &out, const Matrix4x4 &mat)
|
nuclear@10
|
864 {
|
nuclear@10
|
865 for(int i=0; i<4; i++) {
|
nuclear@10
|
866 char str[100];
|
nuclear@10
|
867 sprintf(str, "[ %12.5f %12.5f %12.5f %12.5f ]\n", (float)mat.m[i][0], (float)mat.m[i][1], (float)mat.m[i][2], (float)mat.m[i][3]);
|
nuclear@10
|
868 out << str;
|
nuclear@10
|
869 }
|
nuclear@10
|
870 return out;
|
nuclear@10
|
871 }
|
nuclear@10
|
872 */
|