aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/include/matrix4.h
diff options
context:
space:
mode:
authorDavid Walter Seikel2013-01-13 18:54:10 +1000
committerDavid Walter Seikel2013-01-13 18:54:10 +1000
commit959831f4ef5a3e797f576c3de08cd65032c997ad (patch)
treee7351908be5995f0b325b2ebeaa02d5a34b82583 /libraries/irrlicht-1.8/include/matrix4.h
parentAdd info about changes to Irrlicht. (diff)
downloadSledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.zip
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.gz
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.bz2
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.xz
Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard.
Diffstat (limited to 'libraries/irrlicht-1.8/include/matrix4.h')
-rw-r--r--libraries/irrlicht-1.8/include/matrix4.h4484
1 files changed, 2242 insertions, 2242 deletions
diff --git a/libraries/irrlicht-1.8/include/matrix4.h b/libraries/irrlicht-1.8/include/matrix4.h
index df1e4ea..b04827f 100644
--- a/libraries/irrlicht-1.8/include/matrix4.h
+++ b/libraries/irrlicht-1.8/include/matrix4.h
@@ -1,2242 +1,2242 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt 1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine". 2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h 3// For conditions of distribution and use, see copyright notice in irrlicht.h
4 4
5#ifndef __IRR_MATRIX_H_INCLUDED__ 5#ifndef __IRR_MATRIX_H_INCLUDED__
6#define __IRR_MATRIX_H_INCLUDED__ 6#define __IRR_MATRIX_H_INCLUDED__
7 7
8#include "irrMath.h" 8#include "irrMath.h"
9#include "vector3d.h" 9#include "vector3d.h"
10#include "vector2d.h" 10#include "vector2d.h"
11#include "plane3d.h" 11#include "plane3d.h"
12#include "aabbox3d.h" 12#include "aabbox3d.h"
13#include "rect.h" 13#include "rect.h"
14#include "irrString.h" 14#include "irrString.h"
15 15
16// enable this to keep track of changes to the matrix 16// enable this to keep track of changes to the matrix
17// and make simpler identity check for seldomly changing matrices 17// and make simpler identity check for seldomly changing matrices
18// otherwise identity check will always compare the elements 18// otherwise identity check will always compare the elements
19//#define USE_MATRIX_TEST 19//#define USE_MATRIX_TEST
20 20
21// this is only for debugging purposes 21// this is only for debugging purposes
22//#define USE_MATRIX_TEST_DEBUG 22//#define USE_MATRIX_TEST_DEBUG
23 23
24#if defined( USE_MATRIX_TEST_DEBUG ) 24#if defined( USE_MATRIX_TEST_DEBUG )
25 25
26struct MatrixTest 26struct MatrixTest
27{ 27{
28 MatrixTest () : ID(0), Calls(0) {} 28 MatrixTest () : ID(0), Calls(0) {}
29 char buf[256]; 29 char buf[256];
30 int Calls; 30 int Calls;
31 int ID; 31 int ID;
32}; 32};
33static MatrixTest MTest; 33static MatrixTest MTest;
34 34
35#endif 35#endif
36 36
37namespace irr 37namespace irr
38{ 38{
39namespace core 39namespace core
40{ 40{
41 41
42 //! 4x4 matrix. Mostly used as transformation matrix for 3d calculations. 42 //! 4x4 matrix. Mostly used as transformation matrix for 3d calculations.
43 /** The matrix is a D3D style matrix, row major with translations in the 4th row. */ 43 /** The matrix is a D3D style matrix, row major with translations in the 4th row. */
44 template <class T> 44 template <class T>
45 class CMatrix4 45 class CMatrix4
46 { 46 {
47 public: 47 public:
48 48
49 //! Constructor Flags 49 //! Constructor Flags
50 enum eConstructor 50 enum eConstructor
51 { 51 {
52 EM4CONST_NOTHING = 0, 52 EM4CONST_NOTHING = 0,
53 EM4CONST_COPY, 53 EM4CONST_COPY,
54 EM4CONST_IDENTITY, 54 EM4CONST_IDENTITY,
55 EM4CONST_TRANSPOSED, 55 EM4CONST_TRANSPOSED,
56 EM4CONST_INVERSE, 56 EM4CONST_INVERSE,
57 EM4CONST_INVERSE_TRANSPOSED 57 EM4CONST_INVERSE_TRANSPOSED
58 }; 58 };
59 59
60 //! Default constructor 60 //! Default constructor
61 /** \param constructor Choose the initialization style */ 61 /** \param constructor Choose the initialization style */
62 CMatrix4( eConstructor constructor = EM4CONST_IDENTITY ); 62 CMatrix4( eConstructor constructor = EM4CONST_IDENTITY );
63 //! Copy constructor 63 //! Copy constructor
64 /** \param other Other matrix to copy from 64 /** \param other Other matrix to copy from
65 \param constructor Choose the initialization style */ 65 \param constructor Choose the initialization style */
66 CMatrix4(const CMatrix4<T>& other, eConstructor constructor = EM4CONST_COPY); 66 CMatrix4(const CMatrix4<T>& other, eConstructor constructor = EM4CONST_COPY);
67 67
68 //! Simple operator for directly accessing every element of the matrix. 68 //! Simple operator for directly accessing every element of the matrix.
69 T& operator()(const s32 row, const s32 col) 69 T& operator()(const s32 row, const s32 col)
70 { 70 {
71#if defined ( USE_MATRIX_TEST ) 71#if defined ( USE_MATRIX_TEST )
72 definitelyIdentityMatrix=false; 72 definitelyIdentityMatrix=false;
73#endif 73#endif
74 return M[ row * 4 + col ]; 74 return M[ row * 4 + col ];
75 } 75 }
76 76
77 //! Simple operator for directly accessing every element of the matrix. 77 //! Simple operator for directly accessing every element of the matrix.
78 const T& operator()(const s32 row, const s32 col) const { return M[row * 4 + col]; } 78 const T& operator()(const s32 row, const s32 col) const { return M[row * 4 + col]; }
79 79
80 //! Simple operator for linearly accessing every element of the matrix. 80 //! Simple operator for linearly accessing every element of the matrix.
81 T& operator[](u32 index) 81 T& operator[](u32 index)
82 { 82 {
83#if defined ( USE_MATRIX_TEST ) 83#if defined ( USE_MATRIX_TEST )
84 definitelyIdentityMatrix=false; 84 definitelyIdentityMatrix=false;
85#endif 85#endif
86 return M[index]; 86 return M[index];
87 } 87 }
88 88
89 //! Simple operator for linearly accessing every element of the matrix. 89 //! Simple operator for linearly accessing every element of the matrix.
90 const T& operator[](u32 index) const { return M[index]; } 90 const T& operator[](u32 index) const { return M[index]; }
91 91
92 //! Sets this matrix equal to the other matrix. 92 //! Sets this matrix equal to the other matrix.
93 inline CMatrix4<T>& operator=(const CMatrix4<T> &other); 93 inline CMatrix4<T>& operator=(const CMatrix4<T> &other);
94 94
95 //! Sets all elements of this matrix to the value. 95 //! Sets all elements of this matrix to the value.
96 inline CMatrix4<T>& operator=(const T& scalar); 96 inline CMatrix4<T>& operator=(const T& scalar);
97 97
98 //! Returns pointer to internal array 98 //! Returns pointer to internal array
99 const T* pointer() const { return M; } 99 const T* pointer() const { return M; }
100 T* pointer() 100 T* pointer()
101 { 101 {
102#if defined ( USE_MATRIX_TEST ) 102#if defined ( USE_MATRIX_TEST )
103 definitelyIdentityMatrix=false; 103 definitelyIdentityMatrix=false;
104#endif 104#endif
105 return M; 105 return M;
106 } 106 }
107 107
108 //! Returns true if other matrix is equal to this matrix. 108 //! Returns true if other matrix is equal to this matrix.
109 bool operator==(const CMatrix4<T> &other) const; 109 bool operator==(const CMatrix4<T> &other) const;
110 110
111 //! Returns true if other matrix is not equal to this matrix. 111 //! Returns true if other matrix is not equal to this matrix.
112 bool operator!=(const CMatrix4<T> &other) const; 112 bool operator!=(const CMatrix4<T> &other) const;
113 113
114 //! Add another matrix. 114 //! Add another matrix.
115 CMatrix4<T> operator+(const CMatrix4<T>& other) const; 115 CMatrix4<T> operator+(const CMatrix4<T>& other) const;
116 116
117 //! Add another matrix. 117 //! Add another matrix.
118 CMatrix4<T>& operator+=(const CMatrix4<T>& other); 118 CMatrix4<T>& operator+=(const CMatrix4<T>& other);
119 119
120 //! Subtract another matrix. 120 //! Subtract another matrix.
121 CMatrix4<T> operator-(const CMatrix4<T>& other) const; 121 CMatrix4<T> operator-(const CMatrix4<T>& other) const;
122 122
123 //! Subtract another matrix. 123 //! Subtract another matrix.
124 CMatrix4<T>& operator-=(const CMatrix4<T>& other); 124 CMatrix4<T>& operator-=(const CMatrix4<T>& other);
125 125
126 //! set this matrix to the product of two matrices 126 //! set this matrix to the product of two matrices
127 /** Calculate b*a */ 127 /** Calculate b*a */
128 inline CMatrix4<T>& setbyproduct(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b ); 128 inline CMatrix4<T>& setbyproduct(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
129 129
130 //! Set this matrix to the product of two matrices 130 //! Set this matrix to the product of two matrices
131 /** Calculate b*a, no optimization used, 131 /** Calculate b*a, no optimization used,
132 use it if you know you never have a identity matrix */ 132 use it if you know you never have a identity matrix */
133 CMatrix4<T>& setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b ); 133 CMatrix4<T>& setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
134 134
135 //! Multiply by another matrix. 135 //! Multiply by another matrix.
136 /** Calculate other*this */ 136 /** Calculate other*this */
137 CMatrix4<T> operator*(const CMatrix4<T>& other) const; 137 CMatrix4<T> operator*(const CMatrix4<T>& other) const;
138 138
139 //! Multiply by another matrix. 139 //! Multiply by another matrix.
140 /** Calculate and return other*this */ 140 /** Calculate and return other*this */
141 CMatrix4<T>& operator*=(const CMatrix4<T>& other); 141 CMatrix4<T>& operator*=(const CMatrix4<T>& other);
142 142
143 //! Multiply by scalar. 143 //! Multiply by scalar.
144 CMatrix4<T> operator*(const T& scalar) const; 144 CMatrix4<T> operator*(const T& scalar) const;
145 145
146 //! Multiply by scalar. 146 //! Multiply by scalar.
147 CMatrix4<T>& operator*=(const T& scalar); 147 CMatrix4<T>& operator*=(const T& scalar);
148 148
149 //! Set matrix to identity. 149 //! Set matrix to identity.
150 inline CMatrix4<T>& makeIdentity(); 150 inline CMatrix4<T>& makeIdentity();
151 151
152 //! Returns true if the matrix is the identity matrix 152 //! Returns true if the matrix is the identity matrix
153 inline bool isIdentity() const; 153 inline bool isIdentity() const;
154 154
155 //! Returns true if the matrix is orthogonal 155 //! Returns true if the matrix is orthogonal
156 inline bool isOrthogonal() const; 156 inline bool isOrthogonal() const;
157 157
158 //! Returns true if the matrix is the identity matrix 158 //! Returns true if the matrix is the identity matrix
159 bool isIdentity_integer_base () const; 159 bool isIdentity_integer_base () const;
160 160
161 //! Set the translation of the current matrix. Will erase any previous values. 161 //! Set the translation of the current matrix. Will erase any previous values.
162 CMatrix4<T>& setTranslation( const vector3d<T>& translation ); 162 CMatrix4<T>& setTranslation( const vector3d<T>& translation );
163 163
164 //! Gets the current translation 164 //! Gets the current translation
165 vector3d<T> getTranslation() const; 165 vector3d<T> getTranslation() const;
166 166
167 //! Set the inverse translation of the current matrix. Will erase any previous values. 167 //! Set the inverse translation of the current matrix. Will erase any previous values.
168 CMatrix4<T>& setInverseTranslation( const vector3d<T>& translation ); 168 CMatrix4<T>& setInverseTranslation( const vector3d<T>& translation );
169 169
170 //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified. 170 //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
171 inline CMatrix4<T>& setRotationRadians( const vector3d<T>& rotation ); 171 inline CMatrix4<T>& setRotationRadians( const vector3d<T>& rotation );
172 172
173 //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified. 173 //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
174 CMatrix4<T>& setRotationDegrees( const vector3d<T>& rotation ); 174 CMatrix4<T>& setRotationDegrees( const vector3d<T>& rotation );
175 175
176 //! Returns the rotation, as set by setRotation(). 176 //! Returns the rotation, as set by setRotation().
177 /** This code was orginally written by by Chev. */ 177 /** This code was orginally written by by Chev. */
178 core::vector3d<T> getRotationDegrees() const; 178 core::vector3d<T> getRotationDegrees() const;
179 179
180 //! Make an inverted rotation matrix from Euler angles. 180 //! Make an inverted rotation matrix from Euler angles.
181 /** The 4th row and column are unmodified. */ 181 /** The 4th row and column are unmodified. */
182 inline CMatrix4<T>& setInverseRotationRadians( const vector3d<T>& rotation ); 182 inline CMatrix4<T>& setInverseRotationRadians( const vector3d<T>& rotation );
183 183
184 //! Make an inverted rotation matrix from Euler angles. 184 //! Make an inverted rotation matrix from Euler angles.
185 /** The 4th row and column are unmodified. */ 185 /** The 4th row and column are unmodified. */
186 inline CMatrix4<T>& setInverseRotationDegrees( const vector3d<T>& rotation ); 186 inline CMatrix4<T>& setInverseRotationDegrees( const vector3d<T>& rotation );
187 187
188 //! Make a rotation matrix from angle and axis, assuming left handed rotation. 188 //! Make a rotation matrix from angle and axis, assuming left handed rotation.
189 /** The 4th row and column are unmodified. */ 189 /** The 4th row and column are unmodified. */
190 inline CMatrix4<T>& setRotationAxisRadians(const T& angle, const vector3d<T>& axis); 190 inline CMatrix4<T>& setRotationAxisRadians(const T& angle, const vector3d<T>& axis);
191 191
192 //! Set Scale 192 //! Set Scale
193 CMatrix4<T>& setScale( const vector3d<T>& scale ); 193 CMatrix4<T>& setScale( const vector3d<T>& scale );
194 194
195 //! Set Scale 195 //! Set Scale
196 CMatrix4<T>& setScale( const T scale ) { return setScale(core::vector3d<T>(scale,scale,scale)); } 196 CMatrix4<T>& setScale( const T scale ) { return setScale(core::vector3d<T>(scale,scale,scale)); }
197 197
198 //! Get Scale 198 //! Get Scale
199 core::vector3d<T> getScale() const; 199 core::vector3d<T> getScale() const;
200 200
201 //! Translate a vector by the inverse of the translation part of this matrix. 201 //! Translate a vector by the inverse of the translation part of this matrix.
202 void inverseTranslateVect( vector3df& vect ) const; 202 void inverseTranslateVect( vector3df& vect ) const;
203 203
204 //! Rotate a vector by the inverse of the rotation part of this matrix. 204 //! Rotate a vector by the inverse of the rotation part of this matrix.
205 void inverseRotateVect( vector3df& vect ) const; 205 void inverseRotateVect( vector3df& vect ) const;
206 206
207 //! Rotate a vector by the rotation part of this matrix. 207 //! Rotate a vector by the rotation part of this matrix.
208 void rotateVect( vector3df& vect ) const; 208 void rotateVect( vector3df& vect ) const;
209 209
210 //! An alternate transform vector method, writing into a second vector 210 //! An alternate transform vector method, writing into a second vector
211 void rotateVect(core::vector3df& out, const core::vector3df& in) const; 211 void rotateVect(core::vector3df& out, const core::vector3df& in) const;
212 212
213 //! An alternate transform vector method, writing into an array of 3 floats 213 //! An alternate transform vector method, writing into an array of 3 floats
214 void rotateVect(T *out,const core::vector3df &in) const; 214 void rotateVect(T *out,const core::vector3df &in) const;
215 215
216 //! Transforms the vector by this matrix 216 //! Transforms the vector by this matrix
217 void transformVect( vector3df& vect) const; 217 void transformVect( vector3df& vect) const;
218 218
219 //! Transforms input vector by this matrix and stores result in output vector 219 //! Transforms input vector by this matrix and stores result in output vector
220 void transformVect( vector3df& out, const vector3df& in ) const; 220 void transformVect( vector3df& out, const vector3df& in ) const;
221 221
222 //! An alternate transform vector method, writing into an array of 4 floats 222 //! An alternate transform vector method, writing into an array of 4 floats
223 void transformVect(T *out,const core::vector3df &in) const; 223 void transformVect(T *out,const core::vector3df &in) const;
224 224
225 //! An alternate transform vector method, reading from and writing to an array of 3 floats 225 //! An alternate transform vector method, reading from and writing to an array of 3 floats
226 void transformVec3(T *out, const T * in) const; 226 void transformVec3(T *out, const T * in) const;
227 227
228 //! Translate a vector by the translation part of this matrix. 228 //! Translate a vector by the translation part of this matrix.
229 void translateVect( vector3df& vect ) const; 229 void translateVect( vector3df& vect ) const;
230 230
231 //! Transforms a plane by this matrix 231 //! Transforms a plane by this matrix
232 void transformPlane( core::plane3d<f32> &plane) const; 232 void transformPlane( core::plane3d<f32> &plane) const;
233 233
234 //! Transforms a plane by this matrix 234 //! Transforms a plane by this matrix
235 void transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const; 235 void transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const;
236 236
237 //! Transforms a axis aligned bounding box 237 //! Transforms a axis aligned bounding box
238 /** The result box of this operation may not be accurate at all. For 238 /** The result box of this operation may not be accurate at all. For
239 correct results, use transformBoxEx() */ 239 correct results, use transformBoxEx() */
240 void transformBox(core::aabbox3d<f32>& box) const; 240 void transformBox(core::aabbox3d<f32>& box) const;
241 241
242 //! Transforms a axis aligned bounding box 242 //! Transforms a axis aligned bounding box
243 /** The result box of this operation should by accurate, but this operation 243 /** The result box of this operation should by accurate, but this operation
244 is slower than transformBox(). */ 244 is slower than transformBox(). */
245 void transformBoxEx(core::aabbox3d<f32>& box) const; 245 void transformBoxEx(core::aabbox3d<f32>& box) const;
246 246
247 //! Multiplies this matrix by a 1x4 matrix 247 //! Multiplies this matrix by a 1x4 matrix
248 void multiplyWith1x4Matrix(T* matrix) const; 248 void multiplyWith1x4Matrix(T* matrix) const;
249 249
250 //! Calculates inverse of matrix. Slow. 250 //! Calculates inverse of matrix. Slow.
251 /** \return Returns false if there is no inverse matrix.*/ 251 /** \return Returns false if there is no inverse matrix.*/
252 bool makeInverse(); 252 bool makeInverse();
253 253
254 254
255 //! Inverts a primitive matrix which only contains a translation and a rotation 255 //! Inverts a primitive matrix which only contains a translation and a rotation
256 /** \param out: where result matrix is written to. */ 256 /** \param out: where result matrix is written to. */
257 bool getInversePrimitive ( CMatrix4<T>& out ) const; 257 bool getInversePrimitive ( CMatrix4<T>& out ) const;
258 258
259 //! Gets the inversed matrix of this one 259 //! Gets the inversed matrix of this one
260 /** \param out: where result matrix is written to. 260 /** \param out: where result matrix is written to.
261 \return Returns false if there is no inverse matrix. */ 261 \return Returns false if there is no inverse matrix. */
262 bool getInverse(CMatrix4<T>& out) const; 262 bool getInverse(CMatrix4<T>& out) const;
263 263
264 //! Builds a right-handed perspective projection matrix based on a field of view 264 //! Builds a right-handed perspective projection matrix based on a field of view
265 CMatrix4<T>& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar); 265 CMatrix4<T>& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
266 266
267 //! Builds a left-handed perspective projection matrix based on a field of view 267 //! Builds a left-handed perspective projection matrix based on a field of view
268 CMatrix4<T>& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar); 268 CMatrix4<T>& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
269 269
270 //! Builds a left-handed perspective projection matrix based on a field of view, with far plane at infinity 270 //! Builds a left-handed perspective projection matrix based on a field of view, with far plane at infinity
271 CMatrix4<T>& buildProjectionMatrixPerspectiveFovInfinityLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon=0); 271 CMatrix4<T>& buildProjectionMatrixPerspectiveFovInfinityLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon=0);
272 272
273 //! Builds a right-handed perspective projection matrix. 273 //! Builds a right-handed perspective projection matrix.
274 CMatrix4<T>& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); 274 CMatrix4<T>& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
275 275
276 //! Builds a left-handed perspective projection matrix. 276 //! Builds a left-handed perspective projection matrix.
277 CMatrix4<T>& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); 277 CMatrix4<T>& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
278 278
279 //! Builds a left-handed orthogonal projection matrix. 279 //! Builds a left-handed orthogonal projection matrix.
280 CMatrix4<T>& buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); 280 CMatrix4<T>& buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
281 281
282 //! Builds a right-handed orthogonal projection matrix. 282 //! Builds a right-handed orthogonal projection matrix.
283 CMatrix4<T>& buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar); 283 CMatrix4<T>& buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
284 284
285 //! Builds a left-handed look-at matrix. 285 //! Builds a left-handed look-at matrix.
286 CMatrix4<T>& buildCameraLookAtMatrixLH( 286 CMatrix4<T>& buildCameraLookAtMatrixLH(
287 const vector3df& position, 287 const vector3df& position,
288 const vector3df& target, 288 const vector3df& target,
289 const vector3df& upVector); 289 const vector3df& upVector);
290 290
291 //! Builds a right-handed look-at matrix. 291 //! Builds a right-handed look-at matrix.
292 CMatrix4<T>& buildCameraLookAtMatrixRH( 292 CMatrix4<T>& buildCameraLookAtMatrixRH(
293 const vector3df& position, 293 const vector3df& position,
294 const vector3df& target, 294 const vector3df& target,
295 const vector3df& upVector); 295 const vector3df& upVector);
296 296
297 //! Builds a matrix that flattens geometry into a plane. 297 //! Builds a matrix that flattens geometry into a plane.
298 /** \param light: light source 298 /** \param light: light source
299 \param plane: plane into which the geometry if flattened into 299 \param plane: plane into which the geometry if flattened into
300 \param point: value between 0 and 1, describing the light source. 300 \param point: value between 0 and 1, describing the light source.
301 If this is 1, it is a point light, if it is 0, it is a directional light. */ 301 If this is 1, it is a point light, if it is 0, it is a directional light. */
302 CMatrix4<T>& buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f); 302 CMatrix4<T>& buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f);
303 303
304 //! Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates. 304 //! Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates.
305 /** Used to scale <-1,-1><1,1> to viewport, for example from <-1,-1> <1,1> to the viewport <0,0><0,640> */ 305 /** Used to scale <-1,-1><1,1> to viewport, for example from <-1,-1> <1,1> to the viewport <0,0><0,640> */
306 CMatrix4<T>& buildNDCToDCMatrix( const core::rect<s32>& area, f32 zScale); 306 CMatrix4<T>& buildNDCToDCMatrix( const core::rect<s32>& area, f32 zScale);
307 307
308 //! Creates a new matrix as interpolated matrix from two other ones. 308 //! Creates a new matrix as interpolated matrix from two other ones.
309 /** \param b: other matrix to interpolate with 309 /** \param b: other matrix to interpolate with
310 \param time: Must be a value between 0 and 1. */ 310 \param time: Must be a value between 0 and 1. */
311 CMatrix4<T> interpolate(const core::CMatrix4<T>& b, f32 time) const; 311 CMatrix4<T> interpolate(const core::CMatrix4<T>& b, f32 time) const;
312 312
313 //! Gets transposed matrix 313 //! Gets transposed matrix
314 CMatrix4<T> getTransposed() const; 314 CMatrix4<T> getTransposed() const;
315 315
316 //! Gets transposed matrix 316 //! Gets transposed matrix
317 inline void getTransposed( CMatrix4<T>& dest ) const; 317 inline void getTransposed( CMatrix4<T>& dest ) const;
318 318
319 //! Builds a matrix that rotates from one vector to another 319 //! Builds a matrix that rotates from one vector to another
320 /** \param from: vector to rotate from 320 /** \param from: vector to rotate from
321 \param to: vector to rotate to 321 \param to: vector to rotate to
322 */ 322 */
323 CMatrix4<T>& buildRotateFromTo(const core::vector3df& from, const core::vector3df& to); 323 CMatrix4<T>& buildRotateFromTo(const core::vector3df& from, const core::vector3df& to);
324 324
325 //! Builds a combined matrix which translates to a center before rotation and translates from origin afterwards 325 //! Builds a combined matrix which translates to a center before rotation and translates from origin afterwards
326 /** \param center Position to rotate around 326 /** \param center Position to rotate around
327 \param translate Translation applied after the rotation 327 \param translate Translation applied after the rotation
328 */ 328 */
329 void setRotationCenter(const core::vector3df& center, const core::vector3df& translate); 329 void setRotationCenter(const core::vector3df& center, const core::vector3df& translate);
330 330
331 //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis 331 //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis
332 /** \param camPos: viewer position in world coo 332 /** \param camPos: viewer position in world coo
333 \param center: object position in world-coo and rotation pivot 333 \param center: object position in world-coo and rotation pivot
334 \param translation: object final translation from center 334 \param translation: object final translation from center
335 \param axis: axis to rotate about 335 \param axis: axis to rotate about
336 \param from: source vector to rotate from 336 \param from: source vector to rotate from
337 */ 337 */
338 void buildAxisAlignedBillboard(const core::vector3df& camPos, 338 void buildAxisAlignedBillboard(const core::vector3df& camPos,
339 const core::vector3df& center, 339 const core::vector3df& center,
340 const core::vector3df& translation, 340 const core::vector3df& translation,
341 const core::vector3df& axis, 341 const core::vector3df& axis,
342 const core::vector3df& from); 342 const core::vector3df& from);
343 343
344 /* 344 /*
345 construct 2D Texture transformations 345 construct 2D Texture transformations
346 rotate about center, scale, and transform. 346 rotate about center, scale, and transform.
347 */ 347 */
348 //! Set to a texture transformation matrix with the given parameters. 348 //! Set to a texture transformation matrix with the given parameters.
349 CMatrix4<T>& buildTextureTransform( f32 rotateRad, 349 CMatrix4<T>& buildTextureTransform( f32 rotateRad,
350 const core::vector2df &rotatecenter, 350 const core::vector2df &rotatecenter,
351 const core::vector2df &translate, 351 const core::vector2df &translate,
352 const core::vector2df &scale); 352 const core::vector2df &scale);
353 353
354 //! Set texture transformation rotation 354 //! Set texture transformation rotation
355 /** Rotate about z axis, recenter at (0.5,0.5). 355 /** Rotate about z axis, recenter at (0.5,0.5).
356 Doesn't clear other elements than those affected 356 Doesn't clear other elements than those affected
357 \param radAngle Angle in radians 357 \param radAngle Angle in radians
358 \return Altered matrix */ 358 \return Altered matrix */
359 CMatrix4<T>& setTextureRotationCenter( f32 radAngle ); 359 CMatrix4<T>& setTextureRotationCenter( f32 radAngle );
360 360
361 //! Set texture transformation translation 361 //! Set texture transformation translation
362 /** Doesn't clear other elements than those affected. 362 /** Doesn't clear other elements than those affected.
363 \param x Offset on x axis 363 \param x Offset on x axis
364 \param y Offset on y axis 364 \param y Offset on y axis
365 \return Altered matrix */ 365 \return Altered matrix */
366 CMatrix4<T>& setTextureTranslate( f32 x, f32 y ); 366 CMatrix4<T>& setTextureTranslate( f32 x, f32 y );
367 367
368 //! Set texture transformation translation, using a transposed representation 368 //! Set texture transformation translation, using a transposed representation
369 /** Doesn't clear other elements than those affected. 369 /** Doesn't clear other elements than those affected.
370 \param x Offset on x axis 370 \param x Offset on x axis
371 \param y Offset on y axis 371 \param y Offset on y axis
372 \return Altered matrix */ 372 \return Altered matrix */
373 CMatrix4<T>& setTextureTranslateTransposed( f32 x, f32 y ); 373 CMatrix4<T>& setTextureTranslateTransposed( f32 x, f32 y );
374 374
375 //! Set texture transformation scale 375 //! Set texture transformation scale
376 /** Doesn't clear other elements than those affected. 376 /** Doesn't clear other elements than those affected.
377 \param sx Scale factor on x axis 377 \param sx Scale factor on x axis
378 \param sy Scale factor on y axis 378 \param sy Scale factor on y axis
379 \return Altered matrix. */ 379 \return Altered matrix. */
380 CMatrix4<T>& setTextureScale( f32 sx, f32 sy ); 380 CMatrix4<T>& setTextureScale( f32 sx, f32 sy );
381 381
382 //! Set texture transformation scale, and recenter at (0.5,0.5) 382 //! Set texture transformation scale, and recenter at (0.5,0.5)
383 /** Doesn't clear other elements than those affected. 383 /** Doesn't clear other elements than those affected.
384 \param sx Scale factor on x axis 384 \param sx Scale factor on x axis
385 \param sy Scale factor on y axis 385 \param sy Scale factor on y axis
386 \return Altered matrix. */ 386 \return Altered matrix. */
387 CMatrix4<T>& setTextureScaleCenter( f32 sx, f32 sy ); 387 CMatrix4<T>& setTextureScaleCenter( f32 sx, f32 sy );
388 388
389 //! Sets all matrix data members at once 389 //! Sets all matrix data members at once
390 CMatrix4<T>& setM(const T* data); 390 CMatrix4<T>& setM(const T* data);
391 391
392 //! Sets if the matrix is definitely identity matrix 392 //! Sets if the matrix is definitely identity matrix
393 void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix); 393 void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix);
394 394
395 //! Gets if the matrix is definitely identity matrix 395 //! Gets if the matrix is definitely identity matrix
396 bool getDefinitelyIdentityMatrix() const; 396 bool getDefinitelyIdentityMatrix() const;
397 397
398 //! Compare two matrices using the equal method 398 //! Compare two matrices using the equal method
399 bool equals(const core::CMatrix4<T>& other, const T tolerance=(T)ROUNDING_ERROR_f64) const; 399 bool equals(const core::CMatrix4<T>& other, const T tolerance=(T)ROUNDING_ERROR_f64) const;
400 400
401 private: 401 private:
402 //! Matrix data, stored in row-major order 402 //! Matrix data, stored in row-major order
403 T M[16]; 403 T M[16];
404#if defined ( USE_MATRIX_TEST ) 404#if defined ( USE_MATRIX_TEST )
405 //! Flag is this matrix is identity matrix 405 //! Flag is this matrix is identity matrix
406 mutable u32 definitelyIdentityMatrix; 406 mutable u32 definitelyIdentityMatrix;
407#endif 407#endif
408#if defined ( USE_MATRIX_TEST_DEBUG ) 408#if defined ( USE_MATRIX_TEST_DEBUG )
409 u32 id; 409 u32 id;
410 mutable u32 calls; 410 mutable u32 calls;
411#endif 411#endif
412 412
413 }; 413 };
414 414
415 // Default constructor 415 // Default constructor
416 template <class T> 416 template <class T>
417 inline CMatrix4<T>::CMatrix4( eConstructor constructor ) 417 inline CMatrix4<T>::CMatrix4( eConstructor constructor )
418#if defined ( USE_MATRIX_TEST ) 418#if defined ( USE_MATRIX_TEST )
419 : definitelyIdentityMatrix(BIT_UNTESTED) 419 : definitelyIdentityMatrix(BIT_UNTESTED)
420#endif 420#endif
421#if defined ( USE_MATRIX_TEST_DEBUG ) 421#if defined ( USE_MATRIX_TEST_DEBUG )
422 ,id ( MTest.ID++), calls ( 0 ) 422 ,id ( MTest.ID++), calls ( 0 )
423#endif 423#endif
424 { 424 {
425 switch ( constructor ) 425 switch ( constructor )
426 { 426 {
427 case EM4CONST_NOTHING: 427 case EM4CONST_NOTHING:
428 case EM4CONST_COPY: 428 case EM4CONST_COPY:
429 break; 429 break;
430 case EM4CONST_IDENTITY: 430 case EM4CONST_IDENTITY:
431 case EM4CONST_INVERSE: 431 case EM4CONST_INVERSE:
432 default: 432 default:
433 makeIdentity(); 433 makeIdentity();
434 break; 434 break;
435 } 435 }
436 } 436 }
437 437
438 // Copy constructor 438 // Copy constructor
439 template <class T> 439 template <class T>
440 inline CMatrix4<T>::CMatrix4( const CMatrix4<T>& other, eConstructor constructor) 440 inline CMatrix4<T>::CMatrix4( const CMatrix4<T>& other, eConstructor constructor)
441#if defined ( USE_MATRIX_TEST ) 441#if defined ( USE_MATRIX_TEST )
442 : definitelyIdentityMatrix(BIT_UNTESTED) 442 : definitelyIdentityMatrix(BIT_UNTESTED)
443#endif 443#endif
444#if defined ( USE_MATRIX_TEST_DEBUG ) 444#if defined ( USE_MATRIX_TEST_DEBUG )
445 ,id ( MTest.ID++), calls ( 0 ) 445 ,id ( MTest.ID++), calls ( 0 )
446#endif 446#endif
447 { 447 {
448 switch ( constructor ) 448 switch ( constructor )
449 { 449 {
450 case EM4CONST_IDENTITY: 450 case EM4CONST_IDENTITY:
451 makeIdentity(); 451 makeIdentity();
452 break; 452 break;
453 case EM4CONST_NOTHING: 453 case EM4CONST_NOTHING:
454 break; 454 break;
455 case EM4CONST_COPY: 455 case EM4CONST_COPY:
456 *this = other; 456 *this = other;
457 break; 457 break;
458 case EM4CONST_TRANSPOSED: 458 case EM4CONST_TRANSPOSED:
459 other.getTransposed(*this); 459 other.getTransposed(*this);
460 break; 460 break;
461 case EM4CONST_INVERSE: 461 case EM4CONST_INVERSE:
462 if (!other.getInverse(*this)) 462 if (!other.getInverse(*this))
463 memset(M, 0, 16*sizeof(T)); 463 memset(M, 0, 16*sizeof(T));
464 break; 464 break;
465 case EM4CONST_INVERSE_TRANSPOSED: 465 case EM4CONST_INVERSE_TRANSPOSED:
466 if (!other.getInverse(*this)) 466 if (!other.getInverse(*this))
467 memset(M, 0, 16*sizeof(T)); 467 memset(M, 0, 16*sizeof(T));
468 else 468 else
469 *this=getTransposed(); 469 *this=getTransposed();
470 break; 470 break;
471 } 471 }
472 } 472 }
473 473
474 //! Add another matrix. 474 //! Add another matrix.
475 template <class T> 475 template <class T>
476 inline CMatrix4<T> CMatrix4<T>::operator+(const CMatrix4<T>& other) const 476 inline CMatrix4<T> CMatrix4<T>::operator+(const CMatrix4<T>& other) const
477 { 477 {
478 CMatrix4<T> temp ( EM4CONST_NOTHING ); 478 CMatrix4<T> temp ( EM4CONST_NOTHING );
479 479
480 temp[0] = M[0]+other[0]; 480 temp[0] = M[0]+other[0];
481 temp[1] = M[1]+other[1]; 481 temp[1] = M[1]+other[1];
482 temp[2] = M[2]+other[2]; 482 temp[2] = M[2]+other[2];
483 temp[3] = M[3]+other[3]; 483 temp[3] = M[3]+other[3];
484 temp[4] = M[4]+other[4]; 484 temp[4] = M[4]+other[4];
485 temp[5] = M[5]+other[5]; 485 temp[5] = M[5]+other[5];
486 temp[6] = M[6]+other[6]; 486 temp[6] = M[6]+other[6];
487 temp[7] = M[7]+other[7]; 487 temp[7] = M[7]+other[7];
488 temp[8] = M[8]+other[8]; 488 temp[8] = M[8]+other[8];
489 temp[9] = M[9]+other[9]; 489 temp[9] = M[9]+other[9];
490 temp[10] = M[10]+other[10]; 490 temp[10] = M[10]+other[10];
491 temp[11] = M[11]+other[11]; 491 temp[11] = M[11]+other[11];
492 temp[12] = M[12]+other[12]; 492 temp[12] = M[12]+other[12];
493 temp[13] = M[13]+other[13]; 493 temp[13] = M[13]+other[13];
494 temp[14] = M[14]+other[14]; 494 temp[14] = M[14]+other[14];
495 temp[15] = M[15]+other[15]; 495 temp[15] = M[15]+other[15];
496 496
497 return temp; 497 return temp;
498 } 498 }
499 499
500 //! Add another matrix. 500 //! Add another matrix.
501 template <class T> 501 template <class T>
502 inline CMatrix4<T>& CMatrix4<T>::operator+=(const CMatrix4<T>& other) 502 inline CMatrix4<T>& CMatrix4<T>::operator+=(const CMatrix4<T>& other)
503 { 503 {
504 M[0]+=other[0]; 504 M[0]+=other[0];
505 M[1]+=other[1]; 505 M[1]+=other[1];
506 M[2]+=other[2]; 506 M[2]+=other[2];
507 M[3]+=other[3]; 507 M[3]+=other[3];
508 M[4]+=other[4]; 508 M[4]+=other[4];
509 M[5]+=other[5]; 509 M[5]+=other[5];
510 M[6]+=other[6]; 510 M[6]+=other[6];
511 M[7]+=other[7]; 511 M[7]+=other[7];
512 M[8]+=other[8]; 512 M[8]+=other[8];
513 M[9]+=other[9]; 513 M[9]+=other[9];
514 M[10]+=other[10]; 514 M[10]+=other[10];
515 M[11]+=other[11]; 515 M[11]+=other[11];
516 M[12]+=other[12]; 516 M[12]+=other[12];
517 M[13]+=other[13]; 517 M[13]+=other[13];
518 M[14]+=other[14]; 518 M[14]+=other[14];
519 M[15]+=other[15]; 519 M[15]+=other[15];
520 520
521 return *this; 521 return *this;
522 } 522 }
523 523
524 //! Subtract another matrix. 524 //! Subtract another matrix.
525 template <class T> 525 template <class T>
526 inline CMatrix4<T> CMatrix4<T>::operator-(const CMatrix4<T>& other) const 526 inline CMatrix4<T> CMatrix4<T>::operator-(const CMatrix4<T>& other) const
527 { 527 {
528 CMatrix4<T> temp ( EM4CONST_NOTHING ); 528 CMatrix4<T> temp ( EM4CONST_NOTHING );
529 529
530 temp[0] = M[0]-other[0]; 530 temp[0] = M[0]-other[0];
531 temp[1] = M[1]-other[1]; 531 temp[1] = M[1]-other[1];
532 temp[2] = M[2]-other[2]; 532 temp[2] = M[2]-other[2];
533 temp[3] = M[3]-other[3]; 533 temp[3] = M[3]-other[3];
534 temp[4] = M[4]-other[4]; 534 temp[4] = M[4]-other[4];
535 temp[5] = M[5]-other[5]; 535 temp[5] = M[5]-other[5];
536 temp[6] = M[6]-other[6]; 536 temp[6] = M[6]-other[6];
537 temp[7] = M[7]-other[7]; 537 temp[7] = M[7]-other[7];
538 temp[8] = M[8]-other[8]; 538 temp[8] = M[8]-other[8];
539 temp[9] = M[9]-other[9]; 539 temp[9] = M[9]-other[9];
540 temp[10] = M[10]-other[10]; 540 temp[10] = M[10]-other[10];
541 temp[11] = M[11]-other[11]; 541 temp[11] = M[11]-other[11];
542 temp[12] = M[12]-other[12]; 542 temp[12] = M[12]-other[12];
543 temp[13] = M[13]-other[13]; 543 temp[13] = M[13]-other[13];
544 temp[14] = M[14]-other[14]; 544 temp[14] = M[14]-other[14];
545 temp[15] = M[15]-other[15]; 545 temp[15] = M[15]-other[15];
546 546
547 return temp; 547 return temp;
548 } 548 }
549 549
550 //! Subtract another matrix. 550 //! Subtract another matrix.
551 template <class T> 551 template <class T>
552 inline CMatrix4<T>& CMatrix4<T>::operator-=(const CMatrix4<T>& other) 552 inline CMatrix4<T>& CMatrix4<T>::operator-=(const CMatrix4<T>& other)
553 { 553 {
554 M[0]-=other[0]; 554 M[0]-=other[0];
555 M[1]-=other[1]; 555 M[1]-=other[1];
556 M[2]-=other[2]; 556 M[2]-=other[2];
557 M[3]-=other[3]; 557 M[3]-=other[3];
558 M[4]-=other[4]; 558 M[4]-=other[4];
559 M[5]-=other[5]; 559 M[5]-=other[5];
560 M[6]-=other[6]; 560 M[6]-=other[6];
561 M[7]-=other[7]; 561 M[7]-=other[7];
562 M[8]-=other[8]; 562 M[8]-=other[8];
563 M[9]-=other[9]; 563 M[9]-=other[9];
564 M[10]-=other[10]; 564 M[10]-=other[10];
565 M[11]-=other[11]; 565 M[11]-=other[11];
566 M[12]-=other[12]; 566 M[12]-=other[12];
567 M[13]-=other[13]; 567 M[13]-=other[13];
568 M[14]-=other[14]; 568 M[14]-=other[14];
569 M[15]-=other[15]; 569 M[15]-=other[15];
570 570
571 return *this; 571 return *this;
572 } 572 }
573 573
574 //! Multiply by scalar. 574 //! Multiply by scalar.
575 template <class T> 575 template <class T>
576 inline CMatrix4<T> CMatrix4<T>::operator*(const T& scalar) const 576 inline CMatrix4<T> CMatrix4<T>::operator*(const T& scalar) const
577 { 577 {
578 CMatrix4<T> temp ( EM4CONST_NOTHING ); 578 CMatrix4<T> temp ( EM4CONST_NOTHING );
579 579
580 temp[0] = M[0]*scalar; 580 temp[0] = M[0]*scalar;
581 temp[1] = M[1]*scalar; 581 temp[1] = M[1]*scalar;
582 temp[2] = M[2]*scalar; 582 temp[2] = M[2]*scalar;
583 temp[3] = M[3]*scalar; 583 temp[3] = M[3]*scalar;
584 temp[4] = M[4]*scalar; 584 temp[4] = M[4]*scalar;
585 temp[5] = M[5]*scalar; 585 temp[5] = M[5]*scalar;
586 temp[6] = M[6]*scalar; 586 temp[6] = M[6]*scalar;
587 temp[7] = M[7]*scalar; 587 temp[7] = M[7]*scalar;
588 temp[8] = M[8]*scalar; 588 temp[8] = M[8]*scalar;
589 temp[9] = M[9]*scalar; 589 temp[9] = M[9]*scalar;
590 temp[10] = M[10]*scalar; 590 temp[10] = M[10]*scalar;
591 temp[11] = M[11]*scalar; 591 temp[11] = M[11]*scalar;
592 temp[12] = M[12]*scalar; 592 temp[12] = M[12]*scalar;
593 temp[13] = M[13]*scalar; 593 temp[13] = M[13]*scalar;
594 temp[14] = M[14]*scalar; 594 temp[14] = M[14]*scalar;
595 temp[15] = M[15]*scalar; 595 temp[15] = M[15]*scalar;
596 596
597 return temp; 597 return temp;
598 } 598 }
599 599
600 //! Multiply by scalar. 600 //! Multiply by scalar.
601 template <class T> 601 template <class T>
602 inline CMatrix4<T>& CMatrix4<T>::operator*=(const T& scalar) 602 inline CMatrix4<T>& CMatrix4<T>::operator*=(const T& scalar)
603 { 603 {
604 M[0]*=scalar; 604 M[0]*=scalar;
605 M[1]*=scalar; 605 M[1]*=scalar;
606 M[2]*=scalar; 606 M[2]*=scalar;
607 M[3]*=scalar; 607 M[3]*=scalar;
608 M[4]*=scalar; 608 M[4]*=scalar;
609 M[5]*=scalar; 609 M[5]*=scalar;
610 M[6]*=scalar; 610 M[6]*=scalar;
611 M[7]*=scalar; 611 M[7]*=scalar;
612 M[8]*=scalar; 612 M[8]*=scalar;
613 M[9]*=scalar; 613 M[9]*=scalar;
614 M[10]*=scalar; 614 M[10]*=scalar;
615 M[11]*=scalar; 615 M[11]*=scalar;
616 M[12]*=scalar; 616 M[12]*=scalar;
617 M[13]*=scalar; 617 M[13]*=scalar;
618 M[14]*=scalar; 618 M[14]*=scalar;
619 M[15]*=scalar; 619 M[15]*=scalar;
620 620
621 return *this; 621 return *this;
622 } 622 }
623 623
624 //! Multiply by another matrix. 624 //! Multiply by another matrix.
625 template <class T> 625 template <class T>
626 inline CMatrix4<T>& CMatrix4<T>::operator*=(const CMatrix4<T>& other) 626 inline CMatrix4<T>& CMatrix4<T>::operator*=(const CMatrix4<T>& other)
627 { 627 {
628#if defined ( USE_MATRIX_TEST ) 628#if defined ( USE_MATRIX_TEST )
629 // do checks on your own in order to avoid copy creation 629 // do checks on your own in order to avoid copy creation
630 if ( !other.isIdentity() ) 630 if ( !other.isIdentity() )
631 { 631 {
632 if ( this->isIdentity() ) 632 if ( this->isIdentity() )
633 { 633 {
634 return (*this = other); 634 return (*this = other);
635 } 635 }
636 else 636 else
637 { 637 {
638 CMatrix4<T> temp ( *this ); 638 CMatrix4<T> temp ( *this );
639 return setbyproduct_nocheck( temp, other ); 639 return setbyproduct_nocheck( temp, other );
640 } 640 }
641 } 641 }
642 return *this; 642 return *this;
643#else 643#else
644 CMatrix4<T> temp ( *this ); 644 CMatrix4<T> temp ( *this );
645 return setbyproduct_nocheck( temp, other ); 645 return setbyproduct_nocheck( temp, other );
646#endif 646#endif
647 } 647 }
648 648
649 //! multiply by another matrix 649 //! multiply by another matrix
650 // set this matrix to the product of two other matrices 650 // set this matrix to the product of two other matrices
651 // goal is to reduce stack use and copy 651 // goal is to reduce stack use and copy
652 template <class T> 652 template <class T>
653 inline CMatrix4<T>& CMatrix4<T>::setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b ) 653 inline CMatrix4<T>& CMatrix4<T>::setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b )
654 { 654 {
655 const T *m1 = other_a.M; 655 const T *m1 = other_a.M;
656 const T *m2 = other_b.M; 656 const T *m2 = other_b.M;
657 657
658 M[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3]; 658 M[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
659 M[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3]; 659 M[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
660 M[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3]; 660 M[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
661 M[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3]; 661 M[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
662 662
663 M[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7]; 663 M[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
664 M[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7]; 664 M[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
665 M[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7]; 665 M[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
666 M[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7]; 666 M[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
667 667
668 M[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11]; 668 M[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
669 M[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11]; 669 M[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
670 M[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11]; 670 M[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
671 M[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11]; 671 M[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
672 672
673 M[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15]; 673 M[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
674 M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15]; 674 M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
675 M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15]; 675 M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
676 M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15]; 676 M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
677#if defined ( USE_MATRIX_TEST ) 677#if defined ( USE_MATRIX_TEST )
678 definitelyIdentityMatrix=false; 678 definitelyIdentityMatrix=false;
679#endif 679#endif
680 return *this; 680 return *this;
681 } 681 }
682 682
683 683
684 //! multiply by another matrix 684 //! multiply by another matrix
685 // set this matrix to the product of two other matrices 685 // set this matrix to the product of two other matrices
686 // goal is to reduce stack use and copy 686 // goal is to reduce stack use and copy
687 template <class T> 687 template <class T>
688 inline CMatrix4<T>& CMatrix4<T>::setbyproduct(const CMatrix4<T>& other_a, const CMatrix4<T>& other_b ) 688 inline CMatrix4<T>& CMatrix4<T>::setbyproduct(const CMatrix4<T>& other_a, const CMatrix4<T>& other_b )
689 { 689 {
690#if defined ( USE_MATRIX_TEST ) 690#if defined ( USE_MATRIX_TEST )
691 if ( other_a.isIdentity () ) 691 if ( other_a.isIdentity () )
692 return (*this = other_b); 692 return (*this = other_b);
693 else 693 else
694 if ( other_b.isIdentity () ) 694 if ( other_b.isIdentity () )
695 return (*this = other_a); 695 return (*this = other_a);
696 else 696 else
697 return setbyproduct_nocheck(other_a,other_b); 697 return setbyproduct_nocheck(other_a,other_b);
698#else 698#else
699 return setbyproduct_nocheck(other_a,other_b); 699 return setbyproduct_nocheck(other_a,other_b);
700#endif 700#endif
701 } 701 }
702 702
703 //! multiply by another matrix 703 //! multiply by another matrix
704 template <class T> 704 template <class T>
705 inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T>& m2) const 705 inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T>& m2) const
706 { 706 {
707#if defined ( USE_MATRIX_TEST ) 707#if defined ( USE_MATRIX_TEST )
708 // Testing purpose.. 708 // Testing purpose..
709 if ( this->isIdentity() ) 709 if ( this->isIdentity() )
710 return m2; 710 return m2;
711 if ( m2.isIdentity() ) 711 if ( m2.isIdentity() )
712 return *this; 712 return *this;
713#endif 713#endif
714 714
715 CMatrix4<T> m3 ( EM4CONST_NOTHING ); 715 CMatrix4<T> m3 ( EM4CONST_NOTHING );
716 716
717 const T *m1 = M; 717 const T *m1 = M;
718 718
719 m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3]; 719 m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
720 m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3]; 720 m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
721 m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3]; 721 m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
722 m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3]; 722 m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
723 723
724 m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7]; 724 m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
725 m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7]; 725 m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
726 m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7]; 726 m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
727 m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7]; 727 m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
728 728
729 m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11]; 729 m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
730 m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11]; 730 m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
731 m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11]; 731 m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
732 m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11]; 732 m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
733 733
734 m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15]; 734 m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
735 m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15]; 735 m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
736 m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15]; 736 m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
737 m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15]; 737 m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
738 return m3; 738 return m3;
739 } 739 }
740 740
741 741
742 742
743 template <class T> 743 template <class T>
744 inline vector3d<T> CMatrix4<T>::getTranslation() const 744 inline vector3d<T> CMatrix4<T>::getTranslation() const
745 { 745 {
746 return vector3d<T>(M[12], M[13], M[14]); 746 return vector3d<T>(M[12], M[13], M[14]);
747 } 747 }
748 748
749 749
750 template <class T> 750 template <class T>
751 inline CMatrix4<T>& CMatrix4<T>::setTranslation( const vector3d<T>& translation ) 751 inline CMatrix4<T>& CMatrix4<T>::setTranslation( const vector3d<T>& translation )
752 { 752 {
753 M[12] = translation.X; 753 M[12] = translation.X;
754 M[13] = translation.Y; 754 M[13] = translation.Y;
755 M[14] = translation.Z; 755 M[14] = translation.Z;
756#if defined ( USE_MATRIX_TEST ) 756#if defined ( USE_MATRIX_TEST )
757 definitelyIdentityMatrix=false; 757 definitelyIdentityMatrix=false;
758#endif 758#endif
759 return *this; 759 return *this;
760 } 760 }
761 761
762 template <class T> 762 template <class T>
763 inline CMatrix4<T>& CMatrix4<T>::setInverseTranslation( const vector3d<T>& translation ) 763 inline CMatrix4<T>& CMatrix4<T>::setInverseTranslation( const vector3d<T>& translation )
764 { 764 {
765 M[12] = -translation.X; 765 M[12] = -translation.X;
766 M[13] = -translation.Y; 766 M[13] = -translation.Y;
767 M[14] = -translation.Z; 767 M[14] = -translation.Z;
768#if defined ( USE_MATRIX_TEST ) 768#if defined ( USE_MATRIX_TEST )
769 definitelyIdentityMatrix=false; 769 definitelyIdentityMatrix=false;
770#endif 770#endif
771 return *this; 771 return *this;
772 } 772 }
773 773
774 template <class T> 774 template <class T>
775 inline CMatrix4<T>& CMatrix4<T>::setScale( const vector3d<T>& scale ) 775 inline CMatrix4<T>& CMatrix4<T>::setScale( const vector3d<T>& scale )
776 { 776 {
777 M[0] = scale.X; 777 M[0] = scale.X;
778 M[5] = scale.Y; 778 M[5] = scale.Y;
779 M[10] = scale.Z; 779 M[10] = scale.Z;
780#if defined ( USE_MATRIX_TEST ) 780#if defined ( USE_MATRIX_TEST )
781 definitelyIdentityMatrix=false; 781 definitelyIdentityMatrix=false;
782#endif 782#endif
783 return *this; 783 return *this;
784 } 784 }
785 785
786 //! Returns the absolute values of the scales of the matrix. 786 //! Returns the absolute values of the scales of the matrix.
787 /** 787 /**
788 Note that this returns the absolute (positive) values unless only scale is set. 788 Note that this returns the absolute (positive) values unless only scale is set.
789 Unfortunately it does not appear to be possible to extract any original negative 789 Unfortunately it does not appear to be possible to extract any original negative
790 values. The best that we could do would be to arbitrarily make one scale 790 values. The best that we could do would be to arbitrarily make one scale
791 negative if one or three of them were negative. 791 negative if one or three of them were negative.
792 FIXME - return the original values. 792 FIXME - return the original values.
793 */ 793 */
794 template <class T> 794 template <class T>
795 inline vector3d<T> CMatrix4<T>::getScale() const 795 inline vector3d<T> CMatrix4<T>::getScale() const
796 { 796 {
797 // See http://www.robertblum.com/articles/2005/02/14/decomposing-matrices 797 // See http://www.robertblum.com/articles/2005/02/14/decomposing-matrices
798 798
799 // Deal with the 0 rotation case first 799 // Deal with the 0 rotation case first
800 // Prior to Irrlicht 1.6, we always returned this value. 800 // Prior to Irrlicht 1.6, we always returned this value.
801 if(core::iszero(M[1]) && core::iszero(M[2]) && 801 if(core::iszero(M[1]) && core::iszero(M[2]) &&
802 core::iszero(M[4]) && core::iszero(M[6]) && 802 core::iszero(M[4]) && core::iszero(M[6]) &&
803 core::iszero(M[8]) && core::iszero(M[9])) 803 core::iszero(M[8]) && core::iszero(M[9]))
804 return vector3d<T>(M[0], M[5], M[10]); 804 return vector3d<T>(M[0], M[5], M[10]);
805 805
806 // We have to do the full calculation. 806 // We have to do the full calculation.
807 return vector3d<T>(sqrtf(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]), 807 return vector3d<T>(sqrtf(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]),
808 sqrtf(M[4] * M[4] + M[5] * M[5] + M[6] * M[6]), 808 sqrtf(M[4] * M[4] + M[5] * M[5] + M[6] * M[6]),
809 sqrtf(M[8] * M[8] + M[9] * M[9] + M[10] * M[10])); 809 sqrtf(M[8] * M[8] + M[9] * M[9] + M[10] * M[10]));
810 } 810 }
811 811
812 template <class T> 812 template <class T>
813 inline CMatrix4<T>& CMatrix4<T>::setRotationDegrees( const vector3d<T>& rotation ) 813 inline CMatrix4<T>& CMatrix4<T>::setRotationDegrees( const vector3d<T>& rotation )
814 { 814 {
815 return setRotationRadians( rotation * core::DEGTORAD ); 815 return setRotationRadians( rotation * core::DEGTORAD );
816 } 816 }
817 817
818 template <class T> 818 template <class T>
819 inline CMatrix4<T>& CMatrix4<T>::setInverseRotationDegrees( const vector3d<T>& rotation ) 819 inline CMatrix4<T>& CMatrix4<T>::setInverseRotationDegrees( const vector3d<T>& rotation )
820 { 820 {
821 return setInverseRotationRadians( rotation * core::DEGTORAD ); 821 return setInverseRotationRadians( rotation * core::DEGTORAD );
822 } 822 }
823 823
824 template <class T> 824 template <class T>
825 inline CMatrix4<T>& CMatrix4<T>::setRotationRadians( const vector3d<T>& rotation ) 825 inline CMatrix4<T>& CMatrix4<T>::setRotationRadians( const vector3d<T>& rotation )
826 { 826 {
827 const f64 cr = cos( rotation.X ); 827 const f64 cr = cos( rotation.X );
828 const f64 sr = sin( rotation.X ); 828 const f64 sr = sin( rotation.X );
829 const f64 cp = cos( rotation.Y ); 829 const f64 cp = cos( rotation.Y );
830 const f64 sp = sin( rotation.Y ); 830 const f64 sp = sin( rotation.Y );
831 const f64 cy = cos( rotation.Z ); 831 const f64 cy = cos( rotation.Z );
832 const f64 sy = sin( rotation.Z ); 832 const f64 sy = sin( rotation.Z );
833 833
834 M[0] = (T)( cp*cy ); 834 M[0] = (T)( cp*cy );
835 M[1] = (T)( cp*sy ); 835 M[1] = (T)( cp*sy );
836 M[2] = (T)( -sp ); 836 M[2] = (T)( -sp );
837 837
838 const f64 srsp = sr*sp; 838 const f64 srsp = sr*sp;
839 const f64 crsp = cr*sp; 839 const f64 crsp = cr*sp;
840 840
841 M[4] = (T)( srsp*cy-cr*sy ); 841 M[4] = (T)( srsp*cy-cr*sy );
842 M[5] = (T)( srsp*sy+cr*cy ); 842 M[5] = (T)( srsp*sy+cr*cy );
843 M[6] = (T)( sr*cp ); 843 M[6] = (T)( sr*cp );
844 844
845 M[8] = (T)( crsp*cy+sr*sy ); 845 M[8] = (T)( crsp*cy+sr*sy );
846 M[9] = (T)( crsp*sy-sr*cy ); 846 M[9] = (T)( crsp*sy-sr*cy );
847 M[10] = (T)( cr*cp ); 847 M[10] = (T)( cr*cp );
848#if defined ( USE_MATRIX_TEST ) 848#if defined ( USE_MATRIX_TEST )
849 definitelyIdentityMatrix=false; 849 definitelyIdentityMatrix=false;
850#endif 850#endif
851 return *this; 851 return *this;
852 } 852 }
853 853
854 854
855 //! Returns a rotation that is equivalent to that set by setRotationDegrees(). 855 //! Returns a rotation that is equivalent to that set by setRotationDegrees().
856 /** This code was sent in by Chev. Note that it does not necessarily return 856 /** This code was sent in by Chev. Note that it does not necessarily return
857 the *same* Euler angles as those set by setRotationDegrees(), but the rotation will 857 the *same* Euler angles as those set by setRotationDegrees(), but the rotation will
858 be equivalent, i.e. will have the same result when used to rotate a vector or node. */ 858 be equivalent, i.e. will have the same result when used to rotate a vector or node. */
859 template <class T> 859 template <class T>
860 inline core::vector3d<T> CMatrix4<T>::getRotationDegrees() const 860 inline core::vector3d<T> CMatrix4<T>::getRotationDegrees() const
861 { 861 {
862 const CMatrix4<T> &mat = *this; 862 const CMatrix4<T> &mat = *this;
863 core::vector3d<T> scale = getScale(); 863 core::vector3d<T> scale = getScale();
864 // we need to check for negative scale on to axes, which would bring up wrong results 864 // we need to check for negative scale on to axes, which would bring up wrong results
865 if (scale.Y<0 && scale.Z<0) 865 if (scale.Y<0 && scale.Z<0)
866 { 866 {
867 scale.Y =-scale.Y; 867 scale.Y =-scale.Y;
868 scale.Z =-scale.Z; 868 scale.Z =-scale.Z;
869 } 869 }
870 else if (scale.X<0 && scale.Z<0) 870 else if (scale.X<0 && scale.Z<0)
871 { 871 {
872 scale.X =-scale.X; 872 scale.X =-scale.X;
873 scale.Z =-scale.Z; 873 scale.Z =-scale.Z;
874 } 874 }
875 else if (scale.X<0 && scale.Y<0) 875 else if (scale.X<0 && scale.Y<0)
876 { 876 {
877 scale.X =-scale.X; 877 scale.X =-scale.X;
878 scale.Y =-scale.Y; 878 scale.Y =-scale.Y;
879 } 879 }
880 const core::vector3d<f64> invScale(core::reciprocal(scale.X),core::reciprocal(scale.Y),core::reciprocal(scale.Z)); 880 const core::vector3d<f64> invScale(core::reciprocal(scale.X),core::reciprocal(scale.Y),core::reciprocal(scale.Z));
881 881
882 f64 Y = -asin(core::clamp(mat[2]*invScale.X, -1.0, 1.0)); 882 f64 Y = -asin(core::clamp(mat[2]*invScale.X, -1.0, 1.0));
883 const f64 C = cos(Y); 883 const f64 C = cos(Y);
884 Y *= RADTODEG64; 884 Y *= RADTODEG64;
885 885
886 f64 rotx, roty, X, Z; 886 f64 rotx, roty, X, Z;
887 887
888 if (!core::iszero(C)) 888 if (!core::iszero(C))
889 { 889 {
890 const f64 invC = core::reciprocal(C); 890 const f64 invC = core::reciprocal(C);
891 rotx = mat[10] * invC * invScale.Z; 891 rotx = mat[10] * invC * invScale.Z;
892 roty = mat[6] * invC * invScale.Y; 892 roty = mat[6] * invC * invScale.Y;
893 X = atan2( roty, rotx ) * RADTODEG64; 893 X = atan2( roty, rotx ) * RADTODEG64;
894 rotx = mat[0] * invC * invScale.X; 894 rotx = mat[0] * invC * invScale.X;
895 roty = mat[1] * invC * invScale.X; 895 roty = mat[1] * invC * invScale.X;
896 Z = atan2( roty, rotx ) * RADTODEG64; 896 Z = atan2( roty, rotx ) * RADTODEG64;
897 } 897 }
898 else 898 else
899 { 899 {
900 X = 0.0; 900 X = 0.0;
901 rotx = mat[5] * invScale.Y; 901 rotx = mat[5] * invScale.Y;
902 roty = -mat[4] * invScale.Y; 902 roty = -mat[4] * invScale.Y;
903 Z = atan2( roty, rotx ) * RADTODEG64; 903 Z = atan2( roty, rotx ) * RADTODEG64;
904 } 904 }
905 905
906 // fix values that get below zero 906 // fix values that get below zero
907 if (X < 0.0) X += 360.0; 907 if (X < 0.0) X += 360.0;
908 if (Y < 0.0) Y += 360.0; 908 if (Y < 0.0) Y += 360.0;
909 if (Z < 0.0) Z += 360.0; 909 if (Z < 0.0) Z += 360.0;
910 910
911 return vector3d<T>((T)X,(T)Y,(T)Z); 911 return vector3d<T>((T)X,(T)Y,(T)Z);
912 } 912 }
913 913
914 914
915 //! Sets matrix to rotation matrix of inverse angles given as parameters 915 //! Sets matrix to rotation matrix of inverse angles given as parameters
916 template <class T> 916 template <class T>
917 inline CMatrix4<T>& CMatrix4<T>::setInverseRotationRadians( const vector3d<T>& rotation ) 917 inline CMatrix4<T>& CMatrix4<T>::setInverseRotationRadians( const vector3d<T>& rotation )
918 { 918 {
919 f64 cr = cos( rotation.X ); 919 f64 cr = cos( rotation.X );
920 f64 sr = sin( rotation.X ); 920 f64 sr = sin( rotation.X );
921 f64 cp = cos( rotation.Y ); 921 f64 cp = cos( rotation.Y );
922 f64 sp = sin( rotation.Y ); 922 f64 sp = sin( rotation.Y );
923 f64 cy = cos( rotation.Z ); 923 f64 cy = cos( rotation.Z );
924 f64 sy = sin( rotation.Z ); 924 f64 sy = sin( rotation.Z );
925 925
926 M[0] = (T)( cp*cy ); 926 M[0] = (T)( cp*cy );
927 M[4] = (T)( cp*sy ); 927 M[4] = (T)( cp*sy );
928 M[8] = (T)( -sp ); 928 M[8] = (T)( -sp );
929 929
930 f64 srsp = sr*sp; 930 f64 srsp = sr*sp;
931 f64 crsp = cr*sp; 931 f64 crsp = cr*sp;
932 932
933 M[1] = (T)( srsp*cy-cr*sy ); 933 M[1] = (T)( srsp*cy-cr*sy );
934 M[5] = (T)( srsp*sy+cr*cy ); 934 M[5] = (T)( srsp*sy+cr*cy );
935 M[9] = (T)( sr*cp ); 935 M[9] = (T)( sr*cp );
936 936
937 M[2] = (T)( crsp*cy+sr*sy ); 937 M[2] = (T)( crsp*cy+sr*sy );
938 M[6] = (T)( crsp*sy-sr*cy ); 938 M[6] = (T)( crsp*sy-sr*cy );
939 M[10] = (T)( cr*cp ); 939 M[10] = (T)( cr*cp );
940#if defined ( USE_MATRIX_TEST ) 940#if defined ( USE_MATRIX_TEST )
941 definitelyIdentityMatrix=false; 941 definitelyIdentityMatrix=false;
942#endif 942#endif
943 return *this; 943 return *this;
944 } 944 }
945 945
946 //! Sets matrix to rotation matrix defined by axis and angle, assuming LH rotation 946 //! Sets matrix to rotation matrix defined by axis and angle, assuming LH rotation
947 template <class T> 947 template <class T>
948 inline CMatrix4<T>& CMatrix4<T>::setRotationAxisRadians( const T& angle, const vector3d<T>& axis ) 948 inline CMatrix4<T>& CMatrix4<T>::setRotationAxisRadians( const T& angle, const vector3d<T>& axis )
949 { 949 {
950 const f64 c = cos(angle); 950 const f64 c = cos(angle);
951 const f64 s = sin(angle); 951 const f64 s = sin(angle);
952 const f64 t = 1.0 - c; 952 const f64 t = 1.0 - c;
953 953
954 const f64 tx = t * axis.X; 954 const f64 tx = t * axis.X;
955 const f64 ty = t * axis.Y; 955 const f64 ty = t * axis.Y;
956 const f64 tz = t * axis.Z; 956 const f64 tz = t * axis.Z;
957 957
958 const f64 sx = s * axis.X; 958 const f64 sx = s * axis.X;
959 const f64 sy = s * axis.Y; 959 const f64 sy = s * axis.Y;
960 const f64 sz = s * axis.Z; 960 const f64 sz = s * axis.Z;
961 961
962 M[0] = (T)(tx * axis.X + c); 962 M[0] = (T)(tx * axis.X + c);
963 M[1] = (T)(tx * axis.Y + sz); 963 M[1] = (T)(tx * axis.Y + sz);
964 M[2] = (T)(tx * axis.Z - sy); 964 M[2] = (T)(tx * axis.Z - sy);
965 965
966 M[4] = (T)(ty * axis.X - sz); 966 M[4] = (T)(ty * axis.X - sz);
967 M[5] = (T)(ty * axis.Y + c); 967 M[5] = (T)(ty * axis.Y + c);
968 M[6] = (T)(ty * axis.Z + sx); 968 M[6] = (T)(ty * axis.Z + sx);
969 969
970 M[8] = (T)(tz * axis.X + sy); 970 M[8] = (T)(tz * axis.X + sy);
971 M[9] = (T)(tz * axis.Y - sx); 971 M[9] = (T)(tz * axis.Y - sx);
972 M[10] = (T)(tz * axis.Z + c); 972 M[10] = (T)(tz * axis.Z + c);
973 973
974#if defined ( USE_MATRIX_TEST ) 974#if defined ( USE_MATRIX_TEST )
975 definitelyIdentityMatrix=false; 975 definitelyIdentityMatrix=false;
976#endif 976#endif
977 return *this; 977 return *this;
978 } 978 }
979 979
980 980
981 /*! 981 /*!
982 */ 982 */
983 template <class T> 983 template <class T>
984 inline CMatrix4<T>& CMatrix4<T>::makeIdentity() 984 inline CMatrix4<T>& CMatrix4<T>::makeIdentity()
985 { 985 {
986 memset(M, 0, 16*sizeof(T)); 986 memset(M, 0, 16*sizeof(T));
987 M[0] = M[5] = M[10] = M[15] = (T)1; 987 M[0] = M[5] = M[10] = M[15] = (T)1;
988#if defined ( USE_MATRIX_TEST ) 988#if defined ( USE_MATRIX_TEST )
989 definitelyIdentityMatrix=true; 989 definitelyIdentityMatrix=true;
990#endif 990#endif
991 return *this; 991 return *this;
992 } 992 }
993 993
994 994
995 /* 995 /*
996 check identity with epsilon 996 check identity with epsilon
997 solve floating range problems.. 997 solve floating range problems..
998 */ 998 */
999 template <class T> 999 template <class T>
1000 inline bool CMatrix4<T>::isIdentity() const 1000 inline bool CMatrix4<T>::isIdentity() const
1001 { 1001 {
1002#if defined ( USE_MATRIX_TEST ) 1002#if defined ( USE_MATRIX_TEST )
1003 if (definitelyIdentityMatrix) 1003 if (definitelyIdentityMatrix)
1004 return true; 1004 return true;
1005#endif 1005#endif
1006 if (!core::equals( M[12], (T)0 ) || !core::equals( M[13], (T)0 ) || !core::equals( M[14], (T)0 ) || !core::equals( M[15], (T)1 )) 1006 if (!core::equals( M[12], (T)0 ) || !core::equals( M[13], (T)0 ) || !core::equals( M[14], (T)0 ) || !core::equals( M[15], (T)1 ))
1007 return false; 1007 return false;
1008 1008
1009 if (!core::equals( M[ 0], (T)1 ) || !core::equals( M[ 1], (T)0 ) || !core::equals( M[ 2], (T)0 ) || !core::equals( M[ 3], (T)0 )) 1009 if (!core::equals( M[ 0], (T)1 ) || !core::equals( M[ 1], (T)0 ) || !core::equals( M[ 2], (T)0 ) || !core::equals( M[ 3], (T)0 ))
1010 return false; 1010 return false;
1011 1011
1012 if (!core::equals( M[ 4], (T)0 ) || !core::equals( M[ 5], (T)1 ) || !core::equals( M[ 6], (T)0 ) || !core::equals( M[ 7], (T)0 )) 1012 if (!core::equals( M[ 4], (T)0 ) || !core::equals( M[ 5], (T)1 ) || !core::equals( M[ 6], (T)0 ) || !core::equals( M[ 7], (T)0 ))
1013 return false; 1013 return false;
1014 1014
1015 if (!core::equals( M[ 8], (T)0 ) || !core::equals( M[ 9], (T)0 ) || !core::equals( M[10], (T)1 ) || !core::equals( M[11], (T)0 )) 1015 if (!core::equals( M[ 8], (T)0 ) || !core::equals( M[ 9], (T)0 ) || !core::equals( M[10], (T)1 ) || !core::equals( M[11], (T)0 ))
1016 return false; 1016 return false;
1017/* 1017/*
1018 if (!core::equals( M[ 0], (T)1 ) || 1018 if (!core::equals( M[ 0], (T)1 ) ||
1019 !core::equals( M[ 5], (T)1 ) || 1019 !core::equals( M[ 5], (T)1 ) ||
1020 !core::equals( M[10], (T)1 ) || 1020 !core::equals( M[10], (T)1 ) ||
1021 !core::equals( M[15], (T)1 )) 1021 !core::equals( M[15], (T)1 ))
1022 return false; 1022 return false;
1023 1023
1024 for (s32 i=0; i<4; ++i) 1024 for (s32 i=0; i<4; ++i)
1025 for (s32 j=0; j<4; ++j) 1025 for (s32 j=0; j<4; ++j)
1026 if ((j != i) && (!iszero((*this)(i,j)))) 1026 if ((j != i) && (!iszero((*this)(i,j))))
1027 return false; 1027 return false;
1028*/ 1028*/
1029#if defined ( USE_MATRIX_TEST ) 1029#if defined ( USE_MATRIX_TEST )
1030 definitelyIdentityMatrix=true; 1030 definitelyIdentityMatrix=true;
1031#endif 1031#endif
1032 return true; 1032 return true;
1033 } 1033 }
1034 1034
1035 1035
1036 /* Check orthogonality of matrix. */ 1036 /* Check orthogonality of matrix. */
1037 template <class T> 1037 template <class T>
1038 inline bool CMatrix4<T>::isOrthogonal() const 1038 inline bool CMatrix4<T>::isOrthogonal() const
1039 { 1039 {
1040 T dp=M[0] * M[4 ] + M[1] * M[5 ] + M[2 ] * M[6 ] + M[3 ] * M[7 ]; 1040 T dp=M[0] * M[4 ] + M[1] * M[5 ] + M[2 ] * M[6 ] + M[3 ] * M[7 ];
1041 if (!iszero(dp)) 1041 if (!iszero(dp))
1042 return false; 1042 return false;
1043 dp = M[0] * M[8 ] + M[1] * M[9 ] + M[2 ] * M[10] + M[3 ] * M[11]; 1043 dp = M[0] * M[8 ] + M[1] * M[9 ] + M[2 ] * M[10] + M[3 ] * M[11];
1044 if (!iszero(dp)) 1044 if (!iszero(dp))
1045 return false; 1045 return false;
1046 dp = M[0] * M[12] + M[1] * M[13] + M[2 ] * M[14] + M[3 ] * M[15]; 1046 dp = M[0] * M[12] + M[1] * M[13] + M[2 ] * M[14] + M[3 ] * M[15];
1047 if (!iszero(dp)) 1047 if (!iszero(dp))
1048 return false; 1048 return false;
1049 dp = M[4] * M[8 ] + M[5] * M[9 ] + M[6 ] * M[10] + M[7 ] * M[11]; 1049 dp = M[4] * M[8 ] + M[5] * M[9 ] + M[6 ] * M[10] + M[7 ] * M[11];
1050 if (!iszero(dp)) 1050 if (!iszero(dp))
1051 return false; 1051 return false;
1052 dp = M[4] * M[12] + M[5] * M[13] + M[6 ] * M[14] + M[7 ] * M[15]; 1052 dp = M[4] * M[12] + M[5] * M[13] + M[6 ] * M[14] + M[7 ] * M[15];
1053 if (!iszero(dp)) 1053 if (!iszero(dp))
1054 return false; 1054 return false;
1055 dp = M[8] * M[12] + M[9] * M[13] + M[10] * M[14] + M[11] * M[15]; 1055 dp = M[8] * M[12] + M[9] * M[13] + M[10] * M[14] + M[11] * M[15];
1056 return (iszero(dp)); 1056 return (iszero(dp));
1057 } 1057 }
1058 1058
1059 1059
1060 /* 1060 /*
1061 doesn't solve floating range problems.. 1061 doesn't solve floating range problems..
1062 but takes care on +/- 0 on translation because we are changing it.. 1062 but takes care on +/- 0 on translation because we are changing it..
1063 reducing floating point branches 1063 reducing floating point branches
1064 but it needs the floats in memory.. 1064 but it needs the floats in memory..
1065 */ 1065 */
1066 template <class T> 1066 template <class T>
1067 inline bool CMatrix4<T>::isIdentity_integer_base() const 1067 inline bool CMatrix4<T>::isIdentity_integer_base() const
1068 { 1068 {
1069#if defined ( USE_MATRIX_TEST ) 1069#if defined ( USE_MATRIX_TEST )
1070 if (definitelyIdentityMatrix) 1070 if (definitelyIdentityMatrix)
1071 return true; 1071 return true;
1072#endif 1072#endif
1073 if(IR(M[0])!=F32_VALUE_1) return false; 1073 if(IR(M[0])!=F32_VALUE_1) return false;
1074 if(IR(M[1])!=0) return false; 1074 if(IR(M[1])!=0) return false;
1075 if(IR(M[2])!=0) return false; 1075 if(IR(M[2])!=0) return false;
1076 if(IR(M[3])!=0) return false; 1076 if(IR(M[3])!=0) return false;
1077 1077
1078 if(IR(M[4])!=0) return false; 1078 if(IR(M[4])!=0) return false;
1079 if(IR(M[5])!=F32_VALUE_1) return false; 1079 if(IR(M[5])!=F32_VALUE_1) return false;
1080 if(IR(M[6])!=0) return false; 1080 if(IR(M[6])!=0) return false;
1081 if(IR(M[7])!=0) return false; 1081 if(IR(M[7])!=0) return false;
1082 1082
1083 if(IR(M[8])!=0) return false; 1083 if(IR(M[8])!=0) return false;
1084 if(IR(M[9])!=0) return false; 1084 if(IR(M[9])!=0) return false;
1085 if(IR(M[10])!=F32_VALUE_1) return false; 1085 if(IR(M[10])!=F32_VALUE_1) return false;
1086 if(IR(M[11])!=0) return false; 1086 if(IR(M[11])!=0) return false;
1087 1087
1088 if(IR(M[12])!=0) return false; 1088 if(IR(M[12])!=0) return false;
1089 if(IR(M[13])!=0) return false; 1089 if(IR(M[13])!=0) return false;
1090 if(IR(M[13])!=0) return false; 1090 if(IR(M[13])!=0) return false;
1091 if(IR(M[15])!=F32_VALUE_1) return false; 1091 if(IR(M[15])!=F32_VALUE_1) return false;
1092 1092
1093#if defined ( USE_MATRIX_TEST ) 1093#if defined ( USE_MATRIX_TEST )
1094 definitelyIdentityMatrix=true; 1094 definitelyIdentityMatrix=true;
1095#endif 1095#endif
1096 return true; 1096 return true;
1097 } 1097 }
1098 1098
1099 1099
1100 template <class T> 1100 template <class T>
1101 inline void CMatrix4<T>::rotateVect( vector3df& vect ) const 1101 inline void CMatrix4<T>::rotateVect( vector3df& vect ) const
1102 { 1102 {
1103 vector3df tmp = vect; 1103 vector3df tmp = vect;
1104 vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8]; 1104 vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8];
1105 vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9]; 1105 vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9];
1106 vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10]; 1106 vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10];
1107 } 1107 }
1108 1108
1109 //! An alternate transform vector method, writing into a second vector 1109 //! An alternate transform vector method, writing into a second vector
1110 template <class T> 1110 template <class T>
1111 inline void CMatrix4<T>::rotateVect(core::vector3df& out, const core::vector3df& in) const 1111 inline void CMatrix4<T>::rotateVect(core::vector3df& out, const core::vector3df& in) const
1112 { 1112 {
1113 out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8]; 1113 out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
1114 out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9]; 1114 out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
1115 out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10]; 1115 out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
1116 } 1116 }
1117 1117
1118 //! An alternate transform vector method, writing into an array of 3 floats 1118 //! An alternate transform vector method, writing into an array of 3 floats
1119 template <class T> 1119 template <class T>
1120 inline void CMatrix4<T>::rotateVect(T *out, const core::vector3df& in) const 1120 inline void CMatrix4<T>::rotateVect(T *out, const core::vector3df& in) const
1121 { 1121 {
1122 out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8]; 1122 out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
1123 out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9]; 1123 out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
1124 out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10]; 1124 out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
1125 } 1125 }
1126 1126
1127 template <class T> 1127 template <class T>
1128 inline void CMatrix4<T>::inverseRotateVect( vector3df& vect ) const 1128 inline void CMatrix4<T>::inverseRotateVect( vector3df& vect ) const
1129 { 1129 {
1130 vector3df tmp = vect; 1130 vector3df tmp = vect;
1131 vect.X = tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2]; 1131 vect.X = tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2];
1132 vect.Y = tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6]; 1132 vect.Y = tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6];
1133 vect.Z = tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10]; 1133 vect.Z = tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10];
1134 } 1134 }
1135 1135
1136 template <class T> 1136 template <class T>
1137 inline void CMatrix4<T>::transformVect( vector3df& vect) const 1137 inline void CMatrix4<T>::transformVect( vector3df& vect) const
1138 { 1138 {
1139 f32 vector[3]; 1139 f32 vector[3];
1140 1140
1141 vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12]; 1141 vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12];
1142 vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13]; 1142 vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13];
1143 vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14]; 1143 vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14];
1144 1144
1145 vect.X = vector[0]; 1145 vect.X = vector[0];
1146 vect.Y = vector[1]; 1146 vect.Y = vector[1];
1147 vect.Z = vector[2]; 1147 vect.Z = vector[2];
1148 } 1148 }
1149 1149
1150 template <class T> 1150 template <class T>
1151 inline void CMatrix4<T>::transformVect( vector3df& out, const vector3df& in) const 1151 inline void CMatrix4<T>::transformVect( vector3df& out, const vector3df& in) const
1152 { 1152 {
1153 out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12]; 1153 out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
1154 out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13]; 1154 out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
1155 out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14]; 1155 out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
1156 } 1156 }
1157 1157
1158 1158
1159 template <class T> 1159 template <class T>
1160 inline void CMatrix4<T>::transformVect(T *out, const core::vector3df &in) const 1160 inline void CMatrix4<T>::transformVect(T *out, const core::vector3df &in) const
1161 { 1161 {
1162 out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12]; 1162 out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
1163 out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13]; 1163 out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
1164 out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14]; 1164 out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
1165 out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15]; 1165 out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15];
1166 } 1166 }
1167 1167
1168 template <class T> 1168 template <class T>
1169 inline void CMatrix4<T>::transformVec3(T *out, const T * in) const 1169 inline void CMatrix4<T>::transformVec3(T *out, const T * in) const
1170 { 1170 {
1171 out[0] = in[0]*M[0] + in[1]*M[4] + in[2]*M[8] + M[12]; 1171 out[0] = in[0]*M[0] + in[1]*M[4] + in[2]*M[8] + M[12];
1172 out[1] = in[0]*M[1] + in[1]*M[5] + in[2]*M[9] + M[13]; 1172 out[1] = in[0]*M[1] + in[1]*M[5] + in[2]*M[9] + M[13];
1173 out[2] = in[0]*M[2] + in[1]*M[6] + in[2]*M[10] + M[14]; 1173 out[2] = in[0]*M[2] + in[1]*M[6] + in[2]*M[10] + M[14];
1174 } 1174 }
1175 1175
1176 1176
1177 //! Transforms a plane by this matrix 1177 //! Transforms a plane by this matrix
1178 template <class T> 1178 template <class T>
1179 inline void CMatrix4<T>::transformPlane( core::plane3d<f32> &plane) const 1179 inline void CMatrix4<T>::transformPlane( core::plane3d<f32> &plane) const
1180 { 1180 {
1181 vector3df member; 1181 vector3df member;
1182 // Transform the plane member point, i.e. rotate, translate and scale it. 1182 // Transform the plane member point, i.e. rotate, translate and scale it.
1183 transformVect(member, plane.getMemberPoint()); 1183 transformVect(member, plane.getMemberPoint());
1184 1184
1185 // Transform the normal by the transposed inverse of the matrix 1185 // Transform the normal by the transposed inverse of the matrix
1186 CMatrix4<T> transposedInverse(*this, EM4CONST_INVERSE_TRANSPOSED); 1186 CMatrix4<T> transposedInverse(*this, EM4CONST_INVERSE_TRANSPOSED);
1187 vector3df normal = plane.Normal; 1187 vector3df normal = plane.Normal;
1188 transposedInverse.transformVect(normal); 1188 transposedInverse.transformVect(normal);
1189 1189
1190 plane.setPlane(member, normal); 1190 plane.setPlane(member, normal);
1191 } 1191 }
1192 1192
1193 //! Transforms a plane by this matrix 1193 //! Transforms a plane by this matrix
1194 template <class T> 1194 template <class T>
1195 inline void CMatrix4<T>::transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const 1195 inline void CMatrix4<T>::transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const
1196 { 1196 {
1197 out = in; 1197 out = in;
1198 transformPlane( out ); 1198 transformPlane( out );
1199 } 1199 }
1200 1200
1201 //! Transforms a axis aligned bounding box 1201 //! Transforms a axis aligned bounding box
1202 template <class T> 1202 template <class T>
1203 inline void CMatrix4<T>::transformBox(core::aabbox3d<f32>& box) const 1203 inline void CMatrix4<T>::transformBox(core::aabbox3d<f32>& box) const
1204 { 1204 {
1205#if defined ( USE_MATRIX_TEST ) 1205#if defined ( USE_MATRIX_TEST )
1206 if (isIdentity()) 1206 if (isIdentity())
1207 return; 1207 return;
1208#endif 1208#endif
1209 1209
1210 transformVect(box.MinEdge); 1210 transformVect(box.MinEdge);
1211 transformVect(box.MaxEdge); 1211 transformVect(box.MaxEdge);
1212 box.repair(); 1212 box.repair();
1213 } 1213 }
1214 1214
1215 //! Transforms a axis aligned bounding box more accurately than transformBox() 1215 //! Transforms a axis aligned bounding box more accurately than transformBox()
1216 template <class T> 1216 template <class T>
1217 inline void CMatrix4<T>::transformBoxEx(core::aabbox3d<f32>& box) const 1217 inline void CMatrix4<T>::transformBoxEx(core::aabbox3d<f32>& box) const
1218 { 1218 {
1219#if defined ( USE_MATRIX_TEST ) 1219#if defined ( USE_MATRIX_TEST )
1220 if (isIdentity()) 1220 if (isIdentity())
1221 return; 1221 return;
1222#endif 1222#endif
1223 1223
1224 const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z}; 1224 const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z};
1225 const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z}; 1225 const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z};
1226 1226
1227 f32 Bmin[3]; 1227 f32 Bmin[3];
1228 f32 Bmax[3]; 1228 f32 Bmax[3];
1229 1229
1230 Bmin[0] = Bmax[0] = M[12]; 1230 Bmin[0] = Bmax[0] = M[12];
1231 Bmin[1] = Bmax[1] = M[13]; 1231 Bmin[1] = Bmax[1] = M[13];
1232 Bmin[2] = Bmax[2] = M[14]; 1232 Bmin[2] = Bmax[2] = M[14];
1233 1233
1234 const CMatrix4<T> &m = *this; 1234 const CMatrix4<T> &m = *this;
1235 1235
1236 for (u32 i = 0; i < 3; ++i) 1236 for (u32 i = 0; i < 3; ++i)
1237 { 1237 {
1238 for (u32 j = 0; j < 3; ++j) 1238 for (u32 j = 0; j < 3; ++j)
1239 { 1239 {
1240 const f32 a = m(j,i) * Amin[j]; 1240 const f32 a = m(j,i) * Amin[j];
1241 const f32 b = m(j,i) * Amax[j]; 1241 const f32 b = m(j,i) * Amax[j];
1242 1242
1243 if (a < b) 1243 if (a < b)
1244 { 1244 {
1245 Bmin[i] += a; 1245 Bmin[i] += a;
1246 Bmax[i] += b; 1246 Bmax[i] += b;
1247 } 1247 }
1248 else 1248 else
1249 { 1249 {
1250 Bmin[i] += b; 1250 Bmin[i] += b;
1251 Bmax[i] += a; 1251 Bmax[i] += a;
1252 } 1252 }
1253 } 1253 }
1254 } 1254 }
1255 1255
1256 box.MinEdge.X = Bmin[0]; 1256 box.MinEdge.X = Bmin[0];
1257 box.MinEdge.Y = Bmin[1]; 1257 box.MinEdge.Y = Bmin[1];
1258 box.MinEdge.Z = Bmin[2]; 1258 box.MinEdge.Z = Bmin[2];
1259 1259
1260 box.MaxEdge.X = Bmax[0]; 1260 box.MaxEdge.X = Bmax[0];
1261 box.MaxEdge.Y = Bmax[1]; 1261 box.MaxEdge.Y = Bmax[1];
1262 box.MaxEdge.Z = Bmax[2]; 1262 box.MaxEdge.Z = Bmax[2];
1263 } 1263 }
1264 1264
1265 1265
1266 //! Multiplies this matrix by a 1x4 matrix 1266 //! Multiplies this matrix by a 1x4 matrix
1267 template <class T> 1267 template <class T>
1268 inline void CMatrix4<T>::multiplyWith1x4Matrix(T* matrix) const 1268 inline void CMatrix4<T>::multiplyWith1x4Matrix(T* matrix) const
1269 { 1269 {
1270 /* 1270 /*
1271 0 1 2 3 1271 0 1 2 3
1272 4 5 6 7 1272 4 5 6 7
1273 8 9 10 11 1273 8 9 10 11
1274 12 13 14 15 1274 12 13 14 15
1275 */ 1275 */
1276 1276
1277 T mat[4]; 1277 T mat[4];
1278 mat[0] = matrix[0]; 1278 mat[0] = matrix[0];
1279 mat[1] = matrix[1]; 1279 mat[1] = matrix[1];
1280 mat[2] = matrix[2]; 1280 mat[2] = matrix[2];
1281 mat[3] = matrix[3]; 1281 mat[3] = matrix[3];
1282 1282
1283 matrix[0] = M[0]*mat[0] + M[4]*mat[1] + M[8]*mat[2] + M[12]*mat[3]; 1283 matrix[0] = M[0]*mat[0] + M[4]*mat[1] + M[8]*mat[2] + M[12]*mat[3];
1284 matrix[1] = M[1]*mat[0] + M[5]*mat[1] + M[9]*mat[2] + M[13]*mat[3]; 1284 matrix[1] = M[1]*mat[0] + M[5]*mat[1] + M[9]*mat[2] + M[13]*mat[3];
1285 matrix[2] = M[2]*mat[0] + M[6]*mat[1] + M[10]*mat[2] + M[14]*mat[3]; 1285 matrix[2] = M[2]*mat[0] + M[6]*mat[1] + M[10]*mat[2] + M[14]*mat[3];
1286 matrix[3] = M[3]*mat[0] + M[7]*mat[1] + M[11]*mat[2] + M[15]*mat[3]; 1286 matrix[3] = M[3]*mat[0] + M[7]*mat[1] + M[11]*mat[2] + M[15]*mat[3];
1287 } 1287 }
1288 1288
1289 template <class T> 1289 template <class T>
1290 inline void CMatrix4<T>::inverseTranslateVect( vector3df& vect ) const 1290 inline void CMatrix4<T>::inverseTranslateVect( vector3df& vect ) const
1291 { 1291 {
1292 vect.X = vect.X-M[12]; 1292 vect.X = vect.X-M[12];
1293 vect.Y = vect.Y-M[13]; 1293 vect.Y = vect.Y-M[13];
1294 vect.Z = vect.Z-M[14]; 1294 vect.Z = vect.Z-M[14];
1295 } 1295 }
1296 1296
1297 template <class T> 1297 template <class T>
1298 inline void CMatrix4<T>::translateVect( vector3df& vect ) const 1298 inline void CMatrix4<T>::translateVect( vector3df& vect ) const
1299 { 1299 {
1300 vect.X = vect.X+M[12]; 1300 vect.X = vect.X+M[12];
1301 vect.Y = vect.Y+M[13]; 1301 vect.Y = vect.Y+M[13];
1302 vect.Z = vect.Z+M[14]; 1302 vect.Z = vect.Z+M[14];
1303 } 1303 }
1304 1304
1305 1305
1306 template <class T> 1306 template <class T>
1307 inline bool CMatrix4<T>::getInverse(CMatrix4<T>& out) const 1307 inline bool CMatrix4<T>::getInverse(CMatrix4<T>& out) const
1308 { 1308 {
1309 /// Calculates the inverse of this Matrix 1309 /// Calculates the inverse of this Matrix
1310 /// The inverse is calculated using Cramers rule. 1310 /// The inverse is calculated using Cramers rule.
1311 /// If no inverse exists then 'false' is returned. 1311 /// If no inverse exists then 'false' is returned.
1312 1312
1313#if defined ( USE_MATRIX_TEST ) 1313#if defined ( USE_MATRIX_TEST )
1314 if ( this->isIdentity() ) 1314 if ( this->isIdentity() )
1315 { 1315 {
1316 out=*this; 1316 out=*this;
1317 return true; 1317 return true;
1318 } 1318 }
1319#endif 1319#endif
1320 const CMatrix4<T> &m = *this; 1320 const CMatrix4<T> &m = *this;
1321 1321
1322 f32 d = (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) - 1322 f32 d = (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) -
1323 (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) + 1323 (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
1324 (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)) + 1324 (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)) +
1325 (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) - 1325 (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) -
1326 (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) + 1326 (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
1327 (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)); 1327 (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0));
1328 1328
1329 if( core::iszero ( d, FLT_MIN ) ) 1329 if( core::iszero ( d, FLT_MIN ) )
1330 return false; 1330 return false;
1331 1331
1332 d = core::reciprocal ( d ); 1332 d = core::reciprocal ( d );
1333 1333
1334 out(0, 0) = d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) + 1334 out(0, 0) = d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) +
1335 m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) + 1335 m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) +
1336 m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1))); 1336 m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)));
1337 out(0, 1) = d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) + 1337 out(0, 1) = d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) +
1338 m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) + 1338 m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) +
1339 m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1))); 1339 m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1)));
1340 out(0, 2) = d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) + 1340 out(0, 2) = d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) +
1341 m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) + 1341 m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) +
1342 m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1))); 1342 m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)));
1343 out(0, 3) = d * (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) + 1343 out(0, 3) = d * (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) +
1344 m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) + 1344 m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) +
1345 m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2))); 1345 m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2)));
1346 out(1, 0) = d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) + 1346 out(1, 0) = d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) +
1347 m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) + 1347 m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) +
1348 m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3))); 1348 m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3)));
1349 out(1, 1) = d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) + 1349 out(1, 1) = d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) +
1350 m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) + 1350 m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) +
1351 m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3))); 1351 m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3)));
1352 out(1, 2) = d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) + 1352 out(1, 2) = d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) +
1353 m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) + 1353 m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) +
1354 m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3))); 1354 m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3)));
1355 out(1, 3) = d * (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) + 1355 out(1, 3) = d * (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) +
1356 m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) + 1356 m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
1357 m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2))); 1357 m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2)));
1358 out(2, 0) = d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) + 1358 out(2, 0) = d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) +
1359 m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) + 1359 m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
1360 m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3))); 1360 m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3)));
1361 out(2, 1) = d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) + 1361 out(2, 1) = d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) +
1362 m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) + 1362 m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) +
1363 m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3))); 1363 m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3)));
1364 out(2, 2) = d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) + 1364 out(2, 2) = d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) +
1365 m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) + 1365 m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) +
1366 m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3))); 1366 m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3)));
1367 out(2, 3) = d * (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) + 1367 out(2, 3) = d * (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) +
1368 m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) + 1368 m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) +
1369 m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0))); 1369 m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0)));
1370 out(3, 0) = d * (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) + 1370 out(3, 0) = d * (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) +
1371 m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) + 1371 m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
1372 m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1))); 1372 m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1)));
1373 out(3, 1) = d * (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) + 1373 out(3, 1) = d * (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) +
1374 m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) + 1374 m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) +
1375 m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1))); 1375 m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1)));
1376 out(3, 2) = d * (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) + 1376 out(3, 2) = d * (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) +
1377 m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) + 1377 m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) +
1378 m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1))); 1378 m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1)));
1379 out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) + 1379 out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) +
1380 m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) + 1380 m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) +
1381 m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))); 1381 m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)));
1382 1382
1383#if defined ( USE_MATRIX_TEST ) 1383#if defined ( USE_MATRIX_TEST )
1384 out.definitelyIdentityMatrix = definitelyIdentityMatrix; 1384 out.definitelyIdentityMatrix = definitelyIdentityMatrix;
1385#endif 1385#endif
1386 return true; 1386 return true;
1387 } 1387 }
1388 1388
1389 1389
1390 //! Inverts a primitive matrix which only contains a translation and a rotation 1390 //! Inverts a primitive matrix which only contains a translation and a rotation
1391 //! \param out: where result matrix is written to. 1391 //! \param out: where result matrix is written to.
1392 template <class T> 1392 template <class T>
1393 inline bool CMatrix4<T>::getInversePrimitive ( CMatrix4<T>& out ) const 1393 inline bool CMatrix4<T>::getInversePrimitive ( CMatrix4<T>& out ) const
1394 { 1394 {
1395 out.M[0 ] = M[0]; 1395 out.M[0 ] = M[0];
1396 out.M[1 ] = M[4]; 1396 out.M[1 ] = M[4];
1397 out.M[2 ] = M[8]; 1397 out.M[2 ] = M[8];
1398 out.M[3 ] = 0; 1398 out.M[3 ] = 0;
1399 1399
1400 out.M[4 ] = M[1]; 1400 out.M[4 ] = M[1];
1401 out.M[5 ] = M[5]; 1401 out.M[5 ] = M[5];
1402 out.M[6 ] = M[9]; 1402 out.M[6 ] = M[9];
1403 out.M[7 ] = 0; 1403 out.M[7 ] = 0;
1404 1404
1405 out.M[8 ] = M[2]; 1405 out.M[8 ] = M[2];
1406 out.M[9 ] = M[6]; 1406 out.M[9 ] = M[6];
1407 out.M[10] = M[10]; 1407 out.M[10] = M[10];
1408 out.M[11] = 0; 1408 out.M[11] = 0;
1409 1409
1410 out.M[12] = (T)-(M[12]*M[0] + M[13]*M[1] + M[14]*M[2]); 1410 out.M[12] = (T)-(M[12]*M[0] + M[13]*M[1] + M[14]*M[2]);
1411 out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]); 1411 out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]);
1412 out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]); 1412 out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]);
1413 out.M[15] = 1; 1413 out.M[15] = 1;
1414 1414
1415#if defined ( USE_MATRIX_TEST ) 1415#if defined ( USE_MATRIX_TEST )
1416 out.definitelyIdentityMatrix = definitelyIdentityMatrix; 1416 out.definitelyIdentityMatrix = definitelyIdentityMatrix;
1417#endif 1417#endif
1418 return true; 1418 return true;
1419 } 1419 }
1420 1420
1421 /*! 1421 /*!
1422 */ 1422 */
1423 template <class T> 1423 template <class T>
1424 inline bool CMatrix4<T>::makeInverse() 1424 inline bool CMatrix4<T>::makeInverse()
1425 { 1425 {
1426#if defined ( USE_MATRIX_TEST ) 1426#if defined ( USE_MATRIX_TEST )
1427 if (definitelyIdentityMatrix) 1427 if (definitelyIdentityMatrix)
1428 return true; 1428 return true;
1429#endif 1429#endif
1430 CMatrix4<T> temp ( EM4CONST_NOTHING ); 1430 CMatrix4<T> temp ( EM4CONST_NOTHING );
1431 1431
1432 if (getInverse(temp)) 1432 if (getInverse(temp))
1433 { 1433 {
1434 *this = temp; 1434 *this = temp;
1435 return true; 1435 return true;
1436 } 1436 }
1437 1437
1438 return false; 1438 return false;
1439 } 1439 }
1440 1440
1441 1441
1442 template <class T> 1442 template <class T>
1443 inline CMatrix4<T>& CMatrix4<T>::operator=(const CMatrix4<T> &other) 1443 inline CMatrix4<T>& CMatrix4<T>::operator=(const CMatrix4<T> &other)
1444 { 1444 {
1445 if (this==&other) 1445 if (this==&other)
1446 return *this; 1446 return *this;
1447 memcpy(M, other.M, 16*sizeof(T)); 1447 memcpy(M, other.M, 16*sizeof(T));
1448#if defined ( USE_MATRIX_TEST ) 1448#if defined ( USE_MATRIX_TEST )
1449 definitelyIdentityMatrix=other.definitelyIdentityMatrix; 1449 definitelyIdentityMatrix=other.definitelyIdentityMatrix;
1450#endif 1450#endif
1451 return *this; 1451 return *this;
1452 } 1452 }
1453 1453
1454 1454
1455 template <class T> 1455 template <class T>
1456 inline CMatrix4<T>& CMatrix4<T>::operator=(const T& scalar) 1456 inline CMatrix4<T>& CMatrix4<T>::operator=(const T& scalar)
1457 { 1457 {
1458 for (s32 i = 0; i < 16; ++i) 1458 for (s32 i = 0; i < 16; ++i)
1459 M[i]=scalar; 1459 M[i]=scalar;
1460 1460
1461#if defined ( USE_MATRIX_TEST ) 1461#if defined ( USE_MATRIX_TEST )
1462 definitelyIdentityMatrix=false; 1462 definitelyIdentityMatrix=false;
1463#endif 1463#endif
1464 return *this; 1464 return *this;
1465 } 1465 }
1466 1466
1467 1467
1468 template <class T> 1468 template <class T>
1469 inline bool CMatrix4<T>::operator==(const CMatrix4<T> &other) const 1469 inline bool CMatrix4<T>::operator==(const CMatrix4<T> &other) const
1470 { 1470 {
1471#if defined ( USE_MATRIX_TEST ) 1471#if defined ( USE_MATRIX_TEST )
1472 if (definitelyIdentityMatrix && other.definitelyIdentityMatrix) 1472 if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
1473 return true; 1473 return true;
1474#endif 1474#endif
1475 for (s32 i = 0; i < 16; ++i) 1475 for (s32 i = 0; i < 16; ++i)
1476 if (M[i] != other.M[i]) 1476 if (M[i] != other.M[i])
1477 return false; 1477 return false;
1478 1478
1479 return true; 1479 return true;
1480 } 1480 }
1481 1481
1482 1482
1483 template <class T> 1483 template <class T>
1484 inline bool CMatrix4<T>::operator!=(const CMatrix4<T> &other) const 1484 inline bool CMatrix4<T>::operator!=(const CMatrix4<T> &other) const
1485 { 1485 {
1486 return !(*this == other); 1486 return !(*this == other);
1487 } 1487 }
1488 1488
1489 1489
1490 // Builds a right-handed perspective projection matrix based on a field of view 1490 // Builds a right-handed perspective projection matrix based on a field of view
1491 template <class T> 1491 template <class T>
1492 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovRH( 1492 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovRH(
1493 f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar) 1493 f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
1494 { 1494 {
1495 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5)); 1495 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
1496 _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero 1496 _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
1497 const T w = static_cast<T>(h / aspectRatio); 1497 const T w = static_cast<T>(h / aspectRatio);
1498 1498
1499 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero 1499 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1500 M[0] = w; 1500 M[0] = w;
1501 M[1] = 0; 1501 M[1] = 0;
1502 M[2] = 0; 1502 M[2] = 0;
1503 M[3] = 0; 1503 M[3] = 0;
1504 1504
1505 M[4] = 0; 1505 M[4] = 0;
1506 M[5] = (T)h; 1506 M[5] = (T)h;
1507 M[6] = 0; 1507 M[6] = 0;
1508 M[7] = 0; 1508 M[7] = 0;
1509 1509
1510 M[8] = 0; 1510 M[8] = 0;
1511 M[9] = 0; 1511 M[9] = 0;
1512 M[10] = (T)(zFar/(zNear-zFar)); // DirectX version 1512 M[10] = (T)(zFar/(zNear-zFar)); // DirectX version
1513// M[10] = (T)(zFar+zNear/(zNear-zFar)); // OpenGL version 1513// M[10] = (T)(zFar+zNear/(zNear-zFar)); // OpenGL version
1514 M[11] = -1; 1514 M[11] = -1;
1515 1515
1516 M[12] = 0; 1516 M[12] = 0;
1517 M[13] = 0; 1517 M[13] = 0;
1518 M[14] = (T)(zNear*zFar/(zNear-zFar)); // DirectX version 1518 M[14] = (T)(zNear*zFar/(zNear-zFar)); // DirectX version
1519// M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version 1519// M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version
1520 M[15] = 0; 1520 M[15] = 0;
1521 1521
1522#if defined ( USE_MATRIX_TEST ) 1522#if defined ( USE_MATRIX_TEST )
1523 definitelyIdentityMatrix=false; 1523 definitelyIdentityMatrix=false;
1524#endif 1524#endif
1525 return *this; 1525 return *this;
1526 } 1526 }
1527 1527
1528 1528
1529 // Builds a left-handed perspective projection matrix based on a field of view 1529 // Builds a left-handed perspective projection matrix based on a field of view
1530 template <class T> 1530 template <class T>
1531 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovLH( 1531 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovLH(
1532 f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar) 1532 f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
1533 { 1533 {
1534 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5)); 1534 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
1535 _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero 1535 _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
1536 const T w = static_cast<T>(h / aspectRatio); 1536 const T w = static_cast<T>(h / aspectRatio);
1537 1537
1538 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero 1538 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1539 M[0] = w; 1539 M[0] = w;
1540 M[1] = 0; 1540 M[1] = 0;
1541 M[2] = 0; 1541 M[2] = 0;
1542 M[3] = 0; 1542 M[3] = 0;
1543 1543
1544 M[4] = 0; 1544 M[4] = 0;
1545 M[5] = (T)h; 1545 M[5] = (T)h;
1546 M[6] = 0; 1546 M[6] = 0;
1547 M[7] = 0; 1547 M[7] = 0;
1548 1548
1549 M[8] = 0; 1549 M[8] = 0;
1550 M[9] = 0; 1550 M[9] = 0;
1551 M[10] = (T)(zFar/(zFar-zNear)); 1551 M[10] = (T)(zFar/(zFar-zNear));
1552 M[11] = 1; 1552 M[11] = 1;
1553 1553
1554 M[12] = 0; 1554 M[12] = 0;
1555 M[13] = 0; 1555 M[13] = 0;
1556 M[14] = (T)(-zNear*zFar/(zFar-zNear)); 1556 M[14] = (T)(-zNear*zFar/(zFar-zNear));
1557 M[15] = 0; 1557 M[15] = 0;
1558 1558
1559#if defined ( USE_MATRIX_TEST ) 1559#if defined ( USE_MATRIX_TEST )
1560 definitelyIdentityMatrix=false; 1560 definitelyIdentityMatrix=false;
1561#endif 1561#endif
1562 return *this; 1562 return *this;
1563 } 1563 }
1564 1564
1565 1565
1566 // Builds a left-handed perspective projection matrix based on a field of view, with far plane culling at infinity 1566 // Builds a left-handed perspective projection matrix based on a field of view, with far plane culling at infinity
1567 template <class T> 1567 template <class T>
1568 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovInfinityLH( 1568 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovInfinityLH(
1569 f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon) 1569 f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 epsilon)
1570 { 1570 {
1571 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5)); 1571 const f64 h = reciprocal(tan(fieldOfViewRadians*0.5));
1572 _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero 1572 _IRR_DEBUG_BREAK_IF(aspectRatio==0.f); //divide by zero
1573 const T w = static_cast<T>(h / aspectRatio); 1573 const T w = static_cast<T>(h / aspectRatio);
1574 1574
1575 M[0] = w; 1575 M[0] = w;
1576 M[1] = 0; 1576 M[1] = 0;
1577 M[2] = 0; 1577 M[2] = 0;
1578 M[3] = 0; 1578 M[3] = 0;
1579 1579
1580 M[4] = 0; 1580 M[4] = 0;
1581 M[5] = (T)h; 1581 M[5] = (T)h;
1582 M[6] = 0; 1582 M[6] = 0;
1583 M[7] = 0; 1583 M[7] = 0;
1584 1584
1585 M[8] = 0; 1585 M[8] = 0;
1586 M[9] = 0; 1586 M[9] = 0;
1587 M[10] = (T)(1.f-epsilon); 1587 M[10] = (T)(1.f-epsilon);
1588 M[11] = 1; 1588 M[11] = 1;
1589 1589
1590 M[12] = 0; 1590 M[12] = 0;
1591 M[13] = 0; 1591 M[13] = 0;
1592 M[14] = (T)(zNear*(epsilon-1.f)); 1592 M[14] = (T)(zNear*(epsilon-1.f));
1593 M[15] = 0; 1593 M[15] = 0;
1594 1594
1595#if defined ( USE_MATRIX_TEST ) 1595#if defined ( USE_MATRIX_TEST )
1596 definitelyIdentityMatrix=false; 1596 definitelyIdentityMatrix=false;
1597#endif 1597#endif
1598 return *this; 1598 return *this;
1599 } 1599 }
1600 1600
1601 1601
1602 // Builds a left-handed orthogonal projection matrix. 1602 // Builds a left-handed orthogonal projection matrix.
1603 template <class T> 1603 template <class T>
1604 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoLH( 1604 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoLH(
1605 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) 1605 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
1606 { 1606 {
1607 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero 1607 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1608 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero 1608 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1609 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero 1609 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1610 M[0] = (T)(2/widthOfViewVolume); 1610 M[0] = (T)(2/widthOfViewVolume);
1611 M[1] = 0; 1611 M[1] = 0;
1612 M[2] = 0; 1612 M[2] = 0;
1613 M[3] = 0; 1613 M[3] = 0;
1614 1614
1615 M[4] = 0; 1615 M[4] = 0;
1616 M[5] = (T)(2/heightOfViewVolume); 1616 M[5] = (T)(2/heightOfViewVolume);
1617 M[6] = 0; 1617 M[6] = 0;
1618 M[7] = 0; 1618 M[7] = 0;
1619 1619
1620 M[8] = 0; 1620 M[8] = 0;
1621 M[9] = 0; 1621 M[9] = 0;
1622 M[10] = (T)(1/(zFar-zNear)); 1622 M[10] = (T)(1/(zFar-zNear));
1623 M[11] = 0; 1623 M[11] = 0;
1624 1624
1625 M[12] = 0; 1625 M[12] = 0;
1626 M[13] = 0; 1626 M[13] = 0;
1627 M[14] = (T)(zNear/(zNear-zFar)); 1627 M[14] = (T)(zNear/(zNear-zFar));
1628 M[15] = 1; 1628 M[15] = 1;
1629 1629
1630#if defined ( USE_MATRIX_TEST ) 1630#if defined ( USE_MATRIX_TEST )
1631 definitelyIdentityMatrix=false; 1631 definitelyIdentityMatrix=false;
1632#endif 1632#endif
1633 return *this; 1633 return *this;
1634 } 1634 }
1635 1635
1636 1636
1637 // Builds a right-handed orthogonal projection matrix. 1637 // Builds a right-handed orthogonal projection matrix.
1638 template <class T> 1638 template <class T>
1639 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoRH( 1639 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoRH(
1640 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) 1640 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
1641 { 1641 {
1642 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero 1642 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1643 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero 1643 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1644 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero 1644 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1645 M[0] = (T)(2/widthOfViewVolume); 1645 M[0] = (T)(2/widthOfViewVolume);
1646 M[1] = 0; 1646 M[1] = 0;
1647 M[2] = 0; 1647 M[2] = 0;
1648 M[3] = 0; 1648 M[3] = 0;
1649 1649
1650 M[4] = 0; 1650 M[4] = 0;
1651 M[5] = (T)(2/heightOfViewVolume); 1651 M[5] = (T)(2/heightOfViewVolume);
1652 M[6] = 0; 1652 M[6] = 0;
1653 M[7] = 0; 1653 M[7] = 0;
1654 1654
1655 M[8] = 0; 1655 M[8] = 0;
1656 M[9] = 0; 1656 M[9] = 0;
1657 M[10] = (T)(1/(zNear-zFar)); 1657 M[10] = (T)(1/(zNear-zFar));
1658 M[11] = 0; 1658 M[11] = 0;
1659 1659
1660 M[12] = 0; 1660 M[12] = 0;
1661 M[13] = 0; 1661 M[13] = 0;
1662 M[14] = (T)(zNear/(zNear-zFar)); 1662 M[14] = (T)(zNear/(zNear-zFar));
1663 M[15] = 1; 1663 M[15] = 1;
1664 1664
1665#if defined ( USE_MATRIX_TEST ) 1665#if defined ( USE_MATRIX_TEST )
1666 definitelyIdentityMatrix=false; 1666 definitelyIdentityMatrix=false;
1667#endif 1667#endif
1668 return *this; 1668 return *this;
1669 } 1669 }
1670 1670
1671 1671
1672 // Builds a right-handed perspective projection matrix. 1672 // Builds a right-handed perspective projection matrix.
1673 template <class T> 1673 template <class T>
1674 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveRH( 1674 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveRH(
1675 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) 1675 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
1676 { 1676 {
1677 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero 1677 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1678 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero 1678 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1679 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero 1679 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1680 M[0] = (T)(2*zNear/widthOfViewVolume); 1680 M[0] = (T)(2*zNear/widthOfViewVolume);
1681 M[1] = 0; 1681 M[1] = 0;
1682 M[2] = 0; 1682 M[2] = 0;
1683 M[3] = 0; 1683 M[3] = 0;
1684 1684
1685 M[4] = 0; 1685 M[4] = 0;
1686 M[5] = (T)(2*zNear/heightOfViewVolume); 1686 M[5] = (T)(2*zNear/heightOfViewVolume);
1687 M[6] = 0; 1687 M[6] = 0;
1688 M[7] = 0; 1688 M[7] = 0;
1689 1689
1690 M[8] = 0; 1690 M[8] = 0;
1691 M[9] = 0; 1691 M[9] = 0;
1692 M[10] = (T)(zFar/(zNear-zFar)); 1692 M[10] = (T)(zFar/(zNear-zFar));
1693 M[11] = -1; 1693 M[11] = -1;
1694 1694
1695 M[12] = 0; 1695 M[12] = 0;
1696 M[13] = 0; 1696 M[13] = 0;
1697 M[14] = (T)(zNear*zFar/(zNear-zFar)); 1697 M[14] = (T)(zNear*zFar/(zNear-zFar));
1698 M[15] = 0; 1698 M[15] = 0;
1699 1699
1700#if defined ( USE_MATRIX_TEST ) 1700#if defined ( USE_MATRIX_TEST )
1701 definitelyIdentityMatrix=false; 1701 definitelyIdentityMatrix=false;
1702#endif 1702#endif
1703 return *this; 1703 return *this;
1704 } 1704 }
1705 1705
1706 1706
1707 // Builds a left-handed perspective projection matrix. 1707 // Builds a left-handed perspective projection matrix.
1708 template <class T> 1708 template <class T>
1709 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveLH( 1709 inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveLH(
1710 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar) 1710 f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
1711 { 1711 {
1712 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero 1712 _IRR_DEBUG_BREAK_IF(widthOfViewVolume==0.f); //divide by zero
1713 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero 1713 _IRR_DEBUG_BREAK_IF(heightOfViewVolume==0.f); //divide by zero
1714 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero 1714 _IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero
1715 M[0] = (T)(2*zNear/widthOfViewVolume); 1715 M[0] = (T)(2*zNear/widthOfViewVolume);
1716 M[1] = 0; 1716 M[1] = 0;
1717 M[2] = 0; 1717 M[2] = 0;
1718 M[3] = 0; 1718 M[3] = 0;
1719 1719
1720 M[4] = 0; 1720 M[4] = 0;
1721 M[5] = (T)(2*zNear/heightOfViewVolume); 1721 M[5] = (T)(2*zNear/heightOfViewVolume);
1722 M[6] = 0; 1722 M[6] = 0;
1723 M[7] = 0; 1723 M[7] = 0;
1724 1724
1725 M[8] = 0; 1725 M[8] = 0;
1726 M[9] = 0; 1726 M[9] = 0;
1727 M[10] = (T)(zFar/(zFar-zNear)); 1727 M[10] = (T)(zFar/(zFar-zNear));
1728 M[11] = 1; 1728 M[11] = 1;
1729 1729
1730 M[12] = 0; 1730 M[12] = 0;
1731 M[13] = 0; 1731 M[13] = 0;
1732 M[14] = (T)(zNear*zFar/(zNear-zFar)); 1732 M[14] = (T)(zNear*zFar/(zNear-zFar));
1733 M[15] = 0; 1733 M[15] = 0;
1734#if defined ( USE_MATRIX_TEST ) 1734#if defined ( USE_MATRIX_TEST )
1735 definitelyIdentityMatrix=false; 1735 definitelyIdentityMatrix=false;
1736#endif 1736#endif
1737 return *this; 1737 return *this;
1738 } 1738 }
1739 1739
1740 1740
1741 // Builds a matrix that flattens geometry into a plane. 1741 // Builds a matrix that flattens geometry into a plane.
1742 template <class T> 1742 template <class T>
1743 inline CMatrix4<T>& CMatrix4<T>::buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point) 1743 inline CMatrix4<T>& CMatrix4<T>::buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point)
1744 { 1744 {
1745 plane.Normal.normalize(); 1745 plane.Normal.normalize();
1746 const f32 d = plane.Normal.dotProduct(light); 1746 const f32 d = plane.Normal.dotProduct(light);
1747 1747
1748 M[ 0] = (T)(-plane.Normal.X * light.X + d); 1748 M[ 0] = (T)(-plane.Normal.X * light.X + d);
1749 M[ 1] = (T)(-plane.Normal.X * light.Y); 1749 M[ 1] = (T)(-plane.Normal.X * light.Y);
1750 M[ 2] = (T)(-plane.Normal.X * light.Z); 1750 M[ 2] = (T)(-plane.Normal.X * light.Z);
1751 M[ 3] = (T)(-plane.Normal.X * point); 1751 M[ 3] = (T)(-plane.Normal.X * point);
1752 1752
1753 M[ 4] = (T)(-plane.Normal.Y * light.X); 1753 M[ 4] = (T)(-plane.Normal.Y * light.X);
1754 M[ 5] = (T)(-plane.Normal.Y * light.Y + d); 1754 M[ 5] = (T)(-plane.Normal.Y * light.Y + d);
1755 M[ 6] = (T)(-plane.Normal.Y * light.Z); 1755 M[ 6] = (T)(-plane.Normal.Y * light.Z);
1756 M[ 7] = (T)(-plane.Normal.Y * point); 1756 M[ 7] = (T)(-plane.Normal.Y * point);
1757 1757
1758 M[ 8] = (T)(-plane.Normal.Z * light.X); 1758 M[ 8] = (T)(-plane.Normal.Z * light.X);
1759 M[ 9] = (T)(-plane.Normal.Z * light.Y); 1759 M[ 9] = (T)(-plane.Normal.Z * light.Y);
1760 M[10] = (T)(-plane.Normal.Z * light.Z + d); 1760 M[10] = (T)(-plane.Normal.Z * light.Z + d);
1761 M[11] = (T)(-plane.Normal.Z * point); 1761 M[11] = (T)(-plane.Normal.Z * point);
1762 1762
1763 M[12] = (T)(-plane.D * light.X); 1763 M[12] = (T)(-plane.D * light.X);
1764 M[13] = (T)(-plane.D * light.Y); 1764 M[13] = (T)(-plane.D * light.Y);
1765 M[14] = (T)(-plane.D * light.Z); 1765 M[14] = (T)(-plane.D * light.Z);
1766 M[15] = (T)(-plane.D * point + d); 1766 M[15] = (T)(-plane.D * point + d);
1767#if defined ( USE_MATRIX_TEST ) 1767#if defined ( USE_MATRIX_TEST )
1768 definitelyIdentityMatrix=false; 1768 definitelyIdentityMatrix=false;
1769#endif 1769#endif
1770 return *this; 1770 return *this;
1771 } 1771 }
1772 1772
1773 // Builds a left-handed look-at matrix. 1773 // Builds a left-handed look-at matrix.
1774 template <class T> 1774 template <class T>
1775 inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixLH( 1775 inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixLH(
1776 const vector3df& position, 1776 const vector3df& position,
1777 const vector3df& target, 1777 const vector3df& target,
1778 const vector3df& upVector) 1778 const vector3df& upVector)
1779 { 1779 {
1780 vector3df zaxis = target - position; 1780 vector3df zaxis = target - position;
1781 zaxis.normalize(); 1781 zaxis.normalize();
1782 1782
1783 vector3df xaxis = upVector.crossProduct(zaxis); 1783 vector3df xaxis = upVector.crossProduct(zaxis);
1784 xaxis.normalize(); 1784 xaxis.normalize();
1785 1785
1786 vector3df yaxis = zaxis.crossProduct(xaxis); 1786 vector3df yaxis = zaxis.crossProduct(xaxis);
1787 1787
1788 M[0] = (T)xaxis.X; 1788 M[0] = (T)xaxis.X;
1789 M[1] = (T)yaxis.X; 1789 M[1] = (T)yaxis.X;
1790 M[2] = (T)zaxis.X; 1790 M[2] = (T)zaxis.X;
1791 M[3] = 0; 1791 M[3] = 0;
1792 1792
1793 M[4] = (T)xaxis.Y; 1793 M[4] = (T)xaxis.Y;
1794 M[5] = (T)yaxis.Y; 1794 M[5] = (T)yaxis.Y;
1795 M[6] = (T)zaxis.Y; 1795 M[6] = (T)zaxis.Y;
1796 M[7] = 0; 1796 M[7] = 0;
1797 1797
1798 M[8] = (T)xaxis.Z; 1798 M[8] = (T)xaxis.Z;
1799 M[9] = (T)yaxis.Z; 1799 M[9] = (T)yaxis.Z;
1800 M[10] = (T)zaxis.Z; 1800 M[10] = (T)zaxis.Z;
1801 M[11] = 0; 1801 M[11] = 0;
1802 1802
1803 M[12] = (T)-xaxis.dotProduct(position); 1803 M[12] = (T)-xaxis.dotProduct(position);
1804 M[13] = (T)-yaxis.dotProduct(position); 1804 M[13] = (T)-yaxis.dotProduct(position);
1805 M[14] = (T)-zaxis.dotProduct(position); 1805 M[14] = (T)-zaxis.dotProduct(position);
1806 M[15] = 1; 1806 M[15] = 1;
1807#if defined ( USE_MATRIX_TEST ) 1807#if defined ( USE_MATRIX_TEST )
1808 definitelyIdentityMatrix=false; 1808 definitelyIdentityMatrix=false;
1809#endif 1809#endif
1810 return *this; 1810 return *this;
1811 } 1811 }
1812 1812
1813 1813
1814 // Builds a right-handed look-at matrix. 1814 // Builds a right-handed look-at matrix.
1815 template <class T> 1815 template <class T>
1816 inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixRH( 1816 inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixRH(
1817 const vector3df& position, 1817 const vector3df& position,
1818 const vector3df& target, 1818 const vector3df& target,
1819 const vector3df& upVector) 1819 const vector3df& upVector)
1820 { 1820 {
1821 vector3df zaxis = position - target; 1821 vector3df zaxis = position - target;
1822 zaxis.normalize(); 1822 zaxis.normalize();
1823 1823
1824 vector3df xaxis = upVector.crossProduct(zaxis); 1824 vector3df xaxis = upVector.crossProduct(zaxis);
1825 xaxis.normalize(); 1825 xaxis.normalize();
1826 1826
1827 vector3df yaxis = zaxis.crossProduct(xaxis); 1827 vector3df yaxis = zaxis.crossProduct(xaxis);
1828 1828
1829 M[0] = (T)xaxis.X; 1829 M[0] = (T)xaxis.X;
1830 M[1] = (T)yaxis.X; 1830 M[1] = (T)yaxis.X;
1831 M[2] = (T)zaxis.X; 1831 M[2] = (T)zaxis.X;
1832 M[3] = 0; 1832 M[3] = 0;
1833 1833
1834 M[4] = (T)xaxis.Y; 1834 M[4] = (T)xaxis.Y;
1835 M[5] = (T)yaxis.Y; 1835 M[5] = (T)yaxis.Y;
1836 M[6] = (T)zaxis.Y; 1836 M[6] = (T)zaxis.Y;
1837 M[7] = 0; 1837 M[7] = 0;
1838 1838
1839 M[8] = (T)xaxis.Z; 1839 M[8] = (T)xaxis.Z;
1840 M[9] = (T)yaxis.Z; 1840 M[9] = (T)yaxis.Z;
1841 M[10] = (T)zaxis.Z; 1841 M[10] = (T)zaxis.Z;
1842 M[11] = 0; 1842 M[11] = 0;
1843 1843
1844 M[12] = (T)-xaxis.dotProduct(position); 1844 M[12] = (T)-xaxis.dotProduct(position);
1845 M[13] = (T)-yaxis.dotProduct(position); 1845 M[13] = (T)-yaxis.dotProduct(position);
1846 M[14] = (T)-zaxis.dotProduct(position); 1846 M[14] = (T)-zaxis.dotProduct(position);
1847 M[15] = 1; 1847 M[15] = 1;
1848#if defined ( USE_MATRIX_TEST ) 1848#if defined ( USE_MATRIX_TEST )
1849 definitelyIdentityMatrix=false; 1849 definitelyIdentityMatrix=false;
1850#endif 1850#endif
1851 return *this; 1851 return *this;
1852 } 1852 }
1853 1853
1854 1854
1855 // creates a new matrix as interpolated matrix from this and the passed one. 1855 // creates a new matrix as interpolated matrix from this and the passed one.
1856 template <class T> 1856 template <class T>
1857 inline CMatrix4<T> CMatrix4<T>::interpolate(const core::CMatrix4<T>& b, f32 time) const 1857 inline CMatrix4<T> CMatrix4<T>::interpolate(const core::CMatrix4<T>& b, f32 time) const
1858 { 1858 {
1859 CMatrix4<T> mat ( EM4CONST_NOTHING ); 1859 CMatrix4<T> mat ( EM4CONST_NOTHING );
1860 1860
1861 for (u32 i=0; i < 16; i += 4) 1861 for (u32 i=0; i < 16; i += 4)
1862 { 1862 {
1863 mat.M[i+0] = (T)(M[i+0] + ( b.M[i+0] - M[i+0] ) * time); 1863 mat.M[i+0] = (T)(M[i+0] + ( b.M[i+0] - M[i+0] ) * time);
1864 mat.M[i+1] = (T)(M[i+1] + ( b.M[i+1] - M[i+1] ) * time); 1864 mat.M[i+1] = (T)(M[i+1] + ( b.M[i+1] - M[i+1] ) * time);
1865 mat.M[i+2] = (T)(M[i+2] + ( b.M[i+2] - M[i+2] ) * time); 1865 mat.M[i+2] = (T)(M[i+2] + ( b.M[i+2] - M[i+2] ) * time);
1866 mat.M[i+3] = (T)(M[i+3] + ( b.M[i+3] - M[i+3] ) * time); 1866 mat.M[i+3] = (T)(M[i+3] + ( b.M[i+3] - M[i+3] ) * time);
1867 } 1867 }
1868 return mat; 1868 return mat;
1869 } 1869 }
1870 1870
1871 1871
1872 // returns transposed matrix 1872 // returns transposed matrix
1873 template <class T> 1873 template <class T>
1874 inline CMatrix4<T> CMatrix4<T>::getTransposed() const 1874 inline CMatrix4<T> CMatrix4<T>::getTransposed() const
1875 { 1875 {
1876 CMatrix4<T> t ( EM4CONST_NOTHING ); 1876 CMatrix4<T> t ( EM4CONST_NOTHING );
1877 getTransposed ( t ); 1877 getTransposed ( t );
1878 return t; 1878 return t;
1879 } 1879 }
1880 1880
1881 1881
1882 // returns transposed matrix 1882 // returns transposed matrix
1883 template <class T> 1883 template <class T>
1884 inline void CMatrix4<T>::getTransposed( CMatrix4<T>& o ) const 1884 inline void CMatrix4<T>::getTransposed( CMatrix4<T>& o ) const
1885 { 1885 {
1886 o[ 0] = M[ 0]; 1886 o[ 0] = M[ 0];
1887 o[ 1] = M[ 4]; 1887 o[ 1] = M[ 4];
1888 o[ 2] = M[ 8]; 1888 o[ 2] = M[ 8];
1889 o[ 3] = M[12]; 1889 o[ 3] = M[12];
1890 1890
1891 o[ 4] = M[ 1]; 1891 o[ 4] = M[ 1];
1892 o[ 5] = M[ 5]; 1892 o[ 5] = M[ 5];
1893 o[ 6] = M[ 9]; 1893 o[ 6] = M[ 9];
1894 o[ 7] = M[13]; 1894 o[ 7] = M[13];
1895 1895
1896 o[ 8] = M[ 2]; 1896 o[ 8] = M[ 2];
1897 o[ 9] = M[ 6]; 1897 o[ 9] = M[ 6];
1898 o[10] = M[10]; 1898 o[10] = M[10];
1899 o[11] = M[14]; 1899 o[11] = M[14];
1900 1900
1901 o[12] = M[ 3]; 1901 o[12] = M[ 3];
1902 o[13] = M[ 7]; 1902 o[13] = M[ 7];
1903 o[14] = M[11]; 1903 o[14] = M[11];
1904 o[15] = M[15]; 1904 o[15] = M[15];
1905#if defined ( USE_MATRIX_TEST ) 1905#if defined ( USE_MATRIX_TEST )
1906 o.definitelyIdentityMatrix=definitelyIdentityMatrix; 1906 o.definitelyIdentityMatrix=definitelyIdentityMatrix;
1907#endif 1907#endif
1908 } 1908 }
1909 1909
1910 1910
1911 // used to scale <-1,-1><1,1> to viewport 1911 // used to scale <-1,-1><1,1> to viewport
1912 template <class T> 1912 template <class T>
1913 inline CMatrix4<T>& CMatrix4<T>::buildNDCToDCMatrix( const core::rect<s32>& viewport, f32 zScale) 1913 inline CMatrix4<T>& CMatrix4<T>::buildNDCToDCMatrix( const core::rect<s32>& viewport, f32 zScale)
1914 { 1914 {
1915 const f32 scaleX = (viewport.getWidth() - 0.75f ) * 0.5f; 1915 const f32 scaleX = (viewport.getWidth() - 0.75f ) * 0.5f;
1916 const f32 scaleY = -(viewport.getHeight() - 0.75f ) * 0.5f; 1916 const f32 scaleY = -(viewport.getHeight() - 0.75f ) * 0.5f;
1917 1917
1918 const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f ); 1918 const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) * 0.5f );
1919 const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f ); 1919 const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) * 0.5f );
1920 1920
1921 makeIdentity(); 1921 makeIdentity();
1922 M[12] = (T)dx; 1922 M[12] = (T)dx;
1923 M[13] = (T)dy; 1923 M[13] = (T)dy;
1924 return setScale(core::vector3d<T>((T)scaleX, (T)scaleY, (T)zScale)); 1924 return setScale(core::vector3d<T>((T)scaleX, (T)scaleY, (T)zScale));
1925 } 1925 }
1926 1926
1927 //! Builds a matrix that rotates from one vector to another 1927 //! Builds a matrix that rotates from one vector to another
1928 /** \param from: vector to rotate from 1928 /** \param from: vector to rotate from
1929 \param to: vector to rotate to 1929 \param to: vector to rotate to
1930 1930
1931 http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm 1931 http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm
1932 */ 1932 */
1933 template <class T> 1933 template <class T>
1934 inline CMatrix4<T>& CMatrix4<T>::buildRotateFromTo(const core::vector3df& from, const core::vector3df& to) 1934 inline CMatrix4<T>& CMatrix4<T>::buildRotateFromTo(const core::vector3df& from, const core::vector3df& to)
1935 { 1935 {
1936 // unit vectors 1936 // unit vectors
1937 core::vector3df f(from); 1937 core::vector3df f(from);
1938 core::vector3df t(to); 1938 core::vector3df t(to);
1939 f.normalize(); 1939 f.normalize();
1940 t.normalize(); 1940 t.normalize();
1941 1941
1942 // axis multiplication by sin 1942 // axis multiplication by sin
1943 core::vector3df vs(t.crossProduct(f)); 1943 core::vector3df vs(t.crossProduct(f));
1944 1944
1945 // axis of rotation 1945 // axis of rotation
1946 core::vector3df v(vs); 1946 core::vector3df v(vs);
1947 v.normalize(); 1947 v.normalize();
1948 1948
1949 // cosinus angle 1949 // cosinus angle
1950 T ca = f.dotProduct(t); 1950 T ca = f.dotProduct(t);
1951 1951
1952 core::vector3df vt(v * (1 - ca)); 1952 core::vector3df vt(v * (1 - ca));
1953 1953
1954 M[0] = vt.X * v.X + ca; 1954 M[0] = vt.X * v.X + ca;
1955 M[5] = vt.Y * v.Y + ca; 1955 M[5] = vt.Y * v.Y + ca;
1956 M[10] = vt.Z * v.Z + ca; 1956 M[10] = vt.Z * v.Z + ca;
1957 1957
1958 vt.X *= v.Y; 1958 vt.X *= v.Y;
1959 vt.Z *= v.X; 1959 vt.Z *= v.X;
1960 vt.Y *= v.Z; 1960 vt.Y *= v.Z;
1961 1961
1962 M[1] = vt.X - vs.Z; 1962 M[1] = vt.X - vs.Z;
1963 M[2] = vt.Z + vs.Y; 1963 M[2] = vt.Z + vs.Y;
1964 M[3] = 0; 1964 M[3] = 0;
1965 1965
1966 M[4] = vt.X + vs.Z; 1966 M[4] = vt.X + vs.Z;
1967 M[6] = vt.Y - vs.X; 1967 M[6] = vt.Y - vs.X;
1968 M[7] = 0; 1968 M[7] = 0;
1969 1969
1970 M[8] = vt.Z - vs.Y; 1970 M[8] = vt.Z - vs.Y;
1971 M[9] = vt.Y + vs.X; 1971 M[9] = vt.Y + vs.X;
1972 M[11] = 0; 1972 M[11] = 0;
1973 1973
1974 M[12] = 0; 1974 M[12] = 0;
1975 M[13] = 0; 1975 M[13] = 0;
1976 M[14] = 0; 1976 M[14] = 0;
1977 M[15] = 1; 1977 M[15] = 1;
1978 1978
1979 return *this; 1979 return *this;
1980 } 1980 }
1981 1981
1982 //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis 1982 //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis
1983 /** \param camPos: viewer position in world coord 1983 /** \param camPos: viewer position in world coord
1984 \param center: object position in world-coord, rotation pivot 1984 \param center: object position in world-coord, rotation pivot
1985 \param translation: object final translation from center 1985 \param translation: object final translation from center
1986 \param axis: axis to rotate about 1986 \param axis: axis to rotate about
1987 \param from: source vector to rotate from 1987 \param from: source vector to rotate from
1988 */ 1988 */
1989 template <class T> 1989 template <class T>
1990 inline void CMatrix4<T>::buildAxisAlignedBillboard( 1990 inline void CMatrix4<T>::buildAxisAlignedBillboard(
1991 const core::vector3df& camPos, 1991 const core::vector3df& camPos,
1992 const core::vector3df& center, 1992 const core::vector3df& center,
1993 const core::vector3df& translation, 1993 const core::vector3df& translation,
1994 const core::vector3df& axis, 1994 const core::vector3df& axis,
1995 const core::vector3df& from) 1995 const core::vector3df& from)
1996 { 1996 {
1997 // axis of rotation 1997 // axis of rotation
1998 core::vector3df up = axis; 1998 core::vector3df up = axis;
1999 up.normalize(); 1999 up.normalize();
2000 const core::vector3df forward = (camPos - center).normalize(); 2000 const core::vector3df forward = (camPos - center).normalize();
2001 const core::vector3df right = up.crossProduct(forward).normalize(); 2001 const core::vector3df right = up.crossProduct(forward).normalize();
2002 2002
2003 // correct look vector 2003 // correct look vector
2004 const core::vector3df look = right.crossProduct(up); 2004 const core::vector3df look = right.crossProduct(up);
2005 2005
2006 // rotate from to 2006 // rotate from to
2007 // axis multiplication by sin 2007 // axis multiplication by sin
2008 const core::vector3df vs = look.crossProduct(from); 2008 const core::vector3df vs = look.crossProduct(from);
2009 2009
2010 // cosinus angle 2010 // cosinus angle
2011 const f32 ca = from.dotProduct(look); 2011 const f32 ca = from.dotProduct(look);
2012 2012
2013 core::vector3df vt(up * (1.f - ca)); 2013 core::vector3df vt(up * (1.f - ca));
2014 2014
2015 M[0] = static_cast<T>(vt.X * up.X + ca); 2015 M[0] = static_cast<T>(vt.X * up.X + ca);
2016 M[5] = static_cast<T>(vt.Y * up.Y + ca); 2016 M[5] = static_cast<T>(vt.Y * up.Y + ca);
2017 M[10] = static_cast<T>(vt.Z * up.Z + ca); 2017 M[10] = static_cast<T>(vt.Z * up.Z + ca);
2018 2018
2019 vt.X *= up.Y; 2019 vt.X *= up.Y;
2020 vt.Z *= up.X; 2020 vt.Z *= up.X;
2021 vt.Y *= up.Z; 2021 vt.Y *= up.Z;
2022 2022
2023 M[1] = static_cast<T>(vt.X - vs.Z); 2023 M[1] = static_cast<T>(vt.X - vs.Z);
2024 M[2] = static_cast<T>(vt.Z + vs.Y); 2024 M[2] = static_cast<T>(vt.Z + vs.Y);
2025 M[3] = 0; 2025 M[3] = 0;
2026 2026
2027 M[4] = static_cast<T>(vt.X + vs.Z); 2027 M[4] = static_cast<T>(vt.X + vs.Z);
2028 M[6] = static_cast<T>(vt.Y - vs.X); 2028 M[6] = static_cast<T>(vt.Y - vs.X);
2029 M[7] = 0; 2029 M[7] = 0;
2030 2030
2031 M[8] = static_cast<T>(vt.Z - vs.Y); 2031 M[8] = static_cast<T>(vt.Z - vs.Y);
2032 M[9] = static_cast<T>(vt.Y + vs.X); 2032 M[9] = static_cast<T>(vt.Y + vs.X);
2033 M[11] = 0; 2033 M[11] = 0;
2034 2034
2035 setRotationCenter(center, translation); 2035 setRotationCenter(center, translation);
2036 } 2036 }
2037 2037
2038 2038
2039 //! Builds a combined matrix which translate to a center before rotation and translate afterwards 2039 //! Builds a combined matrix which translate to a center before rotation and translate afterwards
2040 template <class T> 2040 template <class T>
2041 inline void CMatrix4<T>::setRotationCenter(const core::vector3df& center, const core::vector3df& translation) 2041 inline void CMatrix4<T>::setRotationCenter(const core::vector3df& center, const core::vector3df& translation)
2042 { 2042 {
2043 M[12] = -M[0]*center.X - M[4]*center.Y - M[8]*center.Z + (center.X - translation.X ); 2043 M[12] = -M[0]*center.X - M[4]*center.Y - M[8]*center.Z + (center.X - translation.X );
2044 M[13] = -M[1]*center.X - M[5]*center.Y - M[9]*center.Z + (center.Y - translation.Y ); 2044 M[13] = -M[1]*center.X - M[5]*center.Y - M[9]*center.Z + (center.Y - translation.Y );
2045 M[14] = -M[2]*center.X - M[6]*center.Y - M[10]*center.Z + (center.Z - translation.Z ); 2045 M[14] = -M[2]*center.X - M[6]*center.Y - M[10]*center.Z + (center.Z - translation.Z );
2046 M[15] = (T) 1.0; 2046 M[15] = (T) 1.0;
2047#if defined ( USE_MATRIX_TEST ) 2047#if defined ( USE_MATRIX_TEST )
2048 definitelyIdentityMatrix=false; 2048 definitelyIdentityMatrix=false;
2049#endif 2049#endif
2050 } 2050 }
2051 2051
2052 /*! 2052 /*!
2053 Generate texture coordinates as linear functions so that: 2053 Generate texture coordinates as linear functions so that:
2054 u = Ux*x + Uy*y + Uz*z + Uw 2054 u = Ux*x + Uy*y + Uz*z + Uw
2055 v = Vx*x + Vy*y + Vz*z + Vw 2055 v = Vx*x + Vy*y + Vz*z + Vw
2056 The matrix M for this case is: 2056 The matrix M for this case is:
2057 Ux Vx 0 0 2057 Ux Vx 0 0
2058 Uy Vy 0 0 2058 Uy Vy 0 0
2059 Uz Vz 0 0 2059 Uz Vz 0 0
2060 Uw Vw 0 0 2060 Uw Vw 0 0
2061 */ 2061 */
2062 2062
2063 2063
2064 template <class T> 2064 template <class T>
2065 inline CMatrix4<T>& CMatrix4<T>::buildTextureTransform( f32 rotateRad, 2065 inline CMatrix4<T>& CMatrix4<T>::buildTextureTransform( f32 rotateRad,
2066 const core::vector2df &rotatecenter, 2066 const core::vector2df &rotatecenter,
2067 const core::vector2df &translate, 2067 const core::vector2df &translate,
2068 const core::vector2df &scale) 2068 const core::vector2df &scale)
2069 { 2069 {
2070 const f32 c = cosf(rotateRad); 2070 const f32 c = cosf(rotateRad);
2071 const f32 s = sinf(rotateRad); 2071 const f32 s = sinf(rotateRad);
2072 2072
2073 M[0] = (T)(c * scale.X); 2073 M[0] = (T)(c * scale.X);
2074 M[1] = (T)(s * scale.Y); 2074 M[1] = (T)(s * scale.Y);
2075 M[2] = 0; 2075 M[2] = 0;
2076 M[3] = 0; 2076 M[3] = 0;
2077 2077
2078 M[4] = (T)(-s * scale.X); 2078 M[4] = (T)(-s * scale.X);
2079 M[5] = (T)(c * scale.Y); 2079 M[5] = (T)(c * scale.Y);
2080 M[6] = 0; 2080 M[6] = 0;
2081 M[7] = 0; 2081 M[7] = 0;
2082 2082
2083 M[8] = (T)(c * scale.X * rotatecenter.X + -s * rotatecenter.Y + translate.X); 2083 M[8] = (T)(c * scale.X * rotatecenter.X + -s * rotatecenter.Y + translate.X);
2084 M[9] = (T)(s * scale.Y * rotatecenter.X + c * rotatecenter.Y + translate.Y); 2084 M[9] = (T)(s * scale.Y * rotatecenter.X + c * rotatecenter.Y + translate.Y);
2085 M[10] = 1; 2085 M[10] = 1;
2086 M[11] = 0; 2086 M[11] = 0;
2087 2087
2088 M[12] = 0; 2088 M[12] = 0;
2089 M[13] = 0; 2089 M[13] = 0;
2090 M[14] = 0; 2090 M[14] = 0;
2091 M[15] = 1; 2091 M[15] = 1;
2092#if defined ( USE_MATRIX_TEST ) 2092#if defined ( USE_MATRIX_TEST )
2093 definitelyIdentityMatrix=false; 2093 definitelyIdentityMatrix=false;
2094#endif 2094#endif
2095 return *this; 2095 return *this;
2096 } 2096 }
2097 2097
2098 2098
2099 // rotate about z axis, center ( 0.5, 0.5 ) 2099 // rotate about z axis, center ( 0.5, 0.5 )
2100 template <class T> 2100 template <class T>
2101 inline CMatrix4<T>& CMatrix4<T>::setTextureRotationCenter( f32 rotateRad ) 2101 inline CMatrix4<T>& CMatrix4<T>::setTextureRotationCenter( f32 rotateRad )
2102 { 2102 {
2103 const f32 c = cosf(rotateRad); 2103 const f32 c = cosf(rotateRad);
2104 const f32 s = sinf(rotateRad); 2104 const f32 s = sinf(rotateRad);
2105 M[0] = (T)c; 2105 M[0] = (T)c;
2106 M[1] = (T)s; 2106 M[1] = (T)s;
2107 2107
2108 M[4] = (T)-s; 2108 M[4] = (T)-s;
2109 M[5] = (T)c; 2109 M[5] = (T)c;
2110 2110
2111 M[8] = (T)(0.5f * ( s - c) + 0.5f); 2111 M[8] = (T)(0.5f * ( s - c) + 0.5f);
2112 M[9] = (T)(-0.5f * ( s + c) + 0.5f); 2112 M[9] = (T)(-0.5f * ( s + c) + 0.5f);
2113 2113
2114#if defined ( USE_MATRIX_TEST ) 2114#if defined ( USE_MATRIX_TEST )
2115 definitelyIdentityMatrix = definitelyIdentityMatrix && (rotateRad==0.0f); 2115 definitelyIdentityMatrix = definitelyIdentityMatrix && (rotateRad==0.0f);
2116#endif 2116#endif
2117 return *this; 2117 return *this;
2118 } 2118 }
2119 2119
2120 2120
2121 template <class T> 2121 template <class T>
2122 inline CMatrix4<T>& CMatrix4<T>::setTextureTranslate ( f32 x, f32 y ) 2122 inline CMatrix4<T>& CMatrix4<T>::setTextureTranslate ( f32 x, f32 y )
2123 { 2123 {
2124 M[8] = (T)x; 2124 M[8] = (T)x;
2125 M[9] = (T)y; 2125 M[9] = (T)y;
2126 2126
2127#if defined ( USE_MATRIX_TEST ) 2127#if defined ( USE_MATRIX_TEST )
2128 definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f); 2128 definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f);
2129#endif 2129#endif
2130 return *this; 2130 return *this;
2131 } 2131 }
2132 2132
2133 2133
2134 template <class T> 2134 template <class T>
2135 inline CMatrix4<T>& CMatrix4<T>::setTextureTranslateTransposed ( f32 x, f32 y ) 2135 inline CMatrix4<T>& CMatrix4<T>::setTextureTranslateTransposed ( f32 x, f32 y )
2136 { 2136 {
2137 M[2] = (T)x; 2137 M[2] = (T)x;
2138 M[6] = (T)y; 2138 M[6] = (T)y;
2139 2139
2140#if defined ( USE_MATRIX_TEST ) 2140#if defined ( USE_MATRIX_TEST )
2141 definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ; 2141 definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ;
2142#endif 2142#endif
2143 return *this; 2143 return *this;
2144 } 2144 }
2145 2145
2146 template <class T> 2146 template <class T>
2147 inline CMatrix4<T>& CMatrix4<T>::setTextureScale ( f32 sx, f32 sy ) 2147 inline CMatrix4<T>& CMatrix4<T>::setTextureScale ( f32 sx, f32 sy )
2148 { 2148 {
2149 M[0] = (T)sx; 2149 M[0] = (T)sx;
2150 M[5] = (T)sy; 2150 M[5] = (T)sy;
2151#if defined ( USE_MATRIX_TEST ) 2151#if defined ( USE_MATRIX_TEST )
2152 definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f); 2152 definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
2153#endif 2153#endif
2154 return *this; 2154 return *this;
2155 } 2155 }
2156 2156
2157 2157
2158 template <class T> 2158 template <class T>
2159 inline CMatrix4<T>& CMatrix4<T>::setTextureScaleCenter( f32 sx, f32 sy ) 2159 inline CMatrix4<T>& CMatrix4<T>::setTextureScaleCenter( f32 sx, f32 sy )
2160 { 2160 {
2161 M[0] = (T)sx; 2161 M[0] = (T)sx;
2162 M[5] = (T)sy; 2162 M[5] = (T)sy;
2163 M[8] = (T)(0.5f - 0.5f * sx); 2163 M[8] = (T)(0.5f - 0.5f * sx);
2164 M[9] = (T)(0.5f - 0.5f * sy); 2164 M[9] = (T)(0.5f - 0.5f * sy);
2165 2165
2166#if defined ( USE_MATRIX_TEST ) 2166#if defined ( USE_MATRIX_TEST )
2167 definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f); 2167 definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
2168#endif 2168#endif
2169 return *this; 2169 return *this;
2170 } 2170 }
2171 2171
2172 2172
2173 // sets all matrix data members at once 2173 // sets all matrix data members at once
2174 template <class T> 2174 template <class T>
2175 inline CMatrix4<T>& CMatrix4<T>::setM(const T* data) 2175 inline CMatrix4<T>& CMatrix4<T>::setM(const T* data)
2176 { 2176 {
2177 memcpy(M,data, 16*sizeof(T)); 2177 memcpy(M,data, 16*sizeof(T));
2178 2178
2179#if defined ( USE_MATRIX_TEST ) 2179#if defined ( USE_MATRIX_TEST )
2180 definitelyIdentityMatrix=false; 2180 definitelyIdentityMatrix=false;
2181#endif 2181#endif
2182 return *this; 2182 return *this;
2183 } 2183 }
2184 2184
2185 2185
2186 // sets if the matrix is definitely identity matrix 2186 // sets if the matrix is definitely identity matrix
2187 template <class T> 2187 template <class T>
2188 inline void CMatrix4<T>::setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix) 2188 inline void CMatrix4<T>::setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix)
2189 { 2189 {
2190#if defined ( USE_MATRIX_TEST ) 2190#if defined ( USE_MATRIX_TEST )
2191 definitelyIdentityMatrix = isDefinitelyIdentityMatrix; 2191 definitelyIdentityMatrix = isDefinitelyIdentityMatrix;
2192#endif 2192#endif
2193 } 2193 }
2194 2194
2195 2195
2196 // gets if the matrix is definitely identity matrix 2196 // gets if the matrix is definitely identity matrix
2197 template <class T> 2197 template <class T>
2198 inline bool CMatrix4<T>::getDefinitelyIdentityMatrix() const 2198 inline bool CMatrix4<T>::getDefinitelyIdentityMatrix() const
2199 { 2199 {
2200#if defined ( USE_MATRIX_TEST ) 2200#if defined ( USE_MATRIX_TEST )
2201 return definitelyIdentityMatrix; 2201 return definitelyIdentityMatrix;
2202#else 2202#else
2203 return false; 2203 return false;
2204#endif 2204#endif
2205 } 2205 }
2206 2206
2207 2207
2208 //! Compare two matrices using the equal method 2208 //! Compare two matrices using the equal method
2209 template <class T> 2209 template <class T>
2210 inline bool CMatrix4<T>::equals(const core::CMatrix4<T>& other, const T tolerance) const 2210 inline bool CMatrix4<T>::equals(const core::CMatrix4<T>& other, const T tolerance) const
2211 { 2211 {
2212#if defined ( USE_MATRIX_TEST ) 2212#if defined ( USE_MATRIX_TEST )
2213 if (definitelyIdentityMatrix && other.definitelyIdentityMatrix) 2213 if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
2214 return true; 2214 return true;
2215#endif 2215#endif
2216 for (s32 i = 0; i < 16; ++i) 2216 for (s32 i = 0; i < 16; ++i)
2217 if (!core::equals(M[i],other.M[i], tolerance)) 2217 if (!core::equals(M[i],other.M[i], tolerance))
2218 return false; 2218 return false;
2219 2219
2220 return true; 2220 return true;
2221 } 2221 }
2222 2222
2223 2223
2224 // Multiply by scalar. 2224 // Multiply by scalar.
2225 template <class T> 2225 template <class T>
2226 inline CMatrix4<T> operator*(const T scalar, const CMatrix4<T>& mat) 2226 inline CMatrix4<T> operator*(const T scalar, const CMatrix4<T>& mat)
2227 { 2227 {
2228 return mat*scalar; 2228 return mat*scalar;
2229 } 2229 }
2230 2230
2231 2231
2232 //! Typedef for f32 matrix 2232 //! Typedef for f32 matrix
2233 typedef CMatrix4<f32> matrix4; 2233 typedef CMatrix4<f32> matrix4;
2234 2234
2235 //! global const identity matrix 2235 //! global const identity matrix
2236 IRRLICHT_API extern const matrix4 IdentityMatrix; 2236 IRRLICHT_API extern const matrix4 IdentityMatrix;
2237 2237
2238} // end namespace core 2238} // end namespace core
2239} // end namespace irr 2239} // end namespace irr
2240 2240
2241#endif 2241#endif
2242 2242