PixelLightAPI
.
|
00001 /*********************************************************\ 00002 * File: Matrix4x4.h * 00003 * 00004 * Copyright (C) 2002-2012 The PixelLight Team (http://www.pixellight.org/) 00005 * 00006 * This file is part of PixelLight. 00007 * 00008 * PixelLight is free software: you can redistribute it and/or modify 00009 * it under the terms of the GNU Lesser General Public License as published by 00010 * the Free Software Foundation, either version 3 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * PixelLight is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public License 00019 * along with PixelLight. If not, see <http://www.gnu.org/licenses/>. 00020 \*********************************************************/ 00021 00022 00023 #ifndef __PLMATH_MATRIX4X4_H__ 00024 #define __PLMATH_MATRIX4X4_H__ 00025 #pragma once 00026 00027 00028 //[-------------------------------------------------------] 00029 //[ Includes ] 00030 //[-------------------------------------------------------] 00031 #include "PLMath/Vector2.h" 00032 #include "PLMath/Vector4.h" 00033 00034 00035 //[-------------------------------------------------------] 00036 //[ Namespace ] 00037 //[-------------------------------------------------------] 00038 namespace PLMath { 00039 00040 00041 //[-------------------------------------------------------] 00042 //[ Forward declarations ] 00043 //[-------------------------------------------------------] 00044 class Plane; 00045 00046 00047 //[-------------------------------------------------------] 00048 //[ Classes ] 00049 //[-------------------------------------------------------] 00050 /** 00051 * @brief 00052 * 4x4 matrix 00053 * 00054 * @remarks 00055 * Matrices are stored in column major order like OpenGL does. (right-handed matrix) 00056 * So, it's possible to give OpenGL the matrix data without transposing it first. 00057 * 00058 * @note 00059 * - Some symbols within the comments: T = transposed, I = identity 00060 */ 00061 class Matrix4x4 { 00062 00063 00064 //[-------------------------------------------------------] 00065 //[ Public static data ] 00066 //[-------------------------------------------------------] 00067 public: 00068 static PLMATH_API const Matrix4x4 Zero; /**< Zero matrix */ 00069 static PLMATH_API const Matrix4x4 Identity; /**< Identity matrix */ 00070 00071 00072 //[-------------------------------------------------------] 00073 //[ Public data ] 00074 //[-------------------------------------------------------] 00075 public: 00076 /** 00077 * @brief 00078 * Some direct matrix accesses 00079 */ 00080 union { 00081 /** 00082 * @brief 00083 * One dimensional array representation 00084 * 00085 * @remarks 00086 * The entry of the matrix in row r (0 <= r <= 3) and column c (0 <= c <= 3) is 00087 * stored at index i = r+4*c (0 <= i <= 15).\n 00088 * Indices: 00089 * @code 00090 * | 0 4 8 12 | 00091 * | 1 5 9 13 | 00092 * | 2 6 10 14 | 00093 * | 3 7 11 15 | 00094 * @endcode 00095 */ 00096 float fM[16]; 00097 00098 /** 00099 * @brief 00100 * Direct element representation 00101 * 00102 * @remarks 00103 * Indices: (row/column) 00104 * @code 00105 * | xx xy xz xw | 00106 * | yx yy yz yw | 00107 * | zx zy zz zw | 00108 * | wx wy wz ww | 00109 * @endcode 00110 * It's recommended to use this way to access the elements. 00111 */ 00112 struct { 00113 float xx, yx, zx, wx; 00114 float xy, yy, zy, wy; 00115 float xz, yz, zz, wz; 00116 float xw, yw, zw, ww; 00117 }; 00118 00119 /** 00120 * @brief 00121 * Two dimensional array representation 00122 * 00123 * @remarks 00124 * fM44[i][j] -> i=column, j=row\n 00125 * Try to avoid this access mode. This can be a problem on a platform/console that 00126 * chooses to store the data in column-major rather than row-major format. 00127 */ 00128 struct { 00129 float fM44[4][4]; 00130 }; 00131 }; 00132 00133 00134 //[-------------------------------------------------------] 00135 //[ Public functions ] 00136 //[-------------------------------------------------------] 00137 public: 00138 //[-------------------------------------------------------] 00139 //[ Constructor ] 00140 //[-------------------------------------------------------] 00141 /** 00142 * @brief 00143 * Default constructor setting an identity matrix 00144 */ 00145 inline Matrix4x4(); 00146 00147 inline Matrix4x4(const float fS[]); 00148 PLMATH_API Matrix4x4(const Matrix3x3 &mM); 00149 PLMATH_API Matrix4x4(const Matrix3x4 &mM); 00150 inline Matrix4x4(const Matrix4x4 &mM); 00151 inline Matrix4x4(float fXX, float fXY, float fXZ, float fXW, 00152 float fYX, float fYY, float fYZ, float fYW, 00153 float fZX, float fZY, float fZZ, float fZW, 00154 float fWX, float fWY, float fWZ, float fWW); 00155 00156 //[-------------------------------------------------------] 00157 //[ Destructor ] 00158 //[-------------------------------------------------------] 00159 inline ~Matrix4x4(); 00160 00161 //[-------------------------------------------------------] 00162 //[ Comparison ] 00163 //[-------------------------------------------------------] 00164 /** 3x4: The last row is compared with (0, 0, 0, 1) */ 00165 PLMATH_API bool operator ==(const Matrix3x4 &mM) const; 00166 PLMATH_API bool operator ==(const Matrix4x4 &mM) const; 00167 /** 3x4: The last row is compared with (0, 0, 0, 1) */ 00168 PLMATH_API bool operator !=(const Matrix3x4 &mM) const; 00169 PLMATH_API bool operator !=(const Matrix4x4 &mM) const; 00170 // fEpsilon = epsilon environment (to take computation errors into account...) 00171 PLMATH_API bool CompareScale(const Matrix4x4 &mM, float fEpsilon = Math::Epsilon) const; 00172 PLMATH_API bool CompareTranslation(const Matrix4x4 &mM, float fEpsilon = Math::Epsilon) const; 00173 PLMATH_API bool CompareRotation(const Matrix4x4 &mM, float fEpsilon = Math::Epsilon) const; 00174 00175 //[-------------------------------------------------------] 00176 //[ Operators ] 00177 //[-------------------------------------------------------] 00178 inline Matrix4x4 &operator =(const float fS[]); 00179 PLMATH_API Matrix4x4 &operator =(const Matrix3x3 &mM); 00180 PLMATH_API Matrix4x4 &operator =(const Matrix3x4 &mM); 00181 inline Matrix4x4 &operator =(const Matrix4x4 &mM); 00182 inline Matrix4x4 operator +(const Matrix4x4 &mM) const; 00183 inline void operator +=(const Matrix4x4 &mM); 00184 inline Matrix4x4 operator -() const; 00185 inline Matrix4x4 operator -(const Matrix4x4 &mM) const; 00186 inline void operator -=(const Matrix4x4 &mM); 00187 inline Matrix4x4 operator *(float fS) const; 00188 inline void operator *=(float fS); 00189 inline Vector2 operator *(const Vector2 &vV) const; 00190 inline Vector3 operator *(const Vector3 &vV) const; 00191 inline Vector4 operator *(const Vector4 &vV) const; 00192 /** A 4x4*3x4 matrix multiplication is NOT defined, so we use the given 3x4 matrix with 00193 a fourth row (0, 0, 0, 1) which result in a 4x4*4x4 matrix multiplication which is 00194 allowed */ 00195 PLMATH_API Matrix4x4 operator *(const Matrix3x4 &mM) const; 00196 PLMATH_API Matrix4x4 operator *(const Matrix4x4 &mM) const; 00197 /** @see - *(const Matrix3x4 &mM) */ 00198 inline void operator *=(const Matrix3x4 &mM); 00199 inline void operator *=(const Matrix4x4 &mM); 00200 inline Matrix4x4 operator /(float fS) const; 00201 inline void operator /=(float fS); 00202 inline float operator [](int nIndex) const; 00203 inline float &operator [](int nIndex); 00204 inline float operator ()(PLCore::uint32 nRow = 0, PLCore::uint32 nColumn = 0) const; 00205 inline float &operator ()(PLCore::uint32 nRow = 0, PLCore::uint32 nColumn = 0); 00206 inline operator float *(); 00207 inline operator const float *() const; 00208 00209 //[-------------------------------------------------------] 00210 //[ Matrix operations ] 00211 //[-------------------------------------------------------] 00212 /** 00213 * @brief 00214 * Returns whether or not this matrix is the zero matrix using an epsilon environment 00215 * 00216 * @return 00217 * 'true' if this matrix is the zero matrix, else 'false' 00218 */ 00219 inline bool IsZero() const; 00220 00221 /** 00222 * @brief 00223 * Returns whether or not this matrix is truly the zero matrix 00224 * 00225 * @remarks 00226 * All components MUST be exactly 0. Floating point inaccuracy 00227 * is not taken into account. 00228 * 00229 * @return 00230 * 'true' if this matrix is truly the zero matrix, else 'false' 00231 */ 00232 inline bool IsTrueZero() const; 00233 00234 /** 00235 * @brief 00236 * Sets a zero matrix 00237 * 00238 * @remarks 00239 * @code 00240 * | 0 0 0 0 | 00241 * | 0 0 0 0 | 00242 * | 0 0 0 0 | 00243 * | 0 0 0 0 | 00244 * @endcode 00245 */ 00246 inline void SetZero(); 00247 00248 /** 00249 * @brief 00250 * Returns whether or not this matrix is the identity matrix using an epsilon environment 00251 * 00252 * @return 00253 * 'true' if this matrix is the identity matrix, else 'false' 00254 */ 00255 inline bool IsIdentity() const; 00256 00257 /** 00258 * @brief 00259 * Returns whether or not this matrix is truly the identity matrix 00260 * 00261 * @remarks 00262 * All components MUST be exactly either 0 or 1. Floating point inaccuracy 00263 * is not taken into account. 00264 * 00265 * @return 00266 * 'true' if this matrix is truly the identity matrix, else 'false' 00267 */ 00268 inline bool IsTrueIdentity() const; 00269 00270 /** 00271 * @brief 00272 * Sets an identity matrix 00273 * 00274 * @remarks 00275 * @code 00276 * | 1 0 0 0 | 00277 * | 0 1 0 0 | 00278 * | 0 0 1 0 | 00279 * | 0 0 0 1 | 00280 * @endcode 00281 */ 00282 inline void SetIdentity(); 00283 00284 /** 00285 * @brief 00286 * Sets the elements of the matrix 00287 */ 00288 PLMATH_API void Set(float fXX, float fXY, float fXZ, float fXW, 00289 float fYX, float fYY, float fYZ, float fYW, 00290 float fZX, float fZY, float fZZ, float fZW, 00291 float fWX, float fWY, float fWZ, float fWW); 00292 00293 /** 00294 * @brief 00295 * Returns a requested row 00296 * 00297 * @param[in] nRow 00298 * Index of the row to return (0-3) 00299 * 00300 * @return 00301 * The requested row (null vector on error) 00302 * 00303 * @remarks 00304 * @code 00305 * | x y z w | <- Row 0 00306 * | 0 0 0 0 | 00307 * | 0 0 0 0 | 00308 * | 0 0 0 0 | 00309 * @endcode 00310 */ 00311 inline Vector4 GetRow(PLCore::uint8 nRow) const; 00312 00313 /** 00314 * @brief 00315 * Sets a row 00316 * 00317 * @param[in] nRow 00318 * Index of the row to set (0-3) 00319 * @param[in] vRow 00320 * Row vector 00321 * 00322 * @see 00323 * - GetRow() 00324 */ 00325 inline void SetRow(PLCore::uint8 nRow, const Vector4 &vRow); 00326 00327 /** 00328 * @brief 00329 * Returns a requested column 00330 * 00331 * @param[in] nColumn 00332 * Index of the column to return (0-3) 00333 * 00334 * @return 00335 * The requested column (null vector on error) 00336 * 00337 * @remarks 00338 * @code 00339 * | x 0 0 0 | 00340 * | y 0 0 0 | 00341 * | z 0 0 0 | 00342 * | w 0 0 0 | 00343 * ^ 00344 * | 00345 * Column 0 00346 * @endcode 00347 */ 00348 inline Vector4 GetColumn(PLCore::uint8 nColumn) const; 00349 00350 /** 00351 * @brief 00352 * Sets a column 00353 * 00354 * @param[in] nColumn 00355 * Index of the column to set (0-3) 00356 * @param[in] vColumn 00357 * Column vector 00358 * 00359 * @see 00360 * - GetColumn() 00361 */ 00362 inline void SetColumn(PLCore::uint8 nColumn, const Vector4 &vColumn); 00363 00364 /** 00365 * @brief 00366 * Returns true if the matrix is symmetric 00367 * 00368 * @return 00369 * 'true' if the matrix is symmetric, else 'false' 00370 * 00371 * @remarks 00372 * A matrix is symmetric if it is equal to it's transposed matrix.\n 00373 * A = A^T -> a(i, j) = a(j, i) 00374 */ 00375 inline bool IsSymmetric() const; 00376 00377 /** 00378 * @brief 00379 * Returns true if this matrix is orthogonal 00380 * 00381 * @return 00382 * 'true' if the matrix is orthogonal, else 'false' 00383 * 00384 * @remarks 00385 * A matrix is orthogonal if it's transposed matrix is equal to it's inversed matrix.\n 00386 * A^T = A^-1 or A*A^T = A^T*A = I 00387 * 00388 * @note 00389 * - An orthogonal matrix is always nonsingular (invertible) and it's inverse is equal to it's transposed 00390 * - The transpose and inverse of the matrix is orthogonal, too 00391 * - Products of orthogonal matrices are orthogonal, too 00392 * - The determinant of a orthogonal matrix is +/- 1 00393 * - The row and column vectors of an orthogonal matrix form an orthonormal basis, 00394 * that is, these vectors are unit-length and they are mutually perpendicular 00395 */ 00396 inline bool IsOrthogonal() const; 00397 00398 /** 00399 * @brief 00400 * Returns true if this matrix is a rotation matrix 00401 * 00402 * @return 00403 * 'true' if this matrix is a rotation matrix, else 'false' 00404 * 00405 * @remarks 00406 * A rotation matrix is orthogonal and it's determinant is 1 to rule out reflections. 00407 * 00408 * @see 00409 * - IsOrthogonal() 00410 */ 00411 inline bool IsRotationMatrix() const; 00412 00413 /** 00414 * @brief 00415 * Returns true if this matrix is a rotation and translation matrix 00416 * 00417 * @return 00418 * 'true' if this matrix is a rotation and translation matrix, else 'false' 00419 * 00420 * @remarks 00421 * A rotation and translation matrix looks like this: 00422 * @code 00423 * | x x x x | 00424 * | x x x x | 00425 * | x x x x | 00426 * | 0 0 0 1 | 00427 * @endcode 00428 * Were 'x' means this field is used and as you see the last row must be empty. 00429 * 00430 * @see 00431 * - IsRotationMatrix() 00432 */ 00433 inline bool IsRotationTranslationMatrix() const; 00434 00435 /** 00436 * @brief 00437 * Returns the trace of the matrix 00438 * 00439 * @return 00440 * The trace of the matrix 00441 * 00442 * @remarks 00443 * The trace of the matrix is the sum of the main diagonal elements:\n 00444 * xx+yy+zz+ww 00445 */ 00446 inline float GetTrace() const; 00447 00448 /** 00449 * @brief 00450 * Returns the determinant of the matrix 00451 * 00452 * @return 00453 * Determinant of the matrix 00454 * 00455 * @note 00456 * - If the determinant is non-zero, then an inverse matrix exists 00457 * - If the determinant is 0, the matrix is called singular, else nonsingular (invertible) matrix 00458 * - If the determinant is 1, the inverse matrix is equal to the transpose of the matrix 00459 */ 00460 PLMATH_API float GetDeterminant() const; 00461 00462 /** 00463 * @brief 00464 * Transpose this matrix 00465 * 00466 * @remarks 00467 * The transpose of matrix is the matrix generated when every element in 00468 * the matrix is swapped with the opposite relative to the major diagonal 00469 * This can be expressed as the mathematical operation: 00470 * @code 00471 * M' = M 00472 * ij ji 00473 * 00474 * | xx xy xz xw | | xx yx zx wx | 00475 * | yx yy yz yw | the transpose is | xy yy zy wy | 00476 * | zx zy zz zw | | xz yz zz wz | 00477 * | wx wy wz ww | | xw yw zw ww | 00478 * @endcode 00479 * 00480 * @note 00481 * - If the matrix is a rotation matrix (= isotropic matrix = determinant is 1), 00482 * then the transpose is guaranteed to be the inverse of the matrix 00483 */ 00484 PLMATH_API void Transpose(); 00485 00486 /** 00487 * @brief 00488 * Returns the transposed matrix 00489 * 00490 * @return 00491 * Transposed matrix 00492 * 00493 * @see 00494 * - Transpose() 00495 */ 00496 PLMATH_API Matrix4x4 GetTransposed() const; 00497 00498 /** 00499 * @brief 00500 * Inverts the matrix 00501 * 00502 * @return 00503 * 'true' if all went fine, else 'false' (maybe the determinant is null?) 00504 * 00505 * @note 00506 * - If the determinant is 1, the inversed matrix is equal to the transposed one 00507 */ 00508 PLMATH_API bool Invert(); 00509 00510 /** 00511 * @brief 00512 * Returns the inverse of the matrix 00513 * 00514 * @return 00515 * Inverse of the matrix, if the determinant is null, an identity matrix is returned 00516 */ 00517 PLMATH_API Matrix4x4 GetInverted() const; 00518 00519 /** 00520 * @brief 00521 * Rotates a vector 00522 * 00523 * @param[in] fX 00524 * X component of the vector to rotate 00525 * @param[in] fY 00526 * Y component of the vector to rotate 00527 * @param[in] fZ 00528 * Z component of the vector to rotate 00529 * @param[in] bUniformScale 00530 * Is this a uniform scale matrix? (all axis are scaled equally) 00531 * If you know EXACTLY it's one, set this to 'true' to gain some more speed, else DON'T set to 'true'! 00532 * 00533 * @return 00534 * The rotated vector 00535 * 00536 * @remarks 00537 * This function is similar to a matrix * vector operation - except that the 00538 * translation of the matrix is ignored and this function can deal with none 00539 * uniform scale. So, this function can for instance be used to rotate a 00540 * direction vector. (matrix * direction vector) 00541 * 00542 * @note 00543 * - You can't assume that the resulting vector is normalized 00544 * - Use this function to rotate for example a normal vector 00545 */ 00546 PLMATH_API Vector3 RotateVector(float fX, float fY, float fZ, bool bUniformScale = false) const; 00547 00548 /** 00549 * @brief 00550 * Rotates a vector 00551 * 00552 * @param[in] vV 00553 * Vector to rotate 00554 * @param[in] bUniformScale 00555 * Is this a uniform scale matrix? (all axis are scaled equally) 00556 * If you know EXACTLY it's one, set this to 'true' to gain some more speed, else DON'T set to 'true'! 00557 * 00558 * @return 00559 * The rotated vector 00560 * 00561 * @see 00562 * - RotateVector(float, float, float) above 00563 */ 00564 PLMATH_API Vector3 RotateVector(const Vector3 &vV, bool bUniformScale = false) const; 00565 00566 //[-------------------------------------------------------] 00567 //[ Scale ] 00568 //[-------------------------------------------------------] 00569 /** 00570 * @brief 00571 * Sets a scale matrix 00572 * 00573 * @param[in] fX 00574 * X scale 00575 * @param[in] fY 00576 * Y scale 00577 * @param[in] fZ 00578 * Z scale 00579 * 00580 * @remarks 00581 * @code 00582 * | x 0 0 0 | 00583 * | 0 y 0 0 | 00584 * | 0 0 z 0 | 00585 * | 0 0 0 1 | 00586 * @endcode 00587 */ 00588 inline void SetScaleMatrix(float fX, float fY, float fZ); 00589 inline void SetScaleMatrix(const Vector3 &vV); 00590 00591 /** 00592 * @brief 00593 * Extracts the scale vector from the matrix as good as possible 00594 * 00595 * @param[out] fX 00596 * Receives the x scale 00597 * @param[out] fY 00598 * Receives the y scale 00599 * @param[out] fZ 00600 * Receives the z scale 00601 * 00602 * @note 00603 * - This function will not work correctly if one or two components are negative while 00604 * another is/are not (we can't figure out WHICH axis are negative!) 00605 */ 00606 PLMATH_API void GetScale(float &fX, float &fY, float &fZ) const; 00607 inline Vector3 GetScale() const; 00608 inline void GetScale(float fV[]) const; 00609 00610 //[-------------------------------------------------------] 00611 //[ Translation ] 00612 //[-------------------------------------------------------] 00613 /** 00614 * @brief 00615 * Sets a translation matrix 00616 * 00617 * @param[in] fX 00618 * X translation 00619 * @param[in] fY 00620 * Y translation 00621 * @param[in] fZ 00622 * Z translation 00623 * 00624 * @remarks 00625 * @code 00626 * | 1 0 0 x | 00627 * | 0 1 0 y | 00628 * | 0 0 1 z | 00629 * | 0 0 0 1 | 00630 * @endcode 00631 */ 00632 inline void SetTranslationMatrix(float fX, float fY, float fZ); 00633 inline void SetTranslationMatrix(const Vector3 &vV); 00634 00635 // Get and set 00636 inline void GetTranslation(float &fX, float &fY, float &fZ) const; 00637 inline Vector3 GetTranslation() const; 00638 inline void GetTranslation(float fV[]) const; 00639 inline void SetTranslation(float fX = 0.0f, float fY = 0.0f, float fZ = 0.0f); 00640 inline void SetTranslation(const Vector3 &vV); 00641 inline void SetTranslation(const float fV[]); 00642 00643 //[-------------------------------------------------------] 00644 //[ Rotation ] 00645 //[-------------------------------------------------------] 00646 /** 00647 * @brief 00648 * Sets an x axis rotation matrix by using one given Euler angle 00649 * 00650 * @param[in] fAngleX 00651 * Rotation angle around the x axis (in radian, between [0, Math::Pi2]) 00652 * 00653 * @remarks 00654 * @code 00655 * | 1 0 0 0 | 00656 * RX = | 0 cos(a) -sin(a) 0 | 00657 * | 0 sin(a) cos(a) 0 | 00658 * | 0 0 0 1 | 00659 * @endcode 00660 * where a > 0 indicates a counterclockwise rotation in the yz-plane (if you look along -x) 00661 */ 00662 PLMATH_API void FromEulerAngleX(float fAngleX); 00663 00664 /** 00665 * @brief 00666 * Sets an y axis rotation matrix by using one given Euler angle 00667 * 00668 * @param[in] fAngleY 00669 * Rotation angle around the y axis (in radian, between [0, Math::Pi2]) 00670 * 00671 * @remarks 00672 * @code 00673 * | cos(a) 0 sin(a) 0 | 00674 * RY = | 0 1 0 0 | 00675 * | -sin(a) 0 cos(a) 0 | 00676 * | 0 0 0 1 | 00677 * @endcode 00678 * where a > 0 indicates a counterclockwise rotation in the zx-plane (if you look along -y) 00679 */ 00680 PLMATH_API void FromEulerAngleY(float fAngleY); 00681 00682 /** 00683 * @brief 00684 * Sets an z axis rotation matrix by using one given Euler angle 00685 * 00686 * @param[in] fAngleZ 00687 * Rotation angle around the z axis (in radian, between [0, Math::Pi2]) 00688 * 00689 * @remarks 00690 * @code 00691 * | cos(a) -sin(a) 0 0 | 00692 * RZ = | sin(a) cos(a) 0 0 | 00693 * | 0 0 1 0 | 00694 * | 0 0 0 1 | 00695 * @endcode 00696 * where a > 0 indicates a counterclockwise rotation in the xy-plane (if you look along -z) 00697 */ 00698 PLMATH_API void FromEulerAngleZ(float fAngleZ); 00699 00700 /** 00701 * @brief 00702 * Returns a rotation matrix as a selected axis and angle 00703 * 00704 * @param[out] fX 00705 * Will receive the x component of the selected axis 00706 * @param[out] fY 00707 * Will receive the y component of the selected axis 00708 * @param[out] fZ 00709 * Will receive the z component of the selected axis 00710 * @param[out] fAngle 00711 * Will receive the rotation angle around the selected axis (in radian, between [0, Math::Pi]) 00712 */ 00713 PLMATH_API void ToAxisAngle(float &fX, float &fY, float &fZ, float &fAngle) const; 00714 00715 /** 00716 * @brief 00717 * Sets a rotation matrix by using a selected axis and angle 00718 * 00719 * @param[in] fX 00720 * X component of the selected axis 00721 * @param[in] fY 00722 * Y component of the selected axis 00723 * @param[in] fZ 00724 * Z component of the selected axis 00725 * @param[in] fAngle 00726 * Rotation angle around the selected axis (in radian, between [0, Math::Pi]) 00727 * 00728 * @note 00729 * - The given selected axis must be normalized! 00730 */ 00731 PLMATH_API void FromAxisAngle(float fX, float fY, float fZ, float fAngle); 00732 00733 /** 00734 * @brief 00735 * Returns the x (left) axis 00736 * 00737 * @return 00738 * The x (left) axis 00739 * 00740 * @remarks 00741 * @code 00742 * | x 0 0 0 | 00743 * | y 0 0 0 | 00744 * | z 0 0 0 | 00745 * | 0 0 0 1 | 00746 * @endcode 00747 * 00748 * @note 00749 * - It's possible that the axis vector is not normalized because for instance 00750 * the matrix was scaled 00751 */ 00752 inline Vector3 GetXAxis() const; 00753 00754 /** 00755 * @brief 00756 * Returns the y (up) axis 00757 * 00758 * @return 00759 * The y (up) axis 00760 * 00761 * @remarks 00762 * @code 00763 * | 0 x 0 0 | 00764 * | 0 y 0 0 | 00765 * | 0 z 0 0 | 00766 * | 0 0 0 1 | 00767 * @endcode 00768 * 00769 * @see 00770 * - GetXAxis() 00771 */ 00772 inline Vector3 GetYAxis() const; 00773 00774 /** 00775 * @brief 00776 * Returns the z (forward) axis 00777 * 00778 * @return 00779 * The z (forward) axis 00780 * 00781 * @remarks 00782 * @code 00783 * | 0 0 x 0 | 00784 * | 0 0 y 0 | 00785 * | 0 0 z 0 | 00786 * | 0 0 0 1 | 00787 * @endcode 00788 * 00789 * @see 00790 * - GetXAxis() 00791 */ 00792 inline Vector3 GetZAxis() const; 00793 00794 /** 00795 * @brief 00796 * Returns the three axis of a rotation matrix (not normalized) 00797 * 00798 * @param[out] vX 00799 * Will receive the x axis 00800 * @param[out] vY 00801 * Will receive the y axis 00802 * @param[out] vZ 00803 * Will receive the z axis 00804 * 00805 * @remarks 00806 * @code 00807 * | vX.x vY.x vZ.x 0 | 00808 * | vX.y vY.y vZ.y 0 | 00809 * | vX.z vY.z vZ.z 0 | 00810 * | 0 0 0 1 | 00811 * @endcode 00812 */ 00813 PLMATH_API void ToAxis(Vector3 &vX, Vector3 &vY, Vector3 &vZ) const; 00814 00815 /** 00816 * @brief 00817 * Sets a rotation matrix by using three given axis 00818 * 00819 * @param[in] vX 00820 * X axis 00821 * @param[in] vY 00822 * Y axis 00823 * @param[in] vZ 00824 * Z axis 00825 * 00826 * @see 00827 * - ToAxis() 00828 */ 00829 PLMATH_API void FromAxis(const Vector3 &vX, const Vector3 &vY, const Vector3 &vZ); 00830 00831 /** 00832 * @brief 00833 * Builds a look-at matrix 00834 * 00835 * @param[in] vEye 00836 * Eye position 00837 * @param[in] vAt 00838 * Camera look-at target 00839 * @param[in] vUp 00840 * Current world's up, usually [0, 1, 0] 00841 * 00842 * @return 00843 * This instance 00844 */ 00845 PLMATH_API Matrix4x4 &LookAt(const Vector3 &vEye, const Vector3 &vAt, const Vector3 &vUp); 00846 00847 /** 00848 * @brief 00849 * Builds a view matrix 00850 * 00851 * @param[in] qRotation 00852 * Rotation quaternion 00853 * @param[in] vPosition 00854 * Position vector 00855 * 00856 * @return 00857 * This instance 00858 * 00859 * @remarks 00860 * @code 00861 * | RotT.xx RotT.xy RotT.xz T.x | 00862 * | RotT.yx RotT.yy RotT.yz T.y | 00863 * | RotT.zx RotT.zy RotT.zz T.z | 00864 * | 0 0 0 1 | 00865 * @endcode 00866 * 00867 * RotT = Transposed(Rot) 00868 * T = -(Transposed(Rot) * Pos) 00869 */ 00870 PLMATH_API Matrix4x4 &View(const Quaternion &qRotation, const Vector3 &vPosition); 00871 00872 //[-------------------------------------------------------] 00873 //[ Misc ] 00874 //[-------------------------------------------------------] 00875 /** 00876 * @brief 00877 * Sets a matrix using a given quaternion and translation 00878 * 00879 * @param[in] qRotation 00880 * Rotation quaternion 00881 * @param[in] vTranslation 00882 * Translation vector 00883 * 00884 * @return 00885 * This instance 00886 * 00887 * @remarks 00888 * First this function is using Quaternion::ToRotationMatrix() to create a rotation matrix. 00889 * Then the translation components are set. (Matrix4x4::SetTranslation()) 00890 */ 00891 PLMATH_API Matrix4x4 &FromQuatTrans(const Quaternion &qRotation, const Vector3 &vTranslation); 00892 00893 /** 00894 * @brief 00895 * Sets a shearing matrix 00896 * 00897 * @param[in] fShearXY 00898 * Shear X by Y 00899 * @param[in] fShearXZ 00900 * Shear X by Z 00901 * @param[in] fShearYX 00902 * Shear Y by X 00903 * @param[in] fShearYZ 00904 * Shear Y by Z 00905 * @param[in] fShearZX 00906 * Shear Z by X 00907 * @param[in] fShearZY 00908 * Shear Z by Y 00909 * 00910 * @return 00911 * This instance 00912 * 00913 * @remarks 00914 * A shearing matrix can be used to for instance make a 3D model appear to slant 00915 * sideways. Here's a table showing how a combined shearing matrix looks like: 00916 * @code 00917 * | 1 fShearYX fShearZX 0 | 00918 * | fShearXY 1 fShearZY 0 | 00919 * | fShearXZ fShearYZ 1 0 | 00920 * | 0 0 0 1 | 00921 * @endcode 00922 * If you only want to shear one axis it's recommended to construct the matrix by yourself. 00923 */ 00924 inline Matrix4x4 &SetShearing(float fShearXY, float fShearXZ, float fShearYX, float fShearYZ, 00925 float fShearZX, float fShearZY); 00926 00927 /** 00928 * @brief 00929 * Sets a matrix that reflects the coordinate system about a plane 00930 * 00931 * @param[in] cPlane 00932 * Reflection plane (must be normalized!) 00933 * 00934 * @return 00935 * This instance 00936 * 00937 * @remarks 00938 * @code 00939 * | -2*cPlane.a*cPlane.a+1 -2*cPlane.a*cPlane.b -2*cPlane.a*cPlane.c -2*cPlane.a*cPlane.d | 00940 * | -2*cPlane.b*cPlane.a -2*cPlane.b*cPlane.b+1 -2*cPlane.b*cPlane.c -2*cPlane.b*cPlane.d | 00941 * | -2*cPlane.c*cPlane.a -2*cPlane.c*cPlane.b -2*cPlane.c*cPlane.c+1 -2*cPlane.c*cPlane.d | 00942 * | 0 0 0 1 | 00943 * @endcode 00944 */ 00945 PLMATH_API Matrix4x4 &SetReflection(const Plane &cPlane); 00946 00947 /** 00948 * @brief 00949 * Sets a shadow projection matrix 00950 * 00951 * @param[in] vLight 00952 * Light source position (if the light is directional, the w value should be 0) 00953 * @param[in] cPlane 00954 * Plane where to project the shadow onto 00955 * 00956 * @return 00957 * This instance 00958 * 00959 * @remarks 00960 * @code 00961 * | fDot-vLight.x*cPlane.a -vLight.x*cPlane.b -vLight.x*cPlane.c -vLight.x*cPlane.d | 00962 * | -vLight.y*cPlane.a fDot-vLight.y*cPlane.b -vLight.y*cPlane.c -vLight.y*cPlane.d | 00963 * | -vLight.z*cPlane.a -vLight.z*cPlane.b fDot-vLight.z*cPlane.c -vLight.z*cPlane.d | 00964 * | -vLight.w*cPlane.a -vLight.w*cPlane.b -vLight.w*cPlane.c fDot-vLight.w*cPlane.d | 00965 * 00966 * where: 00967 * float fDot = cPlane.a*vLight.x + cPlane.b*vLight.y + cPlane.c*vLight.z + cPlane.d*vLight.w; 00968 * @endcode 00969 */ 00970 PLMATH_API Matrix4x4 &SetShadowProjection(const Vector4 &vLight, const Plane &cPlane); 00971 00972 /** 00973 * @brief 00974 * Creates a projection matrix that restricts drawing to a small region of the given viewport 00975 * 00976 * @param[in] vStartPos 00977 * Region start position 00978 * @param[in] vEndPos 00979 * Region end position 00980 * @param[in] nX 00981 * X component of the pixel coordinate of the upper-left corner of the viewport 00982 * @param[in] nY 00983 * Y component of the pixel coordinate of the upper-left corner of the viewport 00984 * @param[in] nWidth 00985 * Width of the clip volume, in pixels 00986 * @param[in] nHeight 00987 * Height of the clip volume, in pixels 00988 * 00989 * @note 00990 * - The start and end positions are within the given viewport 00991 * - Multiply this projection matrix with our standard projection matrix to get a restricted version 00992 */ 00993 PLMATH_API void RestrictedProjection(const Vector2 &vStartPos, const Vector2 &vEndPos, 00994 int nX, int nY, int nWidth, int nHeight); 00995 00996 /** 00997 * @brief 00998 * Builds a perspective projection matrix 00999 * 01000 * @param[in] fWidth 01001 * Width of the view volume at the near view-plane 01002 * @param[in] fHeight 01003 * Height of the view volume at the near view-plane 01004 * @param[in] fZNear 01005 * Z-value of the near view-plane (always positive) 01006 * @param[in] fZFar 01007 * Z-value of the far view-plane (always positive) 01008 * 01009 * @return 01010 * This instance 01011 * 01012 * @remarks 01013 * @code 01014 * | 2*fZNear/fWidth 0 0 0 | 01015 * | 0 2*fZNear/fHeight 0 0 | 01016 * | 0 0 fZFar/(fZNear-fZFar) fZNear*fZFar/(fZNear-fZFar) | 01017 * | 0 0 -1 0 | 01018 * @endcode 01019 */ 01020 PLMATH_API Matrix4x4 &Perspective(float fWidth, float fHeight, float fZNear, float fZFar); 01021 01022 /** 01023 * @brief 01024 * Builds a perspective projection matrix based on a field of view 01025 * 01026 * @param[in] fFov 01027 * The field of view angle in the y direction (in radian) 01028 * @param[in] fAspect 01029 * The aspect ratio that determines the field of view in the x-direction 01030 * The aspect ratio is the ratio of x (width) to y (height) (width/height) 01031 * @param[in] fZNear 01032 * The distance from the viewer to the near clipping plane (always positive) 01033 * @param[in] fZFar 01034 * The distance from the viewer to the far clipping plane (always positive) 01035 * 01036 * @return 01037 * This instance 01038 * 01039 * @remarks 01040 * @code 01041 * | e/fAspect 0 0 0 | 01042 * | 0 e 0 0 | 01043 * | 0 0 (fZFar+fZNear)/(fZNear-fZFar) (2*fZNear*fZFar)/(fZNear-fZFar) | 01044 * | 0 0 -1 0 | 01045 * 01046 * where: 01047 * float e = 1/tanf(fFov/2); // Focal length 01048 * @endcode 01049 */ 01050 PLMATH_API Matrix4x4 &PerspectiveFov(float fFov, float fAspect, float fZNear, float fZFar); 01051 01052 /** 01053 * @brief 01054 * Builds an infinite perspective projection matrix 01055 * 01056 * @param[in] fWidth 01057 * Width of the view volume at the near view-plane 01058 * @param[in] fHeight 01059 * Height of the view volume at the near view-plane 01060 * @param[in] fZNear 01061 * Z-value of the near view-plane (always positive) 01062 * 01063 * @return 01064 * This instance 01065 * 01066 * @remarks 01067 * @code 01068 * | 2*fZNear/fWidth 0 0 0 | 01069 * | 0 2*fZNear/fHeight 0 0 | 01070 * | 0 0 -1 -2*fZNear | 01071 * | 0 0 -1 0 | 01072 * @endcode 01073 */ 01074 PLMATH_API Matrix4x4 &PerspectiveInfinite(float fWidth, float fHeight, float fZNear); 01075 01076 /** 01077 * @brief 01078 * Builds an infinite perspective projection matrix based on a field of view 01079 * 01080 * @param[in] fFov 01081 * The field of view angle in the y direction (in radian) 01082 * @param[in] fAspect 01083 * The aspect ratio that determines the field of view in the x-direction 01084 * The aspect ratio is the ratio of x (width) to y (height) (width/height) 01085 * @param[in] fZNear 01086 * The distance from the viewer to the near clipping plane (always positive) 01087 * 01088 * @return 01089 * This instance 01090 * 01091 * @remarks 01092 * @code 01093 * | e/fAspect 0 0 0 | 01094 * | 0 e 0 0 | 01095 * | 0 0 -1 -2*fZNear | 01096 * | 0 0 -1 0 | 01097 * 01098 * where: 01099 * float e = 1/tanf(fFov/2); // Focal length 01100 * @endcode 01101 */ 01102 PLMATH_API Matrix4x4 &PerspectiveFovInfinite(float fFov, float fAspect, float fZNear); 01103 01104 /** 01105 * @brief 01106 * Builds a customized, perspective projection matrix 01107 * 01108 * @param[in] fL 01109 * Minimum x-value of view volume 01110 * @param[in] fR 01111 * Maximum x-value of view volume 01112 * @param[in] fT 01113 * Maximum y-value of view volume 01114 * @param[in] fB 01115 * Minimum y-value of view volume 01116 * @param[in] fZNear 01117 * Minimum z-value of the view volume 01118 * @param[in] fZFar 01119 * Maximum z-value of the view volume 01120 * 01121 * @remarks 01122 * @code 01123 * | 2*fZNear/(fR-fL) 0 (fL+fR)/(fR-fL) 0 | 01124 * | 0 2*fZNear/(fT-fB) (fT+fB)/(fT-fB) 0 | 01125 * | 0 0 fZFar/(fZNear-fZFar) fZNear*fZFar/(fZNear-fZFar) | 01126 * | 0 0 -1 0 | 01127 * @endcode 01128 * 01129 * @return 01130 * This instance 01131 */ 01132 PLMATH_API Matrix4x4 &PerspectiveOffCenter(float fL, float fR, float fB, float fT, float fZNear, float fZFar); 01133 01134 /** 01135 * @brief 01136 * Builds a orthogonal projection matrix 01137 * 01138 * @param[in] fWidth 01139 * Width of the view volume 01140 * @param[in] fHeight 01141 * Height of the view volume 01142 * @param[in] fZNear 01143 * Minimum z-value of the view volume 01144 * @param[in] fZFar 01145 * Maximum z-value of the view volume 01146 * 01147 * @return 01148 * This instance 01149 * 01150 * @remarks 01151 * @code 01152 * | 2/fWidth 0 0 0 | 01153 * | 0 2/fHeight 0 0 | 01154 * | 0 0 1/(fZNear-fZFar) fZNear/(fZNear-fZFar) | 01155 * | 0 0 0 1 | 01156 * @endcode 01157 * 01158 * @note 01159 * - An orthogonal matrix is an invertible matrix for which the inverse of the matrix 01160 * is equal to the transpose of the matrix 01161 */ 01162 PLMATH_API Matrix4x4 &Ortho(float fWidth, float fHeight, float fZNear, float fZFar); 01163 01164 /** 01165 * @brief 01166 * Builds a customized, orthogonal projection matrix 01167 * 01168 * @param[in] fL 01169 * Minimum x-value of view volume 01170 * @param[in] fR 01171 * Maximum x-value of view volume 01172 * @param[in] fT 01173 * Maximum y-value of view volume 01174 * @param[in] fB 01175 * Minimum y-value of view volume 01176 * @param[in] fZNear 01177 * Minimum z-value of the view volume 01178 * @param[in] fZFar 01179 * Maximum z-value of the view volume 01180 * 01181 * @return 01182 * This instance 01183 * 01184 * @remarks 01185 * @code 01186 * | 2/(fR-fL) 0 0 (fL+fR)/(fL-fR) | 01187 * | 0 2/(fT-fB) 0 (fT+fB)/(fB-fT) | 01188 * | 0 0 1/(fZNear-fZFar) fZNear/(fZNear-fZFar) | 01189 * | 0 0 0 1 | 01190 * @endcode 01191 * 01192 * @note 01193 * - An orthogonal matrix is an invertible matrix for which the inverse of the matrix 01194 * is equal to the transpose of the matrix 01195 */ 01196 PLMATH_API Matrix4x4 &OrthoOffCenter(float fL, float fR, float fT, float fB, float fZNear, float fZFar); 01197 01198 01199 }; 01200 01201 01202 //[-------------------------------------------------------] 01203 //[ Namespace ] 01204 //[-------------------------------------------------------] 01205 } // PLMath 01206 01207 01208 //[-------------------------------------------------------] 01209 //[ Implementation ] 01210 //[-------------------------------------------------------] 01211 #include "PLMath/Matrix4x4.inl" 01212 01213 01214 #endif // __PLMATH_MATRIX4X4_H__
|