/*
/ BSTMCAMERA.H
/ ************
/ Camera implementation, at present contains support
/ for first-person and static cameras as well as
/ frustum culling.
/
/ Will Beddow 2010 - http://343gs.com/brainstem
/
/ This software is currently under development
/ and is subject to change and improvement. Some
/ aspects of the system are incomplete and/or 
/ unstable due to ongoing implementation.
/
*/

#ifndef __BSTMCAMERA_H__
#define __BSTMCAMERA_H__

#include "Compile.h"
#include "Types.h"
#include "Camera.h"
#include "Kernel.h"
#include "Matrix.h"

#include "BstmDevice.h"

namespace Brainstem
{
	class Camera : public ICamera
	{
	public:
		Camera(IKernel* kernel, IDirect3DDevice9* device, float fov, float znear, float zfar);
		~Camera();

		virtual void Init();
		virtual void Update();

		bool FrustumCubeTest(Vector3<float> min, Vector3<float> max);
		bool FrustumSphereTest(Vector3<float> center, float radius);
		bool FrustumBoxTest(Vector3<float> center, float size);
		bool FrustumTest(Vector3<float> position);

		Matrix4<float> GetViewMatrix() { return View; }
		Matrix4<float> GetProjectionMatrix() { return Projection; }

		Vector3<float> GetDirection() { return Vector3<float>(-(sinf(Yaw) * cosf(Pitch)), sinf(Pitch), -(cosf(Yaw) * cosf(Pitch))); }

		AUTO_OBJECT_SIZE;
		const char* GetName() { return "Camera"; }

	protected:
		IKernel* Kernel;
		IDirect3DDevice9* Device;

		void UpdateFrustumPlanes();
		void UpdateFrustumVertices();

		float OldYaw;
		float OldPitch;

		Plane4 FrustumPlanes[6];
		Vector3<float> FrustumVertices[8];
	};

	class CameraFirstPerson : public Camera
	{
	public:
		CameraFirstPerson(IKernel* kernel, IDirect3DDevice9* device, float fov, float znear, float zfar, float rotationSpeed, float movementSpeed, bool isNoClip);
		~CameraFirstPerson();

		void Init();
		void Update();

		AUTO_OBJECT_SIZE;
		const char* GetName() { return "First-Person Camera"; }

	private:

		void UpdatePosition(float timeDelta);
		void UpdateViewMatrix();
		void UpdateProjectionMatrix();

		Vector2<int> MousePosition_Current;
		Vector2<int> MousePosition_Previous;

		float RotationSpeed;
		float MovementSpeed;

		bool IsNoClip;
	};

	class CameraStatic : public Camera
	{
	public:
		CameraStatic(IKernel* kernel, IDirect3DDevice9* device, float fov, float znear, float zfar, Vector3<float> target);
		~CameraStatic();

		void Init();
		void Update();

		AUTO_OBJECT_SIZE;
		const char* GetName() { return "Static Camera"; }

	private:

		void UpdateViewMatrix();
		void UpdateProjectionMatrix();
	};
}

#endif