#include "common_header.h"
#include "win_OpenGLApp.h"
#include "flyingCamera.h"

const float PI = atan(1.0f)*4.0f;

CFlyingCamera::CFlyingCamera()
{
	ViewMatrix = NULL;
	vEye = vec3(0.0f, 0.0f, 0.0f);
	vView = vec3(0.0f, 0.0, -1.0f);
	vUp = vec3(0.0f, 1.0f, 0.0f);
	fSpeed = 25.0f;
	fSensitivity = 0.25f;
}

CFlyingCamera::CFlyingCamera(vec3 a_vEye, vec3 a_vView, vec3 a_vUp, float a_fSpeed, float a_fSensitivity)
{
	vEye = a_vEye; vView = a_vView; vUp = a_vUp;
	fSpeed = a_fSpeed;
	fSensitivity = a_fSensitivity;
}

void CFlyingCamera::rotateWithMouse(int cx, int cy)
{
	float deltaX = (float)cx * fSensitivity;
	float deltaY = (float)cy * fSensitivity;

	if(deltaX != 0.0f)
	{
		vView -= vEye;
		vView = rotate(vView, deltaX, vec3(0.0f, 1.0f, 0.0f));
		vView += vEye;
	}

	if(deltaY != 0.0f)
	{
		vec3 vAxis = cross(vView-vEye, vUp);
		vAxis = normalize(vAxis);
		float fAngle = deltaY;
		float fNewAngle = fAngle+getAngleX();
		if(fNewAngle > -89.80f && fNewAngle < 89.80f)
		{
			vView -= vEye;
			vView = rotate(vView, deltaY, vAxis);
			vView += vEye;
		}
	}

	look();
}

float CFlyingCamera::getAngleX()
{
	vec3 vDir = vView-vEye;
	vDir = normalize(vDir);
	vec3 vDir2 = vDir; vDir2.y = 0.0f;
	vDir2 = normalize(vDir2);
	float fAngle =  acos(dot(vDir2, vDir))*(180.0f/PI);
	if(vDir.y < 0)fAngle *= -1.0f;
	return fAngle;
}

void CFlyingCamera::update()
{
	vec3 vMove = vView-vEye;
	vMove = normalize(vMove);
	vMove *= fSpeed;

	vec3 vStrafe = cross(vView-vEye, vUp);
	vStrafe = normalize(vStrafe);
	vStrafe *= fSpeed;

	int iMove = 0;
	vec3 vMoveBy;

	if(GetKeyState('W')&0x80)vMoveBy += vMove * appMain.sof(1.0f);
	if(GetKeyState('S')&0x80)vMoveBy -= vMove * appMain.sof(1.0f);
	if(GetKeyState('A')&0x80)vMoveBy -= vStrafe * appMain.sof(1.0f);
	if(GetKeyState('D')&0x80)vMoveBy += vStrafe * appMain.sof(1.0f);

	if(vMoveBy.x != 0.0f || vMoveBy.y != 0.0f || vMoveBy.z != 0.0f)
	{
		vEye += vMoveBy;
		vView += vMoveBy;

		look();
	}
}

void CFlyingCamera::look()
{
	if(ViewMatrix != NULL)
	{
		*ViewMatrix = lookAt(vEye, vView, vUp);
	}
}

void CFlyingCamera::SetViewMatrixPointer(mat4x4 *ViewMatrix)
{
	this->ViewMatrix = ViewMatrix;
	look();
}