text: //Copyright (C) 2011 by Jason L. McKesson
  //This file is licensed by the MIT License.
  
  
  
  #include "MatrixStack.h"
  #include <glm/gtc/matrix_transform.hpp>
  
  namespace glutil
  {
  	void MatrixStack::Rotate( const glm::vec3 axis, float angDegCCW )
  	{
  		m_currMatrix = glm::rotate(m_currMatrix, angDegCCW, axis);
  	}
  
  	void MatrixStack::RotateRadians( const glm::vec3 axisOfRotation, float angRadCCW )
  	{
  		float fCos = cosf(angRadCCW);
  		float fInvCos = 1.0f - fCos;
  		float fSin = sinf(angRadCCW);
  		float fInvSin = 1.0f - fSin;
  
  		glm::vec3 axis = glm::normalize(axisOfRotation);
  
  		glm::mat4 theMat(1.0f);
  		theMat[0].x = (axis.x * axis.x) + ((1 - axis.x * axis.x) * fCos);
  		theMat[1].x = axis.x * axis.y * (fInvCos) - (axis.z * fSin);
  		theMat[2].x = axis.x * axis.z * (fInvCos) + (axis.y * fSin);
  
  		theMat[0].y = axis.x * axis.y * (fInvCos) + (axis.z * fSin);
  		theMat[1].y = (axis.y * axis.y) + ((1 - axis.y * axis.y) * fCos);
  		theMat[2].y = axis.y * axis.z * (fInvCos) - (axis.x * fSin);
  
  		theMat[0].z = axis.x * axis.z * (fInvCos) - (axis.y * fSin);
  		theMat[1].z = axis.y * axis.z * (fInvCos) + (axis.x * fSin);
  		theMat[2].z = (axis.z * axis.z) + ((1 - axis.z * axis.z) * fCos);
  		m_currMatrix *= theMat;
  	}
  
  	void MatrixStack::RotateX( float angDegCCW )
  	{
  		Rotate(glm::vec3(1.0f, 0.0f, 0.0f), angDegCCW);
  	}
  
  	void MatrixStack::RotateY( float angDegCCW )
  	{
  		Rotate(glm::vec3(0.0f, 1.0f, 0.0f), angDegCCW);
  	}
  
  	void MatrixStack::RotateZ( float angDegCCW )
  	{
  		Rotate(glm::vec3(0.0f, 0.0f, 1.0f), angDegCCW);
  	}
  
  	void MatrixStack::Scale( const glm::vec3 &scaleVec )
  	{
  		m_currMatrix = glm::scale(m_currMatrix, scaleVec);
  	}
  
  	void MatrixStack::Translate( const glm::vec3 &offsetVec )
  	{
  		m_currMatrix = glm::translate(m_currMatrix, offsetVec);
  	}
  
  	void MatrixStack::Perspective( float degFOV, float aspectRatio, float zNear, float zFar )
  	{
  		m_currMatrix *= glm::perspective(degFOV, aspectRatio, zNear, zFar);
  	}
  
  	void MatrixStack::Orthographic( float left, float right, float bottom, float top,
  		float zNear, float zFar )
  	{
  		m_currMatrix *= glm::ortho(left, right, bottom, top, zNear, zFar);
  	}
  
  	void MatrixStack::PixelPerfectOrtho( glm::ivec2 size, glm::vec2 depthRange, bool isTopLeft /*= true*/ )
  	{
  		if(isTopLeft)
  		{
  			Translate(-1.0f, 1.0f, (depthRange.x + depthRange.y) / 2.0f);
  			Scale(2.0f / size.x, -2.0f / size.y, 1.0f);
  		}
  		else
  		{
  			Translate(-1.0f, -1.0f, (depthRange.x + depthRange.y) / 2.0f);
  			Scale(2.0f / size.x, 2.0f / size.y, 2.0f / (depthRange.y - depthRange.x));
  		}
  	}
  
  	void MatrixStack::LookAt( const glm::vec3 &cameraPos, const glm::vec3 &lookatPos, const glm::vec3 &upDir )
  	{
  		m_currMatrix *= glm::lookAt(cameraPos, lookatPos, upDir);
  	}
  
  	void MatrixStack::ApplyMatrix( const glm::mat4 &theMatrix )
  	{
  		m_currMatrix *= theMatrix;
  	}
  
  	void MatrixStack::SetMatrix( const glm::mat4 &theMatrix )
  	{
  		m_currMatrix = theMatrix;
  	}
  
  	void MatrixStack::SetIdentity()
  	{
  		m_currMatrix = glm::mat4(1.0f);
  	}
  }
  
  
  