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

#include "Mix/Scene/IActorListener.h"

#include "Mix/Private/Scene/Common/ActorSensor.h"
#include "Mix/Private/Scene/Common/ActorRevision.h"
#include "Mix/Private/Scene/Common/ActorNode.h"
#include "Mix/Private/Scene/Common/ActorMesh.h"
#include "Mix/Private/Scene/Common/ActorConstraint.h"
#include "Mix/Private/Scene/Common/ActorDynamicsDirector.h"
#include "Mix/Private/Scene/Common/ActorKinematicCharacter.h"
#include "Mix/Private/Scene/Common/ActorCollider.h"
#include "Mix/Private/Scene/Common/ActorDynamicsFigure.h"
#include "Mix/Private/Scene/Common/ActorDynamicsPart.h"
#include "Mix/Private/Scene/Common/MotionMixer.h"
#include "Mix/Private/Scene/Common/MotionController.h"

#ifdef _DEBUG
	#include "Mix/Graphics/Utility/IPerspectiveRenderer.h"
	#include "Mix/Dynamics/IRigidBody.h"
	#include "Mix/Dynamics/ISensor.h"
	#include "Mix/Dynamics/IJoint.h"
	#include "Mix/Private/Scene/Common/Debug.h"
#endif //_DEBUG

namespace Mix{ namespace Scene{ namespace Common{

const wchar_t* ActorModel::FAILED_CLONE = L"アクターモデルの複製に失敗";
		
ActorModel* ActorModel::CreateInstance( const wchar_t* pName )
{
	return MIX_LIB_NEW_T( Mix::Memory::SECTION_SCENE, ActorModel, pName );
}

ActorModel::ActorModel( const wchar_t* pName ) :
m_Name( pName ),
m_pDynamicsDirector( NULL ),
m_pDynamicsFigure( NULL ),
m_pMotionMixer( NULL ),
m_pListener( NULL ),
m_pOctObj( NULL ),
m_FarRatio( 0.0f ),
m_RevisionFlags( NULL ),
m_RevisionCounter( 0 ),
m_UserIndex( 0 ),
m_pUserPtr( NULL ),
m_bDraw( True ),
m_bLocalLighting( True ),
m_TRPriority( 0 ),
m_DefWCResult( Mix::Scene::WCR_FRONT )
{
	m_Config.behaviorFlags = Mix::Scene::IActorModel::B_ALL_FLAGS;
	m_Config.farMinDist = 50.0f;
	m_Config.farMaxDist = 100.0f;
	m_Config.maxSkipFrames = 8;

	m_State.farRatio = 0.0f;
	m_State.deltaTimer = 0.0f;
	m_State.skipFrames = 0;
	m_State.curMaxSkipFrames = 0;

#ifdef _DEBUG
	m_DebugDrawAxisScaling = 0.1f;
	m_DebugDrawJointFrameMinSize = 0.01f;
	m_DebugDrawJointLimitScaling = 0.1f;
#endif //_DEBUG
}

ActorModel::~ActorModel( void )
{
	MIX_ASSERT( m_pOctObj == NULL );

	MIX_RELEASE( m_pListener );

	if( m_pMotionMixer != NULL )
	{
		m_pMotionMixer->Dispose();
		MIX_RELEASE( m_pMotionMixer );
	}

	if( m_pDynamicsFigure != NULL )
	{
		m_pDynamicsFigure->Dispose();
		MIX_RELEASE( m_pDynamicsFigure );
	}

	if( m_pDynamicsDirector != NULL )
	{
		m_pDynamicsDirector->Dispose();
		MIX_RELEASE( m_pDynamicsDirector );
	}

	for( ActorModel::NodeList::iterator it = m_NodeList.begin(); it != m_NodeList.end(); ++it )
	{
		Mix::Scene::Common::ActorNode* pNode = ( *it );
		pNode->Dispose();
		MIX_RELEASE( pNode );
	}

	for( ActorModel::RevisionList::iterator it = m_RevisionList.begin(); it != m_RevisionList.end(); ++it )
	{
		Mix::Scene::Common::ActorRevision* pRevision = ( *it );
		MIX_LIB_DELETE_T( ActorRevision, pRevision );
	}

	MIX_LIB_FREE( m_RevisionFlags );
}

Boolean ActorModel::Initialize( UInt32 nodeNum )
{
	MIX_ASSERT( nodeNum > 0 );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ダイナミクスコントローラーを作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_ASSERT( m_pDynamicsDirector == NULL );

	m_pDynamicsDirector = Mix::Scene::Common::ActorDynamicsDirector::CreateInstance( m_Name.GetConstPtr() );
	if( m_pDynamicsDirector != NULL )
	{
		if( m_pDynamicsDirector->Initialize() == False )
		{
			return False;
		}
	}
	else
	{
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// モーションミキサーを作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_ASSERT( m_pMotionMixer == NULL );

	m_pMotionMixer = Mix::Scene::Common::MotionMixer::CreateInstance( this );
	if( m_pMotionMixer == NULL )
	{
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// リビジョン
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_ASSERT( m_RevisionList.size() == 0 );
	MIX_ASSERT( m_RevisionFlags == NULL );

	UInt32 revNum = 1 + nodeNum; //自身(モデル) + ノード数
	UInt32 revBitNum = revNum * Mix::Scene::Common::ActorRevision::TYPE_MAX;
	UInt32 revFlagSize = ( revBitNum / 32 ) + ( ( revBitNum % 32 )? 1 : 0 );

	m_RevisionFlags = reinterpret_cast<UInt32*>( MIX_LIB_MALLOC( Mix::Memory::SECTION_SCENE, sizeof( UInt32 ) * revFlagSize ) );
	MIX_ASSERT( m_RevisionFlags != NULL );
	Mix::Memory::Zero( m_RevisionFlags, sizeof( UInt32 ) * revFlagSize );

	m_RevisionList.reserve( revNum );

	for( UInt32 i = 0; i < revBitNum; i += Mix::Scene::Common::ActorRevision::TYPE_MAX )
	{
		UInt32 index = i / 32;
		UInt32 bit = i % 32;

		UInt32 table[Mix::Scene::Common::ActorRevision::TYPE_MAX];
		UInt32 mask = 0;
		UInt32 clear = 0;

		Mix::Scene::Common::ActorRevision* pRev;

		for( UInt32 j = 0; j < Mix::Scene::Common::ActorRevision::TYPE_MAX; j++ )
		{
			table[j] = 1 << ( bit + j );
			mask |= table[j];
		}

		clear = mask ^ 0xFFFFFFFF;

		pRev = MIX_LIB_NEW_T( Mix::Memory::SECTION_SCENE, Mix::Scene::Common::ActorRevision, &( m_RevisionFlags[index] ), &m_RevisionCounter, mask, clear, table );
		MIX_ASSERT( pRev != NULL );
		m_RevisionList.push_back( pRev );
	}

	m_pRevision = m_RevisionList[0]; //モデル自身のリビジョン

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ノードリスト
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_ASSERT( m_NodeList.size() == 0 );

	m_NodeList.reserve( nodeNum );

	for( UInt32 i = 0; i < nodeNum; i++ )
	{
		Mix::Scene::Common::ActorNode* pNode = ActorNode::CreateInstance( this );
		if( pNode != NULL )
		{
			MIX_ASSERT( m_RevisionList.size() > ( i + 1 ) );
			pNode->SetRevisionPtr( m_RevisionList[i + 1] );

			m_NodeList.push_back( pNode );
		}
		else
		{
			return False;
		}
	}

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

	return True;
}

void ActorModel::Finalize( void )
{
	MIX_ASSERT( m_NodeList.size() > 0 );
	UInt32 nodeNum = static_cast<UInt32>( m_NodeList.size() );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ノード : インデックスマップを作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	for( UInt32 i = 0; i < nodeNum; i++ )
	{
		m_NodeIndexMap.insert( ActorModel::IndexMap::value_type( m_NodeList[i]->GetName(), i ) );
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// メッシュ : ボーンのリンク & リストの作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	for( UIntT i = 0; i < nodeNum; i++ )
	{
		ActorMesh* pMesh = m_NodeList[i]->GetMeshPtr();

		if( pMesh != NULL )
		{
			pMesh->Finalize( this );
			m_MeshList.push_back( pMesh );
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// モーション : カーブを展開
	////////////////////////////////////////////////////////////////////////////////////////////////////

	m_pMotionMixer->Finalize();

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 強制更新
	////////////////////////////////////////////////////////////////////////////////////////////////////

	Reset( IActorModel::R_UPDATE_WORLD_MATRIX );
}

void ActorModel::SetDynamicsFigure( Mix::Scene::Common::ActorDynamicsFigure* pDynamicsFigure )
{
	MIX_ASSERT( pDynamicsFigure != NULL );
	MIX_ASSERT( m_pDynamicsFigure == NULL );

	MIX_ADD_REF( pDynamicsFigure );
	m_pDynamicsFigure = pDynamicsFigure;

	m_pDynamicsFigure->SetLink( this, NULL, &m_RootMat );
}

Mix::Scene::Common::ActorDynamicsFigure* ActorModel::GetDynamicsFigurePtr( void )
{
	return m_pDynamicsFigure;
}

Mix::Scene::Common::ActorDynamicsDirector* ActorModel::GetDynamicsDirectorPtr( void )
{
	MIX_ASSERT( m_pDynamicsDirector != NULL );

	return m_pDynamicsDirector;
}

MotionMixer* ActorModel::GetMotionMixerPtr( void )
{
	MIX_ASSERT( m_pMotionMixer != NULL );

	return m_pMotionMixer;
}

void ActorModel::SetPivotMatrix( const Mix::Matrix4x4& pivotMat )
{
	m_PivotMat = pivotMat;
	m_InvPivotMat = m_PivotMat.ToInverse();
}

Mix::Matrix4x4* ActorModel::GetWorldMatrixPtr( void )
{
	return &m_WorldMat;
}

void ActorModel::Attach( Mix::Scene::Common::ActorModelObject* pOctObj )
{
	MIX_ASSERT( pOctObj != NULL );
	MIX_ASSERT( m_pOctObj == NULL );

	m_pOctObj = pOctObj;

	RendererObject::SetRendering( True );
}

void ActorModel::Detach( void )
{
	if( m_pOctObj != NULL )
	{
		m_pOctObj->Destroy();
		m_pOctObj = NULL;
	}

	RendererObject::SetRendering( False );
}

ActorNode** ActorModel::GetNodeList( void )
{
	MIX_ASSERT( m_NodeList.size() > 0 );
	return &( m_NodeList[0] );
}

Mix::Scene::Common::ActorNode* ActorModel::GetNodePtr( const wchar_t* pName )
{
	UInt32 index = GetNodeIndex( pName );

	if( index == 0xFFFFFFFF )
	{
		return False;
	}

	return m_NodeList[index];
}

ActorNode* ActorModel::GetRootNodePtr( void )
{
	if( m_NodeList.size() == 0 )
	{
		return NULL;
	}

	return m_NodeList[0];
}

const ActorModel::MeshList& ActorModel::GetMeshList( void ) const
{
	return m_MeshList;
}

Mix::Scene::Common::ActorRevision* ActorModel::GetRevisionPtr( void ) const
{
	return m_pRevision;
}

void ActorModel::InternalRefresh( const Mix::Vector3& eyePos )
{
	Float32 farPos = ( m_WorldMat.GetTranslation() - eyePos ).GetLengthF() - m_Config.farMinDist;

	//遠さ
	if( farPos >= 0.0f )
	{
		Float32 temp = MIX_CLAMP( MIX_FLOAT_DIV( farPos, ( m_Config.farMaxDist - m_Config.farMinDist ) ), 0.0f, 1.0f );

		m_FarRatio = min( m_FarRatio, temp );
	}
	else
	{
		m_FarRatio = 0.0f;
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::Common::Model
////////////////////////////////////////////////////////////////////////////////////////////////////

void ActorModel::AttachDynamics( Mix::Dynamics::IWorld* pWorld, Mix::Dynamics::IObjectListener* pObjectListener )
{
	MIX_ASSERT( pWorld != NULL );
	MIX_ASSERT( pObjectListener != NULL );
	MIX_ASSERT( m_pDynamicsDirector != NULL );

	m_pDynamicsDirector->AttachToWorld( pWorld, pObjectListener );
}

void ActorModel::DetachDynamics( Mix::Dynamics::IWorld* pWorld )
{
	MIX_ASSERT( pWorld != NULL );
	MIX_ASSERT( m_pDynamicsDirector != NULL );

	m_pDynamicsDirector->DetachFromWorld( pWorld );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IActorModel
////////////////////////////////////////////////////////////////////////////////////////////////////

const wchar_t* ActorModel::GetName( void ) const
{
	return m_Name.GetConstPtr();
}

const Mix::Scene::IActorModel::CONFIG& ActorModel::GetConfig( void ) const
{
	return m_Config;
}

void ActorModel::SetConfig( const Mix::Scene::IActorModel::CONFIG& config )
{
	m_Config.behaviorFlags = config.behaviorFlags;
	m_Config.farMinDist = max( 0.0f, config.farMinDist );
	m_Config.farMaxDist = max( m_Config.farMinDist, config.farMaxDist );
	m_Config.maxSkipFrames = min( config.maxSkipFrames, MotionMixer::MAX_SKIP_FRAMES );
}

UInt32 ActorModel::GetNodeCount( void ) const
{
	return MIX_UIT_TO_UI32( m_NodeList.size() );
}

UInt32 ActorModel::GetNodeIndex( const wchar_t* pName ) const
{
	ActorModel::IndexMap::const_iterator it = m_NodeIndexMap.find( pName );

	if( it == m_NodeIndexMap.end() )
	{
		return 0xFFFFFFFF;
	}

	return it->second;
}

Boolean ActorModel::GetNodeByIndex( UInt32 index, Mix::Scene::IActorNode** ppNode )
{
	MIX_ASSERT( ppNode != NULL );

	if( m_NodeList.size() <= index )
	{
		return False;
	}

	Mix::Scene::Common::ActorNode* pNode = m_NodeList[index];

	MIX_ADD_REF( pNode );
	( *ppNode ) = pNode;

	return True;
}

Boolean ActorModel::GetNodeByName( const wchar_t* pName, Mix::Scene::IActorNode** ppNode )
{
	MIX_ASSERT( ppNode != NULL );

	UInt32 index = GetNodeIndex( pName );

	if( index == 0xFFFFFFFF )
	{
		return False;
	}

	return GetNodeByIndex( index, ppNode );
}

Boolean ActorModel::ExistsCollider( void ) const
{
	if( m_pDynamicsFigure == NULL )
	{
		return False;
	}

	return ( m_pDynamicsFigure->GetColliderPtr() != NULL ); 
}

Boolean ActorModel::GetCollider( Mix::Scene::IActorCollider** ppCollider )
{
	MIX_ASSERT( ppCollider != NULL );

	if( ExistsCollider() == True )
	{
		Mix::Scene::Common::ActorCollider* pCollider = m_pDynamicsFigure->GetColliderPtr();

		MIX_ADD_REF( pCollider );
		( *ppCollider ) = pCollider;
	}
	else
	{
		return False;
	}

	return True;
}

UInt32 ActorModel::GetSensorCount( void ) const
{
	return ( m_pDynamicsFigure != NULL )? m_pDynamicsFigure->GetSensorCount() : 0;
}

Boolean ActorModel::GetSensor( UInt32 index, Mix::Scene::IActorSensor** ppSensor )
{
	MIX_ASSERT( ppSensor != NULL );

	if( m_pDynamicsFigure == NULL )
	{
		return False;
	}

	Mix::Scene::Common::ActorSensor* pSensor = m_pDynamicsFigure->GetSensorPtr( index );
	if( pSensor != NULL )
	{
		MIX_ADD_REF( pSensor );
		( *ppSensor ) = pSensor;
	}
	else
	{
		return False;
	}

	return True;
}

Boolean ActorModel::ExistsKinematicCharacter( void ) const
{
	return ( ( m_pDynamicsFigure != NULL ) && ( m_pDynamicsFigure->GetCharacterPtr() != NULL ) );
}

Boolean ActorModel::GetKinematicCharacter( Mix::Scene::IActorKinematicCharacter** ppKinematicCharacter )
{
	MIX_ASSERT( ppKinematicCharacter != NULL );

	if( m_pDynamicsFigure == NULL )
	{
		return False;
	}

	Mix::Scene::Common::ActorKinematicCharacter* pKinematicCharacter = m_pDynamicsFigure->GetCharacterPtr();
	if( pKinematicCharacter != NULL )
	{
		MIX_ADD_REF( pKinematicCharacter );
		( *ppKinematicCharacter ) = pKinematicCharacter;
	}
	else
	{
		return False;
	}

	return True;
}

void ActorModel::GetDynamicsDirector( Mix::Scene::IActorDynamicsDirector** ppDynamicsDirector )
{
	MIX_ASSERT( ppDynamicsDirector != NULL );

	MIX_ADD_REF( m_pDynamicsDirector );
	( *ppDynamicsDirector ) = m_pDynamicsDirector;
}

void ActorModel::GetMotionMixer( Mix::Scene::IMotionMixer** ppMotionMixer )
{
	MIX_ASSERT( ppMotionMixer != NULL );

	MIX_ADD_REF( m_pMotionMixer );
	( *ppMotionMixer ) = m_pMotionMixer;
}

Boolean ActorModel::GetListener( Mix::Scene::IActorListener** ppListener )
{
	MIX_ASSERT( ppListener != NULL );

	if( m_pListener != NULL )
	{
		MIX_ADD_REF( m_pListener );
		( *ppListener ) = m_pListener;
	}
	else
	{
		return False;
	}

	return True;
}

void ActorModel::SetListener( Mix::Scene::IActorListener* pListener )
{
	MIX_RELEASE( m_pListener );

	MIX_ADD_REF( pListener );
	m_pListener = pListener;
}

const Mix::Matrix4x4& ActorModel::GetWorldMatrix( void ) const
{
	return m_WorldMat;
}

void ActorModel::SetWorldMatrix( const Mix::Matrix4x4& mat )
{
	MIX_ASSERT( m_pRevision != NULL );

	m_WorldMat = mat;
	m_pRevision->SetLocalTransform();
}

void ActorModel::Reset( UInt32 flags )
{
	MIX_ASSERT( m_NodeList.size() > 0 );

	Boolean bInitLocalMatrix = ( MIX_TESTBIT( flags, IActorModel::R_INIT_LOCAL_MATRIX ) == IActorModel::R_INIT_LOCAL_MATRIX );
	Boolean bUpdateWorldMatrix = ( MIX_TESTBIT( flags, IActorModel::R_UPDATE_WORLD_MATRIX ) == IActorModel::R_UPDATE_WORLD_MATRIX );

	//モーションミキサー
	if( bInitLocalMatrix == False )
	{
		m_pMotionMixer->Reset();
	}

	//ルート
	ResetRoot();

	//ノード
	ResetNode( m_RootMat, m_NodeList[0], bInitLocalMatrix, bUpdateWorldMatrix );

	//メッシュ
	RefreshMesh();

	//ダイナミクスコントローラー
	m_pDynamicsDirector->Reset();

	//オクトリーオブジェクト
	if( m_pOctObj != NULL )
	{
		m_pOctObj->Refresh();
	}

	//ステータス
	m_State.deltaTimer = 0.0f;
	m_State.farRatio = 1.0f;
	m_State.skipFrames = 0;
	m_State.curMaxSkipFrames = 0;

	m_FarRatio = 1.0f;
}

void ActorModel::Update( void )
{
	MIX_ASSERT( m_pDynamicsDirector != NULL );
	MIX_ASSERT( m_NodeList.size() > 0 );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 状態によっての設定の反映
	////////////////////////////////////////////////////////////////////////////////////////////////////

	m_State.deltaTimer = 0.0f;
	m_State.farRatio = m_FarRatio;
	m_State.skipFrames = 0;
	m_State.curMaxSkipFrames = 0;

	m_FarRatio = 1.0f;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 実行
	////////////////////////////////////////////////////////////////////////////////////////////////////

	//ダイナミクスコントローラー
	m_pDynamicsDirector->Update();

	//ルート
	UpdateRoot();
}

void ActorModel::Update( Float32 dt )
{
	MIX_ASSERT( m_pDynamicsDirector != NULL );
	MIX_ASSERT( m_pMotionMixer != NULL );
	MIX_ASSERT( m_NodeList.size() > 0 );

	UInt32 mmMask;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 状態によっての設定の反映
	////////////////////////////////////////////////////////////////////////////////////////////////////

	/*
		遠さ
	*/

	m_State.farRatio = m_FarRatio;
	m_FarRatio = 1.0f;

	/*
		モーション : 更新マスク
	*/

	if( IsValid() == True )
	{
		mmMask = IMotionMixer::ALL_FLAGS;
	}
	else
	{
		if( MIX_TESTBIT( m_Config.behaviorFlags, IActorModel::B_INVALID_ONLY_ROOT_MOTION ) == IActorModel::B_INVALID_ONLY_ROOT_MOTION )
		{
			mmMask = IMotionMixer::ROOT_TRANSFORM | IMotionMixer::FRAME_STEP;
		}
		else
		{
			mmMask = IMotionMixer::ALL_FLAGS;
		}
	}

	/*
		モーション : フレームのスキップ
	*/

	m_State.curMaxSkipFrames = 0;

	if( m_Config.maxSkipFrames > 0 )
	{
		if( ( MIX_TESTBIT( m_Config.behaviorFlags, IActorModel::B_INVISIBLE_SKIP_MOTION_FRAME ) == IActorModel::B_INVISIBLE_SKIP_MOTION_FRAME ) &&
			( IsVisible() == False ) )
		{
			m_State.curMaxSkipFrames = static_cast<UInt32>( static_cast<Float32>( m_Config.maxSkipFrames ) * m_State.farRatio );
		}

		if( ( m_State.curMaxSkipFrames == 0 ) &&
			( MIX_TESTBIT( m_Config.behaviorFlags, IActorModel::B_FAR_SKIP_MOTION_FRAME ) == IActorModel::B_FAR_SKIP_MOTION_FRAME ) &&
			( m_State.farRatio > MIX_FLOAT_EPSILON ) )
		{
			m_State.curMaxSkipFrames = static_cast<UInt32>( static_cast<Float32>( m_Config.maxSkipFrames ) * m_State.farRatio );
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 実行
	////////////////////////////////////////////////////////////////////////////////////////////////////

	//ダイナミクスコントローラー
	//このタイミングで行列(ワールド)の更新を予約( リビジョンカウンターは回さない )
	m_pDynamicsDirector->Update();

	//モーションミキサー
	//ダイナミクスによって予約されていない行列(ローカル)の更新を行う( リビジョンカウンターを回す )
	m_pMotionMixer->Update( dt, mmMask, m_State.curMaxSkipFrames, m_State.deltaTimer, m_State.skipFrames );

	//ルート
	UpdateRoot();
}

const Mix::Quaternion& ActorModel::GetAngularVelocity( void ) const
{
	return m_AngularVelocity;
}

const Mix::Vector3& ActorModel::GetLinearVelocity( void ) const
{
	return m_LinearVelocity;
}

void ActorModel::Refresh( void )
{
	MIX_ASSERT( m_NodeList.size() > 0 );
	MIX_ASSERT( m_pDynamicsDirector != NULL );

	//ダイナミクスコントローラー
	//ダイナミクスによって予約されている行列(ワールド)を更新する( リビジョンカウンターを回す )
	m_pDynamicsDirector->Refresh();

	//リビジョン
	if( m_RevisionCounter > 0 )
	{
		//ルート
		RefreshRoot();

		//ノード
		RefreshNode( m_RootMat, m_NodeList[0] );

		//メッシュ
		RefreshMesh();

		//オクトリーオブジェクト
		if( m_pOctObj != NULL )
		{
			m_pOctObj->Refresh();
		}

		//クリア
		m_RevisionCounter = 0;
	}
}

void ActorModel::Refresh1( void )
{
	MIX_ASSERT( m_NodeList.size() > 0 );
	MIX_ASSERT( m_pDynamicsDirector != NULL );

	//ダイナミクスコントローラー
	//ダイナミクスによって予約されている行列(ワールド)を更新する( リビジョンカウンターを回す )
	m_pDynamicsDirector->Refresh();

	//リビジョン
	if( m_RevisionCounter > 0 )
	{
		//ルート
		RefreshRoot();

		//ノード
		RefreshNode( m_RootMat, m_NodeList[0] );

		//メッシュ
		RefreshMesh();
	}
}

void ActorModel::Refresh2( void )
{
	//リビジョン
	if( m_RevisionCounter > 0 )
	{
		//オクトリーオブジェクト
		if( m_pOctObj != NULL )
		{
			m_pOctObj->Refresh();
		}

		//クリア
		m_RevisionCounter = 0;
	}
}

const Mix::Geometry::Sphere& ActorModel::GetBounds( void ) const
{
	return m_Bounds;
}

const Mix::Scene::IActorModel::STATE& ActorModel::GetState( void ) const
{
	return m_State;
}

Boolean ActorModel::IsVisible( void ) const
{
	return ( m_pOctObj != NULL )? m_pOctObj->IsVisible() : False;
}

Boolean ActorModel::IsVisible( UInt32 id ) const
{
	return ( m_pOctObj != NULL )? m_pOctObj->IsVisible( id ) : False;
}

Boolean ActorModel::IsValid( void ) const
{
	return ( m_pOctObj != NULL )? m_pOctObj->IsActive() : False;
}

Boolean ActorModel::IsValid( UInt32 id ) const
{
	return ( m_pOctObj != NULL )? m_pOctObj->IsActive( id ) : False;
}

Boolean ActorModel::IsIgnored( void ) const
{
	return ( m_pOctObj != NULL )? m_pOctObj->IsIllegal() : True;
}

void ActorModel::ResetRoot( void )
{
	MIX_ASSERT( m_pRevision != NULL );

	//ルート行列を求める
	m_RootMat = m_PivotMat * m_WorldMat;

	//リビジョンをクリア
	m_pRevision->Clear();
}

void ActorModel::ResetNode( const Mix::Matrix4x4& parentWorldMatrix, ActorNode* pNode, Boolean bInitLocalMatrix, Boolean bUpdateWorldMatrix )
{
	UInt32 childCount = pNode->GetChildCount();

	if( bInitLocalMatrix == True ) { pNode->ResetLocalMatrix(); }
	if( bUpdateWorldMatrix == True ) { pNode->Reset( parentWorldMatrix ); }

	for( UInt32 i = 0; i < childCount; i++ )
	{
		ResetNode( pNode->GetWorldMatrix(), pNode->GetChildPtr( i ), bInitLocalMatrix, bUpdateWorldMatrix );
	}
}

void ActorModel::UpdateRoot( void )
{
	MIX_ASSERT( m_pMotionMixer != NULL );

	Boolean bDynCtrl = False;
	Boolean bDynCtrlRD = False;
	Boolean bDynCtrlKC = False;
	Mix::Scene::Common::ActorKinematicCharacter* pDynKChar = NULL;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// トランスフォームをするかどうかの判定素材
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( m_pDynamicsFigure != NULL )
	{
		bDynCtrl = m_pDynamicsFigure->IsControl();
		bDynCtrlRD = m_pDynamicsFigure->IsControl_Ragdoll();
		bDynCtrlKC = m_pDynamicsFigure->IsControl_Character();
		pDynKChar = m_pDynamicsFigure->GetCharacterPtr();
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 速度
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( ( ( bDynCtrl == False ) && ( bDynCtrlRD == False ) && ( bDynCtrlKC == False )  ) ||
		( ( bDynCtrl == True  ) && ( bDynCtrlRD == False ) && ( bDynCtrlKC == True ) ) )
	{
		Mix::Quaternion pose;

		/*
			速度を初期化
		*/

		m_AngularVelocity = m_pMotionMixer->GetAngularVelocity();
		m_LinearVelocity = m_pMotionMixer->GetLinearVelocity();

		/*
			回転
		*/

		//モーション
		m_AngularVelocity = m_pMotionMixer->GetAngularVelocity();

		//キネマティックキャラクター
		if( pDynKChar != NULL )
		{
			m_AngularVelocity = ( m_AngularVelocity * pDynKChar->GetAngularVelocity() ).ToNormalize();
		}

		if( bDynCtrl == True )
		{
			MIX_ASSERT( pDynKChar != NULL );
			pose = pDynKChar->GetWorldRotation();
		}
		else
		{
			pose = m_WorldMat.GetRotation();
		}

		pose = pose * m_AngularVelocity;
		pose = pose.ToNormalize();

		//リスナー : ルートトランスフォームの空間を問い合わせる
		if( m_pListener != NULL )
		{
			Mix::Scene::IActorListener::RT_SPACE_EVENT_ARGS rtSpaceEventArgs;

			rtSpaceEventArgs.pose = pose;

			m_pListener->OnRTQuerySpace( this, rtSpaceEventArgs );

			pose = rtSpaceEventArgs.pose;
		}

		/*
			移動
		*/

		//モーション
		m_LinearVelocity = Mix::Matrix4x4( pose ) * m_pMotionMixer->GetLinearVelocity();

		//キネマティックキャラクター
		if( pDynKChar != NULL )
		{
			m_LinearVelocity += pDynKChar->GetLinearVelocity();
		}

		//リスナー : ルートトランスフォーム適用前を通知する
		if( m_pListener != NULL )
		{
			Mix::Scene::IActorListener::RT_APPLY_EVENT_ARGS rtApplyEventArgs;

			rtApplyEventArgs.angularVelocity = m_AngularVelocity;
			rtApplyEventArgs.linearVelocity = m_LinearVelocity;

			m_pListener->OnRTPreApply( this, rtApplyEventArgs );

			m_AngularVelocity = rtApplyEventArgs.angularVelocity;
			m_LinearVelocity = rtApplyEventArgs.linearVelocity;
		}

		/*
			適用
		*/

		if( bDynCtrl == True )
		{
			MIX_ASSERT( pDynKChar != NULL );
			pDynKChar->ApplyVelocity( m_AngularVelocity, m_LinearVelocity );
		}
	}
	else
	{
		/*
			速度を適用することができないため、クリア
		*/

		m_AngularVelocity = Mix::Quaternion::Identity();
		m_LinearVelocity = Mix::Vector3::Zero();
	}
}

void ActorModel::RefreshRoot( void )
{
	MIX_ASSERT( m_pRevision != NULL );

	if( m_pRevision->IsControlWorldTransform() == True )
	{
		//ワールド行列( m_RootMat )はダイナミクスによって更新される
		if( m_pRevision->IsWorldTransform() == True )
		{
			m_WorldMat = m_InvPivotMat * m_RootMat;
		}
	}
	else
	{
		//ローカル行列( m_WorldMat )は自身( モデル )によって更新される
		Mix::Vector3 worldS;
		Mix::Quaternion worldR;
		Mix::Vector3 worldT;

		m_WorldMat.Decompose( worldS, worldR, worldT );

		worldR = ( worldR * m_AngularVelocity ).ToNormalize();
		worldT = worldT + m_LinearVelocity;

		m_WorldMat = Mix::Matrix4x4( worldS, worldR, worldT );
		m_RootMat = m_PivotMat * m_WorldMat;
	}

	m_pRevision->Clear();
}

void ActorModel::RefreshNode( const Mix::Matrix4x4& parentWorldMatrix, ActorNode* pNode )
{
	MIX_ASSERT( pNode != NULL );

	UInt32 childCount = pNode->GetChildCount();

	pNode->Refresh( parentWorldMatrix );

	if( childCount > 0 )
	{
		Mix::Scene::Common::ActorNode* const* ppChild = pNode->GetChilds();
		Mix::Scene::Common::ActorNode* const* ppChildEnd = ppChild + childCount;

		const Mix::Matrix4x4& worldMat = pNode->GetWorldMatrix();

		while( ppChild != ppChildEnd )
		{
			RefreshNode( worldMat, *ppChild );
			ppChild++;
		}
	}
}

void ActorModel::RefreshMesh( void )
{
	UIntT meshNum = m_MeshList.size();

	if( meshNum == 0 )
	{
		return;
	}

	Mix::Scene::Common::ActorMesh** ppMesh = &( m_MeshList[0] );
	Mix::Scene::Common::ActorMesh** ppMeshEnd = ppMesh + meshNum;

	Mix::Scene::Common::ActorMesh* pMesh;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 最初の一つ目をリフレッシュ( 境界の初期値を設定するため )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pMesh = *ppMesh;

	pMesh->Update();
	m_Bounds = pMesh->GetBounds();

	ppMesh++;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 二つ目以降をリフレッシュ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	while( ppMesh != ppMeshEnd )
	{
		pMesh = *ppMesh;

		pMesh->Update();
		m_Bounds += pMesh->GetBounds();

		ppMesh++;
	}
}

Boolean ActorModel::Clone(	Mix::Scene::IActorModel** ppActorModel, UInt32 flags )
{
	if( ppActorModel == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : Name[%s]", ActorModel::FAILED_CLONE, Mix::STR_ILLEGALARG, m_Name.GetConstPtr() );
		return False;
	}

	Boolean bSharedMaterial = ( MIX_TESTBIT( flags, IActorModel::C_SHARED_MATERIAL ) == IActorModel::C_SHARED_MATERIAL );
	Boolean bSharedMotion = ( MIX_TESTBIT( flags, IActorModel::C_SHARED_MOTION ) == IActorModel::C_SHARED_MOTION );
	Boolean bDupMotionEntries = ( MIX_TESTBIT( flags, IActorModel::C_DUPLICATE_MOTION_ENTRIES ) == IActorModel::C_DUPLICATE_MOTION_ENTRIES );

	UIntT nodeCount = m_NodeList.size();
	ActorNode** srcNodeList = &( m_NodeList[0] );

	ActorNode** dstNodeList = NULL;
	ActorDynamicsCluster* pCastMotionCluster = NULL;
	std::map<Mix::Dynamics::IRigidBody*, Mix::Dynamics::IRigidBody*> rbPair;

	Mix::Scene::Common::MotionMixer* pDstMotMixer = NULL;
	Mix::Scene::Common::ActorDynamicsDirector* pDstDynCtrl = NULL;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// インターフェースを作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	ActorModel* pActorModel = ActorModel::CreateInstance( m_Name.GetConstPtr() );
	if( pActorModel == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : Name[%s]", ActorModel::FAILED_CLONE, Mix::STR_OUTOFMEMORY, m_Name.GetConstPtr() );
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 初期化
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( pActorModel->Initialize( MIX_UIT_TO_UI32( m_NodeList.size() ) ) == True )
	{
		pDstMotMixer = pActorModel->m_pMotionMixer;
		pDstDynCtrl = pActorModel->m_pDynamicsDirector;
	}
	else
	{
		MIX_LOG_ERROR( L"%s : %s : Name[%s]", ActorModel::FAILED_CLONE, Mix::STR_OUTOFMEMORY, m_Name.GetConstPtr() );
		MIX_RELEASE( pActorModel );
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// エンティティの設定
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pActorModel->SetDraw( IsDraw() );
	pActorModel->SetLocalLighting( IsLocalLighting() );
	pActorModel->SetTransparencyPriority( GetTransparencyPriority() );
	pActorModel->SetDefaultWaterContainsResult( GetDefaultWaterContainsResult() );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// マテリアルを複製
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( Model::CloneMaterials( pActorModel, bSharedMaterial ) == False )
	{
		MIX_LOG_ERROR( L"%s : %s : Name[%s]", ActorModel::FAILED_CLONE, Mix::STR_OUTOFMEMORY, m_Name.GetConstPtr() );
		MIX_RELEASE( pActorModel );
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// モーションコントローラーを複製
	////////////////////////////////////////////////////////////////////////////////////////////////////

	UInt32 motCtrlCount = m_pMotionMixer->GetControllerCount();

	pDstMotMixer->ReserveControllerList( m_pMotionMixer->GetControllerCount() );

	for( UInt32 i = 0; i < motCtrlCount; i++ )
	{
		MotionController* pSrcMotCtrl = m_pMotionMixer->GetControllerPtr( i );
		MotionController* pDstMotCtrl = pDstMotMixer->AddController( pSrcMotCtrl->GetName(), pSrcMotCtrl->GetPriority() );

		if( pDstMotCtrl == NULL )
		{
			MIX_LOG_ERROR( L"%s : %s : Name[%s]", ActorModel::FAILED_CLONE, Mix::STR_OUTOFMEMORY, m_Name.GetConstPtr() );
			MIX_RELEASE( pActorModel );
			return False;
		}

		if( pSrcMotCtrl->CloneMotion( pDstMotCtrl, bSharedMotion, bDupMotionEntries ) == False )
		{
			MIX_LOG_ERROR( L"%s : %s : Name[%s]", ActorModel::FAILED_CLONE, Mix::STR_OUTOFMEMORY, m_Name.GetConstPtr() );
			MIX_RELEASE( pActorModel );
			return False;
		}
	}

	pDstMotMixer->CreateControllerIndexMap();

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// メインフレームの複製１
	// ダイナミクスフィギュアの複製１
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pActorModel->SetPivotMatrix( m_PivotMat );

	if( m_pDynamicsFigure != NULL )
	{
		ActorDynamicsFigure* pDstDynFigure = m_pDynamicsFigure->Clone();

		if( pDstDynFigure != NULL )
		{
			ActorCollider* pCollider1 = pDstDynFigure->GetColliderPtr();

			if( pCollider1 != NULL )
			{
				//ジョイントフレームのリジッドボディ検索用
				ActorCollider* pCollider0 = m_pDynamicsFigure->GetColliderPtr();

				MIX_ASSERT( pCollider0 != NULL );
				MIX_ASSERT( pCollider0->GetInternalRigidBodyPtr() != NULL );
				MIX_ASSERT( pCollider1->GetInternalRigidBodyPtr() != NULL );

				Mix::Dynamics::IRigidBody* pRigidBody0 = pCollider0->GetInternalRigidBodyPtr();
				Mix::Dynamics::IRigidBody* pRigidBody1 = pCollider1->GetInternalRigidBodyPtr();

				rbPair.insert( std::pair<Mix::Dynamics::IRigidBody*, Mix::Dynamics::IRigidBody*>( pRigidBody0, pRigidBody1 ) );
			}

			//メッソドを使用して、リンク(ワールド行列のポインタ)を設定
			pActorModel->SetDynamicsFigure( pDstDynFigure );
			pDstDynCtrl->SetFigure( pDstDynFigure );
			MIX_RELEASE( pDstDynFigure );
		}
		else
		{
			MIX_LOG_ERROR( L"%s : %s : Name[%s]", ActorModel::FAILED_CLONE, Mix::STR_OUTOFMEMORY, m_Name.GetConstPtr() );
			MIX_RELEASE( pActorModel );
			return False;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ノードの複製１
	// ダイナミクスパートの複製１
	// モーションミキサーのポーズテーブルを作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	dstNodeList = pActorModel->GetNodeList();
	pDstMotMixer->ReservePoseTable( nodeCount );

	for( UIntT i = 0; i < nodeCount; i++ )
	{
		////////////////////////////////////////////////////////////////////////////////////////////////////

		ActorNode* pSrcNode = srcNodeList[i];
		ActorNode* pDstNode = dstNodeList[i];

		Int32 parentIndex = pSrcNode->GetParentIndex();

		Mix::Scene::Common::ActorMesh* pSrcMesh = pSrcNode->GetMeshPtr();
		Mix::Scene::Common::ActorMesh* pDstMesh = NULL;

		Mix::Scene::Common::ActorDynamicsPart* pSrcDynPart = pSrcNode->GetDynamicsPartPtr();
		Mix::Scene::Common::ActorDynamicsPart* pDstDynPart = NULL;

		const ActorNode::ConstraintMap& constraintMap = pSrcNode->GetConstraintMap();
		ActorNode::ConstraintMap::const_iterator it_cr_begin = constraintMap.begin();
		ActorNode::ConstraintMap::const_iterator it_cr_end = constraintMap.end();
		ActorNode::ConstraintMap::const_iterator it_cr;

		if( pSrcMesh != NULL )
		{
			if( pSrcMesh->Clone( &pDstMesh ) == False )
			{
				MIX_LOG_ERROR( L"%s : %s : Name[%s]", ActorModel::FAILED_CLONE, Mix::STR_OUTOFMEMORY, m_Name.GetConstPtr() );
				MIX_RELEASE( pActorModel );
				return False;
			}
		}

		if( pSrcDynPart != NULL )
		{
			pDstDynPart = pSrcDynPart->Clone();
			if( pDstDynPart != NULL )
			{
				ActorCollider* pCollider1 = pDstDynPart->GetColliderPtr();

				if( pCollider1 != NULL )
				{
					ActorCollider* pCollider0 = pSrcDynPart->GetColliderPtr();

					MIX_ASSERT( pCollider0 != NULL );
					MIX_ASSERT( pCollider0->GetInternalRigidBodyPtr() != NULL );
					MIX_ASSERT( pCollider1->GetInternalRigidBodyPtr() != NULL );

					Mix::Dynamics::IRigidBody* pRigidBody0 = pCollider0->GetInternalRigidBodyPtr();
					Mix::Dynamics::IRigidBody* pRigidBody1 = pCollider1->GetInternalRigidBodyPtr();

					rbPair.insert( std::pair<Mix::Dynamics::IRigidBody*, Mix::Dynamics::IRigidBody*>( pRigidBody0, pRigidBody1 ) );

					if( pCollider1->IsCastMotion() == True )
					{
						MIX_ASSERT( pCastMotionCluster == NULL );
						pCastMotionCluster = pDstDynPart;
					}
				}
			}
			else
			{
				MIX_LOG_ERROR( L"%s : %s : Name[%s]", ActorModel::FAILED_CLONE, Mix::STR_OUTOFMEMORY, m_Name.GetConstPtr() );
				MIX_RELEASE( pActorModel );
				return False;
			}
		}

		pDstNode->SetName( pSrcNode->GetName() );
		pDstNode->SetGeometricMatrix( pSrcNode->GetGeometricMatrix() );
		pDstNode->SetDefLocalMatrix( pSrcNode->GetDefLocalMatrix() );
		pDstNode->SetMesh( pDstMesh );
		pDstNode->SetParent( parentIndex, ( parentIndex >= 0 )? dstNodeList[parentIndex] : NULL );
		pDstNode->ReserveChilds( pSrcNode->GetChildCount() );

		if( pDstDynPart != NULL )
		{
			pDstNode->SetDynamicsPart( pDstDynPart );
			pDstDynCtrl->AddPart( pDstDynPart );
		}

		for( it_cr = it_cr_begin; it_cr != it_cr_end; ++it_cr )
		{
			const ActorConstraint* pSrcConstraint = it_cr->second;
			IActorConstraint* pDstConstraint = NULL;

			if( pDstNode->AddConstraint( pSrcConstraint->GetName(), &pDstConstraint ) == True )
			{
				pDstConstraint->SetLocalMatrix( pSrcConstraint->GetLocalMatrix() );
				MIX_RELEASE( pDstConstraint );
			}
			else
			{
				MIX_LOG_ERROR( L"%s : %s : Name[%s]", ActorModel::FAILED_CLONE, Mix::STR_OUTOFMEMORY, m_Name.GetConstPtr() );
				MIX_RELEASE( pDstDynPart );
				MIX_RELEASE( pDstMesh );
				MIX_RELEASE( pActorModel );
				return False;
			}
		}

		MIX_RELEASE( pDstDynPart );
		MIX_RELEASE( pDstMesh );

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

		const MotionMixer::POSE& srcPose = m_pMotionMixer->GetPose( i );

		pDstMotMixer->AddPose(	srcPose.defScaling,
								srcPose.defRotation,
								srcPose.defTranslation,
								pDstNode->GetLocalMatrixPtr(),
								pDstNode->GetRevisionPtr() );
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 強制アップデート
	//  ジョイントフレームの設定のため、初期姿勢にする
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pActorModel->Reset( IActorModel::R_UPDATE_WORLD_MATRIX );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// メインフレームの複製２
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( m_pDynamicsFigure != NULL )
	{
		Mix::Scene::Common::ActorDynamicsFigure* pSrcDynFigure = m_pDynamicsFigure;
		Mix::Scene::Common::ActorDynamicsFigure* pDstDynFigure = pActorModel->GetDynamicsFigurePtr();

		MIX_ASSERT( pDstDynFigure != NULL );

		if( pCastMotionCluster != NULL )
		{
			pDstDynFigure->SetCastMotionCluster( pCastMotionCluster );
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ノードの複製２
	// ダイナミクスパートの複製２
	////////////////////////////////////////////////////////////////////////////////////////////////////

	for( UIntT i = 0; i < nodeCount; i++ )
	{
		ActorNode* pSrcNode = srcNodeList[i];
		ActorNode* pDstNode = dstNodeList[i];

		Mix::Scene::Common::ActorDynamicsPart* pSrcDynPart = pSrcNode->GetDynamicsPartPtr();

		if( pSrcDynPart != NULL )
		{
			Mix::Scene::Common::ActorDynamicsPart* pDstDynPart = pDstNode->GetDynamicsPartPtr();
			MIX_ASSERT( pDstDynPart != NULL );

			if( pSrcDynPart->CloneFinish( rbPair, pDstDynPart, m_Name.GetConstPtr() ) == False )
			{
				MIX_LOG_ERROR( L"%s : %s : Name[%s]", ActorModel::FAILED_CLONE, Mix::STR_OUTOFMEMORY, m_Name.GetConstPtr() );
				return False;
			}
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ファイナライズ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pActorModel->Finalize();

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 譲渡
	////////////////////////////////////////////////////////////////////////////////////////////////////

	( *ppActorModel ) = pActorModel;

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

	return True;
}

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

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

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

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

Float32 ActorModel::Debug_GetDrawAxisScaling( void ) const
{
#ifdef _DEBUG
	return m_DebugDrawAxisScaling;
#else //_DEBUG
	return 0;
#endif //_DEBUG
}

void ActorModel::Debug_SetDrawAxisScaling( Float32 scaling )
{
#ifdef _DEBUG
	m_DebugDrawAxisScaling = max( 0.0f, scaling );
#endif //_DEBUG
}

Float32 ActorModel::Debug_GetDrawJointFrameMinSize( void ) const
{
#ifdef _DEBUG
	return m_DebugDrawJointFrameMinSize;
#else //_DEBUG
	return 0;
#endif //_DEBUG
}

void ActorModel::Debug_SetDrawJointFrameMinSize( Float32 minSize )
{
#ifdef _DEBUG
	m_DebugDrawJointFrameMinSize = max( 0.0f, minSize );
#endif //_DEBUG
}

Float32 ActorModel::Debug_GetDrawJointLimitScaling( void ) const
{
#ifdef _DEBUG
	return m_DebugDrawJointLimitScaling;
#else //_DEBUG
	return 0;
#endif //_DEBUG
}

void ActorModel::Debug_SetDrawJointLimitScaling( Float32 scaling )
{
#ifdef _DEBUG
	m_DebugDrawJointLimitScaling = max( 0.0f, scaling );
#endif //_DEBUG
}

UInt32 ActorModel::GetMaterialSlotCount( void ) const
{
	return Model::GetMaterialSlotCount();
}

const wchar_t* ActorModel::GetMaterialSlotName( UInt32 slotIndex ) const
{
	return Model::GetMaterialSlotName( slotIndex );
}

UInt32 ActorModel::GetMaterialSlotIndex( const wchar_t* pSlotName )
{
	return Model::GetMaterialSlotIndex( pSlotName );
}

Boolean ActorModel::GetMaterialByIndex( UInt32 slotIndex, Mix::Scene::IMaterial** ppMaterial )
{
	return Model::GetMaterialByIndex( slotIndex, ppMaterial );
}

Boolean ActorModel::GetMaterialByName( const wchar_t* pSlotName, Mix::Scene::IMaterial** ppMaterial )
{
	return Model::GetMaterialByName( pSlotName, ppMaterial );
}

Boolean ActorModel::SetMaterialByIndex( UInt32 slotIndex, Mix::Scene::IMaterial* pMaterial )
{
	return Model::SetMaterialByIndex( slotIndex, pMaterial );
}

Boolean ActorModel::SetMaterialByName( const wchar_t* pSlotName, Mix::Scene::IMaterial* pMaterial )
{
	return Model::SetMaterialByName( pSlotName, pMaterial );
}

Boolean ActorModel::IsDraw( void ) const
{
	return m_bDraw;
}

void ActorModel::SetDraw( Boolean state )
{
	m_bDraw = state;
}

Boolean ActorModel::IsLocalLighting( void ) const
{
	return m_bLocalLighting;
}

void ActorModel::SetLocalLighting( Boolean state )
{
	m_bLocalLighting = state;
}

UInt32 ActorModel::GetTransparencyPriority( void ) const
{
	return m_TRPriority;
}

void ActorModel::SetTransparencyPriority( UInt32 priority )
{
	m_TRPriority = priority;
}

Mix::Scene::WATER_CONTAINS_RESULT ActorModel::GetDefaultWaterContainsResult( void ) const
{
	return m_DefWCResult;
}

void ActorModel::SetDefaultWaterContainsResult( Mix::Scene::WATER_CONTAINS_RESULT result )
{
	m_DefWCResult = result;
}

Mix::Scene::IRendererObject::TYPE ActorModel::GetType( void ) const
{
	return Mix::Scene::IRendererObject::ACTOR_MODEL;
}

Boolean ActorModel::IsRendering( void ) const
{
	return RendererObject::IsRendering();
}

#ifdef _DEBUG

void ActorModel::Debug_Draw( Mix::Graphics::Utility::IPerspectiveRenderer* pPerspectiveRenderer, UInt32 flags )
{
	Mix::Matrix4x4 oldMat = pPerspectiveRenderer->GetMatrix();
	Mix::Vector4 oldColor = pPerspectiveRenderer->GetColor();

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 自身
	////////////////////////////////////////////////////////////////////////////////////////////////////

	/*
		軸
	*/

	if( MIX_TESTBIT( flags, Mix::Scene::DDF_ACTORMODEL_AXIS ) == Mix::Scene::DDF_ACTORMODEL_AXIS )
	{
		pPerspectiveRenderer->SetMatrix( m_WorldMat );
		pPerspectiveRenderer->SetColor( Mix::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
		pPerspectiveRenderer->AddAxis( m_DebugDrawAxisScaling );
	}

	/*
		境界
	*/

	if( MIX_TESTBIT( flags, Mix::Scene::DDF_ACTORMODEL_BOUNDS ) == Mix::Scene::DDF_ACTORMODEL_BOUNDS )
	{
		pPerspectiveRenderer->SetMatrix( Mix::Matrix4x4::Identity() );
		pPerspectiveRenderer->SetColor( Mix::Scene::Common::Debug::GetDrawColor( Mix::Scene::DDC_BOUNDS ) );
		pPerspectiveRenderer->AddSphere( m_Bounds );
	}

	/*
		ダイナミクスフィギュア
	*/

	if( m_pDynamicsFigure != NULL )
	{
		m_pDynamicsFigure->Debug_Draw(	flags,
										pPerspectiveRenderer,
										m_DebugDrawAxisScaling,
										m_DebugDrawJointFrameMinSize,
										m_DebugDrawJointLimitScaling );
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ノード
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( m_NodeList.size() != 0 )
	{
		ActorModel::NodeList::iterator it_node_begin = m_NodeList.begin();
		ActorModel::NodeList::iterator it_node_end = m_NodeList.end();
		ActorModel::NodeList::iterator it_node;

		for( it_node = it_node_begin; it_node != it_node_end; ++it_node )
		{
			( *it_node )->Debug_Draw(	flags,
										pPerspectiveRenderer,
										m_DebugDrawAxisScaling,
										m_DebugDrawJointFrameMinSize,
										m_DebugDrawJointLimitScaling );
		}
	}

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

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

#endif //_DEBUG

}}}
