#include <GL/glew.h>
#include <math.h>
#include "camera.h"

Camera::Camera()
{
	Pos = new Vector();
	Look = new Vector();
	Up = new Vector();
	MoveVector = new Vector();
	MoveVectorStrafe = new Vector();
	Edge1 = new Vector();
	Edge2 = new Vector();
	pVec = new Vector();
	tVec = new Vector();
	qVec = new Vector();

	Pos->ChangePos(100,10,100);
	Look->ChangePos(-50,-10,-20);
	Up->ChangePos(0,1,0);

	roll = 0;
	pitch = 0;
	yaw =0;

	GodMode = true;
}
void Camera::Reset()
{
	Pos->ChangePos(20,10,20);
	Look->ChangePos(0,20,20);
	Up->ChangePos(0,1,0);

	roll = 0;
	pitch = 0;
	yaw =0;
}
void Camera::GetX(float x)
{

	//allows the user to strafe across the level

	MoveVector->SubtractVectors(Look, Pos);
	MoveVectorStrafe->ChangePos(-MoveVector->GetZ(), MoveVector->GetX(), MoveVector->GetY());
	Pos->AddPos(MoveVectorStrafe->GetX()*x, 0, MoveVectorStrafe->GetZ()*x);
	Look->AddPos(MoveVectorStrafe->GetX()*x, 0, MoveVectorStrafe->GetZ()*x);
}
void Camera::GetZ(float z)
{

	//moves the user forwards or backwards depending in buttons pressed

	MoveVector->SubtractVectors(Look, Pos);
	Pos->AddPos(MoveVector->GetX()*z, MoveVector->GetY()*z, MoveVector->GetZ()*z);
	Look->AddPos(MoveVector->GetX()*z, MoveVector->GetY()*z, MoveVector->GetZ()*z);
}
void Camera::GetY(float y)
{
	Pos->AddPos(0, y, 0);
}
void Camera::TurnX(float x)
{
	roll = roll + x;
}
void Camera::TurnZ(float z)
{
	yaw = yaw + z;
}
void Camera::TurnY(float y)
{
	pitch = pitch + y;
}
float Camera::GetPosX()
{
	return Pos->GetX();
}
float Camera::GetPosY()
{
	return Pos->GetY();
}
float Camera::GetPosZ()
{
	return Pos->GetZ();
}
float Camera::GetLookX()
{
	return Look->GetX();
}
float Camera::GetLookY()
{
	return Look->GetY();
}
float Camera::GetLookZ()
{
	return Look->GetZ();
}
void Camera::Update()
{
	float cosR, cosP, cosY;		//temp values for sin/cos from 
	float sinR, sinP, sinY;		//the inputed roll/pitch/yaw
	
// Only Want to calculate these values once. 
// For speeds sake. 
	cosY = cosf(yaw*3.1415/180);
	cosP = cosf(pitch*3.1415/180);
	cosR = cosf(roll*3.1415/180);
	sinY = sinf(yaw*3.1415/180);
	sinP = sinf(pitch*3.1415/180);
	sinR = sinf(roll*3.1415/180);

// We need three vectors to put into  glu Lookat
// Look direction,  position and the up vector. 
// This function also calculates the right vector
// Which is used by someother API’s
	Look->ChangePos(sinY * cosP*360, sinP*360, cosP * -cosY*360);

// Look At Point
//Add Forward Vector to Camera position.	

// Up Vector
	Up->ChangePos(-cosY * sinR - sinY * sinP * cosR, cosP * cosR, -sinY * sinR - sinP * cosR * -cosY);

// Side Vector (right)
//this is a cross product between the forward and up vector. 
//If you don’t need to calculate this,  don’t do it. 
	//LookAt();
	
}
void Camera::LookAt()
{
	Pos->LookAt(Look, Up);
// Where we are, What we look at, and which way is up
}
int Camera::IntersectTriangle(Vector* Tri, Vector* Tri1, Vector* Tri2)
{
	double det,inv_det, u, v, t;

	Edge1->SubtractVectors(Tri1, Tri);
	Edge2->SubtractVectors(Tri2, Tri);

	pVec->CrossProduct(Look, Edge2);

	det = Edge1->DOT(pVec);

#ifdef TEST_CULL

	if(det < EPILSON)
		return 0;

	tVec->SubtractVectors(Pos, Tri);
	u = tVec->DOT(pVec);
	if(u < 0.0|| u > det)
		return 0;

	qVec->CrossProduct(tVec, Edge1);

	v = dir->DOT(qVec);
	if(v < 0.0|| u + v > det)
		return 0;

	t = Edge2->DOT(qVec);
	inv_det = 1.0/det;
	t *= inv_det;
	u *= inv_det;
	v *= inv_det;
#else
	if(det > -EPILSON && det < EPILSON)
		return 0;
	inv_det = 1.0 /det;

	tVec->SubtractVectors(Pos, Tri);

	u = tVec->DOT(pVec) * inv_det;
	if(u < 0.0|| u > 1.0)
		return 0;

	qVec->CrossProduct(tVec, Edge1);


	v = Look->DOT(qVec) * inv_det;
	if(v < 0.0 || u + v > 1.0)
		return 0;

	t = Edge2->DOT(qVec) * inv_det;
#endif
	return 1;
}