diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/include/matrix4.h | 4484 |
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 | ||
26 | struct MatrixTest | 26 | struct 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 | }; |
33 | static MatrixTest MTest; | 33 | static MatrixTest MTest; |
34 | 34 | ||
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | namespace irr | 37 | namespace irr |
38 | { | 38 | { |
39 | namespace core | 39 | namespace 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 | ||