Files
Client/GameTools/Zallad3D SceneClass/Z3DGeneralChrModel.cpp
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

1572 lines
34 KiB
C++

// Z3DGeneralChrModel.cpp: implementation of the CZ3DGeneralChrModel class.
//
//////////////////////////////////////////////////////////////////////
//#include "winsock2.h"
//#include "FunctionPerformanceCheck.h"
#include "Z3DGeneralChrModel.h"
#include "RenderOption.h"
#include "BaseDataDefine.h"
#include <io.h>
std::map<Z3DTOK, CZ3DGCMDS*> CZ3DGeneralChrModel::ms_mapTok2GCMDS;
bool CZ3DGeneralChrModel::_BuildCMDSList( const char* szFileSpec )
{
SimpleString strFullPath( ms_strDataPath, szFileSpec );
char* szFileNamePart;
Z3DTOK tokFileName;
CZ3DGCMDS* pGCMDS;
_finddata_t fileinfo;
long lFindHandle = _findfirst( strFullPath, &fileinfo );
if( -1 == lFindHandle )
{
return false;
}
do
{
szFileNamePart = strrchr( fileinfo.name, '\\' );
if( NULL == szFileNamePart )
{
szFileNamePart = fileinfo.name;
}
else
{
++szFileNamePart;
}
tokFileName = g_TokFileName.Add( szFileNamePart );
pGCMDS = new CZ3DGCMDS;
if( false == pGCMDS->Load( fileinfo.name, ms_strDataPath ) )
{
SAFE_DELETE( pGCMDS );
return false;
}
if( ms_mapTok2GCMDS.end() != ms_mapTok2GCMDS.find( tokFileName ) )
{
SAFE_DELETE( pGCMDS );
return false;
}
ms_mapTok2GCMDS[tokFileName] = pGCMDS;
} while( 0 == _findnext( lFindHandle, &fileinfo ) );
_findclose( lFindHandle );
return true;
}
bool CZ3DGeneralChrModel::_ClearCMDSList()
{
std::map<Z3DTOK, CZ3DGCMDS*>::iterator it;
for( it = ms_mapTok2GCMDS.begin(); it != ms_mapTok2GCMDS.end(); it++ )
{
SAFE_DELETE( it->second );
}
return true;
}
void CZ3DGeneralChrModel::_RetrieveCMDSNameList( std::vector<const char*>& r_vecList )
{
std::map<Z3DTOK, CZ3DGCMDS*>::iterator it;
for( it = ms_mapTok2GCMDS.begin(); it != ms_mapTok2GCMDS.end(); it++ )
{
r_vecList.push_back( g_TokFileName.GetString( it->first ) );
}
}
CZ3DGCMDS* CZ3DGeneralChrModel::_GetGCMDSByName( const char* szFilename )
{
Z3DTOK tokFileName = g_TokFileName.GetTOK( szFilename );
if( NULL_TOK == tokFileName )
{
return false;
}
std::map<Z3DTOK, CZ3DGCMDS*>::iterator it;
if( ms_mapTok2GCMDS.end() == (it = ms_mapTok2GCMDS.find(tokFileName)) )
{
return false;
}
return it->second;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CZ3DGeneralChrModel::CZ3DGeneralChrModel()
{
m_pSkeletonObjects = NULL;
m_pSkin = NULL;
m_pPseudoCloth = NULL;
//m_pTokCurrentAniKeyPackFile = NULL;
m_pTagAniKeyPack = NULL;
m_pAniHolder = NULL;
m_pEventGenerator = NULL;
m_pTagAddonAniKeyPack = NULL;
m_pAddonAniHolder = NULL;
m_pAddonEventGenerator = NULL;
m_fScaleFactor = 1.0f;
m_rpCurrentMotionSheet = NULL;
m_tokCurrentMotionSheet = NULL_TOK;
m_pBoundingCylinder = NULL;
m_bInitialized = false;
m_bAniTestMode = false;
m_fFixHeight = 0.0f;
}
CZ3DGeneralChrModel::~CZ3DGeneralChrModel()
{
std::map<Z3DTOK, Z3D_TOK_N_ATTACHMENT>::iterator itA;
for( itA = m_mapAttachmentSlot.begin(); itA != m_mapAttachmentSlot.end(); itA++ )
{
Z3D_TOK_N_ATTACHMENT tna = itA->second;
if( itA->second.pAttachment )
{
itA->second.pAttachment->UnLink();
SAFE_DELETE( itA->second.pAttachment );
}
}
if( m_pSkeletonObjects )
{
m_pSkeletonObjects[0].UnLink();
}
SAFE_DELETEA( m_pSkeletonObjects );
SAFE_DELETE( m_pSkin );
SAFE_DELETE( m_pPseudoCloth );
//SAFE_DELETEA( m_pTokCurrentAniKeyPackFile );
SAFE_DELETEA( m_pTagAniKeyPack );
SAFE_DELETEA( m_pAniHolder );
SAFE_DELETEA( m_pEventGenerator );
SAFE_DELETEA( m_pTagAddonAniKeyPack );
SAFE_DELETEA( m_pAddonAniHolder );
SAFE_DELETEA( m_pAddonEventGenerator );
std::map<Z3DTOK, Z3DTOK_OVERLAY_SLOT*>::iterator itO;
for( itO = m_mapOutfitSlot.begin(); itO != m_mapOutfitSlot.end(); itO++ )
{
SAFE_DELETE( itO->second );
}
SAFE_DELETEA( m_pBoundingCylinder );
}
bool CZ3DGeneralChrModel::Init( const char* szGCMDSname )
{
if( m_bInitialized )
{
return false; // trying to initialize more than one time on this instance
}
Z3DTOK tokFileName = g_TokFileName.GetTOK( szGCMDSname );
if( NULL_TOK == tokFileName )
{
return false;
}
std::map<Z3DTOK, CZ3DGCMDS*>::iterator it;
if( ms_mapTok2GCMDS.end() == (it = ms_mapTok2GCMDS.find(tokFileName)) )
{
return false;
}
m_rpGCMDS = it->second;
// allocating skeleton obejct & setting hierarchy
if( false == m_rpGCMDS->AllocSkeleton( m_pSkeletonObjects ) )
{
return false;
}
m_pSkin = new CZ3DMultipartSkin( m_rpGCMDS->GetMPT() );
m_pPseudoCloth = new CZ3DPseudoCloth();
m_pPseudoCloth->Link( NULL );
m_pSkin->SetSkeleton( m_pSkeletonObjects, m_rpGCMDS->GetSkeletonCount() );
m_pSkin->SetSkeletonLocalizer( m_rpGCMDS->GetLocalizerMatrix() );
//m_pTokCurrentAniKeyPackFile = new Z3DTOK[m_rpGCMDS->GetAniHolderCount()];
m_pTagAniKeyPack = new H3DAniKeyPackTag[m_rpGCMDS->GetAniHolderCount()];
m_pAniHolder = new Z3DAniHolder[m_rpGCMDS->GetAniHolderCount()];
m_pEventGenerator = new CZ3DChrEventGenerator[m_rpGCMDS->GetAniHolderCount()];
m_pTagAddonAniKeyPack = new H3DAniKeyPackTag[m_rpGCMDS->GetAniHolderCount()];
m_pAddonAniHolder = new Z3DAniHolder[m_rpGCMDS->GetAniHolderCount()];
m_pAddonEventGenerator = new CZ3DChrEventGenerator[m_rpGCMDS->GetAniHolderCount()];
m_AniMixer.Init( m_pSkeletonObjects, m_pAniHolder, m_pAddonAniHolder,
m_rpGCMDS->GetSkeletonCount(), m_rpGCMDS->GetAniHolderCount() );
const std::vector<Z3DTOK>* p_vecTok;
p_vecTok = m_rpGCMDS->GetStaticSlotVector();
for( int i = 0; i < p_vecTok->size(); ++i )
{
m_mapStaticSlot[(*p_vecTok)[i]] = NULL_TOK;
}
const std::vector<long>* p_vecOverlayCount = m_rpGCMDS->GetOutfitSlotOverlayVector();
p_vecTok = m_rpGCMDS->GetOutfitSlotVector();
Z3DTOK_OVERLAY_SLOT* pSlot = NULL;
for( i = 0; i < p_vecTok->size(); ++i )
{
pSlot = new Z3DTOK_OVERLAY_SLOT;
pSlot->Alloc( (*p_vecOverlayCount)[i] );
m_mapOutfitSlot[(*p_vecTok)[i]] = pSlot;
}
Z3D_TOK_N_ATTACHMENT tna;
tna.tokAttachmentName = NULL_TOK;
tna.pAttachment = NULL;
tna.lHolderIndex = 0;
p_vecTok = m_rpGCMDS->GetAttachmentSlotVector();
for( i = 0; i < p_vecTok->size(); ++i )
{
m_mapAttachmentSlot[(*p_vecTok)[i]] = tna;
}
BeginOutfitSetting();
EndOutfitSetting();
SetMotionSheet( m_rpGCMDS->GetDefaultMotionSheet() );
SetMotion( m_rpGCMDS->GetDefaultMotion(), 0, false );
/*(#ifdef _DEBUG
for( int xxxi = 0; xxxi < m_rpGCMDS->GetAniHolderCount(); xxxi++ )
{
if( NULL == m_pAniHolder[xxxi].GetAniKeyPackInterface() )
{
MessageBox( NULL, "CZ3DGeneralChrModel::Init() - 뭔가 수상해뵈네잉..", 0, 0 );
}
}
#endif*/
const std::vector<Z3DTOK_SLOT_ATTACHMENT>* p_vecAttachmentDefSetting =
m_rpGCMDS->GetAttachmentDefaultSettingVector();
for( i = 0; i < p_vecAttachmentDefSetting->size(); ++i )
{
SetAttachmentSlot(
(*p_vecAttachmentDefSetting)[i].tokSlot,
(*p_vecAttachmentDefSetting)[i].tokAttachment, true );
}
const std::vector<Z3D_BOUNDING_CYLINDER_INFO>* pBCList =
m_rpGCMDS->GetBoundingCylinderVector();
if( pBCList->size() )
{
m_pBoundingCylinder = new Z3D_BOUNDING_CYLINDER[pBCList->size()];
for( i = 0; i < pBCList->size(); ++i )
{
m_pBoundingCylinder[i].fBottomRadius = (*pBCList)[i].fBottomRadius;
m_pBoundingCylinder[i].fTopRadius = (*pBCList)[i].fTopRadius;
}
}
m_bInitialized = true;
// 2003.5.8 추가 - default scale 기능 추가
SetScale( 1.0f ); // 이렇게 불러주면 SetScale() 내부에서 알아서 해준다.
m_pSkin->SetTestMode( m_bAniTestMode );
return true;
}
CZ3DObject* CZ3DGeneralChrModel::GetSkeletonPartObject( const char* szSkeletonPartName )
{
if( NULL == m_rpGCMDS )
{
return NULL;
}
long lIndex = m_rpGCMDS->GetSkeletonPartObjectIdx( szSkeletonPartName );
if( -1 == lIndex )
{
return NULL;
}
// else
return &(m_pSkeletonObjects[lIndex]);
}
CZ3DObject* CZ3DGeneralChrModel::GetSkeletonPartObject( Z3DTOK tokSkeletonPartName )
{
if( NULL == m_rpGCMDS )
{
return NULL;
}
long lIndex = m_rpGCMDS->GetSkeletonPartObjectIdx( tokSkeletonPartName );
if( -1 == lIndex )
{
return NULL;
}
// else
return &(m_pSkeletonObjects[lIndex]);
}
Z3DTOKARRAY* CZ3DGeneralChrModel::GetTokArray( Z3DTOK tokMotionName, long lRandomIndex )
{
if( NULL == m_rpCurrentMotionSheet )
{
return NULL;
}
Z3DMOTLET* pMotlet;
Z3DMOTIONSHEET* pSheet = const_cast<Z3DMOTIONSHEET*>(m_rpCurrentMotionSheet);
std::map<Z3DTOK, Z3DMOTLET*>::iterator it;
while( 1 )
{
it = pSheet->mapTok2Motlet.find( tokMotionName );
if( it != pSheet->mapTok2Motlet.end() )
{
// 현재 sheet에서 해당 motion의 motlet을 찾은 경우
pMotlet = it->second;
break;
}
//else
pSheet = pSheet->rpParentSheet;
if( NULL == pSheet )
{
return NULL;
}
}
Z3DTOKARRAY* pTokArr;
if( -1 == lRandomIndex )
{
long lMotSeed = rand() % (pMotlet->lProbalilitySum);
for( int i = 0; i < pMotlet->lCount; ++i )
{
// 확률필드가 없는 데이터의 경우
// lProbalilitySum = 1, lMotSeed = 0 이므로 아래 조건식은 항상 true
if( lMotSeed < pMotlet->pProbabilityIdx[i] )
{
pTokArr = &(pMotlet->pTokArr[i]);
break;
}
}
}
else
{
pTokArr = &(pMotlet->pTokArr[min( lRandomIndex, (pMotlet->lCount-1) )]);
}
return pTokArr;
}
void CZ3DGeneralChrModel::SetMotion( const char* szMotionName, unsigned long ulFlag, bool bTransit, long lRandomIndex )
{
if( NULL == m_rpCurrentMotionSheet )
{
return;
}
Z3DTOK tokMotionName = g_TokMotionName.GetTOK( szMotionName );
if( NULL_TOK == tokMotionName )
{
return;
}
SetMotion( tokMotionName, ulFlag, bTransit, lRandomIndex );
}
void CZ3DGeneralChrModel::SetMotion( Z3DTOK tokMotionName, unsigned long ulFlag, bool bTransit, long lRandomIndex )
{
if( NULL == m_rpCurrentMotionSheet )
{
return;
}
Z3DTOKARRAY* pTokArr = GetTokArray( tokMotionName, lRandomIndex );
if( NULL == pTokArr )
{
return;
}
int i;
if( 0 == ulFlag ) // flag setting 없음. 모든 ani holder에 setting
{
for( i = 0; i < m_rpGCMDS->GetAniHolderCount(); ++i )
{
SetAniKeyPack( i, pTokArr->pArray[i], bTransit );
}
}
else // flag 적용 setting
{
for( i = 0; i < m_rpGCMDS->GetAniHolderCount(); ++i )
{
if( ulFlag & (0x1 << i) )
{
SetAniKeyPack( i, pTokArr->pArray[i], bTransit );
}
}
}
}
void CZ3DGeneralChrModel::AddMotion( const char* szMotionName, unsigned long ulFlag, float fFactorPeak, bool bSustainLast )
{
if( NULL == m_rpCurrentMotionSheet )
{
return;
}
Z3DTOK tokMotionName = g_TokMotionName.GetTOK( szMotionName );
if( NULL_TOK == tokMotionName )
{
return;
}
AddMotion( tokMotionName, ulFlag, fFactorPeak, bSustainLast );
}
void CZ3DGeneralChrModel::AddMotion( Z3DTOK tokMotionName, unsigned long ulFlag, float fFactorPeak, bool bSustainLast )
{
if( NULL == m_rpCurrentMotionSheet )
{
return;
}
Z3DTOKARRAY* pTokArr = GetTokArray( tokMotionName );
if( NULL == pTokArr )
{
return;
}
int i;
if( 0 == ulFlag ) // flag setting 없음. 모든 ani holder에 setting
{
for( i = 0; i < m_rpGCMDS->GetAniHolderCount(); ++i )
{
SetAddonAniKeyPack( i, pTokArr->pArray[i], fFactorPeak );
}
}
else // flag 적용 setting
{
for( i = 0; i < m_rpGCMDS->GetAniHolderCount(); ++i )
{
if( ulFlag & (0x1 << i) )
{
SetAddonAniKeyPack( i, pTokArr->pArray[i], fFactorPeak );
}
}
}
m_AniMixer.SetAddonFactorPeak( fFactorPeak );
m_AniMixer.SustainLast( bSustainLast );
}
void CZ3DGeneralChrModel::Act( Z3D_CHR_ACTION action, long lParam1, long lParam2 )
{
switch( action )
{
case Z3D_CA_SET_MOTION_SHEET:
break;
case Z3D_CA_ACT_MOTION:
break;
case Z3D_CA_SET_STATIC_SLOT:
break;
case Z3D_CA_BEGIN_OUTFIT_SET:
break;
case Z3D_CA_SET_OUTFIT_SLOT:
break;
case Z3D_CA_END_OUTFIT_SET:
break;
case Z3D_CA_SET_WEAPON:
break;
case Z3D_CA_SET_SHIELD:
break;
default:
CZ3DCharacterModel::Act( action, lParam1, lParam2 );
}
}
bool CZ3DGeneralChrModel::SetAniKeyPack( int n, Z3DTOK tokFileName, bool bTransit )
{
H3DAniKeyPackTag tagAniKeyPack;
if( NULL_TOK == tokFileName )
{
return false;
}
if( n >= m_rpGCMDS->GetAniHolderCount() )
{
return false;
}
const char* szFileName = g_TokFileName.GetString( tokFileName );
if( NULL == szFileName )
{
return false;
}
g_ContAniKeyPack.GetObject( tagAniKeyPack, szFileName );
if( NULL == tagAniKeyPack.GetObject() )
{
return false;
}
if( tagAniKeyPack == m_pTagAniKeyPack[n] )
{
tagAniKeyPack.Release();
//return false;
// 이전 것과 같은 동작을 세팅해주더라도 처음부터 다시 플레이하도록 해
// 해 줘야지 그냥 종료해버리면 안된다.
}
else
{
m_pTagAniKeyPack[n] = tagAniKeyPack;
}
m_pAniHolder[n].SetAniPack( m_pTagAniKeyPack[n].GetObject() );
m_AniMixer.Swap( n, bTransit );
m_pEventGenerator[n].SetTokAniPack( tokFileName );
//m_pTokCurrentAniKeyPackFile = tokFileName;
return true;
}
bool CZ3DGeneralChrModel::SetAddonAniKeyPack( int n, Z3DTOK tokFileName, float fFactorPeak )
{
H3DAniKeyPackTag tagAniKeyPack;
if( NULL_TOK == tokFileName )
{
return false;
}
if( n >= m_rpGCMDS->GetAniHolderCount() )
{
return false;
}
const char* szFileName = g_TokFileName.GetString( tokFileName );
if( NULL == szFileName )
{
return false;
}
g_ContAniKeyPack.GetObject( tagAniKeyPack, szFileName );
if( NULL == tagAniKeyPack.GetObject() )
{
return false;
}
if( tagAniKeyPack == m_pTagAddonAniKeyPack[n] )
{
tagAniKeyPack.Release();
//return false;
// 이전 것과 같은 동작을 세팅해주더라도 처음부터 다시 플레이하도록 해
// 해 줘야지 그냥 종료해버리면 안된다.
}
else
{
m_pTagAddonAniKeyPack[n] = tagAniKeyPack;
}
m_pAddonAniHolder[n].SetAniPack( m_pTagAddonAniKeyPack[n].GetObject() );
m_pAddonEventGenerator[n].SetTokAniPack( tokFileName );
//m_pTokCurrentAniKeyPackFile = tokFileName;
return true;
}
bool CZ3DGeneralChrModel::SetStaticSlot( const char* szSlotName, const char* szOutfitName )
{
if( m_rpGCMDS->IsFixed() )
{
return false;
}
if( NULL == m_pSkin )
{
return false;
}
Z3DTOK tokSlotName = g_TokSlotName.GetTOK( szSlotName );
Z3DTOK tokOutfitName = g_TokOutfitName.GetTOK( szOutfitName );
if( NULL_TOK == tokSlotName || NULL_TOK == tokOutfitName )
{
return false;
}
std::map<Z3DTOK, Z3DTOK>::iterator it;
it = m_mapStaticSlot.find( tokSlotName );
if( m_mapStaticSlot.end() == it )
{
return false;
}
it->second = tokOutfitName;
EndOutfitSetting(); // mesh 구성 자체를 완전히 다시 해줘야하므로
return true;
}
void CZ3DGeneralChrModel::BeginOutfitSetting()
{
if( NULL == m_pSkin )
{
return;
}
std::map<Z3DTOK, Z3DTOK_OVERLAY_SLOT*>::iterator it;
for( it = m_mapOutfitSlot.begin(); it != m_mapOutfitSlot.end(); it++ )
{
it->second->lUsed = 0;
for( int i = 0; i < it->second->lCount; ++i )
{
it->second->pArray[i] = NULL_TOK;
}
}
}
bool CZ3DGeneralChrModel::SetOutfitSlot( const char* szSlotName, const char* szOutfitName )
{
if( m_rpGCMDS->IsFixed() )
{
return false;
}
if( NULL == m_pSkin )
{
return false;
}
Z3DTOK tokSlotName = g_TokSlotName.GetTOK( szSlotName );
Z3DTOK tokOutfitName = g_TokOutfitName.GetTOK( szOutfitName );
while( 1 )
{
if( NULL_TOK == tokSlotName || NULL_TOK == tokOutfitName )
{
return false;
}
std::map<Z3DTOK, Z3DTOK_OVERLAY_SLOT*>::iterator it;
it = m_mapOutfitSlot.find( tokSlotName );
if( m_mapOutfitSlot.end() == it )
{
return false;
}
Z3DTOK_OVERLAY_SLOT* pOS = it->second;
if( 1 == pOS->lCount ) // 겹침이 없을 경우(slot holder 1개)
{
// 덮어쓰기가 가능
pOS->pArray[0] = tokOutfitName;
pOS->lUsed = 1;
}
else // 아닐 때는
{
// holder 갯수만큼만 setting 가능하고 덮어쓰기 불가능
if( pOS->lUsed < pOS->lCount )
{
pOS->pArray[pOS->lUsed] = tokOutfitName;
++(pOS->lUsed);
}
}
// link part setting
const Z3DOUTFITINFO* pOI = m_rpGCMDS->GetOutfitInfo( tokOutfitName );
if( NULL == pOI )
{
break;
}
tokOutfitName = pOI->tokLinkOutfit;
tokSlotName = pOI->tokLinkSlot;
}
return true;
}
void CZ3DGeneralChrModel::EndOutfitSetting()
{
//DeclareBlockTimingCheck( "Begin", aa );
//DeclareBlockTimingCheck( "Setting", bb );
//DeclareBlockTimingCheck( "Begin+Setting", cc );
//DeclareBlockTimingCheck( "End", dd );
if( NULL == m_pSkin )
{
return;
}
int i, j;
const std::vector<Z3DTOK>* p_vecTok;
Z3DTOK_OVERLAY_SLOT* pSlot;
//BlockTimingCheckStart(cc);
//BlockTimingCheckStart(aa);
m_pSkin->BatchOpen();
//BlockTimingCheckStop(aa);
//BlockTimingCheckStart(bb);
// 기본형(웃통벗고 반바지..같은거) 적용
ApplyOutfit( m_rpGCMDS->GetDefaultOutfit() );
// static slot(얼굴, 헤어스타일) 적용
p_vecTok = m_rpGCMDS->GetStaticSlotVector();
for( i = 0; i < p_vecTok->size(); ++i )
{
ApplyOutfit( m_mapStaticSlot[(*p_vecTok)[i]] );
}
// 옷가지 적용
p_vecTok = m_rpGCMDS->GetOutfitSlotVector();
for( i = 0; i < p_vecTok->size(); ++i )
{
pSlot = m_mapOutfitSlot[(*p_vecTok)[i]];
for( j = 0; j < pSlot->lUsed; ++j )
{
ApplyOutfit( pSlot->pArray[j] );
}
}
//BlockTimingCheckStop(bb);
m_pSkin->BatchClose();
}
bool CZ3DGeneralChrModel::SetAttachmentSlot( const char* szSlotName, const char* szAttachmentName, bool bForced )
{
if( !bForced && m_rpGCMDS->IsFixed() )
{
return false;
}
Z3DTOK tokSlotName, tokAttachmentName;
tokSlotName = g_TokSlotName.GetTOK( szSlotName );
if( NULL_TOK == tokSlotName )
{
return false;
}
if( NULL == szAttachmentName )
{
return SetAttachmentSlot( tokSlotName, NULL_TOK );
}
tokAttachmentName = g_TokAttachmentName.GetTOK( szAttachmentName );
/*if( NULL_TOK == tokAttachmentName )
{
return false;
}*/
return SetAttachmentSlot( tokSlotName, tokAttachmentName );
}
bool CZ3DGeneralChrModel::SetAttachmentSlot( Z3DTOK tokSlotName, Z3DTOK tokAttachmentName, bool bForced )
{
if( !bForced && m_rpGCMDS->IsFixed() )
{
return false;
}
std::map<Z3DTOK, Z3D_TOK_N_ATTACHMENT>::iterator it;
it = m_mapAttachmentSlot.find( tokSlotName );
if( m_mapAttachmentSlot.end() == it )
{
return false;
}
// attachment 이름이 null : 현재 attachment 삭제
if( NULL_TOK == tokAttachmentName )
{
it->second.tokAttachmentName = NULL_TOK;
SAFE_DELETE( it->second.pAttachment );
return true;
}
const Z3DATTACHMENTINFO* pAInfo = m_rpGCMDS->GetAttachmentInfo( tokAttachmentName );
if( NULL == pAInfo )
{
return false;
}
if( it->second.tokAttachmentName == tokAttachmentName )
{
// 이전에 세팅된것과 같은 attachment
return false;
}
const char* szMeshName = g_TokFileName.GetString( pAInfo->tokMeshFile );
const char* szTexName = g_TokFileName.GetString( pAInfo->tokTextureFile );
const char* szTexName2 = g_TokFileName.GetString( pAInfo->tokTextureFile2 );
if( !(szMeshName && szTexName) )
{
return false;
}
//SAFE_DELETE( it->second.pAttachment );
if( NULL == it->second.pAttachment )
{
it->second.pAttachment = new CZ3DWeapon( GetSkeletonPartObject("R_HAND") );
it->second.pAttachment->SetScale( m_fScaleFactor );
}
char strBumpTextureName[256] = { 0, };
char strSpecTextureName[256] = { 0, };
//if( NULL == szTexName2 && CRenderOption::m_TextureMethod && CRenderOption::m_CharacterPerPixelLighting)
//{
sprintf(strBumpTextureName, "%sTexture\\%s", CHARACTERDATAPATH,szTexName);
int nStrLens=strlen(strBumpTextureName);
strcpy( &strBumpTextureName[nStrLens-4], "_bump.dds" );
FILE *fp=fopen(strBumpTextureName,"rb");
if(fp==NULL)
strcpy(strBumpTextureName,"");
else
{
sprintf(strBumpTextureName, "%s", szTexName);
nStrLens=strlen(strBumpTextureName);
strcpy( &strBumpTextureName[nStrLens-4], "_bump.dds" );
fclose( fp );
}
sprintf(strSpecTextureName, "%sTexture\\%s", CHARACTERDATAPATH,szTexName);
nStrLens=strlen(strSpecTextureName);
strcpy( &strSpecTextureName[nStrLens-4], "_spec.dds" );
fp=fopen(strSpecTextureName,"rb");
if(fp==NULL)
strcpy(strSpecTextureName,"spec_black.dds");
else
{
sprintf(strSpecTextureName, "%s", szTexName);
nStrLens=strlen(strSpecTextureName);
strcpy( &strSpecTextureName[nStrLens-4], "_spec.dds" );
fclose( fp );
}
it->second.pAttachment->Set( szMeshName, szTexName, strBumpTextureName, strSpecTextureName );
//}
//else
//{
// it->second.pAttachment->Set( szMeshName, szTexName, szTexName2, NULL );
//}
const Z3DATTACHMENTHOLDERINFO* pholderInfo =
pAInfo->GetAttachmentHolderInfo(it->second.lHolderIndex);
it->second.pAttachment->Link(
GetSkeletonPartObject(pholderInfo->tokSkelPart) );
it->second.pAttachment->SetPositionLocal( pholderInfo->vPos );
it->second.pAttachment->SetDirectionLocal( pholderInfo->qRot );
if( 5 == pAInfo->lType ) // type 5 == bow
{
it->second.pAttachment->SetBowMode( true );
}
else
{
it->second.pAttachment->SetBowMode( false );
}
it->second.tokAttachmentName = tokAttachmentName;
return true;
}
bool CZ3DGeneralChrModel::SetAttachmentHolder( const char* szSlotName, long lIndex )
{
Z3DTOK tokSlotName;
tokSlotName = g_TokSlotName.GetTOK( szSlotName );
if( NULL_TOK == tokSlotName )
{
return false;
}
return SetAttachmentHolder( tokSlotName, lIndex );
}
bool CZ3DGeneralChrModel::SetAttachmentHolder( Z3DTOK tokSlotName, long lIndex )
{
std::map<Z3DTOK, Z3D_TOK_N_ATTACHMENT>::iterator it;
it = m_mapAttachmentSlot.find( tokSlotName );
if( m_mapAttachmentSlot.end() == it )
{
return false;
}
if( NULL == it->second.pAttachment )
{
return true;
}
const Z3DATTACHMENTINFO* pAInfo = m_rpGCMDS->GetAttachmentInfo( it->second.tokAttachmentName );
if( NULL == pAInfo )
{
return false; // 이쪽이 실행될 일은 없음..
}
const Z3DATTACHMENTHOLDERINFO* pholderInfo = pAInfo->GetAttachmentHolderInfo(lIndex);
it->second.pAttachment->Link(
GetSkeletonPartObject(pholderInfo->tokSkelPart) );
it->second.pAttachment->SetPositionLocal( pholderInfo->vPos );
it->second.pAttachment->SetDirectionLocal( pholderInfo->qRot );
it->second.lHolderIndex = lIndex;
return false;
}
long CZ3DGeneralChrModel::GetAttachmentHolder( const char* szSlotName )
{
Z3DTOK tokSlotName;
tokSlotName = g_TokSlotName.GetTOK( szSlotName );
if( NULL_TOK == tokSlotName )
{
return -1;
}
return GetAttachmentHolder( tokSlotName );
}
long CZ3DGeneralChrModel::GetAttachmentHolder( Z3DTOK tokSlotName )
{
std::map<Z3DTOK, Z3D_TOK_N_ATTACHMENT>::iterator it;
it = m_mapAttachmentSlot.find( tokSlotName );
if( m_mapAttachmentSlot.end() == it )
{
return -1;
}
return it->second.lHolderIndex;
}
CZ3DWeapon* CZ3DGeneralChrModel::GetAttachmentObject( const char* szSlotName )
{
Z3DTOK tokSlotName;
tokSlotName = g_TokSlotName.GetTOK( szSlotName );
if( NULL_TOK == tokSlotName )
{
return NULL;
}
return GetAttachmentObject( tokSlotName );
}
CZ3DWeapon* CZ3DGeneralChrModel::GetAttachmentObject( Z3DTOK tokSlotName )
{
std::map<Z3DTOK, Z3D_TOK_N_ATTACHMENT>::iterator it;
it = m_mapAttachmentSlot.find( tokSlotName );
if( m_mapAttachmentSlot.end() == it )
{
return NULL;
}
return it->second.pAttachment;
}
void CZ3DGeneralChrModel::ApplyOutfit( Z3DTOK tokOutfitName )
{
if( NULL_TOK == tokOutfitName )
{
// 잘못된 oufit 이름
return;
}
const Z3DOUTFITINFO* pOI = m_rpGCMDS->GetOutfitInfo( tokOutfitName );
if( NULL == pOI )
{
return;
}
int i;
const char* szMeshName;
const char* szTextureName;
//const char* szTexture2Name;
if( Z3D_MPT_TEXPIECE == m_rpGCMDS->GetMPT() )
{
// mesh type == texpiece 일 경우
for( i = 0; i < pOI->lCount; i++ )
{
szMeshName = g_TokFileName.GetString( pOI->pTokMeshName[i] );
if( szMeshName )
{
m_pSkin->SetMesh( szMeshName );
}
szTextureName = g_TokFileName.GetString( pOI->pTokTextureName[i] );
char strBumpTextureName[256];
FILE *fp=NULL;
if(CRenderOption::m_TextureMethod && CRenderOption::m_CharacterPerPixelLighting)
{
sprintf(strBumpTextureName, "%sTexture\\", CHARACTERDATAPATH,szTextureName);
}
//szTexture2Name = g_TokFileName.GetString( pOI->pTokTexture2Name[i] );
/*if( NULL_TOK == pOI->pTokTexture2Name[i] )
{
szTexture2Name = NULL;
}
else
{
szTexture2Name = g_TokFileName.GetString( pOI->pTokTexture2Name[i] );
}*/
if( szTextureName )
{
m_pSkin->SetTex( szTextureName, strBumpTextureName);
}
/*
if( szTextureName )
{
m_pSkin->SetTex( szTextureName, szTexture2Name );
}
*/
}
}
else
{
// mesh type == texture 일 경우
for( i = 0; i < pOI->lCount; i++ )
{
szMeshName = g_TokFileName.GetString( pOI->pTokMeshName[i] );
szTextureName = g_TokFileName.GetString( pOI->pTokTextureName[i] );
char strBumpTextureName[256] = { 0, };
char strSpecTextureName[256] = { 0, };
//if(CRenderOption::m_TextureMethod && CRenderOption::m_CharacterPerPixelLighting)
//{
sprintf(strBumpTextureName, "%sTexture\\%s", CHARACTERDATAPATH,szTextureName);
int nStrLens=strlen(strBumpTextureName);
strcpy( &strBumpTextureName[nStrLens-4], "_bump.dds" );
FILE *fp=fopen(strBumpTextureName,"rb");
if(fp==NULL)
strcpy(strBumpTextureName,"");
else
{
sprintf(strBumpTextureName, "%s", szTextureName);
nStrLens=strlen(strBumpTextureName);
strcpy( &strBumpTextureName[nStrLens-4], "_bump.dds" );
fclose( fp );
}
sprintf(strSpecTextureName, "%sTexture\\%s", CHARACTERDATAPATH,szTextureName);
nStrLens=strlen(strSpecTextureName);
strcpy( &strSpecTextureName[nStrLens-4], "_spec.dds" );
fp=fopen(strSpecTextureName,"rb");
if(fp==NULL)
strcpy(strSpecTextureName,"spec_black.dds");
else
{
sprintf(strSpecTextureName, "%s", szTextureName);
nStrLens=strlen(strSpecTextureName);
strcpy( &strSpecTextureName[nStrLens-4], "_spec.dds" );
fclose( fp );
}
//}
//szTexture2Name = g_TokFileName.GetString( pOI->pTokTexture2Name[i] );
if( szMeshName )
{
//m_pSkin->SetMeshTexture( szMeshName, szTextureName, szTexture2Name );
m_pSkin->SetMeshTexture(szMeshName,szTextureName,strBumpTextureName,strSpecTextureName);
}
}
}
}
void CZ3DGeneralChrModel::FrameMove()
{
/*#ifdef _DEBUG
for( int xxxi = 0; xxxi < m_rpGCMDS->GetAniHolderCount(); xxxi++ )
{
if( NULL == m_pAniHolder[xxxi].GetAniKeyPackInterface() )
{
MessageBox( NULL, "AniKeyPack 데이터 손상(this pointer = NULL", 0, 0 );
}
}
#endif*/
int i;
vector3 vd;
if( NULL == m_pAniHolder )
{
return;
}
if( m_bAniTestMode )
{
for( i = 0; i < m_rpGCMDS->GetSkeletonCount(); ++i )
{
m_pSkeletonObjects[i].SetPositionLocal( 0, 0, 0 );
m_pSkeletonObjects[i].SetDirectionLocal( 0, 0, 0, 1 );
}
return;
}
/*for( i = 0; i < m_rpGCMDS->GetSkeletonCount(); i++ )
{
m_pSkeletonObjects[i].ApplyAniKey( m_pAniHolder );
}*/
m_AniMixer.Mix();
/*for( i = 0; i < m_rpGCMDS->GetSkeletonCount(); i++ )
{
m_pSkeletonObjects[i].SetPositionLocal( 0, 0, 0 );
m_pSkeletonObjects[i].SetDirectionLocal( 0, 0, 0, 1 );
}*/
// Bip01 오브젝트와 pelvis 오브젝트간의 x-z거리를 무시한다
/* m_pSkeletonObjects[1].GetPositionLocal( vd );
vd.x = 0;
vd.z = 0;
m_pSkeletonObjects[1].SetPositionLocal( vd );
*/
// 캐릭터모델의 위치를 skin과 attachment 의 pivot으로..
if( m_pSkin )
{
m_pSkin->SetPivot( m_Pos );
}
std::map<Z3DTOK, Z3D_TOK_N_ATTACHMENT>::iterator it;
for( it = m_mapAttachmentSlot.begin(); it != m_mapAttachmentSlot.end(); it++ )
{
if( it->second.pAttachment )
{
it->second.pAttachment->SetPivot( m_Pos );
}
}
quaternion q1, q2;
z3d::QuaternionAxisAngle( q1, 0, 1.0f, 0, m_fDir );
//m_pSkeletonObjects[0].Rotate( q );
m_pSkeletonObjects[0].GetDirectionLocal( q2 );
m_pSkeletonObjects[0].SetDirectionLocal( q2*q1 );
m_pSkeletonObjects[0].GetPositionLocal( vd );
z3d::VectorRotate( vd, vd, q1 );
m_pSkeletonObjects[0].SetPositionLocal( vd );
// event 체크
m_vec_tokEventStorage.clear();
m_vec_tokSecondaryEventStorage.clear();
for( i = 0; i < m_rpGCMDS->GetAniHolderCount(); ++i )
{
m_pEventGenerator[i].CheckEvent(
m_pAniHolder[i].GetCurrentFrame(),
m_pAniHolder[i].GetPrevFrame(),
m_vec_tokEventStorage, m_vec_tokSecondaryEventStorage );
m_pAddonEventGenerator[i].CheckEvent(
m_pAddonAniHolder[i].GetCurrentFrame(),
m_pAddonAniHolder[i].GetPrevFrame(),
m_vec_tokEventStorage, m_vec_tokSecondaryEventStorage );
}
for( i = 0; i < m_rpGCMDS->GetAniHolderCount(); i++ )
{
m_pAniHolder[i].Progress();
m_pAddonAniHolder[i].Progress();
}
}
bool CZ3DGeneralChrModel::CheckEvent( const char* szEventName, Z3DTOK* p_tokSecondaryEvent )
{
Z3DTOK tok = g_TokEventName.GetTOK( szEventName );
if( NULL_TOK == tok )
{
return false;
}
std::vector<Z3DTOK>::iterator it;
if( m_vec_tokEventStorage.end() ==
( it = std::find( m_vec_tokEventStorage.begin(),
m_vec_tokEventStorage.end(), tok ) ) )
{
return false;
}
if( p_tokSecondaryEvent )
{
*p_tokSecondaryEvent =
m_vec_tokSecondaryEventStorage[it - m_vec_tokEventStorage.begin()];
}
*it = NULL_TOK; // clear checked event;
return true;
}
bool CZ3DGeneralChrModel::SetMotionSheet( const char* szSheetName )
{
if( NULL == szSheetName )
{
return false;
}
Z3DTOK tok = g_TokSheetName.GetTOK( szSheetName );
if( NULL_TOK == tok )
{
return false;
}
return SetMotionSheet( tok );
}
bool CZ3DGeneralChrModel::SetMotionSheet( Z3DTOK tokSheetName )
{
if( NULL == m_rpGCMDS )
{
return false;
}
const Z3DMOTIONSHEET* pSheet = m_rpGCMDS->GetMotionsheet( tokSheetName );
if( NULL == pSheet )
{
return false;
}
m_rpCurrentMotionSheet = pSheet;
m_tokCurrentMotionSheet = tokSheetName;
return true;
}
const char* CZ3DGeneralChrModel::GetCurrentMotionSheetName()
{
return g_TokSheetName.GetString( m_tokCurrentMotionSheet );
}
void CZ3DGeneralChrModel::PreRender()
{
if( m_pSkin )
{
m_pSkin->ApplyAnimation();
}
std::map<Z3DTOK, Z3D_TOK_N_ATTACHMENT>::iterator it;
for( it = m_mapAttachmentSlot.begin(); it != m_mapAttachmentSlot.end(); it++ )
{
if( it->second.pAttachment )
{
it->second.pAttachment->ApplyTransform();
}
}
}
void CZ3DGeneralChrModel::Render()
{
if( m_pSkin )
{
m_pSkin->RenderIndividual();
}
std::map<Z3DTOK, Z3D_TOK_N_ATTACHMENT>::iterator it;
for( it = m_mapAttachmentSlot.begin(); it != m_mapAttachmentSlot.end(); it++ )
{
if( it->second.pAttachment )
{
it->second.pAttachment->RenderIndividual();
}
}
}
void CZ3DGeneralChrModel::DrawShadow( DWORD vertexShader )
{
if( m_pSkin )
{
m_pSkin->RenderShadow( vertexShader );
}
std::map<Z3DTOK, Z3D_TOK_N_ATTACHMENT>::iterator it;
for( it = m_mapAttachmentSlot.begin(); it != m_mapAttachmentSlot.end(); it++ )
{
if( it->second.pAttachment )
{
it->second.pAttachment->RenderShadow( vertexShader );
}
}
}
void CZ3DGeneralChrModel::DrawSpecular( DWORD vertexShader )
{
if( m_pSkin )
{
m_pSkin->RenderSpecular( vertexShader );
}
std::map<Z3DTOK, Z3D_TOK_N_ATTACHMENT>::iterator it;
for( it = m_mapAttachmentSlot.begin(); it != m_mapAttachmentSlot.end(); it++ )
{
if( it->second.pAttachment )
{
it->second.pAttachment->RenderSpecular( vertexShader );
}
}
}
void CZ3DGeneralChrModel::GetAniDataDisplacement( vector3 &v_disp, int n )
{
if( !(n < m_rpGCMDS->GetAniHolderCount()) )
{
return;
}
if( NULL == m_pTagAniKeyPack[n].GetObject() )
{
v_disp.Identity();
return;
}
Z3DAniKeyPack* pPack = m_pTagAniKeyPack[n].GetObject();
if( false == pPack->GetDisplacement( v_disp, 0 ) )
{
v_disp.Identity();
}
}
long CZ3DGeneralChrModel::GetAniDataLength( int n )
{
if( !(n < m_rpGCMDS->GetAniHolderCount()) )
{
return 0L;
}
if( NULL == m_pTagAniKeyPack[n].GetObject() )
{
return 0L;
}
Z3DAniKeyPack* pPack = m_pTagAniKeyPack[n].GetObject();
return pPack->GetAniLength();
}
void CZ3DGeneralChrModel::SetDisable( bool bDisabled )
{
CZ3DCharacterModel::SetDisable( bDisabled );
SetCull( bDisabled );
}
void CZ3DGeneralChrModel::SetCull( bool bCulled )
{
if( m_pSkeletonObjects ) // init 의 증거
{
m_pSkeletonObjects[0].SetDisable( bCulled );
}
if( m_pSkin )
{
m_pSkin->SetCull( bCulled );
}
std::map<Z3DTOK, Z3D_TOK_N_ATTACHMENT>::iterator it;
for( it = m_mapAttachmentSlot.begin(); it != m_mapAttachmentSlot.end(); it++ )
{
if( it->second.pAttachment )
{
it->second.pAttachment->SetCull( bCulled );
}
}
}
void CZ3DGeneralChrModel::SetScale( float f )
{
float fDefaultScale = 1.0f;
if( m_rpGCMDS )
{
fDefaultScale = m_rpGCMDS->GetDefaultScale();
}
m_fScaleFactor = f;
if( m_pSkin )
{
m_pSkin->SetScale( f * fDefaultScale );
}
// attachment 관련 설정
std::map<Z3DTOK, Z3D_TOK_N_ATTACHMENT>::iterator it;
for( it = m_mapAttachmentSlot.begin(); it != m_mapAttachmentSlot.end(); it++ )
{
if( it->second.pAttachment )
{
it->second.pAttachment->SetScale( f * fDefaultScale );
}
}
}
float CZ3DGeneralChrModel::GetEffectScale()
{
return this->GetScale() * m_rpGCMDS->GetEffectScale();
}
void CZ3DGeneralChrModel::GetBoundingBox( vector3& r_vmin, vector3& r_vmax )
{
if( NULL == m_pSkin )
{
r_vmin = vector3( 0, 0, 0 );
r_vmax = vector3( 0, 0, 0 );
return;
}
m_pSkin->GetBoundingBox( r_vmin, r_vmax );
}
const Z3D_BOUNDING_CYLINDER* CZ3DGeneralChrModel::GetBoundingCylinderList()
{
if( NULL == m_rpGCMDS )
{
return NULL;
}
const std::vector<Z3D_BOUNDING_CYLINDER_INFO>& rBCIList =
*(m_rpGCMDS->GetBoundingCylinderVector());
for( int i = 0; i < rBCIList.size(); ++i )
{
m_pBoundingCylinder[i].vBottom.x = m_pSkeletonObjects[rBCIList[i].lBottomIdx].GetTM()->_41;
m_pBoundingCylinder[i].vBottom.y = m_pSkeletonObjects[rBCIList[i].lBottomIdx].GetTM()->_42;
m_pBoundingCylinder[i].vBottom.z = m_pSkeletonObjects[rBCIList[i].lBottomIdx].GetTM()->_43;
m_pBoundingCylinder[i].vTop.x = m_pSkeletonObjects[rBCIList[i].lTopIdx].GetTM()->_41;
m_pBoundingCylinder[i].vTop.y = m_pSkeletonObjects[rBCIList[i].lTopIdx].GetTM()->_42;
m_pBoundingCylinder[i].vTop.z = m_pSkeletonObjects[rBCIList[i].lTopIdx].GetTM()->_43;
}
return m_pBoundingCylinder;
}
bool CZ3DGeneralChrModel::IsShaderParameterAvailable( long lIdx )
{
if( NULL == m_rpGCMDS )
{
return false;
}
return m_rpGCMDS->IsShaderParameterAvailable( lIdx );
}
const char* CZ3DGeneralChrModel::GetShaderParameterInfo( long lIdx )
{
if( NULL == m_rpGCMDS )
{
return NULL;
}
return m_rpGCMDS->GetShaderParameterInfo( lIdx );
}
long CZ3DGeneralChrModel::GetEffectInfoList( const char** &rpszEffectInfo )
{
if( NULL == m_rpGCMDS )
{
rpszEffectInfo = NULL;
return 0;
}
return m_rpGCMDS->GetEffectInfoList( rpszEffectInfo );
}