—————————————————————————————————————————————–
I’ve started an other log, dedicated for the engine project, so I won’t talk about it any more here unless it’s very cool or related.
Today I worked with the glm library a bit more and wrote a TransformationMatrix class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
class TransformationMatrix { private: static const glm::mat4 sk_IdentityMatrix; glm::mat4 m_ScaleMatrix; glm::mat4 m_RotationMatrix; glm::mat4 m_TranslationMatrix; glm::mat4 m_FinalMatrix; bool m_Evaluated; public: TransformationMatrix(void); TransformationMatrix & SetScale(const float p_ScaleX, const float p_ScaleY, const float p_ScaleZ); /*! Rotate angles in degrees. */ TransformationMatrix & SetRotation(const float p_AngleX, const float p_AngleY, const float p_AngleZ); /*! */ TransformationMatrix & SetTranslation(const float p_PosX, const float p_PosY, const float p_PosZ); /*! Return the raw pointer to the matrix. Evaluates final transformation matrix if it hasn't already. */ const GLfloat * const GetRawPtr(void); /*! */ const glm::mat4 & GetGLMMatrix(void); /*! Evaluate the final transformation matrix if it's not done already. */ TransformationMatrix & Evaluate(void); }; // MatrixPipeline class |
A very simple class. The name is a bit deceiving. The entire class is actually compose of 4 glm::mat4 objects. 3 for the basic transformations, and the final one being the product of the other 3. The comments are a bit incomplete but you can probably tell what the member functions do already. There are 3 setter methods, for scaling, translation and rotation. There are also two getter methods for getting the final transformation matrix.
What interesting here is that, at the moment the final transformation matrix is only evaluated when it needs to be re-evaluated. Calling any of the setter methods will not trigger the evaluation, but they will m_Evaluated to false. When the getter methods are called. They will re-evaluate the final transformation matrix only if it’s been previous modified.
There are no methods such as TranslateFromCurrentPos or RotateFromCurrentAngle at the moment because I believed those should be implemented in a entity class which will compose one or multiple TransformationMatrix in the render component. This will allow me to implement higher level movement stuff on top while keeping the matrix class lightweight and encapsulated.
Here’s the cpp part of the class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
const glm::mat4 TransformationMatrix::sk_IdentityMatrix(1); TransformationMatrix::TransformationMatrix(void) : m_ScaleMatrix(sk_IdentityMatrix) , m_RotationMatrix(sk_IdentityMatrix) , m_TranslationMatrix(sk_IdentityMatrix) , m_Evaluated(false) { glm::value_ptr(m_FinalMatrix); } TransformationMatrix & TransformationMatrix::SetScale(const float p_ScaleX, const float p_ScaleY, const float p_ScaleZ) { m_ScaleMatrix = glm::scale(p_ScaleX, p_ScaleY, p_ScaleZ); m_Evaluated = false; return *this; } TransformationMatrix & TransformationMatrix::SetRotation(const float p_AngleX, const float p_AngleY, const float p_AngleZ) { m_Evaluated = false; m_RotationMatrix = glm::rotate(sk_IdentityMatrix, p_AngleX, glm::vec3(1, 0, 0)); m_RotationMatrix = glm::rotate(m_RotationMatrix, p_AngleY, glm::vec3(0, 1, 0)); m_RotationMatrix = glm::rotate(m_RotationMatrix, p_AngleZ, glm::vec3(0, 0, 1)); return *this; } TransformationMatrix & TransformationMatrix::SetTranslation(const float p_PosX, const float p_PosY, const float p_PosZ) { m_TranslationMatrix = glm::translate(p_PosX, p_PosY, p_PosZ); m_Evaluated = false; return *this; } const GLfloat * const TransformationMatrix::GetRawPtr(void) { this->Evaluate(); return glm::value_ptr(m_FinalMatrix); } const glm::mat4 & TransformationMatrix::GetGLMMatrix(void) { this->Evaluate(); return m_FinalMatrix; } TransformationMatrix & TransformationMatrix::Evaluate(void) { if (!m_Evaluated) { m_FinalMatrix = m_TranslationMatrix * m_RotationMatrix * m_ScaleMatrix; m_Evaluated = true; } return *this; } |
Of course. The class is incomplete. I will overload some operators for matrix multiplication and what not. At the moment I have to call “GetGLMMatrix()” to pass the matrix to my ShaderProgram class. I will need to add support for this new class into my shader code.
I will begin work on a camera class next, once I’m up to date with this week’s lab work.