Friday, September 2, 2011

A Transform class

When listing all the third party libraries I'm using for the new framework, I forgot to mention one library that has become indispensable in development: GLM, a mathematics library for graphics software based on the OpenGL Shading Language (GLSL) specification, written and maintained by Christophe Riccio.

Despite its excellent design it may be tricky to use sometimes, so I've decided to post my Transform class which is the engine's base class for all translation, rotation and scaling transformations and also computes a view matrix to be used in vertex shaders. Complex hierachies can be created by providing the view matrix of a superordinate Transform's view matrix to the update() routine. The m_timePassed variable may prove useful for physics simulation.

Transform.h
 class Transform  
 {  
      public:  
   
           Transform();  
   
           Transform( const quat &rotation );  
           Transform( const vec3 &translation );  
   
           Transform( const quat &rotation, const vec3 &translation );  
   
      public:  
   
           const vec3 &getScaling() const;  
           const quat &getRotation() const;  
           const vec3 &getTranslation() const;  
   
           void setScaling( const vec3 &scaling );  
           void setRotation( const quat &rotation );  
           void setTranslation( const vec3 &translation );  
   
           void scale( const vec3 &scaling );  
           void rotate( const quat &rotation );  
           void translate( const vec3 &translation, bool global = false );  
   
           void setScaling( const float &scaling )  
           {  
                setScaling( vec3(scaling) );  
           }  
   
           void scale( const float &scaling )  
           {  
                scale( vec3(scaling) );  
           }  
   
      public:  
   
           const mat4 &getModelMatrix() const;  
   
           virtual void update( double deltaTime, const mat4 &modelMatrix = mat4(), bool force = false );  
   
      private:  
   
           vec3 m_scaling;  
           quat m_rotation;  
           vec3 m_translation;  
             
           bool m_needUpdate;  
           long m_timePassed;  
           long m_lastUpdate;  
   
           mat4 m_modelMatrix;  
 };  

Transform.cpp
 #include "Transform.h"  
   
 Transform::Transform()  
 {  
      setScaling( vec3(1.0f) );  
 }  
   
 Transform::Transform( const quat &rotation )  
 {  
      setScaling( vec3(1.0f) );  
   
      setRotation( rotation );  
 }  
   
 Transform::Transform( const vec3 &translation )  
 {  
      setScaling( vec3(1.0f) );  
   
      setTranslation( translation );  
 }  
   
 Transform::Transform( const quat &rotation, const vec3 &translation )  
 {  
      setScaling( vec3(1.0f) );  
   
      setRotation( rotation );  
      setTranslation( translation );  
 }  
   
 const mat4 &Transform::getModelMatrix() const 
 {  
      return m_modelMatrix;  
 }  
   
 const vec3 &Transform::getScaling() const 
 {  
      return m_scaling;  
 }  
   
 const quat &Transform::getRotation() const 
 {  
      return m_rotation;  
 }  
   
 const vec3 &Transform::getTranslation() const 
 {  
      return m_translation;  
 }  
   
 void Transform::setScaling( const vec3 &scaling )  
 {  
      m_scaling = scaling;  
      m_needUpdate = true;  
 }  
   
 void Transform::setRotation( const quat &rotation )  
 {  
      m_rotation = rotation;  
      m_needUpdate = true;  
 }  
   
 void Transform::setTranslation( const vec3 &translation )  
 {  
      m_translation = translation;  
      m_needUpdate = true;  
 }  
   
 void Transform::scale( const vec3 &scaling )  
 {  
      setScaling( m_scaling*scaling );  
 }  
   
 void Transform::rotate( const quat &rotation )  
 {  
      setRotation( glm::cross(m_rotation, rotation) );  
 }  
   
 void Transform::translate( const vec3 &translation, bool global )  
 {  
      if( global )  
      {  
           setTranslation( m_translation+translation );  
      }  
      else  
      {  
           setTranslation( m_translation+(m_rotation*translation) );  
      }  
 }  
   
 void Transform::update( double deltaTime, const mat4 &modelMatrix, bool force )  
 {  
      long thisUpdate = clock();  
      m_timePassed = thisUpdate-m_lastUpdate;  
   
      const bool performUpdate = force || m_needUpdate;  
   
      if( performUpdate )  
      {  
           mat4 rotationMatrix = glm::mat4_cast( glm::normalize(m_rotation) );  
           mat4 translationMatrix = glm::translate( mat4(), m_translation );  
             
           m_modelMatrix = translationMatrix*rotationMatrix;  
           m_modelMatrix = glm::scale( m_modelMatrix, m_scaling );  
   
           m_modelMatrix = modelMatrix*m_modelMatrix;  
   
           m_needUpdate = false;  
      }  
        
      m_lastUpdate = clock();  
 }  

Happy coding!

No comments:

Post a Comment