Ckef01

CWorxEngine - 4x4 Matrix Class

Jul 1st, 2012
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.04 KB | None | 0 0
  1. /*********************************************************
  2.  * mat4.h
  3.  *********************************************************/
  4.  
  5. /*********************************************************
  6.  * CWorx Engine :   Graphics Engine produced by Ckef Worx
  7.  * www          :   http://www.ckef-worx.com
  8.  
  9.  OpenGL used as 2D/3D graphics rendering API, in combination
  10.  with the GLFW library.
  11.  
  12.  * Copyright (c) Stef Velzel :: All Rights Reserved
  13.  *********************************************************/
  14.  
  15. #ifndef __MAT4_H__
  16. #define __MAT4_H__
  17.  
  18. #include "Math/mat3.h"
  19.  
  20. // CWE (CWorx Engine) namespace
  21. namespace CWE
  22. {
  23.     //-----------------------------------------------------------------------
  24.     class DLL mat4
  25.     {
  26.         //-----------------------------------------------------------------------
  27.         protected:
  28.             // Array, row-major
  29.             float m[16];
  30.  
  31.         //-----------------------------------------------------------------------
  32.         public:
  33.             /** Computes the matrix according to a position, orientation and scale
  34.              * @position    The position of the item.
  35.              * @orientation The orientation of the item.
  36.              * @scale       The scale of the item.
  37.              */
  38.             static mat4 createMatrix(const vec3 &position, const quaternion &orientation, const vec3 &scale);
  39.  
  40.             /** Computes the inverse matrix according to a position, orientation and scale
  41.              * @position    The position of the item.
  42.              * @orientation The orientation of the item.
  43.              * @scale       The scale of the item.
  44.              */
  45.             static mat4 createMatrixInverse(const vec3 &position, const quaternion &orientation, const vec3 &scale);
  46.  
  47.             // CONSTANTS
  48.             static const mat4 ZERO;
  49.             static const mat4 IDENTITY;
  50.  
  51.             /** Constructor, NOTE: does not initialize */
  52.             mat4() {}
  53.  
  54.             /** Constructor */
  55.             mat4(const float m00, const float m01, const float m02, const float m03,
  56.                  const float m10, const float m11, const float m12, const float m13,
  57.                  const float m20, const float m21, const float m22, const float m23,
  58.                  const float m30, const float m31, const float m32, const float m33)
  59.             {
  60.                 m[0]  = m00; m[1]  = m01; m[2]  = m02; m[3]  = m03;
  61.                 m[4]  = m10; m[5]  = m11; m[6]  = m12; m[7]  = m13;
  62.                 m[8]  = m20; m[9]  = m21; m[10] = m22; m[11] = m23;
  63.                 m[12] = m30; m[13] = m31; m[14] = m32; m[15] = m33;
  64.             }
  65.  
  66.             /** Constructor
  67.              * @x           The x (right) vector.
  68.              * @y           The y (up) vector.
  69.              * @z           The z (front) vector.
  70.              * @position    The position of the item.
  71.              */
  72.             mat4(const vec3 &x, const vec3 &y, const vec3 &z, const vec3 &position = vec3::ZERO);
  73.  
  74.             /** Constructor
  75.              * @scalar  The diagnal scalar.
  76.              */
  77.             mat4(const float scalar)
  78.             {
  79.                 m[0]  = scalar; m[1]  = 0.0f;   m[2]  = 0.0f;   m[3]  = 0.0f;
  80.                 m[4]  = 0.0f,   m[5]  = scalar; m[6]  = 0.0f;   m[7]  = 0.0f;
  81.                 m[8]  = 0.0f,   m[9]  = 0.0f;   m[10] = scalar; m[11] = 0.0f;
  82.                 m[12] = 0.0f,   m[13] = 0.0f;   m[14] = 0.0f;   m[15] = scalar;
  83.             }
  84.  
  85.             /** Copies from a 3x3 matrix */
  86.             mat4(const mat3 &mat)
  87.             {
  88.                 *this = mat;
  89.             }
  90.  
  91.             /** Copy Constructor */
  92.             mat4(const mat4 &mat)
  93.             {
  94.                 *this = mat;
  95.             }
  96.  
  97.             /** Assignment Copy of 3x3 matrix */
  98.             mat4 &operator=(const mat3 &mat)
  99.             {
  100.                 m[0]  = mat.m[0]; m[1]  = mat.m[1]; m[2]  = mat.m[2]; m[3]  = 0.0f;
  101.                 m[4]  = mat.m[3]; m[5]  = mat.m[4]; m[6]  = mat.m[5]; m[7]  = 0.0f;
  102.                 m[8]  = mat.m[6]; m[9]  = mat.m[7]; m[10] = mat.m[8]; m[11] = 0.0f;
  103.                 m[12] = 0.0f;     m[13] = 0.0f;     m[14] = 0.0f;     m[15] = 1.0f;
  104.  
  105.                 return *this;
  106.             }
  107.  
  108.             /** Assignment Copy */
  109.             mat4 &operator=(const mat4 &mat)
  110.             {
  111.                 m[0]  = mat.m[0];  m[1]  = mat.m[1];  m[2]  = mat.m[2];  m[3]  = mat.m[3];
  112.                 m[4]  = mat.m[4];  m[5]  = mat.m[5];  m[6]  = mat.m[6];  m[7]  = mat.m[7];
  113.                 m[8]  = mat.m[8];  m[9]  = mat.m[9];  m[10] = mat.m[10]; m[11] = mat.m[11];
  114.                 m[12] = mat.m[12]; m[13] = mat.m[13]; m[14] = mat.m[14]; m[15] = mat.m[15];
  115.  
  116.                 return *this;
  117.             }
  118.  
  119.             /** Fetches the value at a given index */
  120.             inline float &operator[](const unsigned short index)
  121.             {
  122.                 assert(index <= 15);
  123.  
  124.                 return m[index];
  125.             }
  126.  
  127.             /** Fetches the value at a given coordinate */
  128.             inline float &operator()(const unsigned short row, const unsigned short collumn)
  129.             {
  130.                 assert(row <= 3 && collumn <= 3);
  131.  
  132.                 return m[4 * row + collumn];
  133.             }
  134.  
  135.             /** Transposes the matrix */
  136.             mat4 &transpose();
  137.  
  138.             /** Inverses the matrix */
  139.             bool inverse(const float tolerance = 0.000006f);
  140.  
  141.             /** Computes the determinant of the matrix */
  142.             float determinant();
  143.  
  144.             //-----------------------------------------------------------------------
  145.             /** Basic Matrix arithmetics
  146.              * Comparison
  147.              * Negation
  148.              * Adding
  149.              * Subtracting
  150.              * Multiplying
  151.              */
  152.  
  153.             // Self modifying
  154.             inline mat4 &operator+=(const mat4 &mat) { *this = *this + mat; return *this; }
  155.             inline mat4 &operator-=(const mat4 &mat) { *this = *this - mat; return *this; }
  156.             inline mat4 &operator*=(const mat4 &mat) { *this = *this * mat; return *this; }
  157.  
  158.             // Non-Self modifying
  159.             bool operator==(const mat4 &mat) const;
  160.             inline bool operator!=(const mat4 &mat) const { return !(*this == mat); }
  161.             inline mat4 operator+() const { return *this; }
  162.             mat4 operator-() const;
  163.  
  164.             inline friend mat4 operator*(const mat4 &mat, const float scalar) { return scalar * mat; }
  165.             friend mat4 operator*(const float scalar, const mat4 &mat) { return mat4(
  166.                     scalar * mat.m[0],  scalar * mat.m[1],  scalar * mat.m[2],  scalar * mat.m[3],
  167.                     scalar * mat.m[4],  scalar * mat.m[5],  scalar * mat.m[6],  scalar * mat.m[7],
  168.                     scalar * mat.m[8],  scalar * mat.m[9],  scalar * mat.m[10], scalar * mat.m[11],
  169.                     scalar * mat.m[12], scalar * mat.m[13], scalar * mat.m[14], scalar * mat.m[15] );
  170.             }
  171.  
  172.             mat4 operator+(const mat4 &mat) const;
  173.             mat4 operator-(const mat4 &mat) const;
  174.             mat4 operator*(const mat4 &mat) const;
  175.             vec4 operator*(const vec4 &vec) const;
  176.             vec3 operator*(const vec3 &vec) const;
  177.     };
  178. }
  179.  
  180. #endif
  181.  
  182.  
  183.  
  184.  
  185. /*********************************************************
  186.  * mat4.cpp
  187.  *********************************************************/
  188.  
  189. #include "Math/mat4.h"
  190.  
  191. #include "Math/mat3.h"
  192. #include "Math/vec4.h"
  193. #include "Math/quaternion.h"
  194.  
  195. // CWE (CWorx Engine) namespace
  196. namespace CWE
  197. {
  198.     //-----------------------------------------------------------------------
  199.     // Static matrix construction
  200.     mat4 mat4::createMatrix(const vec3 &position, const quaternion &orientation, const vec3 &scale)
  201.     {
  202.         // quaternion -> matrix
  203.         mat3 rotMatrix = mat3::ZERO;
  204.         orientation.toMatrix(rotMatrix);
  205.  
  206.         // Stuff 4x4 matrix
  207.         mat4 matrix = rotMatrix;
  208.  
  209.         // Scale/Translate
  210.         matrix[0] *= scale.x; matrix[1] *= scale.y; matrix[2] *= scale.z; matrix[3] = position.x;
  211.         matrix[4] *= scale.x; matrix[5] *= scale.y; matrix[6] *= scale.z; matrix[7] = position.y;
  212.         matrix[8] *= scale.x; matrix[9] *= scale.y; matrix[10] *= scale.z; matrix[11] = position.z;
  213.  
  214.         return matrix;
  215.     }
  216.  
  217.     //-----------------------------------------------------------------------
  218.     // Static inverse matrix construction
  219.     mat4 mat4::createMatrixInverse(const vec3 &position, const quaternion &orientation, const vec3 &scale)
  220.     {
  221.         // quaternion -> inverse -> matrix
  222.         mat3 rotMatrix = mat3::ZERO;
  223.         orientation.inverse().toMatrix(rotMatrix);
  224.  
  225.         // Inverse Scale
  226.         vec3 invScale = 1.0f / scale;
  227.  
  228.         // Apply Scale
  229.         rotMatrix[0] *= invScale.x; rotMatrix[1] *= invScale.x; rotMatrix[2] *= invScale.x;
  230.         rotMatrix[3] *= invScale.y; rotMatrix[4] *= invScale.y; rotMatrix[5] *= invScale.y;
  231.         rotMatrix[6] *= invScale.z; rotMatrix[7] *= invScale.z; rotMatrix[8] *= invScale.z;
  232.         mat4 matrix = rotMatrix;
  233.  
  234.         // Inverse Translate
  235.         vec3 invTranslate = rotMatrix * -position;
  236.  
  237.         // Apply Translate
  238.         matrix[3] = invTranslate.x;
  239.         matrix[7] = invTranslate.y;
  240.         matrix[11] = invTranslate.z;
  241.  
  242.         return matrix;
  243.     }
  244.  
  245.     //-----------------------------------------------------------------------
  246.     const mat4 mat4::ZERO(
  247.         0, 0, 0, 0,
  248.         0, 0, 0, 0,
  249.         0, 0, 0, 0,
  250.         0, 0, 0, 0 );
  251.  
  252.     const mat4 mat4::IDENTITY(
  253.         1, 0, 0, 0,
  254.         0, 1, 0, 0,
  255.         0, 0, 1, 0,
  256.         0, 0, 0, 1 );
  257.  
  258.     //-----------------------------------------------------------------------
  259.     mat4::mat4(const vec3 &x, const vec3 &y, const vec3 &z, const vec3 &position)
  260.     {
  261.         vec3 xAxis = x.normalize();
  262.         vec3 yAxis = y.normalize();
  263.         vec3 zAxis = z.normalize();
  264.  
  265.         m[0]  = xAxis.x; m[1]  = yAxis.x; m[2]  = zAxis.x; m[3]  = position.x;
  266.         m[4]  = xAxis.y; m[5]  = yAxis.y; m[6]  = zAxis.y; m[7]  = position.y;
  267.         m[8]  = xAxis.z; m[9]  = yAxis.z; m[10] = zAxis.z; m[11] = position.z;
  268.         m[12] = 0.0f;    m[13] = 0.0f;    m[14] = 0.0f;    m[15] = 1.0f;
  269.     }
  270.  
  271.     //-----------------------------------------------------------------------
  272.     mat4 &mat4::transpose()
  273.     {
  274.         return *this = mat4(
  275.             m[0], m[4], m[8], m[12],
  276.             m[1], m[5], m[9], m[13],
  277.             m[2], m[6], m[10], m[14],
  278.             m[3], m[7], m[11], m[15] );
  279.     }
  280.  
  281.     //-----------------------------------------------------------------------
  282.     bool mat4::inverse(const float tolerance) // Introduces even more shitty float errors
  283.     {
  284.         // Determinants of 2x2 submatrices
  285.         float S0 = m[0] * m[5] - m[1] * m[4];
  286.         float S1 = m[0] * m[6] - m[2] * m[4];
  287.         float S2 = m[0] * m[7] - m[3] * m[4];
  288.         float S3 = m[1] * m[6] - m[2] * m[5];
  289.         float S4 = m[1] * m[7] - m[3] * m[5];
  290.         float S5 = m[2] * m[7] - m[3] * m[6];
  291.  
  292.         float C5 = m[10] * m[15] - m[11] * m[14];
  293.         float C4 = m[9] * m[15] - m[11] * m[13];
  294.         float C3 = m[9] * m[14] - m[10] * m[13];
  295.         float C2 = m[8] * m[15] - m[11] * m[12];
  296.         float C1 = m[8] * m[14] - m[10] * m[12];
  297.         float C0 = m[8] * m[13] - m[9] * m[12];
  298.  
  299.         // If determinant equals 0, there is no inverse
  300.         float det = S0 * C5 - S1 * C4 + S2 * C3 + S3 * C2 - S4 * C1 + S5 * C0;
  301.         if(fabs(det) <= tolerance) return false;
  302.  
  303.         // Compute adjugate matrix
  304.         *this = (1 / det) * mat4(
  305.              m[5] * C5  - m[6] * C4  + m[7] * C3,  -m[1] * C5 + m[2] * C4  - m[3] * C3,
  306.              m[13] * S5 - m[14] * S4 + m[15] * S3, -m[9] * S5 + m[10] * S4 - m[11] * S3,
  307.  
  308.             -m[4] * C5  + m[6] * C2  - m[7] * C1,   m[0] * C5 - m[2] * C2  + m[3] * C1,
  309.             -m[12] * S5 + m[14] * S2 - m[15] * S1,  m[8] * S5 - m[10] * S2 + m[11] * S1,
  310.  
  311.              m[4] * C4  - m[5] * C2  + m[7] * C0,  -m[0] * C4 + m[1] * C2  - m[3] * C0,
  312.              m[12] * S4 - m[13] * S2 + m[15] * S0, -m[8] * S4 + m[9] * S2  - m[11] * S0,
  313.  
  314.             -m[4] * C3  + m[5] * C1  - m[6] * C0,   m[0] * C3 - m[1] * C1  + m[2] * C0,
  315.             -m[12] * S3 + m[13] * S1 - m[14] * S0,  m[8] * S3 - m[9] * S1  + m[10] * S0 );
  316.  
  317.         return true;
  318.     }
  319.  
  320.     //-----------------------------------------------------------------------
  321.     float mat4::determinant()
  322.     {
  323.         // Determinants of 2x2 submatrices
  324.         float S0 = m[0] * m[5] - m[1] * m[4];
  325.         float S1 = m[0] * m[6] - m[2] * m[4];
  326.         float S2 = m[0] * m[7] - m[3] * m[4];
  327.         float S3 = m[1] * m[6] - m[2] * m[5];
  328.         float S4 = m[1] * m[7] - m[3] * m[5];
  329.         float S5 = m[2] * m[7] - m[3] * m[6];
  330.  
  331.         float C5 = m[10] * m[15] - m[11] * m[14];
  332.         float C4 = m[9] * m[15] - m[11] * m[13];
  333.         float C3 = m[9] * m[14] - m[10] * m[13];
  334.         float C2 = m[8] * m[15] - m[11] * m[12];
  335.         float C1 = m[8] * m[14] - m[10] * m[12];
  336.         float C0 = m[8] * m[13] - m[9] * m[12];
  337.  
  338.         return S0 * C5 - S1 * C4 + S2 * C3 + S3 * C2 - S4 * C1 + S5 * C0;
  339.     }
  340.  
  341.     //-----------------------------------------------------------------------
  342.     bool mat4::operator==(const mat4 &mat) const
  343.     {
  344.         return (
  345.             m[0] == mat.m[0] && m[1] == mat.m[1] && m[2] == mat.m[2] && m[3] == mat.m[3] &&
  346.             m[4] == mat.m[4] && m[5] == mat.m[5] && m[6] == mat.m[6] && m[7] == mat.m[7] &&
  347.             m[8] == mat.m[8] && m[8] == mat.m[8] && m[10] == mat.m[10] && m[11] == mat.m[11] &&
  348.             m[12] == mat.m[12] && m[13] == mat.m[13] && m[14] == mat.m[14] && m[15] == mat.m[15] );
  349.     }
  350.  
  351.     //-----------------------------------------------------------------------
  352.     mat4 mat4::operator-() const
  353.     {
  354.         return mat4(
  355.             -m[0], -m[1], -m[2], -m[3],
  356.             -m[4], -m[5], -m[6], -m[7],
  357.             -m[8], -m[9], -m[10], -m[11],
  358.             -m[12], -m[13], -m[14], -m[15] );
  359.     }
  360.  
  361.     //-----------------------------------------------------------------------
  362.     mat4 mat4::operator+(const mat4 &mat) const
  363.     {
  364.         return mat4(
  365.             m[0] + mat.m[0], m[1] + mat.m[1], m[2] + mat.m[2], m[3] + mat.m[3],
  366.             m[4] + mat.m[4], m[5] + mat.m[5], m[6] + mat.m[6], m[7] + mat.m[7],
  367.             m[8] + mat.m[8], m[9] + mat.m[9], m[10] + mat.m[10], m[11] + mat.m[11],
  368.             m[12] + mat.m[12], m[13] + mat.m[13], m[14] + mat.m[14], m[15] + mat.m[15] );
  369.     }
  370.  
  371.     //-----------------------------------------------------------------------
  372.     mat4 mat4::operator-(const mat4 &mat) const
  373.     {
  374.         return mat4(
  375.             m[0] - mat.m[0], m[1] - mat.m[1], m[2] - mat.m[2], m[3] - mat.m[3],
  376.             m[4] - mat.m[4], m[5] - mat.m[5], m[6] - mat.m[6], m[7] - mat.m[7],
  377.             m[8] - mat.m[8], m[9] - mat.m[9], m[10] - mat.m[10], m[11] - mat.m[11],
  378.             m[12] - mat.m[12], m[13] - mat.m[13], m[14] - mat.m[14], m[15] - mat.m[15] );
  379.     }
  380.  
  381.     //-----------------------------------------------------------------------
  382.     mat4 mat4::operator*(const mat4 &mat) const
  383.     {
  384.         return mat4(
  385.             m[0] * mat.m[0] + m[1] * mat.m[4] + m[2] * mat.m[8] + m[3] * mat.m[12],
  386.             m[0] * mat.m[1] + m[1] * mat.m[5] + m[2] * mat.m[9] + m[3] * mat.m[13],
  387.             m[0] * mat.m[2] + m[1] * mat.m[6] + m[2] * mat.m[10] + m[3] * mat.m[14],
  388.             m[0] * mat.m[3] + m[1] * mat.m[7] + m[2] * mat.m[11] + m[3] * mat.m[15],
  389.  
  390.             m[4] * mat.m[0] + m[5] * mat.m[4] + m[6] * mat.m[8] + m[7] * mat.m[12],
  391.             m[4] * mat.m[1] + m[5] * mat.m[5] + m[6] * mat.m[9] + m[7] * mat.m[13],
  392.             m[4] * mat.m[2] + m[5] * mat.m[6] + m[6] * mat.m[10] + m[7] * mat.m[14],
  393.             m[4] * mat.m[3] + m[5] * mat.m[7] + m[6] * mat.m[11] + m[7] * mat.m[15],
  394.  
  395.             m[8] * mat.m[0] + m[9] * mat.m[4] + m[10] * mat.m[8] + m[11] * mat.m[12],
  396.             m[8] * mat.m[1] + m[9] * mat.m[5] + m[10] * mat.m[9] + m[11] * mat.m[13],
  397.             m[8] * mat.m[2] + m[9] * mat.m[6] + m[10] * mat.m[10] + m[11] * mat.m[14],
  398.             m[8] * mat.m[3] + m[9] * mat.m[7] + m[10] * mat.m[11] + m[11] * mat.m[15],
  399.  
  400.             m[12] * mat.m[0] + m[13] * mat.m[4] + m[14] * mat.m[8] + m[15] * mat.m[12],
  401.             m[12] * mat.m[1] + m[13] * mat.m[5] + m[14] * mat.m[9] + m[15] * mat.m[13],
  402.             m[12] * mat.m[2] + m[13] * mat.m[6] + m[14] * mat.m[10] + m[15] * mat.m[14],
  403.             m[12] * mat.m[3] + m[13] * mat.m[7] + m[14] * mat.m[11] + m[15] * mat.m[15] );
  404.     }
  405.  
  406.     //-----------------------------------------------------------------------
  407.     vec4 mat4::operator*(const vec4 &vec) const
  408.     {
  409.         return vec4(
  410.             m[0] * vec.x  + m[1] * vec.y  + m[2] * vec.z  + m[3] * vec.w,
  411.             m[4] * vec.x  + m[5] * vec.y  + m[6] * vec.z  + m[7] * vec.w,
  412.             m[8] * vec.x  + m[9] * vec.y  + m[10] * vec.z + m[11] * vec.w,
  413.             m[12] * vec.x + m[13] * vec.y + m[14] * vec.z + m[15] * vec.w );
  414.     }
  415.  
  416.     //-----------------------------------------------------------------------
  417.     vec3 mat4::operator*(const vec3 &vec) const
  418.     {
  419.         return vec3(
  420.             m[0] * vec.x + m[1] * vec.y + m[2] * vec.z + m[3],
  421.             m[4] * vec.x + m[5] * vec.y + m[6] * vec.z + m[7],
  422.             m[8] * vec.x + m[9] * vec.y + m[10] * vec.z + m[11] );
  423.     }
  424. }
Advertisement
Add Comment
Please, Sign In to add comment