// Liquid3D - Moteur 3D C++ NDS par Morukutsu
// Surcouche de l'ulibrary de Brunni
// Version alpha 1

#include "CCameraNode.h"

namespace L3D
{
	CCameraNode::CCameraNode(int camtype)
	{
		mNodeType = NODETYPE_CAM;
		mDebugDraw = false;
		m_r = 1024;
		mCamType = camtype;
		mTheta = mPhi = 0;
		mFreeFlySpeed = 64;
		mFreeFlySensibility = 1024;
	}

	CCameraNode::~CCameraNode()
	{

	}

	//Fonction d'affichage
	void CCameraNode::Draw()
	{
		//On est jamais censé afficher une camera, mais c'est utile pour le debug
		if(mDebugDraw)
		{
			glPushMatrix();
				//Déplacement de l'ensemble des objets
				glTranslate3f32(mPosEns.x, mPosEns.y, mPosEns.z);
				MATRIX_SCALE = mScaleEns.x; MATRIX_SCALE = mScaleEns.y; MATRIX_SCALE = mScaleEns.z;
				glRotateXi(mRotEns.x);
				glRotateYi(mRotEns.y);
				glRotateZi(mRotEns.z);
				
				glPushMatrix();
					//Déplacement de cet objet en particulier
					glTranslate3f32(mPosObj.x, mPosObj.y, mPosObj.z);
					MATRIX_SCALE = mScaleObj.x; MATRIX_SCALE = mScaleObj.y; MATRIX_SCALE = mScaleObj.z;
					glRotateXi(mRotObj.x);
					glRotateYi(mRotObj.y);
					glRotateZi(mRotObj.z);
					//glRotatef32(1.0f, mRotObj.x, mRotObj.y, mRotObj.z);
					
					//Affichage du cube
					ulDisableTexture();	
					glPolyFmt(POLY_ALPHA(mAlpha) | POLY_ID(0) | POLY_CULL_BACK | POLY_FORMAT_LIGHT0) ; //TO-DO : Paramètrage du fmt
					
					ulVertexBegin(GL_QUADS);
					ulVertexColor(32767);
					glNormal(NORMAL_PACK(0, 0, 511));
					glVertex3v16(-m_r, -m_r,  m_r);
					glVertex3v16( m_r, -m_r,  m_r);
					glVertex3v16( m_r,  m_r,  m_r);
					glVertex3v16(-m_r,  m_r,  m_r);
					// Back Face
					glNormal(NORMAL_PACK(0, 0, -512));
					glVertex3v16(-m_r, -m_r, -m_r);
					glVertex3v16(-m_r,  m_r, -m_r);
					glVertex3v16( m_r,  m_r, -m_r);
					glVertex3v16( m_r, -m_r, -m_r);
					// Top Face
					glNormal(NORMAL_PACK(0, 511, 0));
					glVertex3v16(-m_r,  m_r, -m_r);
					glVertex3v16(-m_r,  m_r,  m_r);
					glVertex3v16( m_r,  m_r,  m_r);
					glVertex3v16( m_r,  m_r, -m_r);
					// Bottom Face
					glNormal(NORMAL_PACK(0, -512, 0));
					glVertex3v16(-m_r, -m_r, -m_r);
					glVertex3v16( m_r, -m_r, -m_r);
					glVertex3v16( m_r, -m_r,  m_r);
					glVertex3v16(-m_r, -m_r,  m_r);
					// Right Face
					glNormal(NORMAL_PACK(511, 0, 0));
					glVertex3v16( m_r, -m_r, -m_r);
					glVertex3v16( m_r,  m_r, -m_r);
					glVertex3v16( m_r,  m_r,  m_r);
					glVertex3v16( m_r, -m_r,  m_r);
					// Left Face
					glNormal(NORMAL_PACK(-512, 0, 0));				
					glVertex3v16(-m_r, -m_r, -m_r);
					glVertex3v16(-m_r, -m_r,  m_r);
					glVertex3v16(-m_r,  m_r,  m_r);
					glVertex3v16(-m_r,  m_r, -m_r);
					ulVertexEnd();

					glPolyFmt(POLY_ALPHA(31) ) ;
					ulVertexColor(32767);
				glPopMatrix(1);
				//Affichage des enfants
				for(unsigned int k = 0; k < mChildrenCount; k++)
					mChildren[k]->Draw();
			glPopMatrix(1);
		}
	}

	void CCameraNode::Update()
	{
		//Update selon le type de camera
		if(mCamType == CAMTYPE_FREEFLY)
		{
			//Déplacement stylet
			mTheta -= ul_keys.touch.deltaX*mFreeFlySpeed;
			mPhi -= ul_keys.touch.deltaY*mFreeFlySpeed;
			int32 r_temp = cosLerp(mPhi);
			mFoward.z = sinLerp(mPhi);
			mFoward.x = mulf32(r_temp, cosLerp(mTheta));
			mFoward.y = mulf32(r_temp, sinLerp(mTheta));
			mLeft = mUpVec^mFoward;
			mLeft.Normalise();

			//Déplacement cam
			if(ul_keys.held.up)
				mPosEns += mFoward*mFreeFlySensibility;
			if(ul_keys.held.down)
				mPosEns -= mFoward*mFreeFlySensibility;
			if(ul_keys.held.left)
				mPosEns += mLeft*mFreeFlySensibility;
			if(ul_keys.held.right)
				mPosEns -= mLeft*mFreeFlySensibility;

			//Avec la position de la caméra et la direction du regard, on calcule facilement ce que regarde la caméra (la cible)
			mLookAt = mPosEns + mFoward;
		}
	}
	
	void CCameraNode::Set(v3d pos, v3d lookat, v3d upv)
	{
		mPosEns = pos;
		mLookAt = lookat;
		mUpVec = upv;

		if(mCamType == CAMTYPE_FREEFLY)
		{
			//mLookAt -= mPosEns;
		}
	}

	void CCameraNode::SetLookAt(v3d vec)
	{
		mLookAt = vec;
	}

	void CCameraNode::SetUpVector(v3d vec)
	{
		mUpVec = vec;
	}

	void CCameraNode::ApplyCamera()
	{
		gluLookAtf32(mPosEns.x, mPosEns.y, mPosEns.z, mLookAt.x, mLookAt.y, mLookAt.z, mUpVec.x, mUpVec.y, mUpVec.z);
		glMatrixMode(GL_MODELVIEW);
	}

	void CCameraNode::ToggleDebugDraw()
	{
		mDebugDraw = !mDebugDraw;
	}

	void CCameraNode::SetFreeFlyParameters(int32 speed, int32 sensibility)
	{
		mFreeFlySpeed = speed;
		mFreeFlySensibility = sensibility;
	}

};