#include "Utility/FollowCameraHelper.h"

namespace Utility {

FollowCameraHelper::FollowCameraHelper( void ) :
m_RotCoiffe( 0.07f ),
m_PosCoiffe( 0.1f ),
m_EyeCoiffe( 0.1f ),
m_Dist( 0.0f ),
m_Elev( 0.0f )
{
}

FollowCameraHelper::~FollowCameraHelper( void )
{
}

void FollowCameraHelper::Initialize(	const Mix::Quaternion& targetRot,
										const Mix::Vector3& targetPos,
										Float32 dist,
										Float32 elevation,
										const Mix::Vector3& up )
{
	Mix::Quaternion elevRot;

	elevRot.SetRotationAxis( Mix::Vector3( 1.0f, 0.0f, 0.0f ), elevation );

	m_Dist = dist;
	m_Elev = elevation;

	m_TargetRot = targetRot;
	m_TargetPos = targetPos;

	m_EyeVec = Mix::Matrix4x4( elevRot ) * Mix::Vector3( 0.0f, 0.0f, dist );

	m_Eye = m_TargetPos + m_EyeVec;
	m_At = m_TargetPos;
	m_Up = up;
}

Float32 FollowCameraHelper::GetRotCoiffe( void ) const
{
	return m_RotCoiffe;
}

void FollowCameraHelper::SetRotCoiffe( Float32 coiffe )
{
	m_RotCoiffe = MIX_CLAMP( coiffe, 0.0f, 1.0f );
}

Float32 FollowCameraHelper::GetPosCoiffe( void ) const
{
	return m_PosCoiffe;
}

void FollowCameraHelper::SetPosCoiffe( Float32 coiffe )
{
	m_PosCoiffe = MIX_CLAMP( coiffe, 0.0f, 1.0f );
}

Float32 FollowCameraHelper::GetEyeCoiffe( void ) const
{
	return m_EyeCoiffe;
}

void FollowCameraHelper::SetEyeCoiffe( Float32 coiffe )
{
	m_EyeCoiffe = MIX_CLAMP( coiffe, 0.0f, 1.0f );
}

Float32 FollowCameraHelper::GetDistance( void ) const
{
	return m_Dist;
}

void FollowCameraHelper::SetDistance( Float32 dist )
{
	m_Dist = dist;
}

Float32 FollowCameraHelper::GetElevation( void ) const
{
	return m_Elev;
}

void FollowCameraHelper::SetElevation( Float32 elevation )
{
	m_Elev = elevation;
}

void FollowCameraHelper::Update( const Mix::Quaternion& targetRot, const Mix::Vector3& targetPos )
{
	Mix::Quaternion elevRot;

	Mix::Quaternion nextTargetRot = Mix::Quaternion::Slerp( m_TargetRot, targetRot, m_RotCoiffe );
	Mix::Vector3 nextTargetPos = m_At + ( targetPos - m_At ) * m_PosCoiffe;
	Mix::Vector3 nextEyeVec;

	elevRot.SetRotationAxis( Mix::Vector3( 1.0f, 0.0f, 0.0f ), m_Elev );
	nextEyeVec = Mix::Matrix4x4( elevRot ) * Mix::Vector3( 0.0f, 0.0f, m_Dist );
	m_EyeVec = m_EyeVec + ( nextEyeVec - m_EyeVec ) * m_EyeCoiffe;

	m_Eye = nextTargetPos + Mix::Matrix4x4( nextTargetRot ) * m_EyeVec;
	m_At = nextTargetPos;

	m_TargetRot = nextTargetRot;
	m_TargetPos = nextTargetPos;
}

const Mix::Vector3& FollowCameraHelper::GetEye( void ) const
{
	return m_Eye;
}

const Mix::Vector3& FollowCameraHelper::GetAt( void ) const
{
	return m_At;
}

const Mix::Vector3& FollowCameraHelper::GetUp( void ) const
{
	return m_Up;
}

}
