/src/ogre/OgreMain/include/OgreMatrix4.h
Line | Count | Source |
1 | | /* |
2 | | ----------------------------------------------------------------------------- |
3 | | This source file is part of OGRE |
4 | | (Object-oriented Graphics Rendering Engine) |
5 | | For the latest info, see http://www.ogre3d.org/ |
6 | | |
7 | | Copyright (c) 2000-2014 Torus Knot Software Ltd |
8 | | |
9 | | Permission is hereby granted, free of charge, to any person obtaining a copy |
10 | | of this software and associated documentation files (the "Software"), to deal |
11 | | in the Software without restriction, including without limitation the rights |
12 | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
13 | | copies of the Software, and to permit persons to whom the Software is |
14 | | furnished to do so, subject to the following conditions: |
15 | | |
16 | | The above copyright notice and this permission notice shall be included in |
17 | | all copies or substantial portions of the Software. |
18 | | |
19 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
20 | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
21 | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
22 | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
23 | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
24 | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
25 | | THE SOFTWARE. |
26 | | ----------------------------------------------------------------------------- |
27 | | */ |
28 | | #ifndef __Matrix4__ |
29 | | #define __Matrix4__ |
30 | | |
31 | | // Precompiler options |
32 | | #include "OgrePrerequisites.h" |
33 | | |
34 | | #include "OgreMatrix3.h" |
35 | | #include "OgreVector.h" |
36 | | |
37 | | namespace Ogre |
38 | | { |
39 | | /** \addtogroup Core |
40 | | * @{ |
41 | | */ |
42 | | /** \addtogroup Math |
43 | | * @{ |
44 | | */ |
45 | | class Matrix4; |
46 | | class Affine3; |
47 | | Matrix4 operator*(const Matrix4 &m, const Matrix4 &m2); |
48 | | /** Class encapsulating a standard 4x4 homogeneous matrix. |
49 | | |
50 | | OGRE uses column vectors when applying matrix multiplications, |
51 | | This means a vector is represented as a single column, 4-row |
52 | | matrix. This has the effect that the transformations implemented |
53 | | by the matrices happens right-to-left e.g. if vector V is to be |
54 | | transformed by M1 then M2 then M3, the calculation would be |
55 | | M3 * M2 * M1 * V. The order that matrices are concatenated is |
56 | | vital since matrix multiplication is not commutative, i.e. you |
57 | | can get a different result if you concatenate in the wrong order. |
58 | | @par |
59 | | The use of column vectors and right-to-left ordering is the |
60 | | standard in most mathematical texts, and is the same as used in |
61 | | OpenGL. It is, however, the opposite of Direct3D, which has |
62 | | inexplicably chosen to differ from the accepted standard and uses |
63 | | row vectors and left-to-right matrix multiplication. |
64 | | @par |
65 | | OGRE deals with the differences between D3D and OpenGL etc. |
66 | | internally when operating through different render systems. OGRE |
67 | | users only need to conform to standard maths conventions, i.e. |
68 | | right-to-left matrix multiplication, (OGRE transposes matrices it |
69 | | passes to D3D to compensate). |
70 | | @par |
71 | | The generic form M * V which shows the layout of the matrix |
72 | | entries is shown below: |
73 | | <pre> |
74 | | [ m[0][0] m[0][1] m[0][2] m[0][3] ] {x} |
75 | | | m[1][0] m[1][1] m[1][2] m[1][3] | * {y} |
76 | | | m[2][0] m[2][1] m[2][2] m[2][3] | {z} |
77 | | [ m[3][0] m[3][1] m[3][2] m[3][3] ] {1} |
78 | | </pre> |
79 | | */ |
80 | | template<int rows, typename T> class TransformBase |
81 | | { |
82 | | protected: |
83 | | /// The matrix entries, indexed by [row][col]. |
84 | | T m[rows][4]; |
85 | | // do not reduce storage for affine for compatibility with SSE, shader mat4 types |
86 | | public: |
87 | | /// Do <b>NOT</b> initialize for efficiency. |
88 | | TransformBase() {} |
89 | | |
90 | | template<typename U> |
91 | | explicit TransformBase(const U* ptr) { |
92 | | for (int i = 0; i < rows; i++) |
93 | | for (int j = 0; j < 4; j++) |
94 | | m[i][j] = T(ptr[i*4 + j]); |
95 | | } |
96 | | |
97 | | template<typename U> |
98 | | explicit TransformBase(const TransformBase<rows, U>& o) : TransformBase(o[0]) {} |
99 | | |
100 | | T* operator[](size_t iRow) |
101 | 0 | { |
102 | 0 | assert(iRow < rows); |
103 | 0 | return m[iRow]; |
104 | 0 | } |
105 | | |
106 | | const T* operator[](size_t iRow) const |
107 | 0 | { |
108 | 0 | assert(iRow < rows); |
109 | 0 | return m[iRow]; |
110 | 0 | } |
111 | | |
112 | | /// Sets the translation transformation part of the matrix. |
113 | | void setTrans( const Vector<3, T>& v ) |
114 | | { |
115 | | assert(rows > 2); |
116 | | m[0][3] = v[0]; |
117 | | m[1][3] = v[1]; |
118 | | m[2][3] = v[2]; |
119 | | } |
120 | | /// Extracts the translation transformation part of the matrix. |
121 | | Vector<3, T> getTrans() const |
122 | | { |
123 | | assert(rows > 2); |
124 | | return Vector<3, T>(m[0][3], m[1][3], m[2][3]); |
125 | | } |
126 | | /// Sets the scale part of the matrix. |
127 | | void setScale( const Vector<3, T>& v ) |
128 | | { |
129 | | assert(rows > 2); |
130 | | m[0][0] = v[0]; |
131 | | m[1][1] = v[1]; |
132 | | m[2][2] = v[2]; |
133 | | } |
134 | | }; |
135 | | |
136 | | /** Function for writing to a stream. |
137 | | */ |
138 | | template <typename CharT, typename TraitsT, int rows, typename T> |
139 | | std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& o, |
140 | | const TransformBase<rows, T>& mat) |
141 | | { |
142 | | o << "Matrix" << rows << "x4("; |
143 | | for (size_t i = 0; i < rows; ++i) |
144 | | { |
145 | | for (size_t j = 0; j < 4; ++j) |
146 | | { |
147 | | o << mat[i][j]; |
148 | | if(j != 3) |
149 | | o << ", "; |
150 | | } |
151 | | |
152 | | if(i != (rows - 1)) |
153 | | o << "; "; |
154 | | } |
155 | | o << ")"; |
156 | | return o; |
157 | | } |
158 | | |
159 | | struct _OgreExport TransformBaseReal : public TransformBase<4, Real> |
160 | | { |
161 | | /// Do <b>NOT</b> initialize for efficiency. |
162 | 0 | TransformBaseReal() {} |
163 | | template<typename U> |
164 | | explicit TransformBaseReal(const U* ptr) : TransformBase(ptr) {} |
165 | | /** Builds a translation matrix |
166 | | */ |
167 | | void makeTrans( const Vector3& v ) |
168 | 0 | { |
169 | 0 | makeTrans(v.x, v.y, v.z); |
170 | 0 | } |
171 | | |
172 | | void makeTrans( Real tx, Real ty, Real tz ) |
173 | 0 | { |
174 | 0 | m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = tx; |
175 | 0 | m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = ty; |
176 | 0 | m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = tz; |
177 | 0 | m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 1.0; |
178 | 0 | } |
179 | | |
180 | | /** Assignment from 3x3 matrix. |
181 | | */ |
182 | | void set3x3Matrix(const Matrix3& mat3) |
183 | 0 | { |
184 | 0 | m[0][0] = mat3[0][0]; m[0][1] = mat3[0][1]; m[0][2] = mat3[0][2]; |
185 | 0 | m[1][0] = mat3[1][0]; m[1][1] = mat3[1][1]; m[1][2] = mat3[1][2]; |
186 | 0 | m[2][0] = mat3[2][0]; m[2][1] = mat3[2][1]; m[2][2] = mat3[2][2]; |
187 | 0 | } |
188 | | |
189 | | /** Extracts the rotation / scaling part of the Matrix as a 3x3 matrix. |
190 | | */ |
191 | | Matrix3 linear() const |
192 | 0 | { |
193 | 0 | return Matrix3(m[0][0], m[0][1], m[0][2], |
194 | 0 | m[1][0], m[1][1], m[1][2], |
195 | 0 | m[2][0], m[2][1], m[2][2]); |
196 | 0 | } |
197 | | |
198 | 0 | OGRE_DEPRECATED void extract3x3Matrix(Matrix3& m3x3) const { m3x3 = linear(); } |
199 | 0 | OGRE_DEPRECATED Quaternion extractQuaternion() const { return Quaternion(linear()); } |
200 | | |
201 | | Real determinant() const; |
202 | | |
203 | | Matrix4 transpose() const; |
204 | | |
205 | | /** Building a Affine3 from orientation / scale / position. |
206 | | |
207 | | Transform is performed in the order scale, rotate, translation, i.e. translation is independent |
208 | | of orientation axes, scale does not affect size of translation, rotation and scaling are always |
209 | | centered on the origin. |
210 | | */ |
211 | | void makeTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation); |
212 | | |
213 | | /** Building an inverse Affine3 from orientation / scale / position. |
214 | | |
215 | | As makeTransform except it build the inverse given the same data as makeTransform, so |
216 | | performing -translation, -rotate, 1/scale in that order. |
217 | | */ |
218 | | void makeInverseTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation); |
219 | | }; |
220 | | |
221 | | /// Transform specialization for projective - encapsulating a 4x4 Matrix |
222 | | class _OgreExport Matrix4 : public TransformBaseReal |
223 | | { |
224 | | public: |
225 | | /// Do <b>NOT</b> initialize the matrix for efficiency. |
226 | 0 | Matrix4() {} |
227 | | |
228 | | Matrix4( |
229 | | Real m00, Real m01, Real m02, Real m03, |
230 | | Real m10, Real m11, Real m12, Real m13, |
231 | | Real m20, Real m21, Real m22, Real m23, |
232 | | Real m30, Real m31, Real m32, Real m33 ) |
233 | 0 | { |
234 | 0 | m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; |
235 | 0 | m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; |
236 | 0 | m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; |
237 | 0 | m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; |
238 | 0 | } |
239 | | |
240 | | template<typename U> |
241 | | explicit Matrix4(const U* ptr) : TransformBaseReal(ptr) {} |
242 | | explicit Matrix4 (const Real* arr) |
243 | 0 | { |
244 | 0 | memcpy(m,arr,16*sizeof(Real)); |
245 | 0 | } |
246 | | |
247 | | /** Creates a standard 4x4 transformation matrix with a zero translation part from a rotation/scaling 3x3 matrix. |
248 | | */ |
249 | | |
250 | | explicit Matrix4(const Matrix3& m3x3) |
251 | 0 | { |
252 | 0 | operator=(IDENTITY); |
253 | 0 | operator=(m3x3); |
254 | 0 | } |
255 | | |
256 | | /** Creates a standard 4x4 transformation matrix with a zero translation part from a rotation/scaling Quaternion. |
257 | | */ |
258 | | |
259 | | explicit Matrix4(const Quaternion& rot) |
260 | 0 | { |
261 | 0 | Matrix3 m3x3; |
262 | 0 | rot.ToRotationMatrix(m3x3); |
263 | 0 | *this = IDENTITY; |
264 | 0 | *this = m3x3; |
265 | 0 | } |
266 | | |
267 | 0 | Matrix4& operator=(const Matrix3& mat3) { |
268 | 0 | set3x3Matrix(mat3); |
269 | 0 | return *this; |
270 | 0 | } |
271 | | |
272 | 0 | OGRE_DEPRECATED Matrix4 concatenate(const Matrix4& m2) const { return *this * m2; } |
273 | | |
274 | | /** Tests 2 matrices for equality. |
275 | | */ |
276 | | inline bool operator == ( const Matrix4& m2 ) const |
277 | 0 | { |
278 | 0 | if( |
279 | 0 | m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] || |
280 | 0 | m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] || |
281 | 0 | m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] || |
282 | 0 | m[3][0] != m2.m[3][0] || m[3][1] != m2.m[3][1] || m[3][2] != m2.m[3][2] || m[3][3] != m2.m[3][3] ) |
283 | 0 | return false; |
284 | 0 | return true; |
285 | 0 | } |
286 | | |
287 | | /** Tests 2 matrices for inequality. |
288 | | */ |
289 | | inline bool operator != ( const Matrix4& m2 ) const |
290 | 0 | { |
291 | 0 | if( |
292 | 0 | m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] || |
293 | 0 | m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] || |
294 | 0 | m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] || |
295 | 0 | m[3][0] != m2.m[3][0] || m[3][1] != m2.m[3][1] || m[3][2] != m2.m[3][2] || m[3][3] != m2.m[3][3] ) |
296 | 0 | return true; |
297 | 0 | return false; |
298 | 0 | } |
299 | | |
300 | | static const Matrix4 ZERO; |
301 | | static const Matrix4 IDENTITY; |
302 | | /** Useful little matrix which takes 2D clipspace {-1, 1} to {0,1} |
303 | | and inverts the Y. */ |
304 | | static const Matrix4 CLIPSPACE2DTOIMAGESPACE; |
305 | | |
306 | | inline Matrix4 operator*(Real scalar) const |
307 | 0 | { |
308 | 0 | return Matrix4( |
309 | 0 | scalar*m[0][0], scalar*m[0][1], scalar*m[0][2], scalar*m[0][3], |
310 | 0 | scalar*m[1][0], scalar*m[1][1], scalar*m[1][2], scalar*m[1][3], |
311 | 0 | scalar*m[2][0], scalar*m[2][1], scalar*m[2][2], scalar*m[2][3], |
312 | 0 | scalar*m[3][0], scalar*m[3][1], scalar*m[3][2], scalar*m[3][3]); |
313 | 0 | } |
314 | | |
315 | | Matrix4 adjoint() const; |
316 | | Matrix4 inverse() const; |
317 | | }; |
318 | | |
319 | | /// Transform specialization for 3D Affine - encapsulating a 3x4 Matrix |
320 | | class _OgreExport Affine3 : public TransformBaseReal |
321 | | { |
322 | | public: |
323 | | /// Do <b>NOT</b> initialize the matrix for efficiency. |
324 | 0 | Affine3() {} |
325 | | |
326 | | /// @copydoc TransformBaseReal::makeTransform |
327 | | Affine3(const Vector3& position, const Quaternion& orientation, const Vector3& scale = Vector3::UNIT_SCALE) |
328 | 0 | { |
329 | 0 | makeTransform(position, scale, orientation); |
330 | 0 | } |
331 | | |
332 | | template<typename U> |
333 | | explicit Affine3(const U* ptr) |
334 | | { |
335 | | for (int i = 0; i < 3; i++) |
336 | | for (int j = 0; j < 4; j++) |
337 | | m[i][j] = Real(ptr[i*4 + j]); |
338 | | m[3][0] = 0, m[3][1] = 0, m[3][2] = 0, m[3][3] = 1; |
339 | | } |
340 | | |
341 | | explicit Affine3(const Real* arr) |
342 | 0 | { |
343 | 0 | memcpy(m, arr, 12 * sizeof(Real)); |
344 | 0 | m[3][0] = 0, m[3][1] = 0, m[3][2] = 0, m[3][3] = 1; |
345 | 0 | } |
346 | | |
347 | | Affine3( |
348 | | Real m00, Real m01, Real m02, Real m03, |
349 | | Real m10, Real m11, Real m12, Real m13, |
350 | | Real m20, Real m21, Real m22, Real m23) |
351 | 0 | { |
352 | 0 | m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; |
353 | 0 | m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; |
354 | 0 | m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; |
355 | 0 | m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1; |
356 | 0 | } |
357 | | |
358 | | /// extract the Affine part of a Matrix4 |
359 | | explicit Affine3(const Matrix4& mat) |
360 | 0 | { |
361 | 0 | m[0][0] = mat[0][0]; m[0][1] = mat[0][1]; m[0][2] = mat[0][2]; m[0][3] = mat[0][3]; |
362 | 0 | m[1][0] = mat[1][0]; m[1][1] = mat[1][1]; m[1][2] = mat[1][2]; m[1][3] = mat[1][3]; |
363 | 0 | m[2][0] = mat[2][0]; m[2][1] = mat[2][1]; m[2][2] = mat[2][2]; m[2][3] = mat[2][3]; |
364 | 0 | m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1; |
365 | 0 | } |
366 | | |
367 | 0 | Affine3& operator=(const Matrix3& mat3) { |
368 | 0 | set3x3Matrix(mat3); |
369 | 0 | return *this; |
370 | 0 | } |
371 | | |
372 | | /** Tests 2 matrices for equality. |
373 | | */ |
374 | | bool operator==(const Affine3& m2) const |
375 | 0 | { |
376 | 0 | if( |
377 | 0 | m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] || |
378 | 0 | m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] || |
379 | 0 | m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] ) |
380 | 0 | return false; |
381 | 0 | return true; |
382 | 0 | } |
383 | | |
384 | 0 | bool operator!=(const Affine3& m2) const { return !(*this == m2); } |
385 | | |
386 | | Affine3 inverse() const; |
387 | | |
388 | | /** Decompose to orientation / scale / position. |
389 | | */ |
390 | | void decomposition(Vector3& position, Vector3& scale, Quaternion& orientation) const; |
391 | | |
392 | | /// every Affine3 transform is also a _const_ Matrix4 |
393 | 0 | operator const Matrix4&() const { return reinterpret_cast<const Matrix4&>(*this); } |
394 | | |
395 | | using TransformBaseReal::getTrans; |
396 | | |
397 | | /** Gets a translation matrix. |
398 | | */ |
399 | | static Affine3 getTrans( const Vector3& v ) |
400 | 0 | { |
401 | 0 | return getTrans(v.x, v.y, v.z); |
402 | 0 | } |
403 | | |
404 | | /** Gets a translation matrix - variation for not using a vector. |
405 | | */ |
406 | | static Affine3 getTrans( Real t_x, Real t_y, Real t_z ) |
407 | 0 | { |
408 | 0 | return Affine3(1, 0, 0, t_x, |
409 | 0 | 0, 1, 0, t_y, |
410 | 0 | 0, 0, 1, t_z); |
411 | 0 | } |
412 | | |
413 | | /** Gets a scale matrix. |
414 | | */ |
415 | | static Affine3 getScale( const Vector3& v ) |
416 | 0 | { |
417 | 0 | return getScale(v.x, v.y, v.z); |
418 | 0 | } |
419 | | |
420 | | /** Gets a scale matrix - variation for not using a vector. |
421 | | */ |
422 | | static Affine3 getScale( Real s_x, Real s_y, Real s_z ) |
423 | 0 | { |
424 | 0 | return Affine3(s_x, 0, 0, 0, |
425 | 0 | 0, s_y, 0, 0, |
426 | 0 | 0, 0, s_z, 0); |
427 | 0 | } |
428 | | |
429 | | |
430 | | static const Affine3 ZERO; |
431 | | static const Affine3 IDENTITY; |
432 | | }; |
433 | | |
434 | | inline Matrix4 TransformBaseReal::transpose() const |
435 | 0 | { |
436 | 0 | return Matrix4(m[0][0], m[1][0], m[2][0], m[3][0], |
437 | 0 | m[0][1], m[1][1], m[2][1], m[3][1], |
438 | 0 | m[0][2], m[1][2], m[2][2], m[3][2], |
439 | 0 | m[0][3], m[1][3], m[2][3], m[3][3]); |
440 | 0 | } |
441 | | |
442 | | /** Matrix addition. |
443 | | */ |
444 | | inline Matrix4 operator+(const Matrix4& m, const Matrix4& m2) |
445 | 0 | { |
446 | 0 | Matrix4 r; |
447 | 0 |
|
448 | 0 | r[0][0] = m[0][0] + m2[0][0]; |
449 | 0 | r[0][1] = m[0][1] + m2[0][1]; |
450 | 0 | r[0][2] = m[0][2] + m2[0][2]; |
451 | 0 | r[0][3] = m[0][3] + m2[0][3]; |
452 | 0 |
|
453 | 0 | r[1][0] = m[1][0] + m2[1][0]; |
454 | 0 | r[1][1] = m[1][1] + m2[1][1]; |
455 | 0 | r[1][2] = m[1][2] + m2[1][2]; |
456 | 0 | r[1][3] = m[1][3] + m2[1][3]; |
457 | 0 |
|
458 | 0 | r[2][0] = m[2][0] + m2[2][0]; |
459 | 0 | r[2][1] = m[2][1] + m2[2][1]; |
460 | 0 | r[2][2] = m[2][2] + m2[2][2]; |
461 | 0 | r[2][3] = m[2][3] + m2[2][3]; |
462 | 0 |
|
463 | 0 | r[3][0] = m[3][0] + m2[3][0]; |
464 | 0 | r[3][1] = m[3][1] + m2[3][1]; |
465 | 0 | r[3][2] = m[3][2] + m2[3][2]; |
466 | 0 | r[3][3] = m[3][3] + m2[3][3]; |
467 | 0 |
|
468 | 0 | return r; |
469 | 0 | } |
470 | | |
471 | | /** Matrix subtraction. |
472 | | */ |
473 | | inline Matrix4 operator-(const Matrix4& m, const Matrix4& m2) |
474 | 0 | { |
475 | 0 | Matrix4 r; |
476 | 0 | r[0][0] = m[0][0] - m2[0][0]; |
477 | 0 | r[0][1] = m[0][1] - m2[0][1]; |
478 | 0 | r[0][2] = m[0][2] - m2[0][2]; |
479 | 0 | r[0][3] = m[0][3] - m2[0][3]; |
480 | 0 |
|
481 | 0 | r[1][0] = m[1][0] - m2[1][0]; |
482 | 0 | r[1][1] = m[1][1] - m2[1][1]; |
483 | 0 | r[1][2] = m[1][2] - m2[1][2]; |
484 | 0 | r[1][3] = m[1][3] - m2[1][3]; |
485 | 0 |
|
486 | 0 | r[2][0] = m[2][0] - m2[2][0]; |
487 | 0 | r[2][1] = m[2][1] - m2[2][1]; |
488 | 0 | r[2][2] = m[2][2] - m2[2][2]; |
489 | 0 | r[2][3] = m[2][3] - m2[2][3]; |
490 | 0 |
|
491 | 0 | r[3][0] = m[3][0] - m2[3][0]; |
492 | 0 | r[3][1] = m[3][1] - m2[3][1]; |
493 | 0 | r[3][2] = m[3][2] - m2[3][2]; |
494 | 0 | r[3][3] = m[3][3] - m2[3][3]; |
495 | 0 |
|
496 | 0 | return r; |
497 | 0 | } |
498 | | |
499 | | inline Matrix4 operator*(const Matrix4 &m, const Matrix4 &m2) |
500 | 0 | { |
501 | 0 | Matrix4 r; |
502 | 0 | r[0][0] = m[0][0] * m2[0][0] + m[0][1] * m2[1][0] + m[0][2] * m2[2][0] + m[0][3] * m2[3][0]; |
503 | 0 | r[0][1] = m[0][0] * m2[0][1] + m[0][1] * m2[1][1] + m[0][2] * m2[2][1] + m[0][3] * m2[3][1]; |
504 | 0 | r[0][2] = m[0][0] * m2[0][2] + m[0][1] * m2[1][2] + m[0][2] * m2[2][2] + m[0][3] * m2[3][2]; |
505 | 0 | r[0][3] = m[0][0] * m2[0][3] + m[0][1] * m2[1][3] + m[0][2] * m2[2][3] + m[0][3] * m2[3][3]; |
506 | 0 |
|
507 | 0 | r[1][0] = m[1][0] * m2[0][0] + m[1][1] * m2[1][0] + m[1][2] * m2[2][0] + m[1][3] * m2[3][0]; |
508 | 0 | r[1][1] = m[1][0] * m2[0][1] + m[1][1] * m2[1][1] + m[1][2] * m2[2][1] + m[1][3] * m2[3][1]; |
509 | 0 | r[1][2] = m[1][0] * m2[0][2] + m[1][1] * m2[1][2] + m[1][2] * m2[2][2] + m[1][3] * m2[3][2]; |
510 | 0 | r[1][3] = m[1][0] * m2[0][3] + m[1][1] * m2[1][3] + m[1][2] * m2[2][3] + m[1][3] * m2[3][3]; |
511 | 0 |
|
512 | 0 | r[2][0] = m[2][0] * m2[0][0] + m[2][1] * m2[1][0] + m[2][2] * m2[2][0] + m[2][3] * m2[3][0]; |
513 | 0 | r[2][1] = m[2][0] * m2[0][1] + m[2][1] * m2[1][1] + m[2][2] * m2[2][1] + m[2][3] * m2[3][1]; |
514 | 0 | r[2][2] = m[2][0] * m2[0][2] + m[2][1] * m2[1][2] + m[2][2] * m2[2][2] + m[2][3] * m2[3][2]; |
515 | 0 | r[2][3] = m[2][0] * m2[0][3] + m[2][1] * m2[1][3] + m[2][2] * m2[2][3] + m[2][3] * m2[3][3]; |
516 | 0 |
|
517 | 0 | r[3][0] = m[3][0] * m2[0][0] + m[3][1] * m2[1][0] + m[3][2] * m2[2][0] + m[3][3] * m2[3][0]; |
518 | 0 | r[3][1] = m[3][0] * m2[0][1] + m[3][1] * m2[1][1] + m[3][2] * m2[2][1] + m[3][3] * m2[3][1]; |
519 | 0 | r[3][2] = m[3][0] * m2[0][2] + m[3][1] * m2[1][2] + m[3][2] * m2[2][2] + m[3][3] * m2[3][2]; |
520 | 0 | r[3][3] = m[3][0] * m2[0][3] + m[3][1] * m2[1][3] + m[3][2] * m2[2][3] + m[3][3] * m2[3][3]; |
521 | 0 |
|
522 | 0 | return r; |
523 | 0 | } |
524 | | inline Affine3 operator*(const Affine3 &m, const Affine3 &m2) |
525 | 0 | { |
526 | 0 | return Affine3( |
527 | 0 | m[0][0] * m2[0][0] + m[0][1] * m2[1][0] + m[0][2] * m2[2][0], |
528 | 0 | m[0][0] * m2[0][1] + m[0][1] * m2[1][1] + m[0][2] * m2[2][1], |
529 | 0 | m[0][0] * m2[0][2] + m[0][1] * m2[1][2] + m[0][2] * m2[2][2], |
530 | 0 | m[0][0] * m2[0][3] + m[0][1] * m2[1][3] + m[0][2] * m2[2][3] + m[0][3], |
531 | 0 |
|
532 | 0 | m[1][0] * m2[0][0] + m[1][1] * m2[1][0] + m[1][2] * m2[2][0], |
533 | 0 | m[1][0] * m2[0][1] + m[1][1] * m2[1][1] + m[1][2] * m2[2][1], |
534 | 0 | m[1][0] * m2[0][2] + m[1][1] * m2[1][2] + m[1][2] * m2[2][2], |
535 | 0 | m[1][0] * m2[0][3] + m[1][1] * m2[1][3] + m[1][2] * m2[2][3] + m[1][3], |
536 | 0 |
|
537 | 0 | m[2][0] * m2[0][0] + m[2][1] * m2[1][0] + m[2][2] * m2[2][0], |
538 | 0 | m[2][0] * m2[0][1] + m[2][1] * m2[1][1] + m[2][2] * m2[2][1], |
539 | 0 | m[2][0] * m2[0][2] + m[2][1] * m2[1][2] + m[2][2] * m2[2][2], |
540 | 0 | m[2][0] * m2[0][3] + m[2][1] * m2[1][3] + m[2][2] * m2[2][3] + m[2][3]); |
541 | 0 | } |
542 | | |
543 | | /** Vector transformation using '*'. |
544 | | |
545 | | Transforms the given 3-D vector by the matrix, projecting the |
546 | | result back into <i>w</i> = 1. |
547 | | @note |
548 | | This means that the initial <i>w</i> is considered to be 1.0, |
549 | | and then all the tree elements of the resulting 3-D vector are |
550 | | divided by the resulting <i>w</i>. |
551 | | */ |
552 | | inline Vector3 operator*(const Matrix4& m, const Vector3& v) |
553 | 0 | { |
554 | 0 | Vector3 r; |
555 | 0 |
|
556 | 0 | Real fInvW = 1.0f / ( m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] ); |
557 | 0 |
|
558 | 0 | r.x = ( m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] ) * fInvW; |
559 | 0 | r.y = ( m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] ) * fInvW; |
560 | 0 | r.z = ( m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] ) * fInvW; |
561 | 0 |
|
562 | 0 | return r; |
563 | 0 | } |
564 | | /// @overload |
565 | | inline Vector3 operator*(const Affine3& m,const Vector3& v) |
566 | 0 | { |
567 | 0 | return Vector3( |
568 | 0 | m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3], |
569 | 0 | m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3], |
570 | 0 | m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]); |
571 | 0 | } |
572 | | |
573 | | inline Vector4 operator*(const Matrix4& m, const Vector4& v) |
574 | 0 | { |
575 | 0 | return Vector4( |
576 | 0 | m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w, |
577 | 0 | m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w, |
578 | 0 | m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w, |
579 | 0 | m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w); |
580 | 0 | } |
581 | | inline Vector4 operator*(const Affine3& m, const Vector4& v) |
582 | 0 | { |
583 | 0 | return Vector4( |
584 | 0 | m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w, |
585 | 0 | m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w, |
586 | 0 | m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w, |
587 | 0 | v.w); |
588 | 0 | } |
589 | | |
590 | | inline Vector4 operator * (const Vector4& v, const Matrix4& mat) |
591 | 0 | { |
592 | 0 | return Vector4( |
593 | 0 | v.x*mat[0][0] + v.y*mat[1][0] + v.z*mat[2][0] + v.w*mat[3][0], |
594 | 0 | v.x*mat[0][1] + v.y*mat[1][1] + v.z*mat[2][1] + v.w*mat[3][1], |
595 | 0 | v.x*mat[0][2] + v.y*mat[1][2] + v.z*mat[2][2] + v.w*mat[3][2], |
596 | 0 | v.x*mat[0][3] + v.y*mat[1][3] + v.z*mat[2][3] + v.w*mat[3][3] |
597 | 0 | ); |
598 | 0 | } |
599 | | /** @} */ |
600 | | /** @} */ |
601 | | |
602 | | } |
603 | | #endif |