//****************************************************************
// This program demonstrates how to transform a point from object (local) space to world space
// The point    (,,) is transformed to world space by first translating it along the x-axis by , the y-axis by  and the z axis by   .
//next the  point is rotated by 60 degrees about the world space origin
//then the object is translated by   along the x axis
//**************************************************************

//GLM maths library is used here
#include "glm/glm.hpp" // vec2, vec3, mat4, radians
// Include all GLM extensions
#include "glm/ext.hpp" // perspective, translate, rotate


#include <iostream>
using namespace std;

int main(void)
{
    //define point to transform (1,4,7,1)
	glm::vec4 p(1.0, 4.0, 7.0, 1); //initialize p to (1,4,7,1)
    //display it
	cout <<"point, p is "<< "(" << p.x << "," << p.y << "," << p.z << "," << p.w << ")" << endl;

	// define translation x,y and z values
	float tx = 1.5, ty = 2.0, tz = 4.0;
	//create the translation matrix T1
	glm::mat4 T1 = glm::mat4(1.0, 0.0, 0.0, 0.0, // note this is the leftmost column, not the top row
			0.0, 1.0, 0.0, 0.0,
			0.0, 0.0, 1.0, 0.0,
			tx, ty, tz, 1.0);

	// define second translation x,y and z values
	tx = 1.0, ty = 3.0, tz =2.0;
	//create the translation matrix T2
	glm::mat4 T2 = glm::mat4(1.0, 0.0, 0.0, 0.0, // note this is the leftmost column, not the top row
			0.0, 1.0, 0.0, 0.0,
			0.0, 0.0, 1.0, 0.0,
			tx, ty, tz, 1.0);

	//define rotation matrix
	float theta = glm::pi<float>()/ 3.0;
	glm::mat4 R = glm::mat4 (glm::cos(theta), glm::sin(theta), 0.0, 0.0, // note this is the leftmost column, not the top row
		    -glm::sin(theta), glm::cos(theta), 0.0, 0.0,
		    0.0, 0.0, 1.0, 0.0,
		    0.0, 0.0, 0.0, 1.0);

	glm::vec4 P1 = T1 * p;  //translate the point
	cout << "P1=T1*p;   P1 = " <<"(" << P1.x << "," << P1.y << "," << P1.z << "," << P1.w << ")" << endl;
	glm::vec4 P2 = R * P1; //rotate it
	cout << "P2=R*P1;   P2 = " << "(" << P2.x << "," << P2.y << "," << P2.z << "," << P2.w << ")" << endl;
	glm::vec4 P3 = T2 * P2;//translate it further
	cout << "P3=T2*P2;   P3 = " << "(" << P3.x << "," << P3.y << "," << P3.z << "," << P3.w << ")" << endl;

	//Alternatively, form a model matrix M=T2*R*T1 then do P3=M*p.
	//Starting from scatch, create the model matrix M and initialize it to I, the identity matrix
	glm::mat4 M(1.0);
	M = M * T2 * R * T1;   //update model matrix
	P3 = M * p; //transform the point
	cout << "P3=M*p;   P3 = " << "(" << P3.x << "," << P3.y << "," << P3.z << "," << P3.w << ")" << endl;


	//glm's extended library has transformations included.  This makes setting up matrix transforms is easier...
	T1 = glm::translate(glm::mat4(1.0f), glm::vec3(1.5f, 2.0f, 4.0f));
	T2 = glm::translate(glm::mat4(1.0f), glm::vec3(1.0f, 3.0f, 2.0f));
	glm::vec3 V(0.0,0.0,1.0);
	R = glm::rotate(glm::mat4(1.0f), theta, V);
	M = glm::mat4(1.0f);
	M = T2 * R * T1;
	P3 = M * p;
	cout << "P3=M*p;   P3 = " << "(" << P3.x << "," << P3.y << "," << P3.z << "," << P3.w << ")" << endl;

	return 0;
}