#include "Mix/Private/Dynamics/RigidBody.h"

#include "Mix/Dynamics/IShape.h"

#include "Mix/Private/Dynamics/Utility.h"
#include "Mix/Private/Dynamics/World.h"
#include "Mix/Private/Dynamics/CompoundShape.h"
#include "Mix/Private/Dynamics/ObjectContext.h"

#include "Mix/Graphics/Utility/IPerspectiveRenderer.h"

namespace Mix{ namespace Dynamics{

const wchar_t* RigidBody::FAILED_CREATE = L"リジッドボディの作成に失敗";

RigidBody* RigidBody::CreateInstance( Float32 mass, Mix::Dynamics::IShape* pShape )
{
	return MIX_LIB_NEW_T( Mix::Memory::SECTION_DYNAMICS, RigidBody, mass, pShape );
}

RigidBody::RigidBody( Float32 mass, Mix::Dynamics::IShape* pShape ) :
Mix::Dynamics::Object( Mix::Dynamics::OF_ALL, Mix::Dynamics::OF_ALL, Mix::Dynamics::DD_WIREFRAME | Mix::Dynamics::DD_AXIS ),
m_Mass( ( mass < MIX_FLOAT_EPSILON )? 0.0f : mass ),
m_Status( ( mass < MIX_FLOAT_EPSILON )? Mix::Dynamics::IRigidBody::STATIC : Mix::Dynamics::IRigidBody::DEFAULT ),
m_pShape( pShape ),
m_pCompoundShape( NULL ),
m_pMotionState( NULL ),
m_pObject( NULL ),
m_pContext( NULL ),
m_bAlwaysActive( False ),
m_UserIndex( 0 ),
m_pUserPtr( NULL )
{
	MIX_ADD_REF( m_pShape );

	if( m_pShape->GetType() == Mix::Dynamics::IShape::COMPOUND )
	{
		m_pCompoundShape = static_cast<Mix::Dynamics::ICompoundShape*>( m_pShape );
	}
}

RigidBody::~RigidBody( void )
{
	MIX_LIB_DELETE( m_pObject );
	MIX_LIB_DELETE( m_pMotionState );

	MIX_LIB_DELETE_T( ObjectContext, m_pContext );
	MIX_RELEASE( m_pShape );
}

Boolean RigidBody::Initialize( const wchar_t* pDebugName )
{
	btCollisionShape* pCollisionShape = dynamic_cast<Mix::Dynamics::Shape*>( m_pShape )->Bullet_GetCollisionShapePtr();
	btVector3 localInertia( 0.0f, 0.0f, 0.0f );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// コンテキストの作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	m_pContext = MIX_LIB_NEW_T( Mix::Memory::SECTION_DYNAMICS, Mix::Dynamics::ObjectContext, this, pDebugName );
	if( m_pContext == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : DebugName[%s]", RigidBody::FAILED_CREATE, Mix::STR_OUTOFMEMORY, pDebugName );
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// モーションステートの作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	m_pMotionState = MIX_LIB_NEW btDefaultMotionState();
	if( m_pMotionState == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : DebugName[%s]", RigidBody::FAILED_CREATE, Mix::STR_OUTOFMEMORY, pDebugName );
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 剛体を作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pCollisionShape->calculateLocalInertia( m_Mass, localInertia );

	m_pObject = MIX_LIB_NEW btRigidBody( btRigidBody::btRigidBodyConstructionInfo( m_Mass, m_pMotionState, pCollisionShape, localInertia ) );
	if( m_pObject != NULL )
	{
		m_pObject->setUserPointer( m_pContext );
	}
	else
	{
		MIX_LOG_ERROR( L"%s : %s : DebugName[%s]", RigidBody::FAILED_CREATE, Mix::STR_OUTOFMEMORY, pDebugName );
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 初期ステータスを設定
	////////////////////////////////////////////////////////////////////////////////////////////////////

	UpdateStatus();

	////////////////////////////////////////////////////////////////////////////////////////////////////

	return True;
}

void RigidBody::UpdateStatus( void )
{
	if( m_pObject->isKinematicObject() == true )
	{
		m_Status = IRigidBody::KINEMATIC;
	}
	else if( m_pObject->isStaticObject() == true )
	{
		m_Status = IRigidBody::STATIC;
	}
	else
	{
		m_Status = IRigidBody::DEFAULT;
	}
}

Int32 RigidBody::GetActivationState( void ) const
{
	Int32 activationState;

	if( m_pObject->isKinematicObject() == true )
	{
		activationState = DISABLE_DEACTIVATION;
	}
	else if( m_pObject->isStaticObject() == true )
	{
		activationState = ACTIVE_TAG;
	}
	else
	{
		activationState = ( m_bAlwaysActive == True )? DISABLE_DEACTIVATION : ACTIVE_TAG;
	}

	return activationState;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Dynamics::Object
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Dynamics::ObjectContext* RigidBody::GetContextPtr( void ) const
{
	return m_pContext;
}

btCollisionObject* RigidBody::Bullet_GetCollisionObjectPtr( void ) const
{
	return m_pObject;
}

btRigidBody* RigidBody::Bullet_GetRigidBodyPtr( void ) const
{
	return m_pObject;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Dynamics::IRigidBody
////////////////////////////////////////////////////////////////////////////////////////////////////

Boolean RigidBody::IsSimulationEnabled( void ) const
{
	return ( m_pObject->getActivationState() != DISABLE_SIMULATION );
}

void RigidBody::SetSimulationEnabled( Boolean state )
{
	Int32 activateState = m_pObject->getActivationState();

	if( ( activateState == DISABLE_SIMULATION ) &&
		( state == True ) )
	{
		m_pObject->forceActivationState( GetActivationState() );
	}
	else if(	( activateState != DISABLE_SIMULATION ) &&
				( state == False ) )
	{
		m_pObject->forceActivationState( DISABLE_SIMULATION );
	}
}

Float32 RigidBody::GetMass( void ) const
{
	return m_Mass;
}

void RigidBody::SetMass( Float32 mass )
{
	mass = ( mass < ( 0.0f + MIX_FLOAT_EPSILON ) )? 0.0f : mass;

	m_Mass = mass;

	if( m_pObject->isKinematicObject() == true )
	{
		//キネマティックの場合は常に 0.0f が設定される
		mass = 0.0f;
	}

	btCollisionShape* pShapeObject = dynamic_cast<Mix::Dynamics::Shape*>( m_pShape )->Bullet_GetCollisionShapePtr();
	btVector3 localInertia( 0.0f, 0.0f, 0.0f );

	/*
		質量、慣性テンソルの更新
	*/

	pShapeObject->calculateLocalInertia( mass, localInertia );

	m_pObject->setMassProps( mass, localInertia );
	m_pObject->updateInertiaTensor();

	//btDiscreteDynamicsWorld の m_nonStaticRigidBodies を更新する
	//同時に重力も設定させる
	Object::Bullet_Refresh();

	/*
		ステータスの更新
	*/

	UpdateStatus();
}

Mix::Dynamics::IRigidBody::STATUS RigidBody::GetStatus( void ) const
{
	return m_Status;
}

Boolean RigidBody::SetStatus( Mix::Dynamics::IRigidBody::STATUS status )
{
	if( m_Status == status )
	{
		return True;
	}

	if( ( status == Mix::Dynamics::IRigidBody::DEFAULT ) &&
		( MIX_FLOAT_IS_ZERO( m_Mass ) == True ) )
	{
		MIX_LOG_WARNING( L"RigidBody : 質量が０の状態でステータスをデフォルトに設定することはできません" );
		return False;
	}

	Int32 flags = m_pObject->getCollisionFlags();
	Int32 activationState = m_pObject->getActivationState();
	Float32 mass = 0.0f;
	btCollisionShape* pShapeObject = dynamic_cast<Mix::Dynamics::Shape*>( m_pShape )->Bullet_GetCollisionShapePtr();
	btVector3 localInertia( 0.0f, 0.0f, 0.0f );
//	Mix::Quaternion rot = GetWorldRotation();
//	Mix::Vector3 pos = GetWorldPosition();

	/*
		直前のステータスのパラメータをリセット
	*/

	switch( m_Status )
	{
	case Mix::Dynamics::IRigidBody::KINEMATIC:
		MIX_RESETBIT( flags, btCollisionObject::CF_KINEMATIC_OBJECT );
		break;
	}

	/*
		新規のステータスのパラメータを設定
	*/

	switch( status )
	{
	case Mix::Dynamics::IRigidBody::DEFAULT:
		mass = m_Mass;
		break;
	case Mix::Dynamics::IRigidBody::KINEMATIC:
		MIX_SETBIT( flags, btCollisionObject::CF_KINEMATIC_OBJECT );
		break;
	}

	pShapeObject->calculateLocalInertia( mass, localInertia );

	m_pObject->setCollisionFlags( flags );
	m_pObject->setMassProps( mass, localInertia );
	m_pObject->updateInertiaTensor();

	if( activationState != DISABLE_SIMULATION )
	{
		m_pObject->forceActivationState( GetActivationState() );
	}

	//btDiscreteDynamicsWorld の m_nonStaticRigidBodies を更新する
	//同時に重力も設定させる
	Object::Bullet_Refresh();

	/*
		ステータスの更新
	*/

	UpdateStatus();

	return True;
}

Boolean RigidBody::IsAlwaysActive( void ) const
{
	return m_bAlwaysActive;
}

Boolean RigidBody::SetAlwaysActive( Boolean state )
{
	Int32 activationState = ( state == True )? DISABLE_DEACTIVATION : ACTIVE_TAG;

	m_bAlwaysActive = state;

	if( m_pObject->isStaticOrKinematicObject() == false )
	{
		m_pObject->forceActivationState( activationState );
	}

	return ( m_pObject->getActivationState() == activationState );
}

Boolean RigidBody::IsActive( void ) const
{
	Int32 activationState = m_pObject->getActivationState();

	return ( ( activationState != ISLAND_SLEEPING ) && ( activationState != DISABLE_SIMULATION ) );
}

Boolean RigidBody::Activate( void )
{
	Int32 activationState;

	if( m_pObject->isStaticOrKinematicObject() == false )
	{
		m_pObject->activate();
	}

	activationState = m_pObject->getActivationState();

	return ( ( activationState == ACTIVE_TAG ) || ( activationState == DISABLE_DEACTIVATION ) );
}

Boolean RigidBody::Deactivate( Boolean bFroce )
{
	Int32 activationState = ( bFroce == True )? ISLAND_SLEEPING : WANTS_DEACTIVATION;

	if( m_pObject->isStaticOrKinematicObject() == false )
	{
		m_pObject->setActivationState( activationState );
	}

	return ( m_pObject->getActivationState() == activationState );
}

Mix::Vector3 RigidBody::GetLinearFactor( void ) const
{
	const btVector3& factor = m_pObject->getLinearFactor();

	return Mix::Vector3( factor.x(), factor.y(), factor.z() );
}

void RigidBody::SetLinearFactor( const Mix::Vector3& factor )
{
	m_pObject->setLinearFactor( btVector3( factor.x, factor.y, factor.z ) );
}

Float32 RigidBody::GetLinearDamping( void ) const
{
	return m_pObject->getLinearDamping();
}

void RigidBody::SetLinearDamping( Float32 damping )
{
	m_pObject->setDamping( damping, m_pObject->getAngularDamping() );
}

Mix::Vector3 RigidBody::GetLinearVelocity( void )
{
	const btVector3& velocity = m_pObject->getLinearVelocity();
	return Mix::Vector3( velocity.x(), velocity.y(), velocity.z() );
}

Boolean RigidBody::SetLinearVelocity( const Mix::Vector3& velocity )
{
	if( m_pObject->isStaticOrKinematicObject() == false )
	{
		m_pObject->activate();
		m_pObject->setLinearVelocity( btVector3( velocity.x, velocity.y, velocity.z ) );
	}
	else
	{
		return False;
	}

	return True;
}

Float32 RigidBody::GetLinearSleepingThresholds( void ) const
{
	return m_pObject->getLinearSleepingThreshold();
}

void RigidBody::SetLinearSleepingThresholds( Float32 thresholds )
{
	m_pObject->setSleepingThresholds( thresholds, m_pObject->getAngularSleepingThreshold() );
}

Mix::Vector3 RigidBody::GetAngularFactor( void ) const
{
	const btVector3& factor = m_pObject->getAngularFactor();

	return Mix::Vector3( factor.x(), factor.y(), factor.z() );
}

void RigidBody::SetAngularFactor( const Mix::Vector3& factor )
{
	m_pObject->setAngularFactor( btVector3( factor.x, factor.y, factor.z ) );
}

Float32 RigidBody::GetAngularDamping( void ) const
{
	return m_pObject->getAngularDamping();
}

void RigidBody::SetAngularDamping( Float32 damping )
{
	m_pObject->setDamping( m_pObject->getLinearDamping(), damping );
}

Mix::Vector3 RigidBody::GetAngularVelocity( void )
{
	const btVector3& velocity = m_pObject->getAngularVelocity();
	return Mix::Vector3( velocity.x(), velocity.y(), velocity.z() );
}

Boolean RigidBody::SetAngularVelocity( const Mix::Vector3& velocity )
{
	if( m_pObject->isStaticOrKinematicObject() == false )
	{
		m_pObject->activate();
		m_pObject->setAngularVelocity( btVector3( velocity.x, velocity.y, velocity.z ) );
	}
	else
	{
		return False;
	}

	return True;
}

Float32 RigidBody::GetAngularSleepingThresholds( void ) const
{
	return m_pObject->getAngularSleepingThreshold();
}

void RigidBody::SetAngularSleepingThresholds( Float32 thresholds )
{
	m_pObject->setSleepingThresholds( m_pObject->getLinearSleepingThreshold(), thresholds );
}

Boolean RigidBody::ApplyLinearImpulse( const Mix::Vector3& impulse )
{
	if( m_pObject->isStaticOrKinematicObject() == false )
	{
		m_pObject->activate();
		m_pObject->applyCentralImpulse( btVector3( impulse.x, impulse.y, impulse.z ) );
	}
	else
	{
		return False;
	}

	return True;
}

Boolean RigidBody::ApplyAngularImpulse( const Mix::Vector3& impulse )
{
	if( m_pObject->isStaticOrKinematicObject() == false )
	{
		m_pObject->activate();
		m_pObject->applyTorqueImpulse( btVector3( impulse.x, impulse.y, impulse.z ) );
	}
	else
	{
		return False;
	}

	return True;
}

Boolean RigidBody::ApplyImpulse( const Mix::Vector3& impulse, const Mix::Vector3& pos )
{
	if( m_pObject->isStaticOrKinematicObject() == false )
	{
		m_pObject->activate();
		m_pObject->applyImpulse( btVector3( impulse.x, impulse.y, impulse.z ), btVector3( pos.x, pos.y, pos.z ) );
	}
	else
	{
		return False;
	}

	return True;
}

Mix::Vector3 RigidBody::GetTotalLinearForce( void )
{
	const btVector3& totalForce = m_pObject->getTotalForce();
	return Mix::Vector3( totalForce.x(), totalForce.y(), totalForce.z() );
}

Mix::Vector3 RigidBody::GetTotalAngularForce( void )
{
	const btVector3& totalForce = m_pObject->getTotalTorque();
	return Mix::Vector3( totalForce.x(), totalForce.y(), totalForce.z() );
}

Boolean RigidBody::ApplyLinearForce( const Mix::Vector3& force )
{
	if( m_pObject->isStaticOrKinematicObject() == false )
	{
		m_pObject->activate();
		m_pObject->applyCentralForce( btVector3( force.x, force.y, force.z ) );
	}
	else
	{
		return False;
	}

	return True;
}

Boolean RigidBody::ApplyAngularForce( const Mix::Vector3& torque )
{
	if( m_pObject->isStaticOrKinematicObject() == false )
	{
		m_pObject->activate();
		m_pObject->applyTorque( btVector3( torque.x, torque.y, torque.z ) );
	}
	else
	{
		return False;
	}

	return True;
}

Boolean RigidBody::ApplyForce( const Mix::Vector3& force, const Mix::Vector3& pos )
{
	if( m_pObject->isStaticOrKinematicObject() == false )
	{
		m_pObject->activate();
		m_pObject->applyForce( btVector3( force.x, force.y, force.z ), btVector3( pos.x, pos.y, pos.z ) );
	}
	else
	{
		return False;
	}

	return True;
}

void RigidBody::ClearForce( void )
{
	m_pObject->clearForces();
}

void RigidBody::ClearMotion( void )
{
	btTransform tr;

	if( m_pObject->isStaticOrKinematicObject() == true )
	{
		m_pObject->getMotionState()->getWorldTransform( tr );
	}
	else
	{
		tr = m_pObject->getCenterOfMassTransform();
	}

	m_pObject->setLinearVelocity( btVector3( 0.0f, 0.0f, 0.0f ) );
	m_pObject->setAngularVelocity( btVector3( 0.0f, 0.0f, 0.0f ) );
	m_pObject->setCenterOfMassTransform( tr );
	m_pObject->clearForces();
}

void RigidBody::ClearMotion( const Mix::Quaternion& rot, const Mix::Vector3& pos )
{
	btTransform tr( btQuaternion( rot.x, rot.y, rot.z, rot.w ), btVector3( pos.x, pos.y, pos.z ) );

	m_pObject->setWorldTransform( tr );
	m_pObject->getMotionState()->setWorldTransform( tr );

	m_pObject->setLinearVelocity( btVector3( 0.0f, 0.0f, 0.0f ) );
	m_pObject->setAngularVelocity( btVector3( 0.0f, 0.0f, 0.0f ) );
	m_pObject->setCenterOfMassTransform( tr );
	m_pObject->clearForces();
}

Boolean RigidBody::UpdateLocalInertia( void )
{
	if( m_pObject->isStaticOrKinematicObject() == true )
	{
		return False;
	}

	btCollisionShape* pShapeObject = dynamic_cast<Mix::Dynamics::Shape*>( m_pShape )->Bullet_GetCollisionShapePtr();
	btVector3 localInertia( 0.0f, 0.0f, 0.0f );

	pShapeObject->calculateLocalInertia( m_Mass, localInertia );

	m_pObject->setMassProps( m_Mass, localInertia );
	m_pObject->updateInertiaTensor();

	return True;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Dynamics::IObject
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Dynamics::IObject::TYPE RigidBody::GetType( void ) const
{
	return Mix::Dynamics::IObject::RIGIDBODY;
}

Boolean RigidBody::GetShape( Mix::Dynamics::IShape** ppShape )
{
	MIX_ADD_REF( m_pShape );
	( *ppShape ) = m_pShape;

	return True;
}

Float32 RigidBody::GetShapeMargin( void ) const
{
	return m_pShape->GetMargin();
}

void RigidBody::SetShapeMargin( Float32 margin )
{
	m_pShape->SetMargin( margin );
}

UInt16 RigidBody::GetFilterGroup( void ) const
{
	return Object::Bullet_GetFilterGroup();
}

void RigidBody::SetFilterGroup( UInt16 filterGroup )
{
	Object::Bullet_SetFilterGroup( filterGroup );
}

UInt16 RigidBody::GetFilterMask( void ) const
{
	return Object::Bullet_GetFilterMask();
}

void RigidBody::SetFilterMask( UInt16 filterMask )
{
	Object::Bullet_SetFilterMask( filterMask );
}

const Mix::Dynamics::MATERIAL& RigidBody::GetMaterial( void ) const
{
	return m_pContext->GetMaterial();
}

void RigidBody::SetMaterial( const Mix::Dynamics::MATERIAL& material )
{
	m_pContext->SetMaterial( material );
}

Mix::Quaternion RigidBody::GetWorldRotation( void ) const
{
	btTransform world;

	if( m_pObject->isKinematicObject() == true )
	{
		m_pObject->getMotionState()->getWorldTransform( world );
	}
	else
	{
		world = m_pObject->getWorldTransform();
	}

	btQuaternion rot = world.getRotation();

	return Mix::Quaternion( rot.x(), rot.y(), rot.z(), rot.w() );
}

Mix::Vector3 RigidBody::GetWorldPosition( void ) const
{
	btTransform world;

	if( m_pObject->isKinematicObject() == true )
	{
		m_pObject->getMotionState()->getWorldTransform( world );
	}
	else
	{
		world = m_pObject->getWorldTransform();
	}

	const btVector3& pos = world.getOrigin();

	return Mix::Vector3( pos.x(), pos.y(), pos.z() );
}

Mix::Matrix4x4 RigidBody::GetWorldMatrix( void ) const
{
	btTransform world;

	if( m_pObject->isKinematicObject() == true )
	{
		m_pObject->getMotionState()->getWorldTransform( world );
	}
	else
	{
		world = m_pObject->getWorldTransform();
	}

	btQuaternion rot = world.getRotation();
	const btVector3& pos = world.getOrigin();

	return Mix::Matrix4x4( Mix::Quaternion( rot.x(), rot.y(), rot.z(), rot.w() ), Mix::Vector3( pos.x(), pos.y(), pos.z() ) );
}

void RigidBody::SetWorldRotation( const Mix::Quaternion& rotation )
{
	btTransform tr;

	if( m_pObject->isKinematicObject() == true )
	{
		m_pObject->getMotionState()->getWorldTransform( tr );
	}
	else
	{
		tr = m_pObject->getWorldTransform();
	}

	tr.setRotation( btQuaternion( rotation.x, rotation.y, rotation.z, rotation.w ) );

	m_pObject->setWorldTransform( tr );
	m_pObject->getMotionState()->setWorldTransform( tr );
}

void RigidBody::SetWorldPosition( const Mix::Vector3& pos )
{
	btTransform tr;

	if( m_pObject->isKinematicObject() == true )
	{
		m_pObject->getMotionState()->getWorldTransform( tr );
	}
	else
	{
		tr = m_pObject->getWorldTransform();
	}

	tr.setOrigin( btVector3( pos.x, pos.y, pos.z ) );

	m_pObject->setWorldTransform( tr );
	m_pObject->getMotionState()->setWorldTransform( tr );
}

void RigidBody::SetWorldTransform( const Mix::Quaternion& rot, const Mix::Vector3& pos )
{
	btTransform tr;

	tr.setRotation( btQuaternion( rot.x, rot.y, rot.z, rot.w ) );
	tr.setOrigin( btVector3( pos.x, pos.y, pos.z ) );

	m_pObject->setWorldTransform( tr );
	m_pObject->getMotionState()->setWorldTransform( tr );
}

Boolean RigidBody::IsInWorld( void ) const
{
	return Object::IsInWorld();
}

Mix::Geometry::AABB RigidBody::GetBounds( void ) const
{
	btVector3 aabbMin;
	btVector3 aabbMax;

	m_pObject->getAabb( aabbMin, aabbMax );

	return Mix::Geometry::AABB( ToMixVector3( aabbMin ), ToMixVector3( aabbMax ) );
}

Boolean RigidBody::AddListener( Mix::Dynamics::IObjectListener* pListener )
{
	return m_pContext->AddListener( pListener );
}

void RigidBody::RemoveListener( Mix::Dynamics::IObjectListener* pListener )
{
	m_pContext->RemoveListener( pListener );
}

Int32 RigidBody::GetUserIndex( void ) const
{
	return m_UserIndex;
}

void RigidBody::SetUserIndex( Int32 index )
{
	m_UserIndex = index;
}

void* RigidBody::GetUserPtr( void ) const
{
	return m_pUserPtr;
}

void RigidBody::SetUserPtr( void* pData )
{
	m_pUserPtr = pData;
}

UInt32 RigidBody::Debug_GetDrawFlags( void ) const
{
	return m_DebugDrawFlags;
}

void RigidBody::Debug_SetDrawFlags( UInt32 flags )
{
	m_DebugDrawFlags = flags;
}

Float32 RigidBody::Debug_GetDrawAxisScaling( void ) const
{
	return m_DebugDrawAxisScaling;
}

void RigidBody::Debug_SetDrawAxisScaling( Float32 scaling )
{
	m_DebugDrawAxisScaling = max( 0.0f, scaling );
}

void RigidBody::Debug_Draw( Mix::Graphics::Utility::IPerspectiveRenderer* pPerspectiveRenderer, Float32 opacity )
{
	Mix::Matrix4x4 oldMat = pPerspectiveRenderer->GetMatrix();
	Mix::Vector4 oldColor = pPerspectiveRenderer->GetColor();

	pPerspectiveRenderer->SetMatrix( GetWorldMatrix() );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 軸
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( MIX_TESTBIT( m_DebugDrawFlags, Mix::Dynamics::DD_AXIS ) == Mix::Dynamics::DD_AXIS )
	{
		pPerspectiveRenderer->SetColor( Mix::Vector4( 1.0f, 1.0f, 1.0f, opacity ) );
		pPerspectiveRenderer->AddAxis( m_DebugDrawAxisScaling );
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ワイヤーフレーム
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( MIX_TESTBIT( m_DebugDrawFlags, Mix::Dynamics::DD_WIREFRAME ) == Mix::Dynamics::DD_WIREFRAME )
	{
		pPerspectiveRenderer->SetColor( Mix::Dynamics::Debug::GetRigidBodyColor( m_pObject, opacity ) );
		m_pShape->DebugDraw( pPerspectiveRenderer );
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////

	pPerspectiveRenderer->SetColor( oldColor );
	pPerspectiveRenderer->SetMatrix( oldMat );
}

}}
