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