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