Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1009 lines
32 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. //
  9. // VMatrix always postmultiply vectors as in Ax = b.
  10. // Given a set of basis vectors ((F)orward, (L)eft, (U)p), and a (T)ranslation,
  11. // a matrix to transform a vector into that space looks like this:
  12. // Fx Lx Ux Tx
  13. // Fy Ly Uy Ty
  14. // Fz Lz Uz Tz
  15. // 0 0 0 1
  16. // Note that concatenating matrices needs to multiply them in reverse order.
  17. // ie: if I want to apply matrix A, B, then C, the equation needs to look like this:
  18. // C * B * A * v
  19. // ie:
  20. // v = A * v;
  21. // v = B * v;
  22. // v = C * v;
  23. //=============================================================================
  24. #ifndef VMATRIX_H
  25. #define VMATRIX_H
  26. #ifdef _WIN32
  27. #pragma once
  28. #endif
  29. #include <string.h>
  30. #include "mathlib/vector.h"
  31. #include "mathlib/vplane.h"
  32. #include "mathlib/vector4d.h"
  33. #include "mathlib/mathlib.h"
  34. struct cplane_t;
  35. class VMatrix
  36. {
  37. public:
  38. VMatrix();
  39. VMatrix(
  40. vec_t m00, vec_t m01, vec_t m02, vec_t m03,
  41. vec_t m10, vec_t m11, vec_t m12, vec_t m13,
  42. vec_t m20, vec_t m21, vec_t m22, vec_t m23,
  43. vec_t m30, vec_t m31, vec_t m32, vec_t m33
  44. );
  45. // Creates a matrix where the X axis = forward
  46. // the Y axis = left, and the Z axis = up
  47. VMatrix( const Vector& forward, const Vector& left, const Vector& up );
  48. // Construct from a 3x4 matrix
  49. explicit VMatrix( const matrix3x4_t& matrix3x4 );
  50. // Set the values in the matrix.
  51. void Init(
  52. vec_t m00, vec_t m01, vec_t m02, vec_t m03,
  53. vec_t m10, vec_t m11, vec_t m12, vec_t m13,
  54. vec_t m20, vec_t m21, vec_t m22, vec_t m23,
  55. vec_t m30, vec_t m31, vec_t m32, vec_t m33
  56. );
  57. // Initialize from a 3x4
  58. void Init( const matrix3x4_t& matrix3x4 );
  59. // array access
  60. inline float* operator[](int i)
  61. {
  62. return m[i];
  63. }
  64. inline const float* operator[](int i) const
  65. {
  66. return m[i];
  67. }
  68. // Get a pointer to m[0][0]
  69. inline float *Base()
  70. {
  71. return &m[0][0];
  72. }
  73. inline const float *Base() const
  74. {
  75. return &m[0][0];
  76. }
  77. void SetLeft(const Vector &vLeft);
  78. void SetUp(const Vector &vUp);
  79. void SetForward(const Vector &vForward);
  80. void GetBasisVectors(Vector &vForward, Vector &vLeft, Vector &vUp) const;
  81. void SetBasisVectors(const Vector &vForward, const Vector &vLeft, const Vector &vUp);
  82. // Get/set the translation.
  83. Vector & GetTranslation( Vector &vTrans ) const;
  84. void SetTranslation(const Vector &vTrans);
  85. void PreTranslate(const Vector &vTrans);
  86. void PostTranslate(const Vector &vTrans);
  87. matrix3x4_t& As3x4();
  88. const matrix3x4_t& As3x4() const;
  89. void CopyFrom3x4( const matrix3x4_t &m3x4 );
  90. void Set3x4( matrix3x4_t& matrix3x4 ) const;
  91. bool operator==( const VMatrix& src ) const;
  92. bool operator!=( const VMatrix& src ) const { return !( *this == src ); }
  93. #ifndef VECTOR_NO_SLOW_OPERATIONS
  94. // Access the basis vectors.
  95. Vector GetLeft() const;
  96. Vector GetUp() const;
  97. Vector GetForward() const;
  98. Vector GetTranslation() const;
  99. #endif
  100. // Matrix->vector operations.
  101. public:
  102. // Multiply by a 3D vector (same as operator*).
  103. void V3Mul(const Vector &vIn, Vector &vOut) const;
  104. // Multiply by a 4D vector.
  105. void V4Mul(const Vector4D &vIn, Vector4D &vOut) const;
  106. #ifndef VECTOR_NO_SLOW_OPERATIONS
  107. // Applies the rotation (ignores translation in the matrix). (This just calls VMul3x3).
  108. Vector ApplyRotation(const Vector &vVec) const;
  109. // Multiply by a vector (divides by w, assumes input w is 1).
  110. Vector operator*(const Vector &vVec) const;
  111. // Multiply by the upper 3x3 part of the matrix (ie: only apply rotation).
  112. Vector VMul3x3(const Vector &vVec) const;
  113. // Apply the inverse (transposed) rotation (only works on pure rotation matrix)
  114. Vector VMul3x3Transpose(const Vector &vVec) const;
  115. // Multiply by the upper 3 rows.
  116. Vector VMul4x3(const Vector &vVec) const;
  117. // Apply the inverse (transposed) transformation (only works on pure rotation/translation)
  118. Vector VMul4x3Transpose(const Vector &vVec) const;
  119. #endif
  120. // Matrix->plane operations.
  121. public:
  122. // Transform the plane. The matrix can only contain translation and rotation.
  123. void TransformPlane( const VPlane &inPlane, VPlane &outPlane ) const;
  124. #ifndef VECTOR_NO_SLOW_OPERATIONS
  125. // Just calls TransformPlane and returns the result.
  126. VPlane operator*(const VPlane &thePlane) const;
  127. #endif
  128. // Matrix->matrix operations.
  129. public:
  130. VMatrix& operator=(const VMatrix &mOther);
  131. // Multiply two matrices (out = this * vm).
  132. void MatrixMul( const VMatrix &vm, VMatrix &out ) const;
  133. // Add two matrices.
  134. const VMatrix& operator+=(const VMatrix &other);
  135. #ifndef VECTOR_NO_SLOW_OPERATIONS
  136. // Just calls MatrixMul and returns the result.
  137. VMatrix operator*(const VMatrix &mOther) const;
  138. // Add/Subtract two matrices.
  139. VMatrix operator+(const VMatrix &other) const;
  140. VMatrix operator-(const VMatrix &other) const;
  141. // Negation.
  142. VMatrix operator-() const;
  143. // Return inverse matrix. Be careful because the results are undefined
  144. // if the matrix doesn't have an inverse (ie: InverseGeneral returns false).
  145. VMatrix operator~() const;
  146. #endif
  147. // Matrix operations.
  148. public:
  149. // Set to identity.
  150. void Identity();
  151. bool IsIdentity() const;
  152. // Setup a matrix for origin and angles.
  153. void SetupMatrixOrgAngles( const Vector &origin, const QAngle &vAngles );
  154. // General inverse. This may fail so check the return!
  155. bool InverseGeneral(VMatrix &vInverse) const;
  156. // Does a fast inverse, assuming the matrix only contains translation and rotation.
  157. void InverseTR( VMatrix &mRet ) const;
  158. // Usually used for debug checks. Returns true if the upper 3x3 contains
  159. // unit vectors and they are all orthogonal.
  160. bool IsRotationMatrix() const;
  161. #ifndef VECTOR_NO_SLOW_OPERATIONS
  162. // This calls the other InverseTR and returns the result.
  163. VMatrix InverseTR() const;
  164. // Get the scale of the matrix's basis vectors.
  165. Vector GetScale() const;
  166. // (Fast) multiply by a scaling matrix setup from vScale.
  167. VMatrix Scale(const Vector &vScale);
  168. // Normalize the basis vectors.
  169. VMatrix NormalizeBasisVectors() const;
  170. // Transpose.
  171. VMatrix Transpose() const;
  172. // Transpose upper-left 3x3.
  173. VMatrix Transpose3x3() const;
  174. #endif
  175. public:
  176. // The matrix.
  177. vec_t m[4][4];
  178. };
  179. //-----------------------------------------------------------------------------
  180. // Helper functions.
  181. //-----------------------------------------------------------------------------
  182. #ifndef VECTOR_NO_SLOW_OPERATIONS
  183. // Setup an identity matrix.
  184. VMatrix SetupMatrixIdentity();
  185. // Setup as a scaling matrix.
  186. VMatrix SetupMatrixScale(const Vector &vScale);
  187. // Setup a translation matrix.
  188. VMatrix SetupMatrixTranslation(const Vector &vTranslation);
  189. // Setup a matrix to reflect around the plane.
  190. VMatrix SetupMatrixReflection(const VPlane &thePlane);
  191. // Setup a matrix to project from vOrigin onto thePlane.
  192. VMatrix SetupMatrixProjection(const Vector &vOrigin, const VPlane &thePlane);
  193. // Setup a matrix to rotate the specified amount around the specified axis.
  194. VMatrix SetupMatrixAxisRot(const Vector &vAxis, vec_t fDegrees);
  195. // Setup a matrix to rotate one axis onto another. Input vectors must be normalized.
  196. VMatrix SetupMatrixAxisToAxisRot(const Vector &vFromAxis, const Vector &vToAxis);
  197. // Setup a matrix from euler angles. Just sets identity and calls MatrixAngles.
  198. VMatrix SetupMatrixAngles(const QAngle &vAngles);
  199. // Setup a matrix for origin and angles.
  200. VMatrix SetupMatrixOrgAngles(const Vector &origin, const QAngle &vAngles);
  201. #endif
  202. #define VMatToString(mat) (static_cast<const char *>(CFmtStr("[ (%f, %f, %f), (%f, %f, %f), (%f, %f, %f), (%f, %f, %f) ]", mat.m[0][0], mat.m[0][1], mat.m[0][2], mat.m[0][3], mat.m[1][0], mat.m[1][1], mat.m[1][2], mat.m[1][3], mat.m[2][0], mat.m[2][1], mat.m[2][2], mat.m[2][3], mat.m[3][0], mat.m[3][1], mat.m[3][2], mat.m[3][3] ))) // ** Note: this generates a temporary, don't hold reference!
  203. //-----------------------------------------------------------------------------
  204. // Returns the point at the intersection on the 3 planes.
  205. // Returns false if it can't be solved (2 or more planes are parallel).
  206. //-----------------------------------------------------------------------------
  207. bool PlaneIntersection( const VPlane &vp1, const VPlane &vp2, const VPlane &vp3, Vector &vOut );
  208. //-----------------------------------------------------------------------------
  209. // These methods are faster. Use them if you want faster code
  210. //-----------------------------------------------------------------------------
  211. void MatrixSetIdentity( VMatrix &dst );
  212. void MatrixTranspose( const VMatrix& src, VMatrix& dst );
  213. void MatrixCopy( const VMatrix& src, VMatrix& dst );
  214. void MatrixMultiply( const VMatrix& src1, const VMatrix& src2, VMatrix& dst );
  215. // Accessors
  216. void MatrixGetColumn( const VMatrix &src, int nCol, Vector *pColumn );
  217. void MatrixSetColumn( VMatrix &src, int nCol, const Vector &column );
  218. void MatrixGetRow( const VMatrix &src, int nCol, Vector *pColumn );
  219. void MatrixSetRow( VMatrix &src, int nCol, const Vector &column );
  220. // Vector3DMultiply treats src2 as if it's a direction vector
  221. void Vector3DMultiply( const VMatrix& src1, const Vector& src2, Vector& dst );
  222. // Vector3DMultiplyPosition treats src2 as if it's a point (adds the translation)
  223. inline void Vector3DMultiplyPosition( const VMatrix& src1, const VectorByValue src2, Vector& dst );
  224. // Vector3DMultiplyPositionProjective treats src2 as if it's a point
  225. // and does the perspective divide at the end
  226. void Vector3DMultiplyPositionProjective( const VMatrix& src1, const Vector &src2, Vector& dst );
  227. // Vector3DMultiplyPosition treats src2 as if it's a direction
  228. // and does the perspective divide at the end
  229. // NOTE: src1 had better be an inverse transpose to use this correctly
  230. void Vector3DMultiplyProjective( const VMatrix& src1, const Vector &src2, Vector& dst );
  231. void Vector4DMultiply( const VMatrix& src1, const Vector4D& src2, Vector4D& dst );
  232. // Same as Vector4DMultiply except that src2 has an implicit W of 1
  233. void Vector4DMultiplyPosition( const VMatrix& src1, const Vector &src2, Vector4D& dst );
  234. // Multiplies the vector by the transpose of the matrix
  235. void Vector3DMultiplyTranspose( const VMatrix& src1, const Vector& src2, Vector& dst );
  236. void Vector4DMultiplyTranspose( const VMatrix& src1, const Vector4D& src2, Vector4D& dst );
  237. // Transform a plane
  238. void MatrixTransformPlane( const VMatrix &src, const cplane_t &inPlane, cplane_t &outPlane );
  239. // Transform a plane that has an axis-aligned normal
  240. void MatrixTransformAxisAlignedPlane( const VMatrix &src, int nDim, float flSign, float flDist, cplane_t &outPlane );
  241. void MatrixBuildTranslation( VMatrix& dst, float x, float y, float z );
  242. void MatrixBuildTranslation( VMatrix& dst, const Vector &translation );
  243. inline void MatrixTranslate( VMatrix& dst, const Vector &translation )
  244. {
  245. VMatrix matTranslation, temp;
  246. MatrixBuildTranslation( matTranslation, translation );
  247. MatrixMultiply( dst, matTranslation, temp );
  248. dst = temp;
  249. }
  250. void MatrixBuildRotationAboutAxis( VMatrix& dst, const Vector& vAxisOfRot, float angleDegrees );
  251. void MatrixBuildRotateZ( VMatrix& dst, float angleDegrees );
  252. inline void MatrixRotate( VMatrix& dst, const Vector& vAxisOfRot, float angleDegrees )
  253. {
  254. VMatrix rotation, temp;
  255. MatrixBuildRotationAboutAxis( rotation, vAxisOfRot, angleDegrees );
  256. MatrixMultiply( dst, rotation, temp );
  257. dst = temp;
  258. }
  259. // Builds a rotation matrix that rotates one direction vector into another
  260. void MatrixBuildRotation( VMatrix &dst, const Vector& initialDirection, const Vector& finalDirection );
  261. // Builds a scale matrix
  262. void MatrixBuildScale( VMatrix &dst, float x, float y, float z );
  263. void MatrixBuildScale( VMatrix &dst, const Vector& scale );
  264. // Build a perspective matrix.
  265. // zNear and zFar are assumed to be positive.
  266. // You end up looking down positive Z, X is to the right, Y is up.
  267. // X range: [0..1]
  268. // Y range: [0..1]
  269. // Z range: [0..1]
  270. void MatrixBuildPerspective( VMatrix &dst, float fovX, float fovY, float zNear, float zFar );
  271. //-----------------------------------------------------------------------------
  272. // Given a projection matrix, take the extremes of the space in transformed into world space and
  273. // get a bounding box.
  274. //-----------------------------------------------------------------------------
  275. void CalculateAABBFromProjectionMatrix( const VMatrix &worldToVolume, Vector *pMins, Vector *pMaxs );
  276. //-----------------------------------------------------------------------------
  277. // Given a projection matrix, take the extremes of the space in transformed into world space and
  278. // get a bounding sphere.
  279. //-----------------------------------------------------------------------------
  280. void CalculateSphereFromProjectionMatrix( const VMatrix &worldToVolume, Vector *pCenter, float *pflRadius );
  281. //-----------------------------------------------------------------------------
  282. // Given an inverse projection matrix, take the extremes of the space in transformed into world space and
  283. // get a bounding box.
  284. //-----------------------------------------------------------------------------
  285. void CalculateAABBFromProjectionMatrixInverse( const VMatrix &volumeToWorld, Vector *pMins, Vector *pMaxs );
  286. //-----------------------------------------------------------------------------
  287. // Given an inverse projection matrix, take the extremes of the space in transformed into world space and
  288. // get a bounding sphere.
  289. //-----------------------------------------------------------------------------
  290. void CalculateSphereFromProjectionMatrixInverse( const VMatrix &volumeToWorld, Vector *pCenter, float *pflRadius );
  291. //-----------------------------------------------------------------------------
  292. // Calculate frustum planes given a clip->world space transform.
  293. //-----------------------------------------------------------------------------
  294. void FrustumPlanesFromMatrix( const VMatrix &clipToWorld, Frustum_t &frustum );
  295. //-----------------------------------------------------------------------------
  296. // Setup a matrix from euler angles.
  297. //-----------------------------------------------------------------------------
  298. void MatrixFromAngles( const QAngle& vAngles, VMatrix& dst );
  299. //-----------------------------------------------------------------------------
  300. // Creates euler angles from a matrix
  301. //-----------------------------------------------------------------------------
  302. void MatrixToAngles( const VMatrix& src, QAngle& vAngles );
  303. //-----------------------------------------------------------------------------
  304. // Does a fast inverse, assuming the matrix only contains translation and rotation.
  305. //-----------------------------------------------------------------------------
  306. void MatrixInverseTR( const VMatrix& src, VMatrix &dst );
  307. //-----------------------------------------------------------------------------
  308. // Inverts any matrix at all
  309. //-----------------------------------------------------------------------------
  310. bool MatrixInverseGeneral(const VMatrix& src, VMatrix& dst);
  311. //-----------------------------------------------------------------------------
  312. // Computes the inverse transpose
  313. //-----------------------------------------------------------------------------
  314. void MatrixInverseTranspose( const VMatrix& src, VMatrix& dst );
  315. //-----------------------------------------------------------------------------
  316. // VMatrix inlines.
  317. //-----------------------------------------------------------------------------
  318. inline VMatrix::VMatrix()
  319. {
  320. }
  321. inline VMatrix::VMatrix(
  322. vec_t m00, vec_t m01, vec_t m02, vec_t m03,
  323. vec_t m10, vec_t m11, vec_t m12, vec_t m13,
  324. vec_t m20, vec_t m21, vec_t m22, vec_t m23,
  325. vec_t m30, vec_t m31, vec_t m32, vec_t m33)
  326. {
  327. Init(
  328. m00, m01, m02, m03,
  329. m10, m11, m12, m13,
  330. m20, m21, m22, m23,
  331. m30, m31, m32, m33
  332. );
  333. }
  334. inline VMatrix::VMatrix( const matrix3x4_t& matrix3x4 )
  335. {
  336. Init( matrix3x4 );
  337. }
  338. //-----------------------------------------------------------------------------
  339. // Creates a matrix where the X axis = forward
  340. // the Y axis = left, and the Z axis = up
  341. //-----------------------------------------------------------------------------
  342. inline VMatrix::VMatrix( const Vector& xAxis, const Vector& yAxis, const Vector& zAxis )
  343. {
  344. Init(
  345. xAxis.x, yAxis.x, zAxis.x, 0.0f,
  346. xAxis.y, yAxis.y, zAxis.y, 0.0f,
  347. xAxis.z, yAxis.z, zAxis.z, 0.0f,
  348. 0.0f, 0.0f, 0.0f, 1.0f
  349. );
  350. }
  351. inline void VMatrix::Init(
  352. vec_t m00, vec_t m01, vec_t m02, vec_t m03,
  353. vec_t m10, vec_t m11, vec_t m12, vec_t m13,
  354. vec_t m20, vec_t m21, vec_t m22, vec_t m23,
  355. vec_t m30, vec_t m31, vec_t m32, vec_t m33
  356. )
  357. {
  358. m[0][0] = m00;
  359. m[0][1] = m01;
  360. m[0][2] = m02;
  361. m[0][3] = m03;
  362. m[1][0] = m10;
  363. m[1][1] = m11;
  364. m[1][2] = m12;
  365. m[1][3] = m13;
  366. m[2][0] = m20;
  367. m[2][1] = m21;
  368. m[2][2] = m22;
  369. m[2][3] = m23;
  370. m[3][0] = m30;
  371. m[3][1] = m31;
  372. m[3][2] = m32;
  373. m[3][3] = m33;
  374. }
  375. //-----------------------------------------------------------------------------
  376. // Initialize from a 3x4
  377. //-----------------------------------------------------------------------------
  378. inline void VMatrix::Init( const matrix3x4_t& matrix3x4 )
  379. {
  380. memcpy(m, matrix3x4.Base(), sizeof( matrix3x4_t ) );
  381. m[3][0] = 0.0f;
  382. m[3][1] = 0.0f;
  383. m[3][2] = 0.0f;
  384. m[3][3] = 1.0f;
  385. }
  386. //-----------------------------------------------------------------------------
  387. // Methods related to the basis vectors of the matrix
  388. //-----------------------------------------------------------------------------
  389. #ifndef VECTOR_NO_SLOW_OPERATIONS
  390. inline Vector VMatrix::GetForward() const
  391. {
  392. return Vector(m[0][0], m[1][0], m[2][0]);
  393. }
  394. inline Vector VMatrix::GetLeft() const
  395. {
  396. return Vector(m[0][1], m[1][1], m[2][1]);
  397. }
  398. inline Vector VMatrix::GetUp() const
  399. {
  400. return Vector(m[0][2], m[1][2], m[2][2]);
  401. }
  402. #endif
  403. inline void VMatrix::SetForward(const Vector &vForward)
  404. {
  405. m[0][0] = vForward.x;
  406. m[1][0] = vForward.y;
  407. m[2][0] = vForward.z;
  408. }
  409. inline void VMatrix::SetLeft(const Vector &vLeft)
  410. {
  411. m[0][1] = vLeft.x;
  412. m[1][1] = vLeft.y;
  413. m[2][1] = vLeft.z;
  414. }
  415. inline void VMatrix::SetUp(const Vector &vUp)
  416. {
  417. m[0][2] = vUp.x;
  418. m[1][2] = vUp.y;
  419. m[2][2] = vUp.z;
  420. }
  421. inline void VMatrix::GetBasisVectors(Vector &vForward, Vector &vLeft, Vector &vUp) const
  422. {
  423. vForward.Init( m[0][0], m[1][0], m[2][0] );
  424. vLeft.Init( m[0][1], m[1][1], m[2][1] );
  425. vUp.Init( m[0][2], m[1][2], m[2][2] );
  426. }
  427. inline void VMatrix::SetBasisVectors(const Vector &vForward, const Vector &vLeft, const Vector &vUp)
  428. {
  429. SetForward(vForward);
  430. SetLeft(vLeft);
  431. SetUp(vUp);
  432. }
  433. //-----------------------------------------------------------------------------
  434. // Methods related to the translation component of the matrix
  435. //-----------------------------------------------------------------------------
  436. #ifndef VECTOR_NO_SLOW_OPERATIONS
  437. inline Vector VMatrix::GetTranslation() const
  438. {
  439. return Vector(m[0][3], m[1][3], m[2][3]);
  440. }
  441. #endif
  442. inline Vector& VMatrix::GetTranslation( Vector &vTrans ) const
  443. {
  444. vTrans.x = m[0][3];
  445. vTrans.y = m[1][3];
  446. vTrans.z = m[2][3];
  447. return vTrans;
  448. }
  449. inline void VMatrix::SetTranslation(const Vector &vTrans)
  450. {
  451. m[0][3] = vTrans.x;
  452. m[1][3] = vTrans.y;
  453. m[2][3] = vTrans.z;
  454. }
  455. //-----------------------------------------------------------------------------
  456. // appply translation to this matrix in the input space
  457. //-----------------------------------------------------------------------------
  458. inline void VMatrix::PreTranslate(const Vector &vTrans)
  459. {
  460. Vector tmp;
  461. Vector3DMultiplyPosition( *this, vTrans, tmp );
  462. m[0][3] = tmp.x;
  463. m[1][3] = tmp.y;
  464. m[2][3] = tmp.z;
  465. }
  466. //-----------------------------------------------------------------------------
  467. // appply translation to this matrix in the output space
  468. //-----------------------------------------------------------------------------
  469. inline void VMatrix::PostTranslate(const Vector &vTrans)
  470. {
  471. m[0][3] += vTrans.x;
  472. m[1][3] += vTrans.y;
  473. m[2][3] += vTrans.z;
  474. }
  475. inline const matrix3x4_t& VMatrix::As3x4() const
  476. {
  477. return *((const matrix3x4_t*)this);
  478. }
  479. inline matrix3x4_t& VMatrix::As3x4()
  480. {
  481. return *((matrix3x4_t*)this);
  482. }
  483. inline void VMatrix::CopyFrom3x4( const matrix3x4_t &m3x4 )
  484. {
  485. memcpy( m, m3x4.Base(), sizeof( matrix3x4_t ) );
  486. m[3][0] = m[3][1] = m[3][2] = 0;
  487. m[3][3] = 1;
  488. }
  489. inline void VMatrix::Set3x4( matrix3x4_t& matrix3x4 ) const
  490. {
  491. memcpy(matrix3x4.Base(), m, sizeof( matrix3x4_t ) );
  492. }
  493. //-----------------------------------------------------------------------------
  494. // Matrix math operations
  495. //-----------------------------------------------------------------------------
  496. inline const VMatrix& VMatrix::operator+=(const VMatrix &other)
  497. {
  498. for(int i=0; i < 4; i++)
  499. {
  500. for(int j=0; j < 4; j++)
  501. {
  502. m[i][j] += other.m[i][j];
  503. }
  504. }
  505. return *this;
  506. }
  507. #ifndef VECTOR_NO_SLOW_OPERATIONS
  508. inline VMatrix VMatrix::operator+(const VMatrix &other) const
  509. {
  510. VMatrix ret;
  511. for(int i=0; i < 16; i++)
  512. {
  513. ((float*)ret.m)[i] = ((float*)m)[i] + ((float*)other.m)[i];
  514. }
  515. return ret;
  516. }
  517. inline VMatrix VMatrix::operator-(const VMatrix &other) const
  518. {
  519. VMatrix ret;
  520. for(int i=0; i < 4; i++)
  521. {
  522. for(int j=0; j < 4; j++)
  523. {
  524. ret.m[i][j] = m[i][j] - other.m[i][j];
  525. }
  526. }
  527. return ret;
  528. }
  529. inline VMatrix VMatrix::operator-() const
  530. {
  531. VMatrix ret;
  532. for( int i=0; i < 16; i++ )
  533. {
  534. ((float*)ret.m)[i] = -((float*)m)[i];
  535. }
  536. return ret;
  537. }
  538. #endif // VECTOR_NO_SLOW_OPERATIONS
  539. //-----------------------------------------------------------------------------
  540. // Vector transformation
  541. //-----------------------------------------------------------------------------
  542. #ifndef VECTOR_NO_SLOW_OPERATIONS
  543. inline Vector VMatrix::operator*(const Vector &vVec) const
  544. {
  545. Vector vRet;
  546. vRet.x = m[0][0]*vVec.x + m[0][1]*vVec.y + m[0][2]*vVec.z + m[0][3];
  547. vRet.y = m[1][0]*vVec.x + m[1][1]*vVec.y + m[1][2]*vVec.z + m[1][3];
  548. vRet.z = m[2][0]*vVec.x + m[2][1]*vVec.y + m[2][2]*vVec.z + m[2][3];
  549. return vRet;
  550. }
  551. inline Vector VMatrix::VMul4x3(const Vector &vVec) const
  552. {
  553. Vector vResult;
  554. Vector3DMultiplyPosition( *this, vVec, vResult );
  555. return vResult;
  556. }
  557. inline Vector VMatrix::VMul4x3Transpose(const Vector &vVec) const
  558. {
  559. Vector tmp = vVec;
  560. tmp.x -= m[0][3];
  561. tmp.y -= m[1][3];
  562. tmp.z -= m[2][3];
  563. return Vector(
  564. m[0][0]*tmp.x + m[1][0]*tmp.y + m[2][0]*tmp.z,
  565. m[0][1]*tmp.x + m[1][1]*tmp.y + m[2][1]*tmp.z,
  566. m[0][2]*tmp.x + m[1][2]*tmp.y + m[2][2]*tmp.z
  567. );
  568. }
  569. inline Vector VMatrix::VMul3x3(const Vector &vVec) const
  570. {
  571. return Vector(
  572. m[0][0]*vVec.x + m[0][1]*vVec.y + m[0][2]*vVec.z,
  573. m[1][0]*vVec.x + m[1][1]*vVec.y + m[1][2]*vVec.z,
  574. m[2][0]*vVec.x + m[2][1]*vVec.y + m[2][2]*vVec.z
  575. );
  576. }
  577. inline Vector VMatrix::VMul3x3Transpose(const Vector &vVec) const
  578. {
  579. return Vector(
  580. m[0][0]*vVec.x + m[1][0]*vVec.y + m[2][0]*vVec.z,
  581. m[0][1]*vVec.x + m[1][1]*vVec.y + m[2][1]*vVec.z,
  582. m[0][2]*vVec.x + m[1][2]*vVec.y + m[2][2]*vVec.z
  583. );
  584. }
  585. #endif // VECTOR_NO_SLOW_OPERATIONS
  586. inline void VMatrix::V3Mul(const Vector &vIn, Vector &vOut) const
  587. {
  588. vec_t rw;
  589. rw = 1.0f / (m[3][0]*vIn.x + m[3][1]*vIn.y + m[3][2]*vIn.z + m[3][3]);
  590. vOut.x = (m[0][0]*vIn.x + m[0][1]*vIn.y + m[0][2]*vIn.z + m[0][3]) * rw;
  591. vOut.y = (m[1][0]*vIn.x + m[1][1]*vIn.y + m[1][2]*vIn.z + m[1][3]) * rw;
  592. vOut.z = (m[2][0]*vIn.x + m[2][1]*vIn.y + m[2][2]*vIn.z + m[2][3]) * rw;
  593. }
  594. inline void VMatrix::V4Mul(const Vector4D &vIn, Vector4D &vOut) const
  595. {
  596. vOut[0] = m[0][0]*vIn[0] + m[0][1]*vIn[1] + m[0][2]*vIn[2] + m[0][3]*vIn[3];
  597. vOut[1] = m[1][0]*vIn[0] + m[1][1]*vIn[1] + m[1][2]*vIn[2] + m[1][3]*vIn[3];
  598. vOut[2] = m[2][0]*vIn[0] + m[2][1]*vIn[1] + m[2][2]*vIn[2] + m[2][3]*vIn[3];
  599. vOut[3] = m[3][0]*vIn[0] + m[3][1]*vIn[1] + m[3][2]*vIn[2] + m[3][3]*vIn[3];
  600. }
  601. //-----------------------------------------------------------------------------
  602. // Plane transformation
  603. //-----------------------------------------------------------------------------
  604. inline void VMatrix::TransformPlane( const VPlane &inPlane, VPlane &outPlane ) const
  605. {
  606. Vector vTrans;
  607. Vector3DMultiply( *this, inPlane.m_Normal, outPlane.m_Normal );
  608. outPlane.m_Dist = inPlane.m_Dist * DotProduct( outPlane.m_Normal, outPlane.m_Normal );
  609. outPlane.m_Dist += DotProduct( outPlane.m_Normal, GetTranslation( vTrans ) );
  610. }
  611. //-----------------------------------------------------------------------------
  612. // Other random stuff
  613. //-----------------------------------------------------------------------------
  614. inline void VMatrix::Identity()
  615. {
  616. MatrixSetIdentity( *this );
  617. }
  618. inline bool VMatrix::IsIdentity() const
  619. {
  620. return
  621. m[0][0] == 1.0f && m[0][1] == 0.0f && m[0][2] == 0.0f && m[0][3] == 0.0f &&
  622. m[1][0] == 0.0f && m[1][1] == 1.0f && m[1][2] == 0.0f && m[1][3] == 0.0f &&
  623. m[2][0] == 0.0f && m[2][1] == 0.0f && m[2][2] == 1.0f && m[2][3] == 0.0f &&
  624. m[3][0] == 0.0f && m[3][1] == 0.0f && m[3][2] == 0.0f && m[3][3] == 1.0f;
  625. }
  626. #ifndef VECTOR_NO_SLOW_OPERATIONS
  627. inline Vector VMatrix::ApplyRotation(const Vector &vVec) const
  628. {
  629. return VMul3x3(vVec);
  630. }
  631. inline VMatrix VMatrix::operator~() const
  632. {
  633. VMatrix mRet;
  634. InverseGeneral(mRet);
  635. return mRet;
  636. }
  637. #endif
  638. //-----------------------------------------------------------------------------
  639. // Accessors
  640. //-----------------------------------------------------------------------------
  641. inline void MatrixGetColumn( const VMatrix &src, int nCol, Vector *pColumn )
  642. {
  643. Assert( (nCol >= 0) && (nCol <= 3) );
  644. pColumn->x = src[0][nCol];
  645. pColumn->y = src[1][nCol];
  646. pColumn->z = src[2][nCol];
  647. }
  648. inline void MatrixSetColumn( VMatrix &src, int nCol, const Vector &column )
  649. {
  650. Assert( (nCol >= 0) && (nCol <= 3) );
  651. src.m[0][nCol] = column.x;
  652. src.m[1][nCol] = column.y;
  653. src.m[2][nCol] = column.z;
  654. }
  655. inline void MatrixGetRow( const VMatrix &src, int nRow, Vector *pRow )
  656. {
  657. Assert( (nRow >= 0) && (nRow <= 3) );
  658. *pRow = *(Vector*)src[nRow];
  659. }
  660. inline void MatrixSetRow( VMatrix &dst, int nRow, const Vector &row )
  661. {
  662. Assert( (nRow >= 0) && (nRow <= 3) );
  663. *(Vector*)dst[nRow] = row;
  664. }
  665. //-----------------------------------------------------------------------------
  666. // Vector3DMultiplyPosition treats src2 as if it's a point (adds the translation)
  667. //-----------------------------------------------------------------------------
  668. // NJS: src2 is passed in as a full vector rather than a reference to prevent the need
  669. // for 2 branches and a potential copy in the body. (ie, handling the case when the src2
  670. // reference is the same as the dst reference ).
  671. inline void Vector3DMultiplyPosition( const VMatrix& src1, const VectorByValue src2, Vector& dst )
  672. {
  673. dst[0] = src1[0][0] * src2.x + src1[0][1] * src2.y + src1[0][2] * src2.z + src1[0][3];
  674. dst[1] = src1[1][0] * src2.x + src1[1][1] * src2.y + src1[1][2] * src2.z + src1[1][3];
  675. dst[2] = src1[2][0] * src2.x + src1[2][1] * src2.y + src1[2][2] * src2.z + src1[2][3];
  676. }
  677. //-----------------------------------------------------------------------------
  678. // Transform a plane that has an axis-aligned normal
  679. //-----------------------------------------------------------------------------
  680. inline void MatrixTransformAxisAlignedPlane( const VMatrix &src, int nDim, float flSign, float flDist, cplane_t &outPlane )
  681. {
  682. // See MatrixTransformPlane in the .cpp file for an explanation of the algorithm.
  683. MatrixGetColumn( src, nDim, &outPlane.normal );
  684. outPlane.normal *= flSign;
  685. outPlane.dist = flDist * DotProduct( outPlane.normal, outPlane.normal );
  686. // NOTE: Writing this out by hand because it doesn't inline (inline depth isn't large enough)
  687. // This should read outPlane.dist += DotProduct( outPlane.normal, src.GetTranslation );
  688. outPlane.dist += outPlane.normal.x * src.m[0][3] + outPlane.normal.y * src.m[1][3] + outPlane.normal.z * src.m[2][3];
  689. }
  690. //-----------------------------------------------------------------------------
  691. // Matrix equality test
  692. //-----------------------------------------------------------------------------
  693. inline bool MatricesAreEqual( const VMatrix &src1, const VMatrix &src2, float flTolerance )
  694. {
  695. for ( int i = 0; i < 3; ++i )
  696. {
  697. for ( int j = 0; j < 3; ++j )
  698. {
  699. if ( fabs( src1[i][j] - src2[i][j] ) > flTolerance )
  700. return false;
  701. }
  702. }
  703. return true;
  704. }
  705. //-----------------------------------------------------------------------------
  706. //
  707. //-----------------------------------------------------------------------------
  708. void MatrixBuildOrtho( VMatrix& dst, double left, double top, double right, double bottom, double zNear, double zFar );
  709. void MatrixBuildOrthoLH( VMatrix& dst, double left, double top, double right, double bottom, double zNear, double zFar );
  710. void MatrixBuildPerspectiveX( VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar );
  711. void MatrixBuildPerspectiveOffCenterX( VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar, double bottom, double top, double left, double right );
  712. inline void MatrixOrtho( VMatrix& dst, double left, double top, double right, double bottom, double zNear, double zFar )
  713. {
  714. VMatrix mat;
  715. MatrixBuildOrtho( mat, left, top, right, bottom, zNear, zFar );
  716. VMatrix temp;
  717. MatrixMultiply( dst, mat, temp );
  718. dst = temp;
  719. }
  720. inline void MatrixBuildOrthoLH( VMatrix& dst, double left, double top, double right, double bottom, double zNear, double zFar )
  721. {
  722. // Same as XMMatrixOrthographicOffCenterLH().
  723. dst.Init(
  724. 2.0f / ( right - left ), 0.0f, 0.0f, ( left + right ) / ( left - right ),
  725. 0.0f, 2.0f / ( bottom - top ), 0.0f, ( bottom + top ) / ( top - bottom ),
  726. 0.0f, 0.0f, 1.0f / ( zFar - zNear ), zNear / ( zNear - zFar ),
  727. 0.0f, 0.0f, 0.0f, 1.0f );
  728. }
  729. inline void MatrixPerspectiveX( VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar )
  730. {
  731. VMatrix mat;
  732. MatrixBuildPerspectiveX( mat, flFovX, flAspect, flZNear, flZFar );
  733. VMatrix temp;
  734. MatrixMultiply( dst, mat, temp );
  735. dst = temp;
  736. }
  737. inline void MatrixPerspectiveOffCenterX( VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar, double bottom, double top, double left, double right )
  738. {
  739. VMatrix mat;
  740. MatrixBuildPerspectiveOffCenterX( mat, flFovX, flAspect, flZNear, flZFar, bottom, top, left, right );
  741. VMatrix temp;
  742. MatrixMultiply( dst, mat, temp );
  743. dst = temp;
  744. }
  745. inline Vector4D GetMatrixColumnAsVector4D( const VMatrix &mMatrix, int nCol )
  746. {
  747. Vector4D vColumnOut;
  748. vColumnOut.x = mMatrix.m[ 0 ][ nCol ];
  749. vColumnOut.y = mMatrix.m[ 1 ][ nCol ];
  750. vColumnOut.z = mMatrix.m[ 2 ][ nCol ];
  751. vColumnOut.w = mMatrix.m[ 3 ][ nCol ];
  752. return vColumnOut;
  753. }
  754. inline Vector4D MatrixGetRowAsVector4D( const VMatrix &src, int nRow )
  755. {
  756. Assert( (nRow >= 0) && (nRow <= 3) );
  757. return Vector4D( src[nRow] );
  758. }
  759. //-----------------------------------------------------------------------------
  760. // Extracts clip planes from an arbitrary view projection matrix.
  761. // This function assumes the matrix has been transposed.
  762. //-----------------------------------------------------------------------------
  763. inline void ExtractClipPlanesFromTransposedMatrix( const VMatrix &transposedViewProjMatrix, VPlane *pPlanesOut )
  764. {
  765. // Left
  766. Vector4D vPlane = GetMatrixColumnAsVector4D( transposedViewProjMatrix, 0 ) + GetMatrixColumnAsVector4D( transposedViewProjMatrix, 3 );
  767. pPlanesOut[ FRUSTUM_LEFT ].Init( vPlane.AsVector3D(), -vPlane.w );
  768. // Right
  769. vPlane = -GetMatrixColumnAsVector4D( transposedViewProjMatrix, 0 ) + GetMatrixColumnAsVector4D( transposedViewProjMatrix, 3 );
  770. pPlanesOut[ FRUSTUM_RIGHT ].Init( vPlane.AsVector3D(), -vPlane.w );
  771. // Bottom
  772. vPlane = GetMatrixColumnAsVector4D( transposedViewProjMatrix, 1 ) + GetMatrixColumnAsVector4D( transposedViewProjMatrix, 3 );
  773. pPlanesOut[ FRUSTUM_BOTTOM ].Init( vPlane.AsVector3D(), -vPlane.w );
  774. // Top
  775. vPlane = -GetMatrixColumnAsVector4D( transposedViewProjMatrix, 1 ) + GetMatrixColumnAsVector4D( transposedViewProjMatrix, 3 );
  776. pPlanesOut[ FRUSTUM_TOP ].Init( vPlane.AsVector3D(), -vPlane.w );
  777. // Near
  778. vPlane = GetMatrixColumnAsVector4D( transposedViewProjMatrix, 2 ) + GetMatrixColumnAsVector4D( transposedViewProjMatrix, 3 );
  779. pPlanesOut[ FRUSTUM_NEARZ ].Init( vPlane.AsVector3D(), -vPlane.w );
  780. // Far
  781. vPlane = -GetMatrixColumnAsVector4D( transposedViewProjMatrix, 2 ) + GetMatrixColumnAsVector4D( transposedViewProjMatrix, 3 );
  782. pPlanesOut[ FRUSTUM_FARZ ].Init( vPlane.AsVector3D(), -vPlane.w );
  783. }
  784. //-----------------------------------------------------------------------------
  785. // Extracts clip planes from an arbitrary view projection matrix.
  786. // Differences from ExtractClipPlanesFromTransposedMatrix():
  787. // This function assumes the matrix has NOT been transposed.
  788. // If bD3DClippingRange is true, the projection space clipping range is assumed
  789. // to be [0,1], vs. the OpenGL range [-1,1].
  790. // This function always returns normalized planes.
  791. //-----------------------------------------------------------------------------
  792. void ExtractClipPlanesFromNonTransposedMatrix( const VMatrix &viewProjMatrix, VPlane *pPlanesOut, bool bD3DClippingRange = true );
  793. #endif