#include "StdAfx.h" #include "EtAniObject.h" #include "EtSaveMat.h" #ifdef _DEBUG #define new new(_NORMAL_BLOCK,__FILE__,__LINE__) #endif using namespace EternityEngine; CSyncLock CEtAniObject::s_CalcAniLock; CEtAniObject::CEtAniObject(void) { m_bShadowCast = true; m_bShadowReceive = false; m_nCalcPositionFlag = CALC_POSITION_Y; m_nSaveMatIndex = -1; EnableLightMapInfluence( true ); m_bSkipPhysics = false; m_bForceSkipSimulateAni = false; m_nExtraAniIndex = -1; m_fExtraAniFrame = 0.0f; m_bAniObject = true; } CEtAniObject::~CEtAniObject(void) { SAFE_RELEASE_SPTR( m_hAni ); } int CEtAniObject::Initialize( EtSkinHandle hSkin, EtAniHandle hAni ) { bool bSkinReady, bAniReady; m_hSkin = hSkin; m_hAni = hAni; m_pSkinInstance = new CEtSkinInstance(); bSkinReady = !m_hSkin->AddCallback( this ); bAniReady = false; if( m_hAni ) { bAniReady = !m_hAni->AddCallback( this ); if( ( bSkinReady ) && ( bAniReady ) ) { if( m_hSkin->GetMeshHandle() ) { m_hSkin->GetMeshHandle()->LinkToAni( m_hAni ); } } } if( bSkinReady ) { CommonInitialize(); } SetCollisionGroup( COLLISION_GROUP_DYNAMIC( 1 ) ); SetTargetCollisionGroup( COLLISION_GROUP_STATIC( 1 ) ); return ET_OK; } EtMatrix *CEtAniObject::GetBoneTransMat( int nBoneIndex ) { EtMatrix BoneWorldMat; static EtMatrix BoneMat; nBoneIndex = m_hAni->ConvertBoneIndex( nBoneIndex ); if( !GetEtSaveMat()->IsValidIndex( m_nSaveMatIndex ) ) { CalcAni(); } std::vector< EtMatrix > &vecInvWordlList = GetMesh()->GetInvWorldMatList(); // Àӽà siva - ¿¡¼­ ¿¡·¯Ã³¸®·Î ¹Ù²ß´Ï´Ù. if( nBoneIndex < 0 || nBoneIndex >= (int)vecInvWordlList.size() ) { _ASSERT(0&&"º» À妽º°¡ À߸øµÌ½À´Ï´Ù."); } else { EtMatrixInverse( &BoneWorldMat, NULL, &vecInvWordlList[ nBoneIndex ] ); if( GetEtSaveMat()->IsValidIndex( m_nSaveMatIndex + nBoneIndex ) ) { return EtMatrixMultiply( &BoneMat, &BoneWorldMat, GetEtSaveMat()->GetMatrix( m_nSaveMatIndex + nBoneIndex ) ); } } EtMatrixIdentity( &BoneMat ); return &BoneMat; } EtMatrix *CEtAniObject::GetDummyTransMat( int nDummyIndex ) { EtMeshHandle hMesh = m_hSkin->GetMeshHandle(); if( hMesh ) { std::vector< EtMatrix > &vecDummyMat = hMesh->GetDummyMatrixList(); std::vector< std::string > &vecParentName = hMesh->GetDummyParentNameList(); if( nDummyIndex < ( int )vecDummyMat.size() ) { static EtMatrix ReturnMat; int nParentIndex = -1; if( m_hAni ) { nParentIndex = m_hAni->GetBoneIndex( vecParentName[ nDummyIndex ].c_str() ); } if( nParentIndex == -1 ) { ReturnMat = vecDummyMat[ nDummyIndex ]; } else { EtMatrixMultiply( &ReturnMat, &vecDummyMat[ nDummyIndex ], GetBoneTransMat( nParentIndex ) ); } return &ReturnMat; } } return NULL; } EtMatrix *CEtAniObject::GetBoneMat( int nBoneIndex ) { nBoneIndex = m_hAni->ConvertBoneIndex( nBoneIndex ); if( !GetEtSaveMat()->IsValidIndex( m_nSaveMatIndex ) ) { CalcAni(); } if( GetEtSaveMat()->IsValidIndex( m_nSaveMatIndex ) ) { return GetEtSaveMat()->GetMatrix( m_nSaveMatIndex + nBoneIndex ); } return NULL; } void CEtAniObject::ResetAniFrame() { m_vecAniInfo.clear(); m_vecBlendAniInfo.clear(); m_vecDisableBone.clear(); m_vecBoneRotation.clear(); m_vecBoneScale.clear(); m_nSaveMatIndex = -1; } void CEtAniObject::SetAniFrame( int nAni, float fFrame, int nBoneIndex ) { ASSERT( fFrame >= 0.0f ); if( nBoneIndex == 0 ) // ¼ÂÆÃÇÏ´Â º»ÀÌ ·çÆ®º»ÀÏ °æ¿ì´Â ¸ðµç ¾Ö´Ï¸ÞÀ̼ÇÀ» ÃʱâÈ­ ½ÃÄÑÁØ´Ù. { ResetAniFrame(); } SAniInfo AniInfo; if( nAni == -1 ) return; AniInfo.BoneAniInfo.nAni = nAni; AniInfo.BoneAniInfo.fFrame = fFrame; AniInfo.nBoneIndex = nBoneIndex; m_vecAniInfo.push_back( AniInfo ); } void CEtAniObject::BlendAniFrame( int nBlendAni, float fBlendFrame, float fBlendWeight, int nBlendBoneIndex ) { SAniInfo AniInfo; if( nBlendAni == -1 ) return; if( fBlendWeight < 0.0f || fBlendWeight > 10.0f ) { ASSERT( 0 && "À߸øµÈ ºí·»µå ¿þÀÌÆ® °ª" ); return; } AniInfo.BoneAniInfo.nAni = nBlendAni; AniInfo.BoneAniInfo.fFrame = fBlendFrame; AniInfo.BoneAniInfo.fWeight = fBlendWeight; AniInfo.nBoneIndex = nBlendBoneIndex; m_vecBlendAniInfo.push_back( AniInfo ); m_vecDisableBone.resize( m_vecBlendAniInfo.size() ); } void CEtAniObject::BlendAniFrame( int nBlendAni, float fBlendFrame, float fBlendWeight, int nBlendBoneIndex, std::vector< int > &vecDisableBone ) { BlendAniFrame( nBlendAni, fBlendFrame, fBlendWeight, nBlendBoneIndex ); int nBlendCount = ( int )m_vecBlendAniInfo.size(); if( nBlendCount == 0 ) { return; } if( !vecDisableBone.empty() ) { m_vecDisableBone[ nBlendCount - 1 ].resize( vecDisableBone.size() ); std::copy( vecDisableBone.begin(), vecDisableBone.end(), m_vecDisableBone[ nBlendCount - 1 ].begin() ); } } void CEtAniObject::BlendAniFrame( int nBlendAni, float fBlendFrame, float fBlendWeight, int nBlendBoneIndex, int nDisableBoneIndex ) { BlendAniFrame( nBlendAni, fBlendFrame, fBlendWeight, nBlendBoneIndex ); int nBlendCount = ( int )m_vecBlendAniInfo.size(); if( nBlendCount == 0 ) { return; } if( nDisableBoneIndex != -1 ) { m_vecDisableBone[ nBlendCount - 1 ].insert( m_vecDisableBone[ nBlendCount - 1 ].begin(), nDisableBoneIndex ); } // ¹Ì¸® CalcAni()°¡ ºÒ·Á¼­ m_nSaveMatIndex°¡ ValidÇÑ °ªÀÌ¶óµµ Áß°£¿¡ BlendAni³ª SetBoneRotationÀÌ ºÒ¸®¸é // m_nSaveMatIndex°¡ InvalidÇÔÀ» Ç¥½ÃÇÑ´Ù ÀÌ·¸°Ô ÇÏ´Â ÀÌÀ¯´Â m_nSaveMatIndex¸¦ -1·Î ¹Ù²ãÁÙ °æ¿ì ¾Ö´Ï¸ÞÀÌ¼Ç °è»ê µÇ¸é¼­ // °è¼Ó ¸Þ¸ð¸®°¡ ÇÒ´ç µÉ °¡´É¼ºÀÌ ÀÖ´Ù. m_bValidSaveMatIndex = false; } void CEtAniObject::SetBoneRotation( int nBoneIndex, EtVector3 &BoneRotation ) { SBoneRotationInfo BoneRotationInfo; if( nBoneIndex == -1 ) { ASSERT( 0 && "Rotate Bone Index -1" ); return; } BoneRotationInfo.nBoneIndex = nBoneIndex; BoneRotationInfo.BoneRotation = BoneRotation; m_vecBoneRotation.push_back( BoneRotationInfo ); // ¹Ì¸® CalcAni()°¡ ºÒ·Á¼­ m_nSaveMatIndex°¡ ValidÇÑ °ªÀÌ¶óµµ Áß°£¿¡ BlendAni³ª SetBoneRotationÀÌ ºÒ¸®¸é // m_nSaveMatIndex°¡ InvalidÇÔÀ» Ç¥½ÃÇÑ´Ù ÀÌ·¸°Ô ÇÏ´Â ÀÌÀ¯´Â m_nSaveMatIndex¸¦ -1·Î ¹Ù²ãÁÙ °æ¿ì ¾Ö´Ï¸ÞÀÌ¼Ç °è»ê µÇ¸é¼­ // °è¼Ó ¸Þ¸ð¸®°¡ ÇÒ´ç µÉ °¡´É¼ºÀÌ ÀÖ´Ù. m_bValidSaveMatIndex = false; } void CEtAniObject::SetBoneScale( int nBoneIndex, float fScale ) { SBoneScaleInfo BoneScaleInfo; if( nBoneIndex == -1 ) { ASSERT( 0 && "Scale Bone Index -1" ); return; } BoneScaleInfo.nBoneIndex = nBoneIndex; BoneScaleInfo.fScale = fScale; m_vecBoneScale.push_back( BoneScaleInfo ); m_bValidSaveMatIndex = false; } void CEtAniObject::ReBuildSkin( EtSkinHandle hSkin ) { if( ! hSkin ) return; SAFE_RELEASE_SPTR( m_hSkin ); SAFE_DELETE( m_pSkinInstance ); bool bSkinReady, bAniReady; m_hSkin = hSkin; m_pSkinInstance = new CEtSkinInstance(); bSkinReady = !m_hSkin->AddCallback( this ); bAniReady = false; if( m_hAni ) { bAniReady = !m_hAni->AddCallback( this ); if( ( bSkinReady ) && ( bAniReady ) ) { if( m_hSkin->GetMeshHandle() ) { m_hSkin->GetMeshHandle()->LinkToAni( m_hAni ); } } } if( bSkinReady ) { CommonInitialize(); } } void CEtAniObject::CalcAni() { // ´Ù¸¥ ¾²·¹µå¿¡¼­ µ¿½Ã¿¡ È£ÃâµÇ´Â °æ¿ì ÀÖ´Ù.. ¸·¾Æ¾ß ÇÑ´Ù.. ScopeLock< CSyncLock > Lock( s_CalcAniLock ); if( !m_hAni ) { return; } int i, j; m_hAni->Reset(); m_hAni->SetCalcPositionFlag( m_nCalcPositionFlag ); if( m_nExtraAniIndex != -1 ) { SBoneAniInfo BoneInfo; BoneInfo.nAni = m_nExtraAniIndex; BoneInfo.fFrame = m_fExtraAniFrame; BoneInfo.fWeight = 0.0f; m_hAni->SetAni( &BoneInfo, 0 ); } else { for( i = 0; i < ( int )m_vecAniInfo.size(); i++ ) { m_hAni->SetAni( &m_vecAniInfo[ i ].BoneAniInfo, m_vecAniInfo[ i ].nBoneIndex ); } for( i = 0; i < ( int )m_vecBlendAniInfo.size(); i++ ) { for( j = 0; j < ( int )m_vecDisableBone[ i ].size(); j++ ) { m_hAni->EnableBlend( m_vecDisableBone[ i ][ j ], false ); } m_hAni->BlendAni( &m_vecBlendAniInfo[ i ].BoneAniInfo, m_vecBlendAniInfo[ i ].nBoneIndex ); for( j = 0; j < ( int )m_vecDisableBone[ i ].size(); j++ ) { m_hAni->EnableBlend( m_vecDisableBone[ i ][ j ], true ); } } for( i = 0; i < ( int )m_vecBoneRotation.size(); i++ ) { m_hAni->SetBoneRotation( m_vecBoneRotation[ i ].nBoneIndex, &m_vecBoneRotation[ i ].BoneRotation ); } for( i = 0; i < ( int )m_vecBoneScale.size(); i++ ) { m_hAni->SetBoneScale( m_vecBoneScale[ i ].nBoneIndex, m_vecBoneScale[ i ].fScale ); } } m_nSaveMatIndex = m_hAni->CalcAni( GetMesh()->GetInvWorldMatList() ); m_bValidSaveMatIndex = true; } void CEtAniObject::CreateSimulation( const char *szFileName ) { std::map boneIndexMap; int nBoneCount = m_hAni->GetBoneCount(); for( int i = 0; i < nBoneCount; i++) { boneIndexMap[ m_hAni->GetBone(i)->GetName() ] = i; } m_Spring.Create( szFileName, GetMesh()->GetInvWorldMatList(), boneIndexMap ); } void CEtAniObject::SimulateAni() { // ¾Ö´Ï À߸ø ¿¬°áÇÏ¸é ¾Æ·¡ InvWorldMatList ¾ò¾î¿À´Âµ¥¼­ ´ýÇÁ³³´Ï´Ù. if( m_hAni->GetBoneCount() > (int)(GetMesh()->GetInvWorldMatList().size()) ) return; int i; m_Spring.Simulate( m_WorldMat, GetMesh()->GetInvWorldMatList() ); int nBoneCount = m_hAni->GetBoneCount(); EtMatrix *pLockedMatrices = NULL; m_nSaveMatIndex = GetEtSaveMat()->LockMatrix( nBoneCount, &pLockedMatrices); for( i = 0; i < nBoneCount; i++) { EtMatrix TransMat, VertexTransMat; if( i == 0 ) { EtMatrixIdentity( &VertexTransMat ); pLockedMatrices[ i ] = VertexTransMat; } else { EtMatrix InvWorldMat; EtMatrixInverse(&InvWorldMat, NULL, &m_WorldMat); int nChildOffset = 0; if( m_hAni->GetBone( i )->GetChildBoneCount() > 0 ) { nChildOffset = m_hAni->GetBone( i )->GetChild( 0 )->GetBoneIndex() - m_hAni->GetBone( i )->GetBoneIndex(); } else { nChildOffset = m_hAni->GetBone( i )->GetParent()->GetBoneIndex() - m_hAni->GetBone( i )->GetBoneIndex(); } TransMat = m_Spring.GetMatrix( i, nChildOffset ); EtMatrixMultiply( &TransMat, &TransMat, &InvWorldMat); EtMatrixMultiply( &VertexTransMat, &GetMesh()->GetInvWorldMatList()[i], &TransMat ); pLockedMatrices[ i ] = VertexTransMat; } } } void CEtAniObject::ForceSkipSimulateAni( bool bForceSkip, bool bApplyChild ) { if( m_Spring.IsEnable() ) { m_bForceSkipSimulateAni = bForceSkip; } if( bApplyChild ) { for( int i = 0; i < ( int )m_vecChild.size(); i++ ) { if( m_vecChild[ i ]->IsAniObject() ) ( ( EtAniObjectHandle )m_vecChild[ i ] )->ForceSkipSimulateAni( bForceSkip ); } } } void CEtAniObject::InitRender( int nSaveMatIndex ) { if( !IsShow() ) { return; } // #25479 // ¸¶À»¿¡¼­ /go 404Çϴ°Š¸»°í, °ÔÀÓµé¾î°£ »óÅ¿¡¼­ ¶Ç ´Ù½Ã /go 404 ÇÒ¶§ // °ÔÀÓŽºÅ©ÀÇ ProcessÇÔ¼öÀÇ EtInterface::Process( fDelta ); ÀÌ ¶óÀÎÀÌ ¼öÇàµÇ¸é¼­ ÆäÀÌµå ¾Æ¿ôÀÌ ³¡³µÀ»¶§ ´ÙÀ½¹ø ½ºÅ×ÀÌÁö À̴ϼÈÀ» ÇÑ´Ù. // À̶§ ¸ó½ºÅ͵µ »ý¼ºÇÏ°í ¸ó½ºÅͰ¡ µé°íÀÖ´Â ÇÁ·¹ÀÏ ¿ÀºêÁ§Æ®µµ »ý¼ºÇϴµ¥... // ±× ¾Æ·¡ EternityEngine::RenderFrame( fDelta ); ¶óÀÎÀÌ ÇÁ·Î¼¼½ºÈ£ÃâÇϱâÀü¿¡ ¸ÕÀú ¼öÇàµÇ´Â ¹Ù¶÷¿¡, Æ÷Áö¼Ç°ªÀÌ FLT_MAX ÃʱⰪ »óÅ ±×´ë·Î ÀÖ°Ô µÈ´Ù. // ÀÌ »óÅ¿¡¼­ Çà·Ä°è»êÇÏ´Â°Ç ¾îÂ÷ÇÇ ´ÙÀ½¹ø ÇÁ·Î¼¼½º È£ÃâµÇ°í ³ª¼­ ´Ù½Ã È£ÃâµÉ¶§ Àç°è»êµÉÅ×´Ï »ó°ü¾ø´Âµ¥, // ½Ã¹Ä·¹À̼ÇÀº °ªÀ» ´©ÀûÇØ¼­ »ç¿ëÇϱ⶧¹®¿¡ ÇѹøÀÌ¶óµµ FLT_MAX°ªÀÌ µé¾î°¡ÀÖ´Â »óÅ¿¡¼­ °è»êÇÏ¸é °è¼Ó ÀÌ»óÇÑ °ªÀ¸·Î ³²¾ÆÀÖ°Ô µÇ¹ö¸°´Ù. // ±×·¡¼­ ¾Æ·¡¿Í °°ÀÌ FLT_MAXÀÎÁö ÆÇ´ÜÇØ¼­ ¸¸¾à InvalidÇÏ´Ù¸é SimulateAni¸¦ È£ÃâÇÏÁö ¾Êµµ·Ï ÇϰڴÙ. bool bInvalidPos = ( m_PrevWorldMat._11 == FLT_MAX ); // À¯È¿ÇÑ ÃÖ»óÀ§ ºÎ¸ðÀÇ ¿ùµåÇà·Ä°ªÀÌ ÀÌ»óÇÏ¸é ½Ã¹Ä·¹ÀÌ¼Ç ÇÏÁö ¾Ê°Ô ó¸®ÇÑ´Ù. // ¸»Å¸¸é¼­ ¾²·¹µå·Î ºÎ¸ð ¼³Á¤Çϴ°Í, °ÔÀÌÁöFace¿¡¼­ °­Á¦·Î InitRenderÈ£ÃâÇÏ´Â °Íµé¶§¹®¿¡, ÇÁ·Î¼¼½º µ¹±âÀü¿¡ µé¾î¿À´Â °æ¿ì°¡ ÀÖ´Â °Å °°´Ù. if( m_hParent ) { EtObjectHandle hParent = m_hParent; while( 1 ) { if( hParent->GetParent() ) hParent = hParent->GetParent(); else break; } if( hParent->GetWorldMat()->_41 == FLT_MAX ) bInvalidPos = true; } int i; if( m_hParent ) { CalcParentBoneMat(); } if( m_hAni ) { if( m_Spring.IsEnable() ) { if( m_bSkipPhysics ) { CalcAni(); m_Spring.InputKeyframe( m_WorldMat, m_nSaveMatIndex ); } else { if( m_bForceSkipSimulateAni == false && bInvalidPos == false ) SimulateAni(); } } else { if( m_hParent ) { if( m_hAni->GetMyIndex() != m_hParent->GetAniFileIndex() ) { nSaveMatIndex = -1; } else if( m_nLinkBoneIndex != -1 ) { // SaveMatIndex¿¡ ´ëÇØ¼­ °£´ÜÈ÷ ¼³¸íÇϰڴÙ. // ÁÖµÈ ¸ñÀûÀº °°Àº aniÆÄÀÏÀ» »ç¿ëÇÏ´Â ÆÄÃ÷µéÀÇ ¾Ö´Ï °è»êÀ» ¿©·¯¹ø ¹Ýº¹Çؼ­ ÇÏÁö ¾Ê±â À§ÇØ °°Àº SaveMatIndex°ªÀ» ³Ö¾îµÎ°í, // (º¸Åë µ¿ÀÏ Ä³¸¯ÀÇ ¸Ó¸®, Çì¾î, ¸ÓÁö¿ÀºêÁ§Æ®, ¿ö·ÁÀÇ °ÇƲ·¿ µîÀÌ ÇϳªÀÇ ºÎ¸ð¾Æ·¡ ÀÖ´Â ÀÚ½ÄÀ̱⶧¹®¿¡ °°Àº SaveMatIndex¸¦ °¡Áö°Ô µË´Ï´Ù.) // RenderStack::RenderBlock ÇÔ¼ö¿¡¼­ SetWorldMatArray È£ÃâÇÒ¶§ // ÇØ´ç ObjectÀÇ WorldMat¿Í ¼³Á¤µÈ SaveMat°ªÀ» °öÇØ¼­ EtSaveMat::m_vecTransMat¿¡ ³Ö¾îµÎ°í ¾²°ÔµÈ´Ù. // // ±×·±µ¥ À§ AniÆÄÀϸ¸ °Ë»çÇϴ°ŷδ ¹®Á¦°¡ ¹ß»ýÇÒ ¼ö ÀÖ´Ù. // ¸¸¾à °°Àº SaveMatIndex¸¦ »ç¿ëÇÏ´Â Objectµé Áß¿¡ // ´©±¸´Â m_nLinkBoneIndex°¡ -1Àε¥ ´©±¸´Â ƯÁ¤ º»À妽º°ªÀÌ µé¾îÀÖ´Ù¸é, µÎ ObjectÀÇ WorldMat°¡ ´Þ¶óÁú¼ö¹Û¿¡ ¾ø´Ù. // À̶§ ·»´õ¸µ ·çƾÀ» Ÿ¸é¼­ ¸ÕÀú RenderBlockÀÌ È£ÃâµÇ´Â °÷¿¡¼­ TransMat¸¦ Çѹø ±¸Çسõ°í´Â // ÀÌ ÈÄ ±× °ªÀ» °øÀ¯Çؼ­ ¾²±â ¶§¹®¿¡, ƯÁ¤ ¿ÀºêÁ§Æ®¿¡ À߸ø ¸µÅ©µÈ°Íó·³ º¸ÀÌ°Ô µÈ´Ù. // ±×·¡¼­ ÀÌ·¸°Ô LinkBoneIndex°¡ -1ÀÌ ¾Æ´Ï¶ó¸é ºÎ¸ð·ÎºÎÅÍ Àü´Þ¹ÞÀº SaveMatIndex¸¦ ¹«È¿È­½Ã۰í // ½º½º·Î °è»êÇÑ m_nSaveMatIndex¸¦ »ç¿ëÇϵµ·Ï ÇÑ´Ù. nSaveMatIndex = -1; } } bool bMySaveMatInvalid = false; if( ( !GetEtSaveMat()->IsValidIndex( m_nSaveMatIndex ) ) || ( !m_bValidSaveMatIndex ) ) { bMySaveMatInvalid = true; } if( ( !GetEtSaveMat()->IsValidIndex( nSaveMatIndex ) ) && ( bMySaveMatInvalid ) ) { CalcAni(); } else if( !GetEtSaveMat()->IsValidIndex( m_nSaveMatIndex ) ) { m_nSaveMatIndex = nSaveMatIndex; } } } for( i = 0; i < ( int )m_vecChild.size(); i++ ) { m_vecChild[ i ]->InitRender( m_nSaveMatIndex ); } } void CEtAniObject::OnLoadComplete( CBackgroundLoader *pLoader ) { if( m_hAni ) { if( ( m_hSkin->IsReady() ) && ( m_hAni->IsReady() ) ) { if( m_hSkin->GetMeshHandle() ) { m_hSkin->GetMeshHandle()->LinkToAni( m_hAni ); } } } if( m_hSkin->IsReady() ) { return CEtObject::OnLoadComplete( pLoader ); } CBackgroundLoaderCallback::OnLoadComplete( pLoader ); }