1 // Copyright (C) 2002-2007 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
5 #ifndef __IRR_MATRIX_H_INCLUDED__
6 #define __IRR_MATRIX_H_INCLUDED__
21 //! 4x4 matrix. Mostly used as transformation matrix for 3d calculations.
22 /* Matrix4 is mainly used by the Irrlicht engine for doing transformations.
23 The matrix is a D3D style matrix, row major with translations in the 4th row.
38 EM4CONST_INVERSE_TRANSPOSED
41 CMatrix4( eConstructor constructor
= EM4CONST_IDENTITY
);
42 CMatrix4( const CMatrix4
<T
>& other
,eConstructor constructor
= EM4CONST_COPY
);
44 //! Simple operator for directly accessing every element of the matrix.
45 T
& operator()(const s32 row
, const s32 col
) { definitelyIdentityMatrix
=false; return M
[ row
* 4 + col
]; }
47 //! Simple operator for directly accessing every element of the matrix.
48 const T
& operator()(const s32 row
, const s32 col
) const { return M
[row
* 4 + col
]; }
50 //! Simple operator for linearly accessing every element of the matrix.
51 T
& operator[](u32 index
) { definitelyIdentityMatrix
=false; return M
[index
]; }
53 //! Simple operator for linearly accessing every element of the matrix.
54 const T
& operator[](u32 index
) const { return M
[index
]; }
56 //! Sets this matrix equal to the other matrix.
57 inline CMatrix4
<T
>& operator=(const CMatrix4
<T
> &other
);
59 //! Sets all elements of this matrix to the value.
60 inline CMatrix4
<T
>& operator=(const T
& scalar
);
62 //! Returns pointer to internal array
63 const T
* pointer() const { return M
; }
64 T
* pointer() { definitelyIdentityMatrix
=false; return M
; }
66 //! Returns true if other matrix is equal to this matrix.
67 bool operator==(const CMatrix4
<T
> &other
) const;
69 //! Returns true if other matrix is not equal to this matrix.
70 bool operator!=(const CMatrix4
<T
> &other
) const;
72 //! Add another matrix.
73 CMatrix4
<T
> operator+(const CMatrix4
<T
>& other
) const;
75 //! Add another matrix.
76 CMatrix4
<T
>& operator+=(const CMatrix4
<T
>& other
);
78 //! Subtract another matrix.
79 CMatrix4
<T
> operator-(const CMatrix4
<T
>& other
) const;
81 //! Subtract another matrix.
82 CMatrix4
<T
>& operator-=(const CMatrix4
<T
>& other
);
84 //! set this matrix to the product of two matrices
85 inline void setbyproduct(const CMatrix4
<T
>& other_a
,const CMatrix4
<T
>& other_b
);
87 //! set this matrix to the product of two matrices, no logical optimation
88 //! use it if you know you never have a identity matrix
89 void setbyproduct_nocheck(const CMatrix4
<T
>& other_a
,const CMatrix4
<T
>& other_b
);
91 //! Multiply by another matrix.
92 CMatrix4
<T
> operator*(const CMatrix4
<T
>& other
) const;
94 //! Multiply by another matrix.
95 CMatrix4
<T
>& operator*=(const CMatrix4
<T
>& other
);
97 //! Multiply by scalar.
98 CMatrix4
<T
> operator*(const T
& scalar
) const;
100 //! Multiply by scalar.
101 CMatrix4
<T
>& operator*=(const T
& scalar
);
103 //! Set matrix to identity.
104 inline void makeIdentity();
106 //! Returns true if the matrix is the identity matrix
107 inline bool isIdentity() const;
109 //! Returns true if the matrix is the identity matrix
110 bool isIdentity_integer_base () const;
112 //! Set the translation of the current matrix. Will erase any previous values.
113 void setTranslation( const vector3d
<T
>& translation
);
115 //! Gets the current translation
116 vector3d
<T
> getTranslation() const;
118 //! Set the inverse translation of the current matrix. Will erase any previous values.
119 void setInverseTranslation( const vector3d
<T
>& translation
);
121 //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
122 inline void setRotationRadians( const vector3d
<T
>& rotation
);
124 //! Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
125 void setRotationDegrees( const vector3d
<T
>& rotation
);
127 //! Returns the rotation, as set by setRotation(). This code was orginally written by by Chev.
128 core::vector3d
<T
> getRotationDegrees() const;
130 //! Make an inverted rotation matrix from Euler angles. The 4th row and column are unmodified.
131 inline void setInverseRotationRadians( const vector3d
<T
>& rotation
);
133 //! Make an inverted rotation matrix from Euler angles. The 4th row and column are unmodified.
134 void setInverseRotationDegrees( const vector3d
<T
>& rotation
);
137 void setScale( const vector3d
<T
>& scale
);
140 core::vector3d
<T
> getScale() const;
142 //! Translate a vector by the inverse of the translation part of this matrix.
143 void inverseTranslateVect( vector3df
& vect
) const;
145 //! Rotate a vector by the inverse of the rotation part of this matrix.
146 void inverseRotateVect( vector3df
& vect
) const;
148 //! Rotate a vector by the rotation part of this matrix.
149 void rotateVect( vector3df
& vect
) const;
151 //! An alternate transform vector method, writing into a second vector
152 void rotateVect(vector3df
& out
,const core::vector3df
& in
) const;
154 //! An alternate transform vector method, writing into an array of 3 floats
155 void rotateVect(T
*out
,const core::vector3df
&in
) const;
157 //! Transforms the vector by this matrix
158 void transformVect( vector3df
& vect
) const;
160 //! Transforms input vector by this matrix and stores result in output vector
161 void transformVect( vector3df
& out
, const vector3df
& in
) const;
163 //! An alternate transform vector method, writing into an array of 4 floats
164 void transformVect(T
*out
,const core::vector3df
&in
) const;
166 //! Translate a vector by the translation part of this matrix.
167 void translateVect( vector3df
& vect
) const;
169 //! Transforms a plane by this matrix
170 void transformPlane( core::plane3d
<f32
> &plane
) const;
172 //! Transforms a plane by this matrix ( some problems to solve..)
173 void transformPlane_new( core::plane3d
<f32
> &plane
) const;
175 //! Transforms a plane by this matrix
176 void transformPlane( const core::plane3d
<f32
> &in
, core::plane3d
<f32
> &out
) const;
178 //! Transforms a axis aligned bounding box
179 /** The result box of this operation may not be very accurate. For
180 accurate results, use transformBoxEx() */
181 void transformBox(core::aabbox3d
<f32
>& box
) const;
183 //! Transforms a axis aligned bounding box more accurately than transformBox()
184 /** The result box of this operation should by quite accurate, but this operation
185 is slower than transformBox(). */
186 void transformBoxEx(core::aabbox3d
<f32
>& box
) const;
188 //! Multiplies this matrix by a 1x4 matrix
189 void multiplyWith1x4Matrix(T
* matrix
) const;
191 //! Calculates inverse of matrix. Slow.
192 //! \return Returns false if there is no inverse matrix.
196 //! Inverts a primitive matrix which only contains a translation and a rotation
197 //! \param out: where result matrix is written to.
198 bool getInversePrimitive ( CMatrix4
<T
>& out
) const;
200 //! returns the inversed matrix of this one
201 //! \param out: where result matrix is written to.
202 //! \return Returns false if there is no inverse matrix.
203 bool getInverse(CMatrix4
<T
>& out
) const;
205 //! Builds a right-handed perspective projection matrix based on a field of view
206 void buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians
, f32 aspectRatio
, f32 zNear
, f32 zFar
);
208 //! Builds a left-handed perspective projection matrix based on a field of view
209 void buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians
, f32 aspectRatio
, f32 zNear
, f32 zFar
);
211 //! Builds a right-handed perspective projection matrix.
212 void buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume
, f32 heightOfViewVolume
, f32 zNear
, f32 zFar
);
214 //! Builds a left-handed perspective projection matrix.
215 void buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume
, f32 heightOfViewVolume
, f32 zNear
, f32 zFar
);
217 //! Builds a left-handed orthogonal projection matrix.
218 void buildProjectionMatrixOrthoLH(f32 widthOfViewVolume
, f32 heightOfViewVolume
, f32 zNear
, f32 zFar
);
220 //! Builds a right-handed orthogonal projection matrix.
221 void buildProjectionMatrixOrthoRH(f32 widthOfViewVolume
, f32 heightOfViewVolume
, f32 zNear
, f32 zFar
);
223 //! Builds a left-handed look-at matrix.
224 void buildCameraLookAtMatrixLH(const vector3df
& position
, const vector3df
& target
, const vector3df
& upVector
);
226 //! Builds a right-handed look-at matrix.
227 void buildCameraLookAtMatrixRH(const vector3df
& position
, const vector3df
& target
, const vector3df
& upVector
);
229 //! Builds a matrix that flattens geometry into a plane.
230 //! \param light: light source
231 //! \param plane: plane into which the geometry if flattened into
232 //! \param point: value between 0 and 1, describing the light source.
233 //! If this is 1, it is a point light, if it is 0, it is a directional light.
234 void buildShadowMatrix(const core::vector3df
& light
, core::plane3df plane
, f32 point
=1.0f
);
236 //! Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates.
237 /** Used to scale <-1,-1><1,1> to viewport, for example from von <-1,-1> <1,1> to the viewport <0,0><0,640> */
238 void buildNDCToDCMatrix( const core::rect
<s32
>& area
, f32 zScale
);
240 //! creates a new matrix as interpolated matrix from two other ones.
241 //! \param b: other matrix to interpolate with
242 //! \param time: Must be a value between 0 and 1.
243 CMatrix4
<T
> interpolate(const core::CMatrix4
<T
>& b
, f32 time
) const;
245 //! returns transposed matrix
246 CMatrix4
<T
> getTransposed() const;
248 //! returns transposed matrix to a plain 4x4 float matrix
249 inline void getTransposed( CMatrix4
<T
>& dest
) const;
252 construct 2D Texture transformations
253 rotate about center, scale, and transform.
255 void setTextureScale( f32 sx
, f32 sy
);
257 void setTextureRotationCenter( f32 radAngle
);
258 void setTextureScaleCenter( f32 sx
, f32 sy
);
260 void setTextureTranslate( f32 x
, f32 y
);
262 void buildTextureTransform( f32 rotateRad
,
263 const core::vector2df
&rotatecenter
,
264 const core::vector2df
&translate
,
265 const core::vector2df
&scale
);
267 //! sets all matrix data members at once
268 void setM(const T
* data
);
270 //! sets if the matrix is definitely identity matrix
271 void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix
);
273 //! gets if the matrix is definitely identity matrix
274 bool getDefinitelyIdentityMatrix() const;
277 //! Matrix data, stored in row-major order
279 mutable bool definitelyIdentityMatrix
;
283 inline CMatrix4
<T
>::CMatrix4( eConstructor constructor
) : definitelyIdentityMatrix(false)
285 switch ( constructor
)
287 case EM4CONST_NOTHING
:
290 case EM4CONST_IDENTITY
:
291 case EM4CONST_INVERSE
:
299 inline CMatrix4
<T
>::CMatrix4( const CMatrix4
<T
>& other
, eConstructor constructor
) : definitelyIdentityMatrix(false)
301 switch ( constructor
)
303 case EM4CONST_IDENTITY
:
306 case EM4CONST_NOTHING
:
311 case EM4CONST_TRANSPOSED
:
312 other
.getTransposed(*this);
314 case EM4CONST_INVERSE
:
315 if (!other
.getInverse(*this))
316 memset(M
, 0, 16*sizeof(T
));
318 case EM4CONST_INVERSE_TRANSPOSED
:
319 if (!other
.getInverse(*this))
320 memset(M
, 0, 16*sizeof(T
));
322 *this=getTransposed();
327 //! Add another matrix.
329 inline CMatrix4
<T
> CMatrix4
<T
>::operator+(const CMatrix4
<T
>& other
) const
331 CMatrix4
<T
> temp ( EM4CONST_NOTHING
);
333 temp
[0] = M
[0]+other
[0];
334 temp
[1] = M
[1]+other
[1];
335 temp
[2] = M
[2]+other
[2];
336 temp
[3] = M
[3]+other
[3];
337 temp
[4] = M
[4]+other
[4];
338 temp
[5] = M
[5]+other
[5];
339 temp
[6] = M
[6]+other
[6];
340 temp
[7] = M
[7]+other
[7];
341 temp
[8] = M
[8]+other
[8];
342 temp
[9] = M
[9]+other
[9];
343 temp
[10] = M
[10]+other
[10];
344 temp
[11] = M
[11]+other
[11];
345 temp
[12] = M
[12]+other
[12];
346 temp
[13] = M
[13]+other
[13];
347 temp
[14] = M
[14]+other
[14];
348 temp
[15] = M
[15]+other
[15];
353 //! Add another matrix.
355 inline CMatrix4
<T
>& CMatrix4
<T
>::operator+=(const CMatrix4
<T
>& other
)
377 //! Subtract another matrix.
379 inline CMatrix4
<T
> CMatrix4
<T
>::operator-(const CMatrix4
<T
>& other
) const
381 CMatrix4
<T
> temp ( EM4CONST_NOTHING
);
383 temp
[0] = M
[0]-other
[0];
384 temp
[1] = M
[1]-other
[1];
385 temp
[2] = M
[2]-other
[2];
386 temp
[3] = M
[3]-other
[3];
387 temp
[4] = M
[4]-other
[4];
388 temp
[5] = M
[5]-other
[5];
389 temp
[6] = M
[6]-other
[6];
390 temp
[7] = M
[7]-other
[7];
391 temp
[8] = M
[8]-other
[8];
392 temp
[9] = M
[9]-other
[9];
393 temp
[10] = M
[10]-other
[10];
394 temp
[11] = M
[11]-other
[11];
395 temp
[12] = M
[12]-other
[12];
396 temp
[13] = M
[13]-other
[13];
397 temp
[14] = M
[14]-other
[14];
398 temp
[15] = M
[15]-other
[15];
403 //! Subtract another matrix.
405 inline CMatrix4
<T
>& CMatrix4
<T
>::operator-=(const CMatrix4
<T
>& other
)
427 //! Multiply by scalar.
429 inline CMatrix4
<T
> CMatrix4
<T
>::operator*(const T
& scalar
) const
431 CMatrix4
<T
> temp ( EM4CONST_NOTHING
);
433 temp
[0] = M
[0]*scalar
;
434 temp
[1] = M
[1]*scalar
;
435 temp
[2] = M
[2]*scalar
;
436 temp
[3] = M
[3]*scalar
;
437 temp
[4] = M
[4]*scalar
;
438 temp
[5] = M
[5]*scalar
;
439 temp
[6] = M
[6]*scalar
;
440 temp
[7] = M
[7]*scalar
;
441 temp
[8] = M
[8]*scalar
;
442 temp
[9] = M
[9]*scalar
;
443 temp
[10] = M
[10]*scalar
;
444 temp
[11] = M
[11]*scalar
;
445 temp
[12] = M
[12]*scalar
;
446 temp
[13] = M
[13]*scalar
;
447 temp
[14] = M
[14]*scalar
;
448 temp
[15] = M
[15]*scalar
;
453 //! Multiply by scalar.
455 inline CMatrix4
<T
>& CMatrix4
<T
>::operator*=(const T
& scalar
)
477 //! Multiply by another matrix.
479 inline CMatrix4
<T
>& CMatrix4
<T
>::operator*=(const CMatrix4
<T
>& other
)
481 // do chacks on your own in order to avoid copy creation
482 if ( !other
.isIdentity() )
484 if ( this->isIdentity() )
490 CMatrix4
<T
> temp ( *this );
491 setbyproduct_nocheck( temp
, other
);
497 //! multiply by another matrix
498 // set this matrix to the product of two other matrices
499 // goal is to reduce stack use and copy
501 inline void CMatrix4
<T
>::setbyproduct_nocheck(const CMatrix4
<T
>& other_a
,const CMatrix4
<T
>& other_b
)
503 const T
*m1
= other_a
.M
;
504 const T
*m2
= other_b
.M
;
506 M
[0] = m1
[0]*m2
[0] + m1
[4]*m2
[1] + m1
[8]*m2
[2] + m1
[12]*m2
[3];
507 M
[1] = m1
[1]*m2
[0] + m1
[5]*m2
[1] + m1
[9]*m2
[2] + m1
[13]*m2
[3];
508 M
[2] = m1
[2]*m2
[0] + m1
[6]*m2
[1] + m1
[10]*m2
[2] + m1
[14]*m2
[3];
509 M
[3] = m1
[3]*m2
[0] + m1
[7]*m2
[1] + m1
[11]*m2
[2] + m1
[15]*m2
[3];
511 M
[4] = m1
[0]*m2
[4] + m1
[4]*m2
[5] + m1
[8]*m2
[6] + m1
[12]*m2
[7];
512 M
[5] = m1
[1]*m2
[4] + m1
[5]*m2
[5] + m1
[9]*m2
[6] + m1
[13]*m2
[7];
513 M
[6] = m1
[2]*m2
[4] + m1
[6]*m2
[5] + m1
[10]*m2
[6] + m1
[14]*m2
[7];
514 M
[7] = m1
[3]*m2
[4] + m1
[7]*m2
[5] + m1
[11]*m2
[6] + m1
[15]*m2
[7];
516 M
[8] = m1
[0]*m2
[8] + m1
[4]*m2
[9] + m1
[8]*m2
[10] + m1
[12]*m2
[11];
517 M
[9] = m1
[1]*m2
[8] + m1
[5]*m2
[9] + m1
[9]*m2
[10] + m1
[13]*m2
[11];
518 M
[10] = m1
[2]*m2
[8] + m1
[6]*m2
[9] + m1
[10]*m2
[10] + m1
[14]*m2
[11];
519 M
[11] = m1
[3]*m2
[8] + m1
[7]*m2
[9] + m1
[11]*m2
[10] + m1
[15]*m2
[11];
521 M
[12] = m1
[0]*m2
[12] + m1
[4]*m2
[13] + m1
[8]*m2
[14] + m1
[12]*m2
[15];
522 M
[13] = m1
[1]*m2
[12] + m1
[5]*m2
[13] + m1
[9]*m2
[14] + m1
[13]*m2
[15];
523 M
[14] = m1
[2]*m2
[12] + m1
[6]*m2
[13] + m1
[10]*m2
[14] + m1
[14]*m2
[15];
524 M
[15] = m1
[3]*m2
[12] + m1
[7]*m2
[13] + m1
[11]*m2
[14] + m1
[15]*m2
[15];
525 definitelyIdentityMatrix
=false;
529 //! multiply by another matrix
530 // set this matrix to the product of two other matrices
531 // goal is to reduce stack use and copy
533 inline void CMatrix4
<T
>::setbyproduct(const CMatrix4
<T
>& other_a
,const CMatrix4
<T
>& other_b
)
535 if ( other_a
.isIdentity () )
541 if ( other_b
.isIdentity () )
546 setbyproduct_nocheck(other_a
,other_b
);
549 //! multiply by another matrix
551 inline CMatrix4
<T
> CMatrix4
<T
>::operator*(const CMatrix4
<T
>& m2
) const
554 if ( this->isIdentity() )
556 if ( m2
.isIdentity() )
559 CMatrix4
<T
> m3 ( EM4CONST_NOTHING
);
563 m3
[0] = m1
[0]*m2
[0] + m1
[4]*m2
[1] + m1
[8]*m2
[2] + m1
[12]*m2
[3];
564 m3
[1] = m1
[1]*m2
[0] + m1
[5]*m2
[1] + m1
[9]*m2
[2] + m1
[13]*m2
[3];
565 m3
[2] = m1
[2]*m2
[0] + m1
[6]*m2
[1] + m1
[10]*m2
[2] + m1
[14]*m2
[3];
566 m3
[3] = m1
[3]*m2
[0] + m1
[7]*m2
[1] + m1
[11]*m2
[2] + m1
[15]*m2
[3];
568 m3
[4] = m1
[0]*m2
[4] + m1
[4]*m2
[5] + m1
[8]*m2
[6] + m1
[12]*m2
[7];
569 m3
[5] = m1
[1]*m2
[4] + m1
[5]*m2
[5] + m1
[9]*m2
[6] + m1
[13]*m2
[7];
570 m3
[6] = m1
[2]*m2
[4] + m1
[6]*m2
[5] + m1
[10]*m2
[6] + m1
[14]*m2
[7];
571 m3
[7] = m1
[3]*m2
[4] + m1
[7]*m2
[5] + m1
[11]*m2
[6] + m1
[15]*m2
[7];
573 m3
[8] = m1
[0]*m2
[8] + m1
[4]*m2
[9] + m1
[8]*m2
[10] + m1
[12]*m2
[11];
574 m3
[9] = m1
[1]*m2
[8] + m1
[5]*m2
[9] + m1
[9]*m2
[10] + m1
[13]*m2
[11];
575 m3
[10] = m1
[2]*m2
[8] + m1
[6]*m2
[9] + m1
[10]*m2
[10] + m1
[14]*m2
[11];
576 m3
[11] = m1
[3]*m2
[8] + m1
[7]*m2
[9] + m1
[11]*m2
[10] + m1
[15]*m2
[11];
578 m3
[12] = m1
[0]*m2
[12] + m1
[4]*m2
[13] + m1
[8]*m2
[14] + m1
[12]*m2
[15];
579 m3
[13] = m1
[1]*m2
[12] + m1
[5]*m2
[13] + m1
[9]*m2
[14] + m1
[13]*m2
[15];
580 m3
[14] = m1
[2]*m2
[12] + m1
[6]*m2
[13] + m1
[10]*m2
[14] + m1
[14]*m2
[15];
581 m3
[15] = m1
[3]*m2
[12] + m1
[7]*m2
[13] + m1
[11]*m2
[14] + m1
[15]*m2
[15];
588 inline vector3d
<T
> CMatrix4
<T
>::getTranslation() const
590 return vector3d
<T
>(M
[12], M
[13], M
[14]);
595 inline void CMatrix4
<T
>::setTranslation( const vector3d
<T
>& translation
)
597 M
[12] = translation
.X
;
598 M
[13] = translation
.Y
;
599 M
[14] = translation
.Z
;
600 definitelyIdentityMatrix
=false;
604 inline void CMatrix4
<T
>::setInverseTranslation( const vector3d
<T
>& translation
)
606 M
[12] = -translation
.X
;
607 M
[13] = -translation
.Y
;
608 M
[14] = -translation
.Z
;
609 definitelyIdentityMatrix
=false;
613 inline void CMatrix4
<T
>::setScale( const vector3d
<T
>& scale
)
618 definitelyIdentityMatrix
=false;
622 inline vector3d
<T
> CMatrix4
<T
>::getScale() const
624 return vector3d
<T
>(M
[0],M
[5],M
[10]);
628 inline void CMatrix4
<T
>::setRotationDegrees( const vector3d
<T
>& rotation
)
630 setRotationRadians( rotation
* core::DEGTORAD
);
634 inline void CMatrix4
<T
>::setInverseRotationDegrees( const vector3d
<T
>& rotation
)
636 setInverseRotationRadians( rotation
* core::DEGTORAD
);
640 inline void CMatrix4
<T
>::setRotationRadians( const vector3d
<T
>& rotation
)
642 f64 cr
= cos( rotation
.X
);
643 f64 sr
= sin( rotation
.X
);
644 f64 cp
= cos( rotation
.Y
);
645 f64 sp
= sin( rotation
.Y
);
646 f64 cy
= cos( rotation
.Z
);
647 f64 sy
= sin( rotation
.Z
);
656 M
[4] = (T
)( srsp
*cy
-cr
*sy
);
657 M
[5] = (T
)( srsp
*sy
+cr
*cy
);
660 M
[8] = (T
)( crsp
*cy
+sr
*sy
);
661 M
[9] = (T
)( crsp
*sy
-sr
*cy
);
662 M
[10] = (T
)( cr
*cp
);
663 definitelyIdentityMatrix
=false;
668 //! Returns the rotation, as set by setRotation(). This code was sent
671 inline core::vector3d
<T
> CMatrix4
<T
>::getRotationDegrees() const
673 const CMatrix4
<T
> &mat
= *this;
675 f64 Y
= -asin(mat(0,2));
679 f64 rotx
, roty
, X
, Z
;
685 X
= atan2( roty
, rotx
) * RADTODEG64
;
688 Z
= atan2( roty
, rotx
) * RADTODEG64
;
695 Z
= atan2( roty
, rotx
) * RADTODEG64
;
698 // fix values that get below zero
699 // before it would set (!) values to 360
700 // that where above 360:
701 if (X
< 0.0) X
+= 360.0;
702 if (Y
< 0.0) Y
+= 360.0;
703 if (Z
< 0.0) Z
+= 360.0;
705 return vector3d
<T
>((f32
)X
,(f32
)Y
,(f32
)Z
);
709 inline void CMatrix4
<T
>::setInverseRotationRadians( const vector3d
<T
>& rotation
)
711 f64 cr
= cos( rotation
.X
);
712 f64 sr
= sin( rotation
.X
);
713 f64 cp
= cos( rotation
.Y
);
714 f64 sp
= sin( rotation
.Y
);
715 f64 cy
= cos( rotation
.Z
);
716 f64 sy
= sin( rotation
.Z
);
725 M
[1] = (T
)( srsp
*cy
-cr
*sy
);
726 M
[5] = (T
)( srsp
*sy
+cr
*cy
);
729 M
[2] = (T
)( crsp
*cy
+sr
*sy
);
730 M
[6] = (T
)( crsp
*sy
-sr
*cy
);
731 M
[10] = (T
)( cr
*cp
);
732 definitelyIdentityMatrix
=false;
739 inline void CMatrix4
<T
>::makeIdentity()
741 memset(M
, 0, 16*sizeof(T
));
742 M
[0] = M
[5] = M
[10] = M
[15] = (T
)1;
743 definitelyIdentityMatrix
=true;
748 check identity with epsilon
749 solve floating range problems..
752 inline bool CMatrix4
<T
>::isIdentity() const
754 if (definitelyIdentityMatrix
)
756 if ( !equals ( M
[ 0], (T
)1 ) ||
757 !equals ( M
[ 5], (T
)1 ) ||
758 !equals ( M
[10], (T
)1 ) ||
759 !equals ( M
[15], (T
)1 )
763 for (s32 i
=0; i
<4; ++i
)
764 for (s32 j
=0; j
<4; ++j
)
766 if (!iszero((*this)(i
,j
)))
769 definitelyIdentityMatrix
=true;
774 doesn't solve floating range problems..
775 but takes care on +/- 0 on translation because we are changing it..
776 reducing floating point branches
777 but it needs the floats in memory..
780 inline bool CMatrix4
<T
>::isIdentity_integer_base() const
782 if (definitelyIdentityMatrix
)
784 if(IR(M
[0])!=F32_VALUE_1
) return false;
785 if(IR(M
[1])!=0) return false;
786 if(IR(M
[2])!=0) return false;
787 if(IR(M
[3])!=0) return false;
789 if(IR(M
[4])!=0) return false;
790 if(IR(M
[5])!=F32_VALUE_1
) return false;
791 if(IR(M
[6])!=0) return false;
792 if(IR(M
[7])!=0) return false;
794 if(IR(M
[8])!=0) return false;
795 if(IR(M
[9])!=0) return false;
796 if(IR(M
[10])!=F32_VALUE_1
) return false;
797 if(IR(M
[11])!=0) return false;
799 if(IR(M
[12])!=0) return false;
800 if(IR(M
[13])!=0) return false;
801 if(IR(M
[13])!=0) return false;
802 if(IR(M
[15])!=F32_VALUE_1
) return false;
803 definitelyIdentityMatrix
=true;
810 inline void CMatrix4
<T
>::rotateVect( vector3df
& vect
) const
812 vector3df tmp
= vect
;
813 vect
.X
= tmp
.X
*M
[0] + tmp
.Y
*M
[4] + tmp
.Z
*M
[8];
814 vect
.Y
= tmp
.X
*M
[1] + tmp
.Y
*M
[5] + tmp
.Z
*M
[9];
815 vect
.Z
= tmp
.X
*M
[2] + tmp
.Y
*M
[6] + tmp
.Z
*M
[10];
818 //! An alternate transform vector method, writing into a second vector
820 inline void CMatrix4
<T
>::rotateVect(core::vector3df
& out
, const core::vector3df
& in
) const
822 out
.X
= in
.X
*M
[0] + in
.Y
*M
[4] + in
.Z
*M
[8];
823 out
.Y
= in
.X
*M
[1] + in
.Y
*M
[5] + in
.Z
*M
[9];
824 out
.Z
= in
.X
*M
[2] + in
.Y
*M
[6] + in
.Z
*M
[10];
827 //! An alternate transform vector method, writing into an array of 3 floats
829 inline void CMatrix4
<T
>::rotateVect(T
*out
, const core::vector3df
& in
) const
831 out
[0] = in
.X
*M
[0] + in
.Y
*M
[4] + in
.Z
*M
[8];
832 out
[1] = in
.X
*M
[1] + in
.Y
*M
[5] + in
.Z
*M
[9];
833 out
[2] = in
.X
*M
[2] + in
.Y
*M
[6] + in
.Z
*M
[10];
837 inline void CMatrix4
<T
>::inverseRotateVect( vector3df
& vect
) const
839 vector3df tmp
= vect
;
840 vect
.X
= tmp
.X
*M
[0] + tmp
.Y
*M
[1] + tmp
.Z
*M
[2];
841 vect
.Y
= tmp
.X
*M
[4] + tmp
.Y
*M
[5] + tmp
.Z
*M
[6];
842 vect
.Z
= tmp
.X
*M
[8] + tmp
.Y
*M
[9] + tmp
.Z
*M
[10];
846 inline void CMatrix4
<T
>::transformVect( vector3df
& vect
) const
850 vector
[0] = vect
.X
*M
[0] + vect
.Y
*M
[4] + vect
.Z
*M
[8] + M
[12];
851 vector
[1] = vect
.X
*M
[1] + vect
.Y
*M
[5] + vect
.Z
*M
[9] + M
[13];
852 vector
[2] = vect
.X
*M
[2] + vect
.Y
*M
[6] + vect
.Z
*M
[10] + M
[14];
860 inline void CMatrix4
<T
>::transformVect( vector3df
& out
, const vector3df
& in
) const
862 out
.X
= in
.X
*M
[0] + in
.Y
*M
[4] + in
.Z
*M
[8] + M
[12];
863 out
.Y
= in
.X
*M
[1] + in
.Y
*M
[5] + in
.Z
*M
[9] + M
[13];
864 out
.Z
= in
.X
*M
[2] + in
.Y
*M
[6] + in
.Z
*M
[10] + M
[14];
869 inline void CMatrix4
<T
>::transformVect(T
*out
,const vector3df
&in
) const
871 out
[0] = in
.X
*M
[0] + in
.Y
*M
[4] + in
.Z
*M
[8] + M
[12];
872 out
[1] = in
.X
*M
[1] + in
.Y
*M
[5] + in
.Z
*M
[9] + M
[13];
873 out
[2] = in
.X
*M
[2] + in
.Y
*M
[6] + in
.Z
*M
[10] + M
[14];
874 out
[3] = in
.X
*M
[3] + in
.Y
*M
[7] + in
.Z
*M
[11] + M
[15];
878 //! Transforms a plane by this matrix
880 inline void CMatrix4
<T
>::transformPlane( core::plane3d
<f32
> &plane
) const
883 transformVect(member
, plane
.getMemberPoint());
885 vector3df
origin(0,0,0);
886 transformVect(plane
.Normal
);
887 transformVect(origin
);
889 plane
.Normal
-= origin
;
890 plane
.D
= - member
.dotProduct(plane
.Normal
);
893 //! Transforms a plane by this matrix
895 inline void CMatrix4
<T
>::transformPlane_new( core::plane3d
<f32
> &plane
) const
897 // rotate normal -> rotateVect ( plane.n );
899 n
.X
= plane
.Normal
.X
*M
[0] + plane
.Normal
.Y
*M
[4] + plane
.Normal
.Z
*M
[8];
900 n
.Y
= plane
.Normal
.X
*M
[1] + plane
.Normal
.Y
*M
[5] + plane
.Normal
.Z
*M
[9];
901 n
.Z
= plane
.Normal
.X
*M
[2] + plane
.Normal
.Y
*M
[6] + plane
.Normal
.Z
*M
[10];
903 // compute new d. -> getTranslation(). dotproduct ( plane.n )
904 plane
.D
-= M
[12] * n
.X
+ M
[13] * n
.Y
+ M
[14] * n
.Z
;
905 plane
.Normal
.X
= n
.X
;
906 plane
.Normal
.Y
= n
.Y
;
907 plane
.Normal
.Z
= n
.Z
;
910 //! Transforms a plane by this matrix
912 inline void CMatrix4
<T
>::transformPlane( const core::plane3d
<f32
> &in
, core::plane3d
<f32
> &out
) const
915 transformPlane( out
);
918 //! Transforms a axis aligned bounding box
920 inline void CMatrix4
<T
>::transformBox(core::aabbox3d
<f32
>& box
) const
925 transformVect(box
.MinEdge
);
926 transformVect(box
.MaxEdge
);
930 //! Transforms a axis aligned bounding box more accurately than transformBox()
932 inline void CMatrix4
<T
>::transformBoxEx(core::aabbox3d
<f32
>& box
) const
939 Amin
[0] = box
.MinEdge
.X
;
940 Amin
[1] = box
.MinEdge
.Y
;
941 Amin
[2] = box
.MinEdge
.Z
;
943 Amax
[0] = box
.MaxEdge
.X
;
944 Amax
[1] = box
.MaxEdge
.Y
;
945 Amax
[2] = box
.MaxEdge
.Z
;
947 Bmin
[0] = Bmax
[0] = M
[12];
948 Bmin
[1] = Bmax
[1] = M
[13];
949 Bmin
[2] = Bmax
[2] = M
[14];
952 const CMatrix4
<T
> &m
= *this;
954 for (i
= 0; i
< 3; ++i
)
956 for (j
= 0; j
< 3; ++j
)
958 f32 a
= m(j
,i
) * Amin
[j
];
959 f32 b
= m(j
,i
) * Amax
[j
];
974 box
.MinEdge
.X
= Bmin
[0];
975 box
.MinEdge
.Y
= Bmin
[1];
976 box
.MinEdge
.Z
= Bmin
[2];
978 box
.MaxEdge
.X
= Bmax
[0];
979 box
.MaxEdge
.Y
= Bmax
[1];
980 box
.MaxEdge
.Z
= Bmax
[2];
984 //! Multiplies this matrix by a 1x4 matrix
986 inline void CMatrix4
<T
>::multiplyWith1x4Matrix(T
* matrix
) const
1001 matrix
[0] = M
[0]*mat
[0] + M
[4]*mat
[1] + M
[8]*mat
[2] + M
[12]*mat
[3];
1002 matrix
[1] = M
[1]*mat
[0] + M
[5]*mat
[1] + M
[9]*mat
[2] + M
[13]*mat
[3];
1003 matrix
[2] = M
[2]*mat
[0] + M
[6]*mat
[1] + M
[10]*mat
[2] + M
[14]*mat
[3];
1004 matrix
[3] = M
[3]*mat
[0] + M
[7]*mat
[1] + M
[11]*mat
[2] + M
[15]*mat
[3];
1008 inline void CMatrix4
<T
>::inverseTranslateVect( vector3df
& vect
) const
1010 vect
.X
= vect
.X
-M
[12];
1011 vect
.Y
= vect
.Y
-M
[13];
1012 vect
.Z
= vect
.Z
-M
[14];
1016 inline void CMatrix4
<T
>::translateVect( vector3df
& vect
) const
1018 vect
.X
= vect
.X
+M
[12];
1019 vect
.Y
= vect
.Y
+M
[13];
1020 vect
.Z
= vect
.Z
+M
[14];
1025 inline bool CMatrix4
<T
>::getInverse(CMatrix4
<T
>& out
) const
1027 /// Calculates the inverse of this Matrix
1028 /// The inverse is calculated using Cramers rule.
1029 /// If no inverse exists then 'false' is returned.
1031 if ( this->isIdentity() )
1037 const CMatrix4
<T
> &m
= *this;
1039 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)) -
1040 (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
1041 (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)) +
1042 (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) -
1043 (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
1044 (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0));
1046 if( core::iszero ( d
) )
1049 d
= core::reciprocal ( d
);
1051 out(0, 0) = d
* (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) + m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) + m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)));
1052 out(0, 1) = d
* (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) + m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) + m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1)));
1053 out(0, 2) = d
* (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) + m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) + m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)));
1054 out(0, 3) = d
* (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) + m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) + m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2)));
1055 out(1, 0) = d
* (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) + m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) + m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3)));
1056 out(1, 1) = d
* (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) + m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) + m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3)));
1057 out(1, 2) = d
* (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) + m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) + m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3)));
1058 out(1, 3) = d
* (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) + m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) + m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2)));
1059 out(2, 0) = d
* (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) + m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) + m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3)));
1060 out(2, 1) = d
* (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) + m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) + m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3)));
1061 out(2, 2) = d
* (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) + m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) + m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3)));
1062 out(2, 3) = d
* (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) + m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) + m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0)));
1063 out(3, 0) = d
* (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) + m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) + m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1)));
1064 out(3, 1) = d
* (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) + m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) + m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1)));
1065 out(3, 2) = d
* (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) + m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) + m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1)));
1066 out(3, 3) = d
* (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) + m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) + m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)));
1067 out
.definitelyIdentityMatrix
= definitelyIdentityMatrix
;
1072 //! Inverts a primitive matrix which only contains a translation and a rotation
1073 //! \param out: where result matrix is written to.
1075 inline bool CMatrix4
<T
>::getInversePrimitive ( CMatrix4
<T
>& out
) const
1092 out
.M
[12] = (T
)-(M
[12]*M
[0] + M
[13]*M
[1] + M
[14]*M
[2]);
1093 out
.M
[13] = (T
)-(M
[12]*M
[4] + M
[13]*M
[5] + M
[14]*M
[6]);
1094 out
.M
[14] = (T
)-(M
[12]*M
[8] + M
[13]*M
[9] + M
[14]*M
[10]);
1096 out
.definitelyIdentityMatrix
= definitelyIdentityMatrix
;
1103 inline bool CMatrix4
<T
>::makeInverse()
1105 if (definitelyIdentityMatrix
)
1108 CMatrix4
<T
> temp ( EM4CONST_NOTHING
);
1110 if (getInverse(temp
))
1122 inline CMatrix4
<T
>& CMatrix4
<T
>::operator=(const CMatrix4
<T
> &other
)
1126 memcpy(M
, other
.M
, 16*sizeof(T
));
1127 definitelyIdentityMatrix
=other
.definitelyIdentityMatrix
;
1134 inline CMatrix4
<T
>& CMatrix4
<T
>::operator=(const T
& scalar
)
1136 for (s32 i
= 0; i
< 16; ++i
)
1138 definitelyIdentityMatrix
=false;
1145 inline bool CMatrix4
<T
>::operator==(const CMatrix4
<T
> &other
) const
1147 if (definitelyIdentityMatrix
&& other
.definitelyIdentityMatrix
)
1149 for (s32 i
= 0; i
< 16; ++i
)
1150 if (M
[i
] != other
.M
[i
])
1159 inline bool CMatrix4
<T
>::operator!=(const CMatrix4
<T
> &other
) const
1161 return !(*this == other
);
1166 //! Builds a right-handed perspective projection matrix based on a field of view
1168 inline void CMatrix4
<T
>::buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians
, f32 aspectRatio
, f32 zNear
, f32 zFar
)
1170 f64 h
= 1.0/tan(fieldOfViewRadians
/2.0);
1171 T w
= h
/ aspectRatio
;
1185 M
[10] = (T
)(zFar
/(zNear
-zFar
)); // DirectX version
1186 // M[10] = (T)(zFar+zNear/(zNear-zFar)); // OpenGL version
1191 M
[14] = (T
)(zNear
*zFar
/(zNear
-zFar
)); // DirectX version
1192 // M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version
1194 definitelyIdentityMatrix
=false;
1199 //! Builds a left-handed perspective projection matrix based on a field of view
1201 inline void CMatrix4
<T
>::buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians
, f32 aspectRatio
, f32 zNear
, f32 zFar
)
1203 f64 h
= 1.0/tan(fieldOfViewRadians
/2.0);
1204 T w
= (T
)(h
/ aspectRatio
);
1218 M
[10] = (T
)(zFar
/(zFar
-zNear
));
1223 M
[14] = (T
)(-zNear
*zFar
/(zFar
-zNear
));
1225 definitelyIdentityMatrix
=false;
1230 //! Builds a left-handed orthogonal projection matrix.
1232 inline void CMatrix4
<T
>::buildProjectionMatrixOrthoLH(f32 widthOfViewVolume
, f32 heightOfViewVolume
, f32 zNear
, f32 zFar
)
1234 M
[0] = (T
)(2/widthOfViewVolume
);
1240 M
[5] = (T
)(2/heightOfViewVolume
);
1246 M
[10] = (T
)(1/(zFar
-zNear
));
1251 M
[14] = (T
)(zNear
/(zNear
-zFar
));
1253 definitelyIdentityMatrix
=false;
1258 //! Builds a right-handed orthogonal projection matrix.
1260 inline void CMatrix4
<T
>::buildProjectionMatrixOrthoRH(f32 widthOfViewVolume
, f32 heightOfViewVolume
, f32 zNear
, f32 zFar
)
1262 M
[0] = (T
)(2/widthOfViewVolume
);
1268 M
[5] = (T
)(2/heightOfViewVolume
);
1274 M
[10] = (T
)(1/(zNear
-zFar
));
1279 M
[14] = (T
)(zNear
/(zNear
-zFar
));
1281 definitelyIdentityMatrix
=false;
1285 //! Builds a right-handed perspective projection matrix.
1287 inline void CMatrix4
<T
>::buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume
, f32 heightOfViewVolume
, f32 zNear
, f32 zFar
)
1289 M
[0] = (T
)(2*zNear
/widthOfViewVolume
);
1295 M
[5] = (T
)(2*zNear
/heightOfViewVolume
);
1301 M
[10] = (T
)(zFar
/(zNear
-zFar
));
1306 M
[14] = (T
)(zNear
*zFar
/(zNear
-zFar
));
1308 definitelyIdentityMatrix
=false;
1312 //! Builds a left-handed perspective projection matrix.
1314 inline void CMatrix4
<T
>::buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume
, f32 heightOfViewVolume
, f32 zNear
, f32 zFar
)
1316 M
[0] = (T
)(2*zNear
/widthOfViewVolume
);
1322 M
[5] = (T
)(2*zNear
/heightOfViewVolume
);
1328 M
[10] = (T
)(zFar
/(zFar
-zNear
));
1333 M
[14] = (T
)(zNear
*zFar
/(zNear
-zFar
));
1335 definitelyIdentityMatrix
=false;
1339 //! Builds a matrix that flattens geometry into a plane.
1341 inline void CMatrix4
<T
>::buildShadowMatrix(const core::vector3df
& light
, core::plane3df plane
, f32 point
)
1343 plane
.Normal
.normalize();
1344 f32 d
= plane
.Normal
.dotProduct(light
);
1346 M
[ 0] = (T
)(-plane
.Normal
.X
* light
.X
+ d
);
1347 M
[ 1] = (T
)(-plane
.Normal
.X
* light
.Y
);
1348 M
[ 2] = (T
)(-plane
.Normal
.X
* light
.Z
);
1349 M
[ 3] = (T
)(-plane
.Normal
.X
* point
);
1351 M
[ 4] = (T
)(-plane
.Normal
.Y
* light
.X
);
1352 M
[ 5] = (T
)(-plane
.Normal
.Y
* light
.Y
+ d
);
1353 M
[ 6] = (T
)(-plane
.Normal
.Y
* light
.Z
);
1354 M
[ 7] = (T
)(-plane
.Normal
.Y
* point
);
1356 M
[ 8] = (T
)(-plane
.Normal
.Z
* light
.X
);
1357 M
[ 9] = (T
)(-plane
.Normal
.Z
* light
.Y
);
1358 M
[10] = (T
)(-plane
.Normal
.Z
* light
.Z
+ d
);
1359 M
[11] = (T
)(-plane
.Normal
.Z
* point
);
1361 M
[12] = (T
)(-plane
.D
* light
.X
);
1362 M
[13] = (T
)(-plane
.D
* light
.Y
);
1363 M
[14] = (T
)(-plane
.D
* light
.Z
);
1364 M
[15] = (T
)(-plane
.D
* point
+ d
);
1365 definitelyIdentityMatrix
=false;
1368 //! Builds a left-handed look-at matrix.
1370 inline void CMatrix4
<T
>::buildCameraLookAtMatrixLH(
1371 const vector3df
& position
,
1372 const vector3df
& target
,
1373 const vector3df
& upVector
)
1375 vector3df zaxis
= target
- position
;
1378 vector3df xaxis
= upVector
.crossProduct(zaxis
);
1381 vector3df yaxis
= zaxis
.crossProduct(xaxis
);
1398 M
[12] = (T
)-xaxis
.dotProduct(position
);
1399 M
[13] = (T
)-yaxis
.dotProduct(position
);
1400 M
[14] = (T
)-zaxis
.dotProduct(position
);
1402 definitelyIdentityMatrix
=false;
1407 //! Builds a right-handed look-at matrix.
1409 inline void CMatrix4
<T
>::buildCameraLookAtMatrixRH(
1410 const vector3df
& position
,
1411 const vector3df
& target
,
1412 const vector3df
& upVector
)
1414 vector3df zaxis
= position
- target
;
1417 vector3df xaxis
= upVector
.crossProduct(zaxis
);
1420 vector3df yaxis
= zaxis
.crossProduct(xaxis
);
1437 M
[12] = (T
)-xaxis
.dotProduct(position
);
1438 M
[13] = (T
)-yaxis
.dotProduct(position
);
1439 M
[14] = (T
)-zaxis
.dotProduct(position
);
1441 definitelyIdentityMatrix
=false;
1445 //! creates a new matrix as interpolated matrix from to other ones.
1446 //! \param time: Must be a value between 0 and 1.
1448 inline CMatrix4
<T
> CMatrix4
<T
>::interpolate(const core::CMatrix4
<T
>& b
, f32 time
) const
1450 CMatrix4
<T
> mat ( EM4CONST_NOTHING
);
1452 for (u32 i
=0; i
< 16; i
+= 4)
1454 mat
.M
[i
+0] = (T
)(M
[i
+0] + ( b
.M
[i
+0] - M
[i
+0] ) * time
);
1455 mat
.M
[i
+1] = (T
)(M
[i
+1] + ( b
.M
[i
+1] - M
[i
+1] ) * time
);
1456 mat
.M
[i
+2] = (T
)(M
[i
+2] + ( b
.M
[i
+2] - M
[i
+2] ) * time
);
1457 mat
.M
[i
+3] = (T
)(M
[i
+3] + ( b
.M
[i
+3] - M
[i
+3] ) * time
);
1462 //! returns transposed matrix
1464 inline CMatrix4
<T
> CMatrix4
<T
>::getTransposed() const
1466 CMatrix4
<T
> t ( EM4CONST_NOTHING
);
1467 getTransposed ( t
);
1471 //! returns transposed matrix
1473 inline void CMatrix4
<T
>::getTransposed( CMatrix4
<T
>& o
) const
1494 o
.definitelyIdentityMatrix
=definitelyIdentityMatrix
;
1498 // used to scale <-1,-1><1,1> to viewport
1500 inline void CMatrix4
<T
>::buildNDCToDCMatrix( const core::rect
<s32
>& viewport
, f32 zScale
)
1502 f32 scaleX
= (viewport
.getWidth() - 0.75f
) / 2.0f
;
1503 f32 scaleY
= -(viewport
.getHeight() - 0.75f
) / 2.0f
;
1505 f32 dx
= -0.5f
+ ( (viewport
.UpperLeftCorner
.X
+ viewport
.LowerRightCorner
.X
) / 2.0f
);
1506 f32 dy
= -0.5f
+ ( (viewport
.UpperLeftCorner
.Y
+ viewport
.LowerRightCorner
.Y
) / 2.0f
);
1514 definitelyIdentityMatrix
=false;
1518 Generate texture coordinates as linear functions so that:
1519 u = Ux*x + Uy*y + Uz*z + Uw
1520 v = Vx*x + Vy*y + Vz*z + Vw
1521 The matrix M for this case is:
1529 inline void CMatrix4
<T
>::buildTextureTransform( f32 rotateRad
,
1530 const core::vector2df
&rotatecenter
,
1531 const core::vector2df
&translate
,
1532 const core::vector2df
&scale
)
1534 const f32 c
= cosf(rotateRad
);
1535 const f32 s
= sinf(rotateRad
);
1537 M
[0] = (T
)(c
* scale
.X
);
1538 M
[1] = (T
)(s
* scale
.Y
);
1542 M
[4] = (T
)(-s
* scale
.X
);
1543 M
[5] = (T
)(c
* scale
.Y
);
1547 M
[8] = (T
)(c
* scale
.X
* rotatecenter
.X
+ -s
* rotatecenter
.Y
+ translate
.X
);
1548 M
[9] = (T
)(s
* scale
.Y
* rotatecenter
.X
+ c
* rotatecenter
.Y
+ translate
.Y
);
1556 definitelyIdentityMatrix
=false;
1559 //! rotate about z axis, center ( 0.5, 0.5 )
1561 inline void CMatrix4
<T
>::setTextureRotationCenter( f32 rotateRad
)
1563 const f32 c
= cosf(rotateRad
);
1564 const f32 s
= sinf(rotateRad
);
1567 M
[2] = (T
)(-0.5f
* ( c
+ s
) + 0.5f
);
1571 M
[6] = (T
)(-0.5f
* (-s
+ c
) + 0.5f
);
1572 definitelyIdentityMatrix
=false;
1576 inline void CMatrix4
<T
>::setTextureTranslate ( f32 x
, f32 y
)
1580 definitelyIdentityMatrix
= definitelyIdentityMatrix
&& (x
==0.0f
) && (y
==0.0f
) ;
1584 inline void CMatrix4
<T
>::setTextureScale ( f32 sx
, f32 sy
)
1588 definitelyIdentityMatrix
= definitelyIdentityMatrix
&& (sx
==1.0f
) && (sy
==1.0f
) ;
1592 inline void CMatrix4
<T
>::setTextureScaleCenter( f32 sx
, f32 sy
)
1595 M
[2] = (T
)(-0.5f
* sx
+ 0.5f
);
1597 M
[6] = (T
)(-0.5f
* sy
+ 0.5f
);
1598 definitelyIdentityMatrix
= definitelyIdentityMatrix
&& (sx
==1.0f
) && (sy
==1.0f
) ;
1601 //! sets all matrix data members at once
1603 inline void CMatrix4
<T
>::setM(const T
* data
)
1605 for (u32 i
= 0; i
< 16; ++i
)
1608 definitelyIdentityMatrix
= false;
1611 //! sets if the matrix is definitely identity matrix
1613 inline void CMatrix4
<T
>::setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix
)
1615 definitelyIdentityMatrix
= isDefinitelyIdentityMatrix
;
1618 //! gets if the matrix is definitely identity matrix
1620 inline bool CMatrix4
<T
>::getDefinitelyIdentityMatrix() const
1622 return definitelyIdentityMatrix
;
1625 //! Multiply by scalar.
1627 inline CMatrix4
<T
> operator*(const T scalar
, const CMatrix4
<T
>& mat
)
1632 typedef CMatrix4
<f32
> matrix4
;
1633 const matrix4
IdentityMatrix(matrix4::EM4CONST_IDENTITY
);
1635 } // end namespace core
1636 } // end namespace irr