#include "Mix/Private/Scene/Common/TerrainCollider.h"

#include "Mix/Dynamics/IStaticMesh.h"
#include "Mix/Scene/IRendererObject.h"

namespace Mix{ namespace Scene{ namespace Common{

const UInt16 TerrainCollider::FILTER_GROUP	=	Mix::Dynamics::OF_STATIC;
const UInt16 TerrainCollider::FILTER_MASK	=	Mix::Dynamics::OF_DEFAULT |
												Mix::Dynamics::OF_KINEMATIC |
												Mix::Dynamics::OF_SENSOR |
												Mix::Dynamics::OF_CHARACTER |
												Mix::Dynamics::OF_DEBRIS;

TerrainCollider* TerrainCollider::CreateInstance( Mix::Scene::IRendererObject* pOwner, Mix::Dynamics::IStaticMesh* pObject )
{
	return MIX_LIB_NEW_T( Mix::Memory::SECTION_SCENE, TerrainCollider, pOwner, pObject );
}

TerrainCollider::TerrainCollider( Mix::Scene::IRendererObject* pOwner, Mix::Dynamics::IStaticMesh* pObject ) :
m_pOwner( NULL ),
m_pObject( NULL )
{
	MIX_ASSERT( pOwner != NULL );
	MIX_ASSERT( pObject != NULL );

	m_pOwner = pOwner;

	MIX_ADD_REF( pObject );
	m_pObject = pObject;

	m_pObject->SetFilterGroup( TerrainCollider::FILTER_GROUP );
	m_pObject->SetFilterMask( TerrainCollider::FILTER_MASK );

	DynamicsObject::Initialize( this );
}

TerrainCollider::~TerrainCollider( void )
{
	MIX_ASSERT( m_pOwner == NULL );
	MIX_RELEASE( m_pObject );
}

Mix::Dynamics::IStaticMesh* TerrainCollider::GetObjectPtr( void ) const
{
	return m_pObject;
}

void TerrainCollider::Dispose( void )
{
	m_pOwner = NULL;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::Common::DynamicsObject
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Dynamics::IObject* TerrainCollider::GetInternalObjectPtr( void ) const
{
	return m_pObject;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::ITerrainCollider
////////////////////////////////////////////////////////////////////////////////////////////////////

UInt32 TerrainCollider::GetPartCount( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetPartCount();
}

UInt32 TerrainCollider::GetPolygonCount( UInt32 partIndex ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetPolygonCount( partIndex );
}

UInt32 TerrainCollider::GetTotalPolygonCount( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetTotalPolygonCount();
}

UInt32 TerrainCollider::GetMaterialCount( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetMaterialCount();
}

UInt32 TerrainCollider::GetMaterialIndex( UInt32 partIndex, UInt32 polygonIndex ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetMaterialIndex( partIndex, polygonIndex );
}

Boolean TerrainCollider::SetMaterialIndex( UInt32 partIndex, UInt32 polygonIndex, UInt32 materialIndex )
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->SetMaterialIndex( partIndex, polygonIndex, materialIndex );
}

UInt32 TerrainCollider::LockMaterialIndices( UInt32 partIndex, UInt32 polygonStartIndex, UInt32 polygonCount, UInt32** ppMaterialIndices ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->LockMaterialIndices( partIndex, polygonStartIndex, polygonCount, ppMaterialIndices );
}

const Mix::Dynamics::MATERIAL& TerrainCollider::GetMaterial( UInt32 index ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetMaterial( index );
}

Boolean TerrainCollider::GetMaterial( UInt32 index, Mix::Dynamics::MATERIAL& material ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetMaterial( index, material );
}

const Mix::Dynamics::MATERIAL& TerrainCollider::GetMaterial( UInt32 partIndex, UInt32 polygonIndex ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetMaterial( partIndex, polygonIndex );
}

Boolean TerrainCollider::GetMaterial( UInt32 partIndex, UInt32 polygonIndex, Mix::Dynamics::MATERIAL& material ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetMaterial( partIndex, polygonIndex, material );
}

Boolean TerrainCollider::SetMaterial( UInt32 index, const Mix::Dynamics::MATERIAL& material )
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->SetMaterial( index, material );
}

UInt32 TerrainCollider::LockMaterials( UInt32 startIndex, UInt32 count, Mix::Dynamics::MATERIAL** ppMaterials ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->LockMaterials( startIndex, count, ppMaterials );
}

UInt16 TerrainCollider::GetFilterGroup( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetFilterGroup();
}

void TerrainCollider::SetFilterGroup( UInt16 filterGroup )
{
	MIX_ASSERT( m_pObject != NULL );

	m_pObject->SetFilterGroup( filterGroup );
}

UInt16 TerrainCollider::GetFilterMask( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetFilterMask();
}

void TerrainCollider::SetFilterMask( UInt16 filterMask )
{
	MIX_ASSERT( m_pObject != NULL );

	m_pObject->SetFilterMask( filterMask );
}

Float32 TerrainCollider::GetMargin( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetShapeMargin();
}

void TerrainCollider::SetMargin( Float32 margin )
{
	MIX_ASSERT( m_pObject != NULL );

	m_pObject->SetShapeMargin( margin );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::ICollider
////////////////////////////////////////////////////////////////////////////////////////////////////

Boolean TerrainCollider::IsDefault( void ) const
{
	return False;
}

Boolean TerrainCollider::IsStatic( void ) const
{
	return True;
}

Boolean TerrainCollider::IsKinematic( void ) const
{
	return False;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IDynamicsObject
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Scene::IDynamicsObject::TYPE TerrainCollider::GetType( void ) const
{
	return Mix::Scene::IDynamicsObject::TERRAIN_COLLIDER;
}

Boolean TerrainCollider::GetOwner( Mix::Scene::IRendererObject** ppOwner )
{
	if( m_pOwner != NULL )
	{
		MIX_ADD_REF( m_pOwner );
		( *ppOwner ) = m_pOwner;
	}
	else
	{
		return False;
	}

	return True;
}

Mix::Scene::IRendererObject* TerrainCollider::GetOwnerPtr( void ) const
{
	return m_pOwner;
}

Mix::Matrix4x4 TerrainCollider::GetWorldMatrix( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetWorldMatrix();
}

Mix::Quaternion TerrainCollider::GetWorldRotation( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetWorldRotation();
}

Mix::Vector3 TerrainCollider::GetWorldPosition( void ) const
{
	MIX_ASSERT( m_pObject != NULL );

	return m_pObject->GetWorldPosition();
}

Boolean TerrainCollider::HasContactListener( void ) const
{
	return DynamicsObject::HasContactListener();
}

Boolean TerrainCollider::ContainsContactListener( Mix::Scene::IContactListener* pListener ) const
{
	return DynamicsObject::ContainsContactListener( pListener );
}

Boolean TerrainCollider::AddContactListener( Mix::Scene::IContactListener* pListener )
{
	return DynamicsObject::AddContactListener( pListener );
}

Boolean TerrainCollider::RemoveContactListener( Mix::Scene::IContactListener* pListener )
{
	return DynamicsObject::RemoveContactListener( pListener );
}

void TerrainCollider::ClearContactListener( void )
{
	DynamicsObject::ClearContactListener();
}

Int32 TerrainCollider::GetUserIndex( void )  const
{
	return DynamicsObject::GetUserIndex();
}

void TerrainCollider::SetUserIndex( Int32 index )
{
	DynamicsObject::SetUserIndex( index );
}

void* TerrainCollider::GetUserPtr( void ) const
{
	return DynamicsObject::GetUserPtr();
}

void TerrainCollider::SetUserPtr( void* ptr )
{
	DynamicsObject::SetUserPtr( ptr );
}

}}}
