// Copyright: (c) by Crytek GmbH
#include "stdafx.h"														// for precompiled headers (has to be in first place)
#include <D3dx8math.h>												// D3DXVECTOR3
#include <assert.h>														// assert
#include "3DTargetOrientation.h"							// C3DTargetOrientation



// constructor
C3DTargetOrientation::C3DTargetOrientation()
{
	m_vFrom=D3DXVECTOR3(0,-100,0);
	m_vTo=D3DXVECTOR3(0,0,0);
	m_vUp=D3DXVECTOR3(0,0,1);
}

// destrcutor
C3DTargetOrientation::~C3DTargetOrientation()
{
}



// rotate around the target point
void C3DTargetOrientation::RotateAroundTarget( const float infYaw, const float infPitch )
{
	D3DXMATRIX mRot;
	D3DXVECTOR3 vRel = m_vFrom - m_vTo;

	float dist3d=(float)sqrt(vRel.x*vRel.x+vRel.y*vRel.y+vRel.z*vRel.z);
	float dist2d=(float)sqrt(vRel.x*vRel.x+vRel.y*vRel.y);
	float wi_angle=-(float)atan2(vRel.x,vRel.y);
	float up_angle=(float)atan2(dist2d,vRel.z);

	wi_angle+=infYaw;
	up_angle+=infPitch;

	if(up_angle<0.1f)up_angle=0.1f;
	if(up_angle>D3DX_PI-0.1f)up_angle=D3DX_PI-0.1f;

	vRel.x=-dist3d*(float)(sin(up_angle)*sin(wi_angle));
	vRel.y=dist3d*(float)(sin(up_angle)*cos(wi_angle));
	vRel.z=dist3d*(float)(cos(up_angle));

	m_vFrom = vRel + m_vTo;
}



// get the view matrix (left handed)
void C3DTargetOrientation::GetViewTransform( D3DXMATRIX &outMatrix ) const 
{
	D3DXMatrixLookAtLH(&outMatrix,&m_vFrom,&m_vTo,&m_vUp);

	// mirroring is neccessary because OBJ Format has a differnt base 
	D3DXMATRIX mir;

	D3DXMatrixReflect(&mir,&D3DXPLANE(1,0,0,0));
	D3DXMatrixMultiply(&outMatrix,&outMatrix,&mir);
}


//
void C3DTargetOrientation::GetBase( D3DXVECTOR3 &outRight, D3DXVECTOR3 &outUp, D3DXVECTOR3 &outIn ) const
{
	D3DXMATRIX mRot;
	D3DXMATRIX mRot2;

	GetViewTransform(mRot2);

	D3DXMatrixInverse(&mRot,0,&mRot2);

	D3DXVec3TransformNormal(&outRight,&D3DXVECTOR3(1,0,0),&mRot);
	D3DXVec3TransformNormal(&outUp,		&D3DXVECTOR3(0,1,0),&mRot);
	D3DXVec3TransformNormal(&outIn,		&D3DXVECTOR3(0,0,1),&mRot);
}



// get attribute
D3DXVECTOR3 C3DTargetOrientation::GetTo() const
{
	return(m_vTo);
}

// set attribute
void C3DTargetOrientation::SetTo( D3DXVECTOR3 &inTo )
{
	m_vTo=inTo;
}

// get attribute
D3DXVECTOR3 C3DTargetOrientation::GetFrom() const
{
	return(m_vFrom);
}

// set attribute
void C3DTargetOrientation::SetFrom( D3DXVECTOR3 &inFrom )
{
	m_vFrom=inFrom;
}


// get direction (To-From).Normalize()
D3DXVECTOR3 C3DTargetOrientation::GetDirection() const
{
	D3DXVECTOR3 vRet;

	D3DXVec3Normalize(&vRet,&(m_vTo-m_vFrom));

	return(vRet);
}
