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

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

CFlyingCamera::CFlyingCamera()
{
	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.1f;
}

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()
{
	GetCursorPos(&pCur);
	RECT rRect; GetWindowRect(appMain.hWnd, &rRect);
	int iCentX = (rRect.left+rRect.right)>>1,
		iCentY = (rRect.top+rRect.bottom)>>1;

	float deltaX = (float)(iCentX-pCur.x)*fSensitivity;
	float deltaY = (float)(iCentY-pCur.y)*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;
		}
	}
	SetCursorPos(iCentX, iCentY);
}

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

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::setMovingKeys(int a_iForw, int a_iBack, int a_iLeft, int a_iRight)
{
	iForw = a_iForw;
	iBack = a_iBack;
	iLeft = a_iLeft;
	iRight = a_iRight;
}

void CFlyingCamera::update()
{
	rotateWithMouse();

	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(iForw)&0x80)vMoveBy += vMove*appMain.sof(1.0f);
	if(GetKeyState(iBack)&0x80)vMoveBy -= vMove*appMain.sof(1.0f);
	if(GetKeyState(iLeft)&0x80)vMoveBy -= vStrafe*appMain.sof(1.0f);
	if(GetKeyState(iRight)&0x80)vMoveBy += vStrafe*appMain.sof(1.0f);

	vEye += vMoveBy; vView += vMoveBy;
}

void CFlyingCamera::resetMouse()
{
	RECT rRect; GetWindowRect(appMain.hWnd, &rRect);
	int iCentX = (rRect.left+rRect.right)>>1,
		iCentY = (rRect.top+rRect.bottom)>>1;
	SetCursorPos(iCentX, iCentY);
}

mat4 CFlyingCamera::look()
{
	return lookAt(vEye, vView, vUp);
}
