#include "stdafx.h" #include "KNX3Loader.h" #include "K3DBound.h" #include "KResourceManager.h" #include "nx10.h" #include #include "k3dpccp.h" using namespace trf; namespace { void fillAnimatrixFromArray(float* pArray, K3DMatrix* pOutput) { pOutput->_11 = pArray[0]; pOutput->_12 = pArray[1]; pOutput->_13 = pArray[2]; pOutput->_14 = .0f; pOutput->_21 = pArray[3]; pOutput->_22 = pArray[4]; pOutput->_23 = pArray[5]; pOutput->_24 = .0f; pOutput->_31 = pArray[6]; pOutput->_32 = pArray[7]; pOutput->_33 = pArray[8]; pOutput->_34 = .0f; pOutput->_41 = pArray[9]; pOutput->_42 = pArray[10]; pOutput->_43 = pArray[11]; pOutput->_44 = 1.0f; } inline const char* SafeStr( const char* pStr ) { return pStr ? pStr : ""; } } enum LIGHT_TYPE { NX3LIGHT_OMNI = 0, NX3LIGHT_SIMPLE_OMNI, NX3LIGHT_TARGET_DIRECTIONAL, NX3LIGHT_FREE_DIRECTIONAL, }; KNX3MtlChannel::KNX3MtlChannel(K3DRenderDevice * pGraphics) { m_pGraphics = pGraphics; m_vtMtlList.clear(); } KNX3MtlChannel::~KNX3MtlChannel() { Clear(); } void KNX3MtlChannel::Clear() { m_pGraphics = NULL; SAFE_DELETE_VECTOR(m_vtMtlList); } KNX3Mtl * KNX3MtlChannel::GetMtl(int nID) { for(unsigned int i(0); i < m_vtMtlList.size(); ++i) { KNX3Mtl * pMtl = m_vtMtlList.at(i); if(pMtl->GetMtlID() == nID) { return pMtl; } } return NULL; } BOOL KNX3MtlChannel::Load( KTemplateDataObject* pObject, const NX3LoadPack * pLoadPack ) { DWORD dwTime = GetSafeTickCount(); DWORD dwNumMtl; KSimpleDataObject * pNumMtl = pObject->GetSimpleDataMemberObject("mtl_size"); pNumMtl->GetDWORD(&dwNumMtl); KTemplateDataArrayObject * pMtlArray = pObject->GetTemplateDataArrayMemberObject("mtl_array"); for(unsigned int i(0); i < dwNumMtl; ++i) { KNX3Mtl * pMtl = new KNX3Mtl(m_pGraphics); pMtl->Load( pMtlArray->GetData(i), pLoadPack ); m_vtMtlList.push_back(pMtl); } if( GetSafeTickCount()-dwTime > 80 ) { // _oprint( "Load Time : KNX3MtlChannel::Load - %d : %dms\n", dwNumMtl, GetSafeTickCount()-dwTime ); } return TRUE; } bool KNX3MtlChannel::LoadTRF( trf::MTemplatePtr pObject, const NX3LoadPack * pLoadPack ) { DWORD dwTime = GetSafeTickCount(); trf::MTemplateArrayPtr pMtlArray = pObject->getTemplateArrayBy("mtl_array"); for(int i(0); i < pMtlArray->count(); ++i) { KNX3Mtl * pMtl = new KNX3Mtl(m_pGraphics); pMtl->LoadTRF( pMtlArray->getTemplateAt(i), pLoadPack ); m_vtMtlList.push_back(pMtl); } if( GetSafeTickCount()-dwTime > 80 ) { // _oprint( "Load Time : KNX3MtlChannel::Load - %d : %dms\n", pMtlArray->count(), GetSafeTickCount()-dwTime ); } return true; } // Material KNX3Mtl::KNX3Mtl(K3DRenderDevice * pGraphics) { m_pGraphics = pGraphics; m_vtMtlElement.clear(); } KNX3Mtl::~KNX3Mtl() { Clear(); } void KNX3Mtl::Clear() { m_pGraphics = NULL; SAFE_DELETE_VECTOR(m_vtMtlElement); } BOOL KNX3Mtl::Load( KTemplateDataObject * pObject, const NX3LoadPack * pLoadPack ) { DWORD dwTime = GetSafeTickCount(); DWORD dwNumSubMtl; KSimpleDataObject * pNumSubMtl = pObject->GetSimpleDataMemberObject("sub_mtl_block_size"); pNumSubMtl->GetDWORD(&dwNumSubMtl); KTemplateDataArrayObject * pSubMtlArray = pObject->GetTemplateDataArrayMemberObject("sub_mtl_block_array"); for(unsigned int i(0); i < dwNumSubMtl; ++i) { KNX3MtlElement* pElement = new KNX3MtlElement(); pElement->Load( pSubMtlArray->GetData(i), pLoadPack ); m_vtMtlElement.push_back(pElement); } // _oprint( "Load Cnt : KNX3MtlElement::Load : %d\n", dwNumSubMtl ); // _oprint( "Load Time : KNX3Mtl::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } bool KNX3Mtl::LoadTRF( trf::MTemplatePtr pObject, const NX3LoadPack * pLoadPack ) { DWORD dwTime = GetSafeTickCount(); trf::MTemplateArrayPtr pSubMtlArray = pObject->getTemplateArrayBy("sub_mtl_block_array"); for(int i(0); i < pSubMtlArray->count(); ++i) { KNX3MtlElement* pElement = new KNX3MtlElement(); pElement->LoadTRF( pSubMtlArray->getTemplateAt(i), pLoadPack ); m_vtMtlElement.push_back(pElement); } return true; } // Material Element KNX3MtlElement::KNX3MtlElement() { m_pMaterial = NULL; m_dwMtlID = 0; m_nBlendmode = K3DMaterial::MBM_DEFAULT; } KNX3MtlElement::~KNX3MtlElement() { Clear(); } void KNX3MtlElement::Clear() { SAFE_DELETE(m_pMaterial); m_dwMtlID = 0; } BOOL KNX3MtlElement::Load( KTemplateDataObject * pObject, const NX3LoadPack * ploadpack ) { DWORD dwTime = GetSafeTickCount(); char lpszTextureName[512]; ZeroMemory( lpszTextureName, sizeof( lpszTextureName ) ); int iStrLen = 512; m_pLoadPack = ploadpack; m_pMaterial = new K3DMaterial; KSimpleDataObject * pTextureName = pObject->GetSimpleDataMemberObject("texture_name"); pTextureName->GetString(lpszTextureName, iStrLen); m_sTextureName = lpszTextureName; KSimpleDataObject * pMtlID = pObject->GetSimpleDataMemberObject("mtl_id"); pMtlID->GetDWORD(&m_dwMtlID); float fPower; KSimpleDataObject * pPower = pObject->GetSimpleDataMemberObject("power"); pPower->GetFloat(&fPower); m_pMaterial->SetSpecularPower( fPower ); DWORD dwAmbient; KSimpleDataObject * pAmbient = pObject->GetSimpleDataMemberObject("ambient"); pAmbient->GetDWORD(&dwAmbient); m_pMaterial->SetAmbient( K3DColor(dwAmbient) ); DWORD dwDiffuse; KSimpleDataObject * pDiffuse = pObject->GetSimpleDataMemberObject("diffuse"); pDiffuse->GetDWORD(&dwDiffuse); m_pMaterial->SetDiffuse( K3DColor(dwDiffuse) ); DWORD dwSpecular; KSimpleDataObject * pSpecular = pObject->GetSimpleDataMemberObject("specular"); pSpecular->GetDWORD(&dwSpecular); m_pMaterial->SetSpecular( K3DColor(dwSpecular) ); /* m_pMaterial->SetAmbient( K3DColor( .2f, .2f, .2f ) ); m_pMaterial->SetDiffuse( K3DColor( 8.f, 8.f, 8.f ) ); m_pMaterial->SetSpecular( K3DColor( 1.f, 1.f, 1.f ) ); */ float fSelfIlum; KSimpleDataObject * pSelfIlum = pObject->GetSimpleDataMemberObject("self_illumi"); pSelfIlum->GetFloat(&fSelfIlum); if( fSelfIlum > 0.8f ) { m_nBlendmode = K3DMaterial::MBM_ADDITIVE; m_pMaterial->SetAmbient( K3DColor( .5f, .5f, .5f ) ); m_pMaterial->SetDiffuse( K3DColor( 8.f, 8.f, 8.f ) ); m_pMaterial->SetSpecular( K3DColor( 1.f, 1.f, 1.f ) ); } else if( fSelfIlum > 0.6f ) { m_nBlendmode = K3DMaterial::MBM_ALPHABLENDTWOPASS; } else if( fSelfIlum > 0.4f ) { m_nBlendmode = K3DMaterial::MBM_ALPHABLEND; } else { m_nBlendmode = K3DMaterial::MBM_DEFAULT; } return TRUE; } bool KNX3MtlElement::LoadTRF( trf::MTemplatePtr pObject, const NX3LoadPack * ploadpack ) { DWORD dwTime = GetSafeTickCount(); m_pLoadPack = ploadpack; m_pMaterial = new K3DMaterial; m_sTextureName = SafeStr( pObject->getStringBy("texture_name") ); m_dwMtlID = pObject->getDWordBy("mtl_id"); m_pMaterial->SetSpecularPower( pObject->getFloatBy("power") ); m_pMaterial->SetAmbient( K3DColor( pObject->getDWordBy("ambient") ) ); m_pMaterial->SetDiffuse( K3DColor( pObject->getDWordBy("diffuse") ) ); m_pMaterial->SetSpecular( K3DColor( pObject->getDWordBy("specular") ) ); float fSelfIlum = pObject->getFloatBy("self_illumi"); if( fSelfIlum > 0.8f ) { m_nBlendmode = K3DMaterial::MBM_ADDITIVE; m_pMaterial->SetAmbient( K3DColor( .5f, .5f, .5f ) ); m_pMaterial->SetDiffuse( K3DColor( 8.f, 8.f, 8.f ) ); m_pMaterial->SetSpecular( K3DColor( 1.f, 1.f, 1.f ) ); } else if( fSelfIlum > 0.6f ) { m_nBlendmode = K3DMaterial::MBM_ALPHABLENDTWOPASS; } else if( fSelfIlum > 0.4f ) { m_nBlendmode = K3DMaterial::MBM_ALPHABLEND; } else { m_nBlendmode = K3DMaterial::MBM_DEFAULT; } return true; } K3DTexture* KNX3MtlElement::GetTexture() { if(NULL == m_spTexture && false == m_sTextureName.empty()) m_spTexture = _GetTexture(m_sTextureName.c_str() ); return m_spTexture; } K3DTexture* KNX3MtlElement::GetBumpTexture() { #define DO_NOT_LOAD_BUMPMAP #ifndef DO_NOT_LOAD_BUMPMAP if(NULL == m_spTexture_Bump && false == m_sTextureName.empty()) { std::string name = m_sTextureName; name.replace( name.size() - 4, 1, "_bump." ); m_spTexture_Bump = _GetTexture(name.c_str() ); } #endif // DO_NOT_LOAD_BUMPMAP return m_spTexture_Bump; } K3DTexture* KNX3MtlElement::GetIlluminTexture() { if(NULL == m_spTexture_Illumin && false == m_sTextureName.empty()) { std::string name = m_sTextureName; name.replace( name.size() - 4, 1, "_illumin." ); m_spTexture_Illumin = _GetTexture(name.c_str() ); } return m_spTexture_Illumin; } K3DTexture* KNX3MtlElement::GetSpecularTexture() { if(NULL == m_spTexture_Specular && false == m_sTextureName.empty()) { // 2010.05.19 faceÀÇ ½ºÆåŧ¶ó ¸ÊÀº ÀϰýÀûÀ¸·Î face_spec.dds¸¦ ¾²µµ·Ï ¼öÁ¤- prodongi int facePos = m_sTextureName.find("face"); if (facePos >= 0) { m_spTexture_Specular = _GetTexture("face_spec.dds"); } else { #ifdef _SPECULAR_EDITING_ std::string nameL = m_sTextureName; nameL.replace( nameL.size() - 4, 1, "_l_spec." ); m_spTexture_Specular = _GetTexture(nameL.c_str()); if( NULL == m_spTexture_Specular ) { std::string nameM = m_sTextureName; nameM.replace( nameM.size() - 4, 1, "_m_spec." ); m_spTexture_Specular = _GetTexture(nameM.c_str()); if( NULL == m_spTexture_Specular ) { std::string name = m_sTextureName; name.replace( name.size() - 4, 1, "_spec." ); m_spTexture_Specular = _GetTexture(name.c_str()); } } #else std::string name = m_sTextureName; name.replace( name.size() - 4, 1, "_spec." ); m_spTexture_Specular = _GetTexture(name.c_str() ); #endif } } return m_spTexture_Specular; } K3DTexture* KNX3MtlElement::GetSpecularColorTexture() { #ifdef _SPECULAR_EDITING_ if( NULL == m_spTexture_SpecularColorMap && false == m_sTextureName.empty() ) { std::string nameL = m_sTextureName; nameL.replace( nameL.size() - 4, 1, "_l_spec." ); std::string nameM = m_sTextureName; nameM.replace( nameM.size() - 4, 1, "_m_spec." ); if ( NULL != _GetTexture(nameL.c_str()) ) m_spTexture_SpecularColorMap = _GetTexture("leather_specular_color.dds"); else if( NULL != _GetTexture(nameM.c_str()) ) m_spTexture_SpecularColorMap = _GetTexture("specularColorMap.dds"); else m_spTexture_SpecularColorMap = NULL; } #else if(NULL == m_spTexture_SpecularColorMap && false == m_sTextureName.empty()) m_spTexture_SpecularColorMap = _GetTexture("specularColorMap.dds"); #endif return m_spTexture_SpecularColorMap; } K3DTexture* KNX3MtlElement::_GetTexture(LPCSTR name) { #ifdef _RAC if( KTextureManager::GetManager()->IsExistTexture( name , m_pLoadPack ) ) { return KTextureManager::GetManager()->GetTexture( name, m_pLoadPack, true, KTextureManager::GetManager()->GetMipMapBiasLevel() ); } #else if( KTextureManager::GetManager()->IsExistTexture( name, m_pLoadPack ) ) { return KTextureManager::GetManager()->GetTexture( name, m_pLoadPack ); } #endif return NULL; } //======================================================================================================================= //KNX3BoneChannel======================================================================================================== //======================================================================================================================= BOOL KNX3Bone::Load( KTemplateDataObject * pObject ) { DWORD dwTime = GetSafeTickCount(); KSimpleDataObject *pParentIndex = pObject->GetSimpleDataMemberObject("parent_Index"); DWORD dwParentIndex; pParentIndex->GetDWORD(&dwParentIndex); m_nParentIndex = dwParentIndex; KSimpleDataArrayObject *pBaseTM = pObject->GetSimpleDataArrayMemberObject("base_tm"); KSimpleDataObject *pFlag = pObject->GetSimpleDataMemberObject("flag"); pFlag->GetDWORD(&m_dwFlag); //Name int iStrLen = 64; KSimpleDataObject * pBoneName = pObject->GetSimpleDataMemberObject("szName"); pBoneName->GetString( szName, iStrLen ); //멤버 Load pBaseTM->GetDataFloat(0, m_BaseTM, sizeof( m_BaseTM ), 16); // OutputDebugString(szName); // OutputDebugString("\n"); //Pos Key KSimpleDataObject *pPosTimeSize = pObject->GetSimpleDataMemberObject("pos_time_size"); pPosTimeSize->GetDWORD(&m_dwPosCount); KSimpleDataArrayObject *pPosTimeArray = pObject->GetSimpleDataArrayMemberObject("pos_time_array"); KSimpleDataObject *pPosKeySize = pObject->GetSimpleDataMemberObject("pos_key_size"); m_dwPosCount = pPosTimeArray->GetDataCount(); //시간만큼 있다. KSimpleDataArrayObject *pPosKeyArray = pObject->GetSimpleDataArrayMemberObject("pos_key_array"); int n(0); std::vector< DWORD > _time_list; std::vector< K3DVector > _pos_list; K3DVector prev_pos = K3DVector(-10000,-10000, -10000); DWORD prev_time = -1; DWORD save_time = -1; //_oprint( " Bone Pos Optimize : %4d -> ", m_dwPosCount ); for( DWORD i(0); static_cast(m_dwPosCount) > i; i++ ) { DWORD postime; pPosTimeArray->GetDataDWORD(i, &postime, sizeof( postime ), 1); float fpos[3]; pPosKeyArray->GetDataFloat(n, fpos, sizeof( fpos ), 3); n+=3; K3DVector pos = K3DVector( fpos[0], fpos[1], fpos[2] ); float fLen = (pos - prev_pos).Magnitude(); if( fLen > 0.005f || i == m_dwPosCount - 1 ) { //이전 것과 현재 것이 다르면서, 이전 것을 추가 한다.(더 정확한 보간 위한) if( prev_time != save_time ) { _pos_list.push_back( prev_pos ); _time_list.push_back( prev_time ); } prev_pos = pos; save_time = postime; _pos_list.push_back( pos ); _time_list.push_back( postime ); } prev_time = postime; } //_oprint( " %4d / ", _pos_list.size() ); if( !_pos_list.empty() ) { m_dwPosCount = _pos_list.size(); assert( _pos_list.size() == _time_list.size() && "애니메이션 데이타 position 사이즈 이상" ); m_pPosKey = new KNXgeneric_key_t[_pos_list.size()]; memset( m_pPosKey, 0, sizeof(KNXgeneric_key_t)*_pos_list.size() ); float fpos[3]; for( unsigned int i(0); _pos_list.size()>i; i++ ) { fpos[0] = _pos_list[i].x; fpos[1] = _pos_list[i].y; fpos[2] = _pos_list[i].z; m_pPosKey[i].msec = _time_list[i]; memcpy( &m_pPosKey[i].lin_pos, fpos, sizeof(float)*3 ); } } //Rot Key KSimpleDataObject *pRotTimeSize = pObject->GetSimpleDataMemberObject("rot_time_size"); pRotTimeSize->GetDWORD(&m_dwRotCount); KSimpleDataArrayObject *pRotTimeArray = pObject->GetSimpleDataArrayMemberObject("rot_time_array"); KSimpleDataObject *pRotKeySize = pObject->GetSimpleDataMemberObject("rot_key_size"); m_dwRotCount = pRotTimeArray->GetDataCount(); KSimpleDataArrayObject *pRotKeyArray = pObject->GetSimpleDataArrayMemberObject("rot_key_array"); n=0; //0 0 0 1 std::vector< DWORD > _rot_time_list; std::vector< K3DQuaternion > _rot_list; K3DQuaternion prev_rot_q = K3DQuaternion(-1, 0, 0, 0); K3DQuaternion quat; K3DQuaternion tempq; prev_time = -1; save_time = -1; //_oprint( " Bone Rot Optimize : %4d -> ", m_dwRotCount ); for( int i(0); static_cast(m_dwRotCount) > i; i++ ) { DWORD rottime; pRotTimeArray->GetDataDWORD(i, &rottime, sizeof( rottime ), 1); float rot[4]; pRotKeyArray->GetDataFloat(n, rot, sizeof( rot ), 4); n+=4; quat = K3DQuaternion( rot[0], rot[1], rot[2], rot[3] ); K3DQuaternionInverse( tempq, prev_rot_q ); tempq = quat * tempq; float quat_len = K3DVectorLength(K3DVector(tempq.x, tempq.y, tempq.z)); if( !(quat_len < 0.002f && tempq.w > 0.99f) || i == m_dwRotCount - 1 ) { //이전 것과 현재 것이 다르면서, 이전 것을 추가 한다.(더 정확한 보간 위한) if( prev_time != save_time ) { _rot_time_list.push_back( prev_time ); _rot_list.push_back( prev_rot_q ); } prev_rot_q = quat; save_time = rottime; _rot_time_list.push_back( rottime ); _rot_list.push_back( quat ); } prev_time = rottime; } //_oprint( " %4d\n", _rot_time_list.size() ); if( !_rot_time_list.empty() ) { assert( _rot_time_list.size() == _rot_list.size() && "애니메이션 데이타 position 사이즈 이상" ); m_pRotKey = new KNXgeneric_key_t[_rot_time_list.size()]; memset( m_pRotKey, 0, sizeof(KNXgeneric_key_t)*_rot_time_list.size() ); for( unsigned i(0); _rot_time_list.size()>i; i++ ) { float frot[4]; frot[0] = _rot_list[i].x; frot[1] = _rot_list[i].y; frot[2] = _rot_list[i].z; frot[3] = _rot_list[i].w; m_pRotKey[i].msec = _rot_time_list[i]; memcpy( &m_pRotKey[i].lin_rot, frot, sizeof(float)*4 ); } } m_dwRotCount = _rot_time_list.size(); //Child Index KSimpleDataObject *pChildSize = pObject->GetSimpleDataMemberObject("child_size"); pChildSize->GetDWORD(&m_dwChildCount); KSimpleDataArrayObject *pChildIndexArray = pObject->GetSimpleDataArrayMemberObject("child_Index_array"); if( m_dwChildCount>0 ) { m_pChildList = new int [m_dwChildCount]; pChildIndexArray->GetDataDWORD(0, (DWORD*)m_pChildList, sizeof( int )*m_dwChildCount, m_dwChildCount); } // _oprint( "Load Time : KNX3Bone::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } /* bool KNX3Bone::LoadTRF( trf::MTemplatePtr pObject ) { DWORD dwTime = GetSafeTickCount(); //Name strncpy( szName, SafeStr( pObject->getStringBy("szName") ), 64 ); m_nParentIndex = pObject->getDWordBy("parent_Index"); pObject->getArrayBy("base_tm")->readFixedData( 0, 16, &m_BaseTM, sizeof(m_BaseTM) ); m_dwFlag = pObject->getDWordBy("flag"); //멤버 Load //Pos Key trf::MArrayPtr pPosTimeArray = pObject->getArrayBy( "pos_time_array" ); trf::MArrayPtr pPosKeyArray = pObject->getArrayBy( "pos_key_array" ); m_dwPosCount = pPosTimeArray->count(); assert( m_dwPosCount * 3 == pPosKeyArray->count() && "애니메이션 데이타 position 사이즈 이상" ); const DWORD* pTimeList = pPosTimeArray->getDWordArray(); const float* pPosList = pPosKeyArray->getFloatArray(); int n(0); std::vector< int > indexList; indexList.reserve( m_dwPosCount ); K3DVector prev_pos = K3DVector(-10000,-10000, -10000); DWORD prev_time = -1; DWORD save_time = -1; int prev_index = -1; //_oprint( " Bone Pos Optimize : %4d -> ", m_dwPosCount ); for( DWORD i(0); static_cast(m_dwPosCount) > i; i++ ) { DWORD postime = pTimeList[ i ]; const K3DVector& pos = *reinterpret_cast< const K3DVector* >( &pPosList[ n ] ); n += 3; float fLen = (pos - prev_pos).Magnitude(); if( fLen > 0.005f || i == m_dwPosCount - 1 ) { //이전 것과 현재 것이 다르면서, 이전 것을 추가 한다.(더 정확한 보간 위한) if( prev_time != save_time ) { indexList.push_back( prev_index ); } prev_pos = pos; save_time = postime; indexList.push_back( i ); } prev_time = postime; prev_index = i; } //_oprint( " %4d / ", _pos_list.size() ); if( !indexList.empty() ) { m_dwPosCount = indexList.size(); m_pPosKey = new KNXgeneric_key_t[ m_dwPosCount ]; memset( m_pPosKey, 0, sizeof(KNXgeneric_key_t) * m_dwPosCount ); for( unsigned int i(0); m_dwPosCount > i; i++ ) { int index = indexList[ i ]; m_pPosKey[i].msec = pTimeList[ index ]; memcpy( &m_pPosKey[i].lin_pos, &pPosList[ index*3 ], sizeof(float)*3 ); } } //Rot Key trf::MArrayPtr pRotTimeArray = pObject->getArrayBy( "rot_time_array" ); trf::MArrayPtr pRotKeyArray = pObject->getArrayBy( "rot_key_array" ); m_dwRotCount = pRotTimeArray->count(); assert( m_dwRotCount * 4 == pRotKeyArray->count() && "애니메이션 데이타 rotation 사이즈 이상" ); const DWORD* pRotTimeList = pRotTimeArray->getDWordArray(); const float* pRotList = pRotKeyArray->getFloatArray(); n=0; //0 0 0 1 indexList.clear(); indexList.reserve( m_dwRotCount ); K3DQuaternion prev_rot_q = K3DQuaternion(-1, 0, 0, 0); K3DQuaternion quat; K3DQuaternion tempq; prev_time = -1; save_time = -1; prev_index = -1; //_oprint( " Bone Rot Optimize : %4d -> ", m_dwRotCount ); for( int i(0); static_cast(m_dwRotCount) > i; i++ ) { DWORD rottime = pRotTimeList[ i ]; const K3DQuaternion& quat = *reinterpret_cast< const K3DQuaternion* >( &pRotList[ n ] ); n += 4; K3DQuaternionInverse( tempq, prev_rot_q ); tempq = quat * tempq; float quat_len = tempq.AsVec3().Magnitude(); if( !(quat_len < 0.002f && tempq.w > 0.99f) || i == m_dwRotCount - 1 ) { //이전 것과 현재 것이 다르면서, 이전 것을 추가 한다.(더 정확한 보간 위한) if( prev_time != save_time ) { indexList.push_back( prev_index ); } prev_rot_q = quat; save_time = rottime; indexList.push_back( i ); } prev_time = rottime; prev_index = i; } //_oprint( " %4d\n", _rot_time_list.size() ); m_dwRotCount = indexList.size(); if( !indexList.empty() ) { m_pRotKey = new KNXgeneric_key_t[ m_dwRotCount ]; memset( m_pRotKey, 0, sizeof(KNXgeneric_key_t) * m_dwRotCount ); for( unsigned i(0); m_dwRotCount > i; i++ ) { int index = indexList[ i ]; m_pRotKey[i].msec = pRotTimeList[ index ]; memcpy( &m_pRotKey[i].lin_rot, &pRotList[ index*4 ], sizeof(float)*4 ); } } //Child Index trf::MArrayPtr pChildIndexArray = pObject->getArrayBy( "child_Index_array" ); m_dwChildCount = pChildIndexArray->count(); if( m_dwChildCount>0 ) { m_pChildList = new int[ m_dwChildCount ]; pChildIndexArray->readFixedData( 0, m_dwChildCount, m_pChildList, m_dwChildCount*sizeof(int) ); } // _oprint( "Load Time : KNX3Bone::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } /*/ bool KNX3Bone::LoadTRF( trf::MTemplatePtr pObject ) { DWORD dwTime = GetSafeTickCount(); //Name strncpy( szName, SafeStr( pObject->getStringBy("szName") ), 64 ); m_nParentIndex = pObject->getDWordBy("parent_Index"); pObject->getArrayBy("base_tm")->readFixedData( 0, 16, &m_BaseTM, sizeof(m_BaseTM) ); m_dwFlag = pObject->getDWordBy("flag"); //멤버 Load //Pos Key trf::MArrayPtr pPosTimeArray = pObject->getArrayBy( "pos_time_array" ); trf::MArrayPtr pPosKeyArray = pObject->getArrayBy( "pos_key_array" ); m_dwPosCount = pPosTimeArray->count(); int n(0); std::vector< DWORD > _time_list; std::vector< K3DVector > _pos_list; _time_list.reserve( m_dwPosCount ); _pos_list.reserve( m_dwPosCount ); K3DVector prev_pos = K3DVector(-10000,-10000, -10000); DWORD prev_time = -1; DWORD save_time = -1; //_oprint( " Bone Pos Optimize : %4d -> ", m_dwPosCount ); for( DWORD i(0); static_cast(m_dwPosCount) > i; i++ ) { DWORD postime = pPosTimeArray->getDWordAt(i); const float* fpos = pPosKeyArray->getFloatArray( n ); n+=3; K3DVector pos = K3DVector( fpos[0], fpos[1], fpos[2] ); float fLen = (pos - prev_pos).Magnitude(); if( fLen > 0.005f || i == m_dwPosCount - 1 ) { //이전 것과 현재 것이 다르면서, 이전 것을 추가 한다.(더 정확한 보간 위한) if( prev_time != save_time ) { _pos_list.push_back( prev_pos ); _time_list.push_back( prev_time ); } prev_pos = pos; save_time = postime; _pos_list.push_back( pos ); _time_list.push_back( postime ); } prev_time = postime; } //_oprint( " %4d / ", _pos_list.size() ); if( !_pos_list.empty() ) { m_dwPosCount = _pos_list.size(); assert( _pos_list.size() == _time_list.size() && "애니메이션 데이타 position 사이즈 이상" ); m_pPosKey = new KNXgeneric_key_t[_pos_list.size()]; memset( m_pPosKey, 0, sizeof(KNXgeneric_key_t)*_pos_list.size() ); for( unsigned int i(0); _pos_list.size()>i; i++ ) { m_pPosKey[i].msec = _time_list[i]; memcpy( &m_pPosKey[i].lin_pos, &_pos_list[i], sizeof(float)*3 ); } } //Rot Key trf::MArrayPtr pRotTimeArray = pObject->getArrayBy( "rot_time_array" ); trf::MArrayPtr pRotKeyArray = pObject->getArrayBy( "rot_key_array" ); m_dwRotCount = pRotTimeArray->count(); n=0; //0 0 0 1 std::vector< DWORD > _rot_time_list; std::vector< K3DQuaternion > _rot_list; _rot_time_list.reserve( m_dwRotCount ); _rot_list.reserve( m_dwRotCount ); K3DQuaternion prev_rot_q = K3DQuaternion(-1, 0, 0, 0); K3DQuaternion quat; K3DQuaternion tempq; prev_time = -1; save_time = -1; //_oprint( " Bone Rot Optimize : %4d -> ", m_dwRotCount ); for( int i(0); static_cast(m_dwRotCount) > i; i++ ) { DWORD rottime = pRotTimeArray->getDWordAt( i ); const float* rot = pRotKeyArray->getFloatArray( n ); n+=4; quat = K3DQuaternion( rot[0], rot[1], rot[2], rot[3] ); K3DQuaternionInverse( tempq, prev_rot_q ); tempq = quat * tempq; float quat_len = K3DVectorLength(K3DVector(tempq.x, tempq.y, tempq.z)); if( !(quat_len < 0.002f && tempq.w > 0.99f) || i == m_dwRotCount - 1 ) { //이전 것과 현재 것이 다르면서, 이전 것을 추가 한다.(더 정확한 보간 위한) if( prev_time != save_time ) { _rot_time_list.push_back( prev_time ); _rot_list.push_back( prev_rot_q ); } prev_rot_q = quat; save_time = rottime; _rot_time_list.push_back( rottime ); _rot_list.push_back( quat ); } prev_time = rottime; } //_oprint( " %4d\n", _rot_time_list.size() ); if( !_rot_time_list.empty() ) { assert( _rot_time_list.size() == _rot_list.size() && "애니메이션 데이타 position 사이즈 이상" ); m_pRotKey = new KNXgeneric_key_t[_rot_time_list.size()]; memset( m_pRotKey, 0, sizeof(KNXgeneric_key_t)*_rot_time_list.size() ); for( unsigned i(0); _rot_time_list.size() > i; i++ ) { m_pRotKey[i].msec = _rot_time_list[i]; memcpy( &m_pRotKey[i].lin_rot, &_rot_list[i], sizeof(float)*4 ); } } m_dwRotCount = _rot_time_list.size(); //Child Index trf::MArrayPtr pChildIndexArray = pObject->getArrayBy( "child_Index_array" ); m_dwChildCount = pChildIndexArray->count(); if( m_dwChildCount>0 ) { m_pChildList = new int [m_dwChildCount]; pChildIndexArray->readFixedData( 0, m_dwChildCount, m_pChildList, m_dwChildCount*sizeof(int) ); } // _oprint( "Load Time : KNX3Bone::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } //*/ void KNX3BoneChannel::Clear() { m_spBoneRes = NULL; } /// Load from filer. BOOL KNX3BoneChannel::Load( KTemplateDataObject * pObject, const char * szName, DWORD dwVersion ) { DWORD dwTime = GetSafeTickCount(); m_spBoneRes = new K3DBoneResource; m_spBoneRes->SetVersion( dwVersion ); m_spBoneRes->SetName( szName ); KFT_nx3_bone_ani_header bone_ani_header(pObject); KSimpleDataObject * pBoneCount = pObject->GetSimpleDataMemberObject( "bone_count" ); KSimpleDataObject * pChannelCount = pObject->GetSimpleDataMemberObject( "channel_count" ); KTemplateDataArrayObject * pChannel_Array = pObject->GetTemplateDataArrayMemberObject( "channel_array" ); DWORD dwBoneCount = 0; DWORD dwChannelCount = 0; dwBoneCount = bone_ani_header.GetValue_bone_count(); dwChannelCount = bone_ani_header.GetValue_channel_count(); pBoneCount->GetDWORD( &dwBoneCount ); pChannelCount->GetDWORD( &dwChannelCount ); if( dwBoneCount <= 0 ) _oprint( "[KNX3BoneChannel::Load] Bones count is less than 0!\n" ); //채널은 한개만 지원 된다. KTemplateDataObject * pChannelObject = pChannel_Array->GetData(0); //작업중.. KSimpleDataObject * pChannel_flag = pChannelObject->GetSimpleDataMemberObject( "channel_flag" ); KSimpleDataObject * pChannel_timespan = pChannelObject->GetSimpleDataMemberObject( "channel_time_span" ); KSimpleDataObject * pChannel_framerate = pChannelObject->GetSimpleDataMemberObject( "channel_frame_rate" ); KSimpleDataObject * pChannel_channelname = pChannelObject->GetSimpleDataMemberObject( "channel_name" ); m_dwChannelFlag = 0; m_dwChannelTimeSpan = 0; m_dwChannelFrameRate = 0; m_szChannelName[_countof(m_szChannelName)-1] = '\0'; pChannel_flag->GetDWORD(&m_dwChannelFlag); pChannel_timespan->GetDWORD(&m_dwChannelTimeSpan); pChannel_framerate->GetDWORD(&m_dwChannelFrameRate); int nLen = pChannel_channelname->GetSize(); if( nLen < _countof(m_szChannelName) ) pChannel_channelname->GetString(m_szChannelName, nLen ); DWORD dwBoneSize = 0; KSimpleDataObject * pBoneSize = pChannelObject->GetSimpleDataMemberObject( "bone_ani_size" ); pBoneSize->GetDWORD(&dwBoneSize); KTemplateDataArrayObject * pBoneArray = pChannelObject->GetTemplateDataArrayMemberObject( "bone_ani_array" ); m_spBoneRes->SetTimeSpan(m_dwChannelTimeSpan); m_spBoneRes->SetBone(dwBoneSize); for(unsigned int i(0); i < dwBoneSize; ++i) { KTemplateDataObject * pTemplateBone = pBoneArray->GetData(i); KNX3Bone Bone; Bone.Load( pTemplateBone ); K3DBone * pBoneRes = new K3DBone; pBoneRes->SetParentIndex( Bone.GetParentIndex() ); pBoneRes->SetBaseTM( Bone.GetBaseTM() ); pBoneRes->SetFlag( Bone.GetFlag() ); pBoneRes->SetPosKey( Bone.GetPosCount(), (Kgeneric_key_t *)Bone.GetPosKey() ); pBoneRes->SetRotKey( Bone.GetRotCount(), (Kgeneric_key_t *)Bone.GetRotKey() ); pBoneRes->SetChildList( Bone.GetChildCount(), Bone.GetChildList() ); pBoneRes->SetName( Bone.GetName() ); m_spBoneRes->AddBone( i, pBoneRes ); } //자식 본 포인터 설정 int nChildren = 0; for( unsigned int i(0); i < dwBoneSize; ++i) { K3DBone * pBone = m_spBoneRes->GetBone(i); int nParentIndex = pBone->GetParentIndex(); if( nParentIndex >= 0 && static_cast(nParentIndex) < dwBoneSize ) { pBone->SetParentBone( m_spBoneRes->GetBone(nParentIndex) ); } else { nChildren++; pBone->SetParentBone( NULL ); } for( int j(0); pBone->GetChildCount()>j; j++ ) { K3DBone * pChildBone = m_spBoneRes->GetBone(pBone->GetChildIndex(j)); if( pChildBone ) pBone->SetChildBone( j, pChildBone ); } } //최상위 본의 자식 설정 m_spBoneRes->SetChildCount( nChildren ); // _oprint( "Load Time : KNX3BoneChannel::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } bool KNX3BoneChannel::LoadTRF( trf::MTemplatePtr pObject, const char * szName, DWORD dwVersion ) { DWORD dwTime = GetSafeTickCount(); m_spBoneRes = new K3DBoneResource; m_spBoneRes->SetName( szName ); m_spBoneRes->SetVersion( dwVersion ); DWORD dwBoneCount = pObject->getDWordBy( "bone_count" ); trf::MTemplateArrayPtr pChannel_Array = pObject->getTemplateArrayBy( "channel_array" ); if( dwBoneCount <= 0 ) _oprint( "[KNX3BoneChannel::LoadTRF] Bones count is less than 0!\n" ); //채널은 한개만 지원 된다. trf::MTemplatePtr pChannelObject = pChannel_Array->getTemplateAt(0); //작업중.. strncpy( m_szChannelName, SafeStr( pChannelObject->getStringBy( "channel_name" ) ), 127 ); m_dwChannelFlag = pChannelObject->getDWordBy( "channel_flag" ); m_dwChannelTimeSpan = pChannelObject->getDWordBy( "channel_time_span" ); m_dwChannelFrameRate = pChannelObject->getDWordBy( "channel_frame_rate" ); trf::MTemplateArrayPtr pBoneArray = pChannelObject->getTemplateArrayBy( "bone_ani_array" ); DWORD dwBoneSize = pBoneArray->count(); m_spBoneRes->SetTimeSpan(m_dwChannelTimeSpan); m_spBoneRes->SetBone(dwBoneSize); for(unsigned int i(0); i < dwBoneSize; ++i) { trf::MTemplatePtr pTemplateBone = pBoneArray->getTemplateAt(i); KNX3Bone Bone; Bone.LoadTRF( pTemplateBone ); K3DBone * pBoneRes = new K3DBone; pBoneRes->SetParentIndex( Bone.GetParentIndex() ); pBoneRes->SetBaseTM( Bone.GetBaseTM() ); pBoneRes->SetFlag( Bone.GetFlag() ); pBoneRes->SetPosKey( Bone.GetPosCount(), (Kgeneric_key_t *)Bone.GetPosKey() ); pBoneRes->SetRotKey( Bone.GetRotCount(), (Kgeneric_key_t *)Bone.GetRotKey() ); pBoneRes->SetChildList( Bone.GetChildCount(), Bone.GetChildList() ); pBoneRes->SetName( Bone.GetName() ); m_spBoneRes->AddBone( i, pBoneRes ); } //자식 본 포인터 설정 int nChildren = 0; for( unsigned int i(0); i < dwBoneSize; ++i) { K3DBone * pBone = m_spBoneRes->GetBone(i); int nParentIndex = pBone->GetParentIndex(); if( nParentIndex >= 0 && static_cast(nParentIndex) < dwBoneSize ) { pBone->SetParentBone( m_spBoneRes->GetBone(nParentIndex) ); } else { nChildren++; pBone->SetParentBone( NULL ); } for( int j(0); pBone->GetChildCount()>j; j++ ) { K3DBone * pChildBone = m_spBoneRes->GetBone(pBone->GetChildIndex(j)); if( pChildBone ) pBone->SetChildBone( j, pChildBone ); } } //최상위 본의 자식 설정 m_spBoneRes->SetChildCount( nChildren ); // _oprint( "Load Time : KNX3BoneChannel::Load - %d\n", GetSafeTickCount()-dwTime ); return true; } //======================================================================================================================= //KNX3MeshChannel======================================================================================================== //======================================================================================================================= KNX3MeshChannel::KNX3MeshChannel(K3DRenderDevice * pGraphics, KNX3MtlChannel * pMtlChannel) { m_pGraphics = pGraphics; m_pMtlChannel = pMtlChannel; m_vtMeshList.clear(); } KNX3MeshChannel::~KNX3MeshChannel() { Clear(); } void KNX3MeshChannel::Clear() { m_pGraphics = NULL; m_pMtlChannel = NULL; SAFE_DELETE_VECTOR(m_vtMeshList); SAFE_DELETE_VECTOR(m_vtMeshTM); } BOOL KNX3MeshChannel::Load( const NX3LoadPack * pLoadPack, KTemplateDataObject * pObject , int loadType) { DWORD dwTime = GetSafeTickCount(); DWORD dwMeshSize; KSimpleDataObject * pMeshSize = pObject->GetSimpleDataMemberObject("mesh_size"); pMeshSize->GetDWORD(&dwMeshSize); KTemplateDataArrayObject * pMeshArray = pObject->GetTemplateDataArrayMemberObject("mesh_array"); m_vtMeshList.reserve( dwMeshSize ); for(unsigned int i(0); i < dwMeshSize; ++i) { KNX3Mesh * pMesh = new KNX3Mesh(m_pGraphics); pMesh->Load( pLoadPack, pMeshArray->GetData(i), m_pMtlChannel, loadType ); m_vtMeshList.push_back(pMesh); } m_vtMeshTM.erase( m_vtMeshTM.begin(), m_vtMeshTM.end() ); DWORD dwMeshTMSize = 0; KSimpleDataObject * pMeshTMSize = pObject->GetSimpleDataMemberObject("mesh_tm_size"); pMeshTMSize->GetDWORD(&dwMeshTMSize); KTemplateDataArrayObject * pMeshTMArray = pObject->GetTemplateDataArrayMemberObject("mesh_tm_array"); for(unsigned int i(0); i < dwMeshTMSize; ++i) { KNX3MeshTM * pMeshTM = new KNX3MeshTM; memset( pMeshTM, 0, sizeof(*pMeshTM) ); KTemplateDataObject * pObject = pMeshTMArray->GetData(i); //Load KSimpleDataObject * pName = pObject->GetSimpleDataMemberObject( "name" ); int nLen = 64; pName->GetString( pMeshTM->szName, nLen ); KSimpleDataArrayObject * pBaseTM = pObject->GetSimpleDataArrayMemberObject("tm"); pBaseTM->GetDataFloat(0, pMeshTM->baseTM, sizeof( pMeshTM->baseTM ), 16); m_vtMeshTM.push_back( pMeshTM ); } if( GetSafeTickCount()-dwTime > 80 ) { // _oprint( "Load Time : KNX3MeshChannel::Load - %dms\n", GetSafeTickCount()-dwTime ); } return TRUE; } bool KNX3MeshChannel::LoadTRF( const NX3LoadPack * pLoadPack, trf::MTemplatePtr pObject , int loadType) { DWORD dwTime = GetSafeTickCount(); trf::MTemplateArrayPtr pMeshArray = pObject->getTemplateArrayBy("mesh_array"); DWORD dwMeshSize = pMeshArray->count(); m_vtMeshList.reserve( dwMeshSize ); for(unsigned int i(0); i < dwMeshSize; ++i) { KNX3Mesh * pMesh = new KNX3Mesh(m_pGraphics); pMesh->LoadTRF( pLoadPack, pMeshArray->getTemplateAt(i), m_pMtlChannel, loadType ); m_vtMeshList.push_back(pMesh); } m_vtMeshTM.erase( m_vtMeshTM.begin(), m_vtMeshTM.end() ); trf::MTemplateArrayPtr pMeshTMArray = pObject->getTemplateArrayBy("mesh_tm_array"); DWORD dwMeshTMSize = pMeshTMArray->count(); for(unsigned int i(0); i < dwMeshTMSize; ++i) { KNX3MeshTM * pMeshTM = new KNX3MeshTM; memset( pMeshTM, 0, sizeof(*pMeshTM) ); trf::MTemplatePtr pObject = pMeshTMArray->getTemplateAt(i); //Load strncpy( pMeshTM->szName, SafeStr( pObject->getStringBy("name") ), 64 ); pObject->getArrayBy( "tm" )->readFixedData( 0, 16, pMeshTM->baseTM, sizeof( pMeshTM->baseTM ) ); m_vtMeshTM.push_back( pMeshTM ); } if( GetSafeTickCount()-dwTime > 80 ) { // _oprint( "Load Time : KNX3MeshChannel::Load - %dms\n", GetSafeTickCount()-dwTime ); } return true; } KNX3Mesh::KNX3Mesh(K3DRenderDevice * pGraphics) { m_pGraphics = pGraphics; m_dwMaterialID = 0; m_dwChannelID = 0; m_vtMeshElement.clear(); m_spAniElement = NULL; m_spVisiElement = NULL; m_spUVAniElement = NULL; m_vtFX.clear(); m_vtChildMesh.clear(); m_bIsFX = false; m_bIsEventBox = false; m_bIsEventPoint = false; } KNX3Mesh::~KNX3Mesh() { Clear(); } void KNX3Mesh::Clear() { m_pGraphics = NULL; SAFE_DELETE_VECTOR(m_vtMeshElement); m_spAniElement = NULL; m_spVisiElement = NULL; m_spUVAniElement = NULL; SAFE_DELETE_VECTOR(m_vtFX); SAFE_DELETE_VECTOR(m_vtChildMesh); } void KNX3Mesh::loadUVAni( KNX3FX *pFX ) { DWORD dwTime = GetSafeTickCount(); std::vector vFXEle; for ( unsigned int i=0; iGetFXElementSize() ; ++i ) { if( pFX->GetFxElementByIndeX(i)->GetValue( "UVTRANSFORM" ) != NULL || pFX->GetFxElementByIndeX(i)->GetValue( "UVANI" ) != NULL ) vFXEle.push_back( pFX->GetFxElementByIndeX( i ) ); } if ( vFXEle.size() > 0 ) { int nMode = 0; int nTexSize = 1024; K3DVector vecUvAni; K3DResMeshUVAnimation::Key *key = new K3DResMeshUVAnimation::Key[vFXEle.size()]; m_spUVAniElement = new K3DResMeshUVAnimation; for( unsigned int i = 0; i < vFXEle.size(); ++i ) { KNX3FXElement *fxele = vFXEle[i]; key[i].time = fxele->GetFrameTime(); if( i == 0 ) { nMode = fxele->GetNumValue( "UVMODE", nMode ); vecUvAni = fxele->GetVectorValue( "UVANI", K3DVector( 0.0f, 0.0f, 0.0f ) ); } nTexSize = fxele->GetNumValue( "UVTEXTURESIZE", nTexSize ); K3DVector pos(0,0,0); pos = fxele->Get2DVectorValue( "UVTRANSFORM", pos ); pos.x /= (float)nTexSize; pos.y /= (float)nTexSize; K3DMatrixIdentity( key[i].mat ); key[i].mat._31 = pos.x; key[i].mat._32 = pos.y; } m_spUVAniElement->SetMode( nMode ); m_spUVAniElement->SetUvAnimation( vecUvAni.x > 0.0f, static_cast< int >( vecUvAni.y ), static_cast< int >( vecUvAni.z ) ); m_spUVAniElement->SetWholeKey( key, (int)vFXEle.size() ); delete[] key; } // _oprint( "Load Time : KNX3Mesh::loadUVAni - %d\n", GetSafeTickCount()-dwTime ); } BOOL KNX3Mesh::Load( const NX3LoadPack * pLoadPack, KTemplateDataObject * pObject, KNX3MtlChannel * pMtlChannel,int loadType ) { DWORD dwTime = GetSafeTickCount(); KSimpleDataObject *pMeshName = pObject->GetSimpleDataMemberObject( "mesh_name" ); char name[1024]; int namelen = 1024; pMeshName->GetString( name, namelen ); m_sMeshName = name; int nMtlID; KSimpleDataObject * pMtlID = pObject->GetSimpleDataMemberObject("material_id"); pMtlID->GetDWORD(reinterpret_cast(&nMtlID) ); if(pMtlChannel) m_pMtl = pMtlChannel->GetMtl(nMtlID); else m_pMtl = NULL; DWORD dwMeshSize; KSimpleDataObject * pMeshBlockSize = pObject->GetSimpleDataMemberObject("mesh_block_size"); pMeshBlockSize->GetDWORD(&dwMeshSize); KTemplateDataArrayObject * pMeshBlockArray = pObject->GetTemplateDataArrayMemberObject("mesh_block_array"); // Mesh Data Load int i; for(i = 0; i < (int)dwMeshSize; ++i) { KNX3MeshElement* pElement = new KNX3MeshElement(m_pGraphics); pElement->Load( pLoadPack, name, pMeshBlockArray->GetData(i), m_pMtl ); m_vtMeshElement.push_back(pElement); } if ( dwMeshSize > 0 ) { m_bIsEventPoint = m_vtMeshElement[0]->IsEventPoint(); m_bIsEventBox = m_vtMeshElement[0]->IsEventBox(); } // Animation & Visi Block Load if(loadType == KNX3MeshChannel::LT_OLD_MESH) loadAniAndVisiBlockOldType(pObject); else loadAniAndVisiBlockNewType(pObject); // FX Load KTemplateDataArrayObject * pFXArray = pObject->GetTemplateDataArrayMemberObject("fx_array"); for( i=0; i < pFXArray->GetDataCount(); ++i ) { KNX3FX * pFX = new KNX3FX(); pFX->Load(pFXArray->GetData(i)); if ( pFX->IsFX() ) m_bIsFX = true; if ( pFX->GetFXElementSize() > 0 ) { if ( pFX->GetFXElement( 0 )->GetValue( "UVTRANSFORM" ) != NULL ) { loadUVAni( pFX ); } } m_vtFX.push_back(pFX); } // Children Load DWORD dwChildrenSize; KSimpleDataObject * pMeshChildrenSize = pObject->GetSimpleDataMemberObject("mesh_children_size"); pMeshChildrenSize->GetDWORD(&dwChildrenSize); KTemplateDataArrayObject * pMeshChildrenArray = pObject->GetTemplateDataArrayMemberObject("mesh_children_array"); for( i=0; i < (int)dwChildrenSize; ++i ) { KNX3Mesh * pMesh = new KNX3Mesh(m_pGraphics); pMesh->Load( pLoadPack, pMeshChildrenArray->GetData(i), pMtlChannel, loadType ); m_vtChildMesh.push_back(pMesh); } // _oprint( "Load Time : KNX3Mesh::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } bool KNX3Mesh::LoadTRF( const NX3LoadPack * pLoadPack, trf::MTemplatePtr pObject, KNX3MtlChannel * pMtlChannel, int loadType ) { DWORD dwTime = GetSafeTickCount(); m_sMeshName = SafeStr( pObject->getStringBy( "mesh_name" ) ); int nMtlID = pObject->getDWordBy( "material_id" ); if(pMtlChannel) m_pMtl = pMtlChannel->GetMtl(nMtlID); else m_pMtl = NULL; trf::MTemplateArrayPtr pMeshBlockArray = pObject->getTemplateArrayBy( "mesh_block_array" ); DWORD dwMeshSize = pMeshBlockArray->count(); // Mesh Data Load int i; for(i = 0; i < (int)dwMeshSize; ++i) { KNX3MeshElement* pElement = new KNX3MeshElement(m_pGraphics); pElement->LoadTRF( pLoadPack, m_sMeshName.c_str(), pMeshBlockArray->getTemplateAt(i), m_pMtl ); m_vtMeshElement.push_back(pElement); } if ( dwMeshSize > 0 ) { m_bIsEventPoint = m_vtMeshElement[0]->IsEventPoint(); m_bIsEventBox = m_vtMeshElement[0]->IsEventBox(); } // Animation & Visi Block Load if(loadType == KNX3MeshChannel::LT_OLD_MESH) loadAniAndVisiBlockOldType(pObject); else loadAniAndVisiBlockNewType(pObject); // FX Load trf::MTemplateArrayPtr pFXArray = pObject->getTemplateArrayBy("fx_array"); for( i=0; i < pFXArray->count(); ++i ) { KNX3FX * pFX = new KNX3FX(); pFX->LoadTRF( pFXArray->getTemplateAt(i) ); if ( pFX->IsFX() ) m_bIsFX = true; if ( pFX->GetFXElementSize() > 0 ) { if( pFX->GetFXElement( 0 )->GetValue( "UVTRANSFORM" ) != NULL || pFX->GetFXElement( 0 )->GetValue( "UVANI" ) != NULL ) { loadUVAni( pFX ); //UVTRANSFORM,UVANI가 적용된 매쉬는 라이트 맵 적용 안시킨다 MeshVector::iterator iter = m_vtMeshElement.begin(); for( ; iter != m_vtMeshElement.end(); ++iter ) { (*iter)->SetLightMapIndex( 0 ); } } } m_vtFX.push_back(pFX); } // Children Load trf::MTemplateArrayPtr pMeshChildrenArray = pObject->getTemplateArrayBy("mesh_children_array"); DWORD dwChildrenSize = pMeshChildrenArray->count(); for( i=0; i < (int)dwChildrenSize; ++i ) { KNX3Mesh * pMesh = new KNX3Mesh(m_pGraphics); pMesh->LoadTRF( pLoadPack, pMeshChildrenArray->getTemplateAt(i), pMtlChannel, loadType ); m_vtChildMesh.push_back(pMesh); } // _oprint( "Load Time : KNX3Mesh::Load - %d\n", GetSafeTickCount()-dwTime ); return true; } void KNX3Mesh::loadAniAndVisiBlockOldType(KTemplateDataObject* pObject) { KTemplateDataArrayObject * pAniBlockArray = pObject->GetTemplateDataArrayMemberObject("ani_block_array"); if ( pAniBlockArray->GetDataCount() > 0 ) { K3DResMeshMatrixAnimation::Key *key = new K3DResMeshMatrixAnimation::Key[pAniBlockArray->GetDataCount()]; m_spAniElement = new K3DResMeshMatrixAnimation; for(int i = 0; i < pAniBlockArray->GetDataCount(); ++i ) { KTemplateDataObject * pObject = pAniBlockArray->GetData(i); KSimpleDataObject * pTime = pObject->GetSimpleDataMemberObject("time"); pTime->GetDWORD(reinterpret_cast(&key[i].time)); float fArray[12]; KSimpleDataArrayObject * pMatrix = pObject->GetSimpleDataArrayMemberObject("matrix"); pMatrix->GetDataFloat(0, fArray, sizeof( fArray ), 12); fillAnimatrixFromArray(fArray, &key[i].mat); } m_spAniElement->SetWholeKey( key, pAniBlockArray->GetDataCount() ); for ( unsigned int i=0 ; iGetWritableEventCube().SetTransform( key[0].mat ); pElement->GetWritableBoundSphere().SetTransform( key[0].mat ); } delete[] key; } // Visibility Block Load KTemplateDataArrayObject * pVisiBlockArray = pObject->GetTemplateDataArrayMemberObject("visi_block_array"); if ( pVisiBlockArray->GetDataCount() > 0 ) { K3DResMeshVisibilityAnimation::Key *viskey = new K3DResMeshVisibilityAnimation::Key[pVisiBlockArray->GetDataCount()]; m_spVisiElement = new K3DResMeshVisibilityAnimation; for(int i =0 ; i < pVisiBlockArray->GetDataCount(); ++i ) { KTemplateDataObject *pObject = pVisiBlockArray->GetData(i); KSimpleDataObject * pTime = pObject->GetSimpleDataMemberObject("time"); pTime->GetDWORD(reinterpret_cast(&viskey[i].time)); KSimpleDataObject * pVisibility = pObject->GetSimpleDataMemberObject("visibility"); pVisibility->GetFloat(&viskey[i].val); } m_spVisiElement->SetWholeKey( viskey, pVisiBlockArray->GetDataCount() ); delete[] viskey; } } void KNX3Mesh::loadAniAndVisiBlockNewType(KTemplateDataObject* pObject) { KSimpleDataArrayObject * pAniTimeArray = pObject->GetSimpleDataArrayMemberObject("ani_time_array"); KSimpleDataArrayObject * pAniMatrixArray = pObject->GetSimpleDataArrayMemberObject("ani_matrix_array"); int count = pAniTimeArray->GetDataCount(); if(count > 0) { K3DResMeshMatrixAnimation::Key *key = new K3DResMeshMatrixAnimation::Key[count]; m_spAniElement = new K3DResMeshMatrixAnimation; const size_t MATRIX_SIZE = 12; static float fArray[MATRIX_SIZE]; for( int i = 0; i < count; ++i) { pAniTimeArray->GetDataDWORD(i, reinterpret_cast(&key[i].time), sizeof( key[i].time ), 1); pAniMatrixArray->GetDataFloat(i * MATRIX_SIZE, fArray, sizeof( fArray ), MATRIX_SIZE); fillAnimatrixFromArray(fArray,&key[i].mat); } m_spAniElement->SetWholeKey(key, count); for ( unsigned int i=0 ; iGetWritableEventCube().SetTransform( key[0].mat ); pElement->GetWritableBoundSphere().SetTransform( key[0].mat ); } delete[] key; } // Visibility Block Load KSimpleDataArrayObject * pVisiTimeArray = pObject->GetSimpleDataArrayMemberObject("visi_time_array"); KSimpleDataArrayObject * pVisiValueArray = pObject->GetSimpleDataArrayMemberObject("visi_value_array"); count = pVisiTimeArray->GetDataCount(); if ( count > 0) { K3DResMeshVisibilityAnimation::Key *viskey = new K3DResMeshVisibilityAnimation::Key[count]; m_spVisiElement = new K3DResMeshVisibilityAnimation; for(int i = 0; i < count; ++i) { pVisiTimeArray->GetDataDWORD(i, reinterpret_cast(&viskey[i].time), sizeof( viskey[i].time ), 1); pVisiValueArray->GetDataFloat(i, &viskey[i].val, sizeof( viskey[i].val ), 1); } m_spVisiElement->SetWholeKey( viskey, count); delete[] viskey; } } void KNX3Mesh::loadAniAndVisiBlockOldType( trf::MTemplatePtr pObject ) { trf::MTemplateArrayPtr pAniBlockArray = pObject->getTemplateArrayBy("ani_block_array"); if ( pAniBlockArray->count() > 0 ) { K3DResMeshMatrixAnimation::Key* key = new K3DResMeshMatrixAnimation::Key[ pAniBlockArray->count() ]; m_spAniElement = new K3DResMeshMatrixAnimation; for(int i = 0; i < pAniBlockArray->count(); ++i ) { trf::MTemplatePtr pObject = pAniBlockArray->getTemplateAt(i); key[i].time = pObject->getDWordBy("time"); float fArray[12]; pObject->getArrayBy("matrix")->readFixedData( 0, 12, fArray, sizeof(fArray) ); fillAnimatrixFromArray(fArray, &key[i].mat); } m_spAniElement->SetWholeKey( key, pAniBlockArray->count() ); for ( unsigned int i=0 ; iGetWritableEventCube().SetTransform( key[0].mat ); pElement->GetWritableBoundSphere().SetTransform( key[0].mat ); } delete[] key; } // Visibility Block Load trf::MTemplateArrayPtr pVisiBlockArray = pObject->getTemplateArrayBy("visi_block_array"); if ( pVisiBlockArray->count() > 0 ) { K3DResMeshVisibilityAnimation::Key *viskey = new K3DResMeshVisibilityAnimation::Key[ pVisiBlockArray->count() ]; m_spVisiElement = new K3DResMeshVisibilityAnimation; for(int i =0 ; i < pVisiBlockArray->count(); ++i ) { trf::MTemplatePtr pObject = pVisiBlockArray->getTemplateAt(i); viskey[i].time = pObject->getDWordBy("time"); viskey[i].val = pObject->getFloatBy("visibility"); } m_spVisiElement->SetWholeKey( viskey, pVisiBlockArray->count() ); delete[] viskey; } } void KNX3Mesh::loadAniAndVisiBlockNewType( trf::MTemplatePtr pObject ) { trf::MArrayPtr pAniTimeArray = pObject->getArrayBy("ani_time_array"); trf::MArrayPtr pAniMatrixArray = pObject->getArrayBy("ani_matrix_array"); int count = pAniTimeArray->count(); if(count > 0) { K3DResMeshMatrixAnimation::Key *key = new K3DResMeshMatrixAnimation::Key[count]; m_spAniElement = new K3DResMeshMatrixAnimation; const size_t MATRIX_SIZE = 12; float fArray[MATRIX_SIZE]; for( int i = 0; i < count; ++i) { key[i].time = pAniTimeArray->getDWordAt( i ); pAniMatrixArray->readFixedData( i*MATRIX_SIZE, MATRIX_SIZE, fArray, sizeof(fArray) ); fillAnimatrixFromArray(fArray,&key[i].mat); } m_spAniElement->SetWholeKey(key, count); for ( unsigned int i=0 ; iGetWritableEventCube().SetTransform( key[0].mat ); pElement->GetWritableBoundSphere().SetTransform( key[0].mat ); } delete[] key; } // Visibility Block Load trf::MArrayPtr pVisiTimeArray = pObject->getArrayBy("visi_time_array"); trf::MArrayPtr pVisiValueArray = pObject->getArrayBy("visi_value_array"); count = pVisiTimeArray->count(); if ( count > 0) { K3DResMeshVisibilityAnimation::Key *viskey = new K3DResMeshVisibilityAnimation::Key[count]; m_spVisiElement = new K3DResMeshVisibilityAnimation; for(int i = 0; i < count; ++i) { viskey[i].time = pVisiTimeArray->getDWordAt(i); viskey[i].val = pVisiValueArray->getFloatAt(i); } m_spVisiElement->SetWholeKey( viskey, count); delete[] viskey; } } KNX3MeshElement::KNX3MeshElement( K3DRenderDevice * pGraphics ) { m_bIsEventBox = false; m_bIsEventPoint = false; m_pGraphics = pGraphics; m_pMaterial = NULL; m_bDeletK3DMaterial = FALSE; m_dwFormat = 0; m_dwStride = 0; m_dwNumIndexBuffer = 0; m_vtMeshFrame.clear(); } KNX3MeshElement::~KNX3MeshElement() { Clear(); } void KNX3MeshElement::Clear() { m_spIndices = NULL; m_spIdxarry = NULL; SAFE_DELETE_VECTOR(m_vtMeshFrame); if(m_bDeletK3DMaterial) { SAFE_DELETE(m_pMaterial); } else { m_pMaterial = NULL; } } BOOL KNX3MeshElement::Load(const NX3LoadPack * pLoadPack, const char *meshname, KTemplateDataObject * pObject, KNX3Mtl * pMtl) { if ( _strnicmp( meshname, "ep_", 3 ) == 0 ) { m_bIsEventPoint = true; return TRUE; } else if ( (_strnicmp( meshname, "ev_", 3 ) == 0 ) ) { m_bIsEventBox = true; const int EVBOX_VTX_COUNT = 3 * 8; KTemplateDataArrayObject * pMeshFrameArray = pObject->GetTemplateDataArrayMemberObject("mesh_frame_array"); assert(pMeshFrameArray); KTemplateDataObject* pMeshFrame = pMeshFrameArray->GetData(0); assert(pMeshFrame); KSimpleDataArrayObject * pVertexArray = pMeshFrame->GetSimpleDataArrayMemberObject("vertex_array"); assert(pVertexArray->GetDataCount() == EVBOX_VTX_COUNT); K3DVector p[8]; pVertexArray->GetDataFloat( 0, reinterpret_cast(&p[0]), sizeof( p ), EVBOX_VTX_COUNT); K3DBoundSetCube( &m_bEventCube, p, 8 ); return TRUE; } // DWORD dwTime = GetSafeTickCount(); DWORD dwTextureIndex; KNX3MtlElement * pMtlElement = NULL; KSimpleDataObject * pTextureIndex = pObject->GetSimpleDataMemberObject("texture_index"); pTextureIndex->GetDWORD(&dwTextureIndex); KSimpleDataObject* pLightMapIndex = pObject->GetSimpleDataMemberObject("lightmap_index"); if(pLightMapIndex) pLightMapIndex->GetDWORD(&m_lightMapIndex); else m_lightMapIndex = 0; if(NULL != pMtl && NULL != (pMtlElement = pMtl->GetMtlElement(dwTextureIndex) ) ) { m_spTexture = pMtlElement->GetTexture(); m_spTexture_Bump = pMtlElement->GetBumpTexture(); m_spTexture_Illumin = pMtlElement->GetIlluminTexture(); m_spTexture_Specular = pMtlElement->GetSpecularTexture(); m_spTexture_SpecularColor = pMtlElement->GetSpecularColorTexture(); m_pMaterial = pMtlElement->GetMaterial(); m_nBlendMode = pMtlElement->GetBlendMode(); } else { // Default Material로 세팅 m_bDeletK3DMaterial = TRUE; m_pMaterial = new K3DMaterial; m_pMaterial->SetAmbient( K3DColor(.1f, .1f, .1f) ); m_pMaterial->SetDiffuse( K3DColor( .8f, .8f, .8f ) ); m_pMaterial->SetSpecular( K3DColor( .8f, .8f, .8f) ); m_pMaterial->SetSpecularPower( 1.0f ); m_nBlendMode = K3DMaterial::MBM_DEFAULT; } DWORD dwMeshFrameSize; KSimpleDataObject * pMeshFrameSize = pObject->GetSimpleDataMemberObject("mesh_frame_size"); pMeshFrameSize->GetDWORD(&dwMeshFrameSize); KTemplateDataArrayObject * pMeshFrameArray = pObject->GetTemplateDataArrayMemberObject("mesh_frame_array"); // 인덱스 먼저 읽음 KSimpleDataObject * pIndexBufferSize = pObject->GetSimpleDataMemberObject("index_buffer_size"); pIndexBufferSize->GetDWORD(&m_dwNumIndexBuffer); KSimpleDataArrayObject * pIndexBufferArray = pObject->GetSimpleDataArrayMemberObject("index_buffer_array"); unsigned short *_idxlist = new unsigned short[m_dwNumIndexBuffer]; pIndexBufferArray->GetDataWORD( 0, _idxlist, sizeof( unsigned short )*m_dwNumIndexBuffer, m_dwNumIndexBuffer ); KTemplateDataObject *pFirstTemplateFrame = pMeshFrameArray->GetData(0); KNX3MeshFrame * pMeshFrameFirst = new KNX3MeshFrame( m_pGraphics ); pMeshFrameFirst->Load(pLoadPack, meshname, m_dwNumIndexBuffer, _idxlist, pFirstTemplateFrame, m_dwFormat, m_dwStride,m_dwNumVertex); m_vtMeshFrame.push_back(pMeshFrameFirst); m_bEventCube = pMeshFrameFirst->GetCube(); m_bSphere = pMeshFrameFirst->GetSphere(); for(size_t i = 0; i < dwMeshFrameSize; ++i) { KNX3MeshFrame * pMeshFrame = new KNX3MeshFrame( m_pGraphics ); pMeshFrame->Load(pLoadPack, meshname, m_dwNumIndexBuffer, _idxlist, pMeshFrameArray->GetData(i), m_dwFormat, m_dwStride,m_dwNumVertex,pFirstTemplateFrame); m_vtMeshFrame.push_back(pMeshFrame); } m_nSimultaneousFrameCount = m_vtMeshFrame[0]->GetSimultaneousFrameCount(); int size = m_dwNumIndexBuffer * sizeof(WORD); m_spIndices = m_pGraphics->CreateIndexBuffer( m_dwNumIndexBuffer); if( m_spIndices && m_spIndices->IsValidVtx() ) { char *tmpbuffer = NULL; m_spIndices->Lock( (void**)&tmpbuffer, size ); if( tmpbuffer != NULL ) { memcpy(tmpbuffer, _idxlist, size ); m_spIndices->Unlock(); } } if( pLoadPack && pLoadPack->bLoad_PolyGon ) { m_spIdxarry = new K3DUnsignedShortRes; m_spIdxarry->SetArray( _idxlist, m_dwNumIndexBuffer ); } delete[] _idxlist; // _oprint( "Load Time : KNX3MeshElement::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } bool KNX3MeshElement::LoadTRF(const NX3LoadPack * pLoadPack, const char *meshname, trf::MTemplatePtr pObject, KNX3Mtl * pMtl) { if ( _strnicmp( meshname, "ep_", 3 ) == 0 ) { m_bIsEventPoint = true; return true; } else if ( (_strnicmp( meshname, "ev_", 3 ) == 0 ) ) { m_bIsEventBox = true; const int EVBOX_VTX_COUNT = 3 * 8; trf::MTemplateArrayPtr pMeshFrameArray = pObject->getTemplateArrayBy("mesh_frame_array"); assert(pMeshFrameArray); trf::MTemplatePtr pMeshFrame = pMeshFrameArray->getTemplateAt(0); assert(pMeshFrame); K3DVector p[8]; pMeshFrame->getArrayBy( "vertex_array" )->readFixedData( 0, EVBOX_VTX_COUNT, p, sizeof( p ) ); K3DBoundSetCube( &m_bEventCube, p, 8 ); return true; } // DWORD dwTime = GetSafeTickCount(); // Fraun MTE reminder (KNX3MtlElement) DWORD dwTextureIndex = pObject->getDWordBy( "texture_index" ); KNX3MtlElement * pMtlElement = NULL; int index = pObject->indexBy( "lightmap_index" ); if ( index >= 0 && index < pObject->count() ) m_lightMapIndex = pObject->getDWordAt( index ); else m_lightMapIndex = 0; if(NULL != pMtl && NULL != (pMtlElement = pMtl->GetMtlElement(dwTextureIndex) ) ) { m_spTexture = pMtlElement->GetTexture(); m_spTexture_Bump = pMtlElement->GetBumpTexture(); m_spTexture_Illumin = pMtlElement->GetIlluminTexture(); m_spTexture_Specular = pMtlElement->GetSpecularTexture(); m_spTexture_SpecularColor = pMtlElement->GetSpecularColorTexture(); m_pMaterial = pMtlElement->GetMaterial(); m_nBlendMode = pMtlElement->GetBlendMode(); } else { // Default Material로 세팅 m_bDeletK3DMaterial = TRUE; m_pMaterial = new K3DMaterial; m_pMaterial->SetAmbient( K3DColor(.1f, .1f, .1f) ); m_pMaterial->SetDiffuse( K3DColor( .8f, .8f, .8f ) ); m_pMaterial->SetSpecular( K3DColor( .8f, .8f, .8f) ); m_pMaterial->SetSpecularPower( 1.0f ); m_nBlendMode = K3DMaterial::MBM_DEFAULT; } trf::MTemplateArrayPtr pMeshFrameArray = pObject->getTemplateArrayBy("mesh_frame_array"); DWORD dwMeshFrameSize = pMeshFrameArray->count(); // 인덱스 먼저 읽음 trf::MArrayPtr pIndexBufferArray = pObject->getArrayBy("index_buffer_array"); m_dwNumIndexBuffer = pIndexBufferArray->count(); unsigned short *_idxlist = new unsigned short[m_dwNumIndexBuffer]; pIndexBufferArray->readFixedData( 0, m_dwNumIndexBuffer, _idxlist, m_dwNumIndexBuffer * sizeof(unsigned short) ); trf::MTemplatePtr pFirstTemplateFrame = pMeshFrameArray->getTemplateAt(0); KNX3MeshFrame * pMeshFrameFirst = new KNX3MeshFrame( m_pGraphics ); pMeshFrameFirst->LoadTRF( pLoadPack, meshname, m_dwNumIndexBuffer, _idxlist, pFirstTemplateFrame, m_dwFormat, m_dwStride, m_dwNumVertex ); m_vtMeshFrame.push_back(pMeshFrameFirst); m_bEventCube = pMeshFrameFirst->GetCube(); m_bSphere = pMeshFrameFirst->GetSphere(); for(size_t i = 0; i < dwMeshFrameSize; ++i) { KNX3MeshFrame * pMeshFrame = new KNX3MeshFrame( m_pGraphics ); pMeshFrame->LoadTRF( pLoadPack, meshname, m_dwNumIndexBuffer, _idxlist, pMeshFrameArray->getTemplateAt(i), m_dwFormat, m_dwStride,m_dwNumVertex,pFirstTemplateFrame ); m_vtMeshFrame.push_back(pMeshFrame); } m_nSimultaneousFrameCount = m_vtMeshFrame[0]->GetSimultaneousFrameCount(); int size = m_dwNumIndexBuffer * sizeof(WORD); m_spIndices = m_pGraphics->CreateIndexBuffer( m_dwNumIndexBuffer); if( m_spIndices && m_spIndices->IsValidVtx() ) { char *tmpbuffer = NULL; m_spIndices->Lock( (void**)&tmpbuffer, size ); if( tmpbuffer != NULL ) { memcpy(tmpbuffer, _idxlist, size ); m_spIndices->Unlock(); } } if( pLoadPack && pLoadPack->bLoad_PolyGon ) { m_spIdxarry = new K3DUnsignedShortRes; m_spIdxarry->SetArray( _idxlist, m_dwNumIndexBuffer ); } delete[] _idxlist; // _oprint( "Load Time : KNX3MeshElement::Load - %d\n", GetSafeTickCount()-dwTime ); return true; } KNX3MeshFrame::KNX3MeshFrame( K3DRenderDevice *pGraphics ) { m_pGraphics = pGraphics; m_dwFrameTime = 0; m_bIsEventBox = false; m_bIsEventPoint = false; m_dwBoneSize = 0; m_bIsBlended = false; } KNX3MeshFrame::~KNX3MeshFrame() { Clear(); } void KNX3MeshFrame::Clear() { m_spVtxArray = NULL; m_spVertexBuffer = NULL; for( size_t i(0); m_vWeightList.size()>i; i++ ) { delete m_vWeightList[i]; } m_vWeightList.clear(); m_vUseBoneList.clear(); } //사용하는 본들을 모은다... void KNX3MeshFrame::AddUseBoneIndex( int nIndex ) { for( unsigned int i(0); m_vUseBoneList.size()>i; i++ ) { if( m_vUseBoneList[i] == nIndex ) return; } m_vUseBoneList.push_back( nIndex ); } //새로 정렬된 인덱스를 알려준다. int KNX3MeshFrame::GetNewBoneIndex( int nBoneIndex ) { for( unsigned int i(0); m_vUseBoneList.size()>i; i++ ) { if( m_vUseBoneList[i] == nBoneIndex ) return i; } assert( 0 && "이 메세지는, 피지크가 3개이상일 경우도 발생됨...여기는 말두 안돼!!! - Call BERSERK~" ); return 0; } //#define _USE_NORMAL_ namespace { void CalculateTangentArray(long vertexCount, K3DBLENDEDBUMPVERTEX *vertex, long triangleCount, const unsigned short *triangle) { K3DVector* tan1 = new K3DVector[vertexCount * 2]; K3DVector* tan2 = tan1 + vertexCount; ZeroMemory(tan1, vertexCount * sizeof(K3DVector) * 2); for (long a = 0; a < triangleCount; a+=3) { long i1 = triangle[0]; long i2 = triangle[1]; long i3 = triangle[2]; const K3DVertex& v1 = vertex[i1].position; const K3DVertex& v2 = vertex[i2].position; const K3DVertex& v3 = vertex[i3].position; const K3DPoint& w1 = vertex[i1].texcoord; const K3DPoint& w2 = vertex[i2].texcoord; const K3DPoint& w3 = vertex[i3].texcoord; float x1 = v2.x - v1.x; float x2 = v3.x - v1.x; float y1 = v2.y - v1.y; float y2 = v3.y - v1.y; float z1 = v2.z - v1.z; float z2 = v3.z - v1.z; float s1 = w2.x - w1.x; float s2 = w3.x - w1.x; float t1 = w2.y - w1.y; float t2 = w3.y - w1.y; float r = 1.0F / (s1 * t2 - s2 * t1); K3DVector sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); K3DVector tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); tan1[i1] += sdir; tan1[i2] += sdir; tan1[i3] += sdir; tan2[i1] += tdir; tan2[i2] += tdir; tan2[i3] += tdir; triangle+=3; } long count = vertexCount; for (long a = 0; a < count; a++) { const K3DVector& n = vertex[a].normal; const K3DVector& t = tan1[a]; // Gram-Schmidt orthogonalize K3DVector cross = DotProduct(n,t) * n; cross = (t - cross); Normalize(cross); vertex[a].tangent = K3DVector4(cross.x, cross.y, cross.z, 0); // Calculate handedness cross = CrossProduct(n,t); vertex[a].tangent.w = DotProduct(cross,tan2[a]) < 0.f ? -1.0f : 1.0f; } delete[] tan1; } }; BOOL KNX3MeshFrame::Load(const NX3LoadPack * pLoadPack, const char *meshname, int idxcount, const WORD *_idxlist, KTemplateDataObject * pObject, DWORD & dwFormat, DWORD & dwStride, DWORD & dwNumVertex, KTemplateDataObject * pFirstObject) { DWORD dwTime = GetSafeTickCount(); KSimpleDataObject * pTimeValue = pObject->GetSimpleDataMemberObject("time_value"); pTimeValue->GetDWORD(&m_dwFrameTime); KSimpleDataArrayObject * pVertexArray = pObject->GetSimpleDataArrayMemberObject("vertex_array"); KSimpleDataArrayObject * pNormalArray = pObject->GetSimpleDataArrayMemberObject("normal_array"); KSimpleDataArrayObject * pColorArray = NULL; KSimpleDataArrayObject * pTexelArray = NULL; if(pFirstObject) { pColorArray = pFirstObject->GetSimpleDataArrayMemberObject("color_array"); pTexelArray = pFirstObject->GetSimpleDataArrayMemberObject("texel_array"); } else { pColorArray = pObject->GetSimpleDataArrayMemberObject("color_array"); pTexelArray = pObject->GetSimpleDataArrayMemberObject("texel_array"); } if(NULL != pColorArray && pColorArray->GetDataCount() == 0) pColorArray = NULL; if(NULL != pTexelArray && pTexelArray->GetDataCount() == 0) pTexelArray = NULL; KSimpleDataArrayObject * pMeshTMArray = pObject->GetSimpleDataArrayMemberObject("mesh_tm"); float fArray[16]; if( pMeshTMArray ) { pMeshTMArray->GetDataFloat(0, fArray, sizeof(fArray), 16); m_NodeTM = K3DMatrix( fArray ); } //Weight 작업중.. KSimpleDataObject * pBoneSize = pObject->GetSimpleDataMemberObject("bone_size"); pBoneSize->GetDWORD(&m_dwBoneSize); if( m_dwBoneSize > 0 ) { m_bIsBlended = true; } KTemplateDataArrayObject * pWeightArray = pObject->GetTemplateDataArrayMemberObject("bone_block"); if( pWeightArray ) { // Format은 현재 사용하고 있지않음. dwFormat = 0; dwStride = sizeof(K3DBLENDEDBUMPVERTEX); dwNumVertex = pVertexArray->GetDataCount() / 3; _MakeVertexBuffer(dwNumVertex, dwFormat, dwStride,pWeightArray, pLoadPack, pVertexArray,pNormalArray,pColorArray,pTexelArray, idxcount, _idxlist); // _oprint( "Load Time : KNX3MeshFrame::Load - %d\n", GetSafeTickCount()-dwTime ); } return TRUE; } bool KNX3MeshFrame::LoadTRF(const NX3LoadPack * pLoadPack, const char *meshname, int idxcount, const WORD *_idxlist, trf::MTemplatePtr pObject, DWORD & dwFormat, DWORD & dwStride, DWORD & dwNumVertex, trf::MTemplatePtr pFirstObject) { DWORD dwTime = GetSafeTickCount(); m_dwFrameTime = pObject->getDWordBy("time_value"); trf::MArrayPtr pVertexArray = pObject->getArrayBy("vertex_array"); trf::MArrayPtr pNormalArray = pObject->getArrayBy("normal_array"); trf::MArrayPtr pColorArray = NULL; trf::MArrayPtr pTexelArray = NULL; if(pFirstObject) { pColorArray = pFirstObject->getArrayBy("color_array"); pTexelArray = pFirstObject->getArrayBy("texel_array"); } else { pColorArray = pObject->getArrayBy("color_array"); pTexelArray = pObject->getArrayBy("texel_array"); } if(NULL != pColorArray && pColorArray->count() == 0) pColorArray = NULL; if(NULL != pTexelArray && pTexelArray->count() == 0) pTexelArray = NULL; float fArray[16]; pObject->getArrayBy("mesh_tm")->readFixedData( 0, 16, fArray, sizeof(fArray) ); m_NodeTM = K3DMatrix( fArray ); //Weight 작업중.. trf::MTemplateArrayPtr pWeightArray = pObject->getTemplateArrayBy("bone_block"); m_dwBoneSize = pWeightArray->count(); if( m_dwBoneSize > 0 ) { m_bIsBlended = true; } // Format은 현재 사용하고 있지않음. dwFormat = 0; dwStride = sizeof(K3DBLENDEDBUMPVERTEX); dwNumVertex = pVertexArray->count() / 3; _MakeVertexBuffer(dwNumVertex, dwFormat, dwStride,pWeightArray, pLoadPack, pVertexArray,pNormalArray,pColorArray,pTexelArray, idxcount, _idxlist); // _oprint( "Load Time : KNX3MeshFrame::Load - %d\n", GetSafeTickCount()-dwTime ); return true; } template< typename T > static inline T _min( const T& a, const T& b ) { return a < b ? a : b; } template< typename T > static inline T _max( const T& a, const T& b ) { return a > b ? a : b; } void KNX3MeshFrame::_MakeVertexBuffer(DWORD numVertex, DWORD format, DWORD stride, KTemplateDataArrayObject* pWeightArray, const NX3LoadPack * pLoadPack, KSimpleDataArrayObject* pVertexArray,KSimpleDataArrayObject* pNormalArray, KSimpleDataArrayObject* pColorArray, KSimpleDataArrayObject* pTexelArray, int indexCount, const WORD* pIndexArray) { K3DVector sp_pos; float sp_radius = 0; if ( numVertex > 0) // 초기값은 첫번째 버텍스로 넣어준다 pVertexArray->GetDataFloat( 0, reinterpret_cast (&sp_pos), sizeof( sp_pos ), 3 ); K3DVector cube_min(sp_pos), cube_max(sp_pos); K3DVertex* pVtxArray = NULL; if( NULL != pLoadPack && pLoadPack->bLoad_PolyGon ) { pVtxArray = new K3DVertex[numVertex]; m_spVtxArray = new K3DVertexRes; } // Data가 기존의 2배라면 Light map용 채널이 같이 들어 있다. bool bLoadLightMapUV = pTexelArray && pTexelArray->GetDataCount() / 2 == (pVertexArray->GetDataCount() / 3) * 2; K3DBLENDEDBUMPVERTEX* pBlendVtxArray = new K3DBLENDEDBUMPVERTEX[numVertex]; for(DWORD i = 0; i < numVertex; ++i) { K3DBLENDEDBUMPVERTEX* pCurBlendVtx = &(pBlendVtxArray[i]); pCurBlendVtx->matrixIndices = 0; pCurBlendVtx->matrixWeights.x = m_bIsBlended ? 0.f : 1.f; pCurBlendVtx->matrixWeights.y = 0.f; pVertexArray->GetDataFloat(i * 3, reinterpret_cast (&(pCurBlendVtx->position)), sizeof( pCurBlendVtx->position ), 3 ); if(pVtxArray != NULL) pVtxArray[i] = pCurBlendVtx->position; pNormalArray->GetDataFloat(i * 3, reinterpret_cast (&(pCurBlendVtx->normal)), sizeof( pCurBlendVtx->normal ), 3 ); if(NULL != pTexelArray) { pTexelArray->GetDataFloat(i * 2, reinterpret_cast (&(pCurBlendVtx->texcoord)), sizeof( pCurBlendVtx->texcoord ), 2 ); // 우선 Lightmap쓰는 놈은 Skinning을 절대 하지 않으므로 Weight에 넣어볼까? -_- (뜯어 고치기 귀찮3) if(bLoadLightMapUV) pTexelArray->GetDataFloat(numVertex * 2 + i * 2, reinterpret_cast (&(pCurBlendVtx->matrixWeights)), sizeof( pCurBlendVtx->matrixWeights ), 2 ); } if(NULL != pColorArray) pColorArray->GetDataDWORD( i, reinterpret_cast (&(pCurBlendVtx->color)), sizeof( pCurBlendVtx->color ), 1 ); else pCurBlendVtx->color = 0xFFFFFFFF; ////////////////////////////////////////////////////////////////////////////// // make bound object // sphere calc const K3DVector& vCur = pCurBlendVtx->position; K3DVector vDiff = vCur - sp_pos; // 원점으로부터 새로 들어온 점까지의 벡터 float fLen = K3DVectorLength(vDiff); if( fLen > sp_radius ) { // 반지름의 크기를 가지는 vDiff의 반대 방향 K3DVector vDV = vDiff - ( sp_radius / fLen ) * vDiff; sp_pos += vDV * .5f; sp_radius = (fLen + sp_radius) / 2.f; } // make axis aligned cube cube_min.x = _min(cube_min.x , vCur.x); cube_min.y = _min(cube_min.y , vCur.y); cube_min.z = _min(cube_min.z , vCur.z); cube_max.x = _max(cube_max.x , vCur.x); cube_max.y = _max(cube_max.y , vCur.y); cube_max.z = _max(cube_max.z , vCur.z); ////////////////////////////////////////////////////////////////////////////// } if(true == m_bIsBlended ) { _MakeWeightInfo(pWeightArray, pBlendVtxArray, numVertex); #ifdef _USE_NORMAL_ CalculateTangentArray(numVertex,pBlendVtxArray, indexCount, pIndexArray ); #endif } // Blended Vertex Array m_spVertexBuffer = m_pGraphics->CreateVertexBufferBlend( stride, format, numVertex); K3DBLENDEDBUMPVERTEX* pVtxBuffer = NULL; int vtxCount = numVertex; m_spVertexBuffer->Lock( reinterpret_cast(&pVtxBuffer), vtxCount); if( pVtxBuffer ) { memcpy(pVtxBuffer,pBlendVtxArray, stride * numVertex ); m_spVertexBuffer->Unlock(); } if(NULL != pVtxArray) { m_spVtxArray->SetArray( pVtxArray, numVertex ); delete [] pVtxArray; } m_nMeshSimultaneousFrameCount = 1; // set bounding sphere m_bSphere.SetPosition( sp_pos ); m_bSphere.SetRadius( sp_radius ); // set bounding cube K3DVertex rotc[8]; cube_min += K3DVector(-1, -1, -1); cube_max += K3DVector( 1, 1, 1); for(size_t i = 0; i < 8; ++i) rotc[i] = KPCCP::get_cube_vertex(i, cube_min.x, cube_max.x, cube_min.y, cube_max.y, cube_min.z, cube_max.z); m_bCube.SetCube(rotc); delete [] pBlendVtxArray; } void KNX3MeshFrame::_MakeVertexBuffer(DWORD numVertex, DWORD format, DWORD stride, trf::MTemplateArrayPtr pWeightArray, const NX3LoadPack * pLoadPack, trf::MArrayPtr pVertexArray, trf::MArrayPtr pNormalArray, trf::MArrayPtr pColorArray, trf::MArrayPtr pTexelArray, int indexCount, const WORD* pIndexArray) { K3DVector sp_pos; float sp_radius = 0; if ( numVertex > 0) // 초기값은 첫번째 버텍스로 넣어준다 pVertexArray->readFixedData( 0, 3, &sp_pos, sizeof( sp_pos ) ); K3DVector cube_min(sp_pos), cube_max(sp_pos); K3DVertex* pVtxArray = NULL; if( NULL != pLoadPack && pLoadPack->bLoad_PolyGon ) { pVtxArray = new K3DVertex[numVertex]; m_spVtxArray = new K3DVertexRes; } // Data가 기존의 2배라면 Light map용 채널이 같이 들어 있다. bool bLoadLightMapUV = pTexelArray && pTexelArray->count() / 2 == (pVertexArray->count() / 3) * 2; K3DBLENDEDBUMPVERTEX* pBlendVtxArray = new K3DBLENDEDBUMPVERTEX[numVertex]; for(DWORD i = 0; i < numVertex; ++i) { K3DBLENDEDBUMPVERTEX* pCurBlendVtx = &(pBlendVtxArray[i]); pCurBlendVtx->matrixIndices = 0; pCurBlendVtx->matrixWeights.x = m_bIsBlended ? 0.f : 1.f; pCurBlendVtx->matrixWeights.y = 0.f; pVertexArray->readFixedData(i * 3, 3, &(pCurBlendVtx->position), sizeof( pCurBlendVtx->position ) ); if(pVtxArray != NULL) pVtxArray[i] = pCurBlendVtx->position; pNormalArray->readFixedData(i * 3, 3, &(pCurBlendVtx->normal), sizeof( pCurBlendVtx->normal ) ); if(NULL != pTexelArray) pTexelArray->readFixedData(i * 2, 2, &(pCurBlendVtx->texcoord), sizeof( pCurBlendVtx->texcoord ) ); // 우선 Lightmap쓰는 놈은 Skinning을 절대 하지 않으므로 Weight에 넣어볼까? -_- (뜯어 고치기 귀찮3) if(bLoadLightMapUV) pTexelArray->readFixedData(numVertex * 2 + i * 2, 2, reinterpret_cast (&(pCurBlendVtx->matrixWeights) ), sizeof( pCurBlendVtx->matrixWeights ) ); if(NULL != pColorArray) pCurBlendVtx->color = pColorArray->getDWordAt( i ); else pCurBlendVtx->color = 0xFFFFFFFF; ////////////////////////////////////////////////////////////////////////////// // make bound object // sphere calc const K3DVector& vCur = pCurBlendVtx->position; K3DVector vDiff = vCur - sp_pos; // 원점으로부터 새로 들어온 점까지의 벡터 float fLen = K3DVectorLength(vDiff); if( fLen > sp_radius ) { // 반지름의 크기를 가지는 vDiff의 반대 방향 K3DVector vDV = vDiff - ( sp_radius / fLen ) * vDiff; sp_pos += vDV * .5f; sp_radius = (fLen + sp_radius) / 2.f; } // make axis aligned cube cube_min.x = _min(cube_min.x , vCur.x); cube_min.y = _min(cube_min.y , vCur.y); cube_min.z = _min(cube_min.z , vCur.z); cube_max.x = _max(cube_max.x , vCur.x); cube_max.y = _max(cube_max.y , vCur.y); cube_max.z = _max(cube_max.z , vCur.z); ////////////////////////////////////////////////////////////////////////////// } if(true == m_bIsBlended ) { _MakeWeightInfo(pWeightArray, pBlendVtxArray, numVertex); #ifdef _USE_NORMAL_ CalculateTangentArray(numVertex,pBlendVtxArray, indexCount, pIndexArray ); #endif } // Blended Vertex Array m_spVertexBuffer = m_pGraphics->CreateVertexBufferBlend( stride, format, numVertex); K3DBLENDEDBUMPVERTEX* pVtxBuffer = NULL; int vtxCount = numVertex; m_spVertexBuffer->Lock( reinterpret_cast(&pVtxBuffer), vtxCount); if( pVtxBuffer ) { memcpy(pVtxBuffer,pBlendVtxArray, stride * numVertex ); m_spVertexBuffer->Unlock(); } if(NULL != pVtxArray) { m_spVtxArray->SetArray( pVtxArray, numVertex ); delete [] pVtxArray; } m_nMeshSimultaneousFrameCount = 1; // set bounding sphere m_bSphere.SetPosition( sp_pos ); m_bSphere.SetRadius( sp_radius ); // set bounding cube K3DVertex rotc[8]; cube_min += K3DVector(-1, -1, -1); cube_max += K3DVector( 1, 1, 1); for(size_t i = 0; i < 8; ++i) rotc[i] = KPCCP::get_cube_vertex(i, cube_min.x, cube_max.x, cube_min.y, cube_max.y, cube_min.z, cube_max.z); m_bCube.SetCube(rotc); delete [] pBlendVtxArray; } void KNX3MeshFrame::_MakeWeightInfo(KTemplateDataArrayObject* pWeightArray, K3DBLENDEDBUMPVERTEX* pBlendVtxArray, DWORD numVertex) { //Weight 작업중. Blended 버텍스 넣어 주기 위해, 미리 로드 한다. for( DWORD i = 0; m_dwBoneSize > i; ++i) { KNX3WeightElement * pWeightElement = new KNX3WeightElement; pWeightElement->Load( pWeightArray->GetData(i) ); m_vWeightList.push_back(pWeightElement); } //Weight 와 Bone Index를 설정. std::vector useBone; for( unsigned int i(0); m_dwBoneSize>i; i++ ) { DWORD nVtxCount = m_vWeightList[i]->GetWeightSize(); for( DWORD j(0); nVtxCount>j; j++ ) { float * pVtxIndexArray = m_vWeightList[i]->GetVertexIndex(); float * pWeightArray = m_vWeightList[i]->GetVertexWeight(); int nVtxIdx = (int)pVtxIndexArray[j]; //버텍스 인덱스 float fWeight = pWeightArray[j]; //가중치 K3DBLENDEDBUMPVERTEX * pCurBleneVtx = &(pBlendVtxArray[nVtxIdx]); if( pCurBleneVtx->matrixWeights.x == 0.f ) //가중치가 설정이 안되어 있으면.. { pCurBleneVtx->matrixWeights.x = fWeight; pCurBleneVtx->matrixIndices = i; AddUseBoneIndex( i ); //사용하는 본으로 추가 } else if( pCurBleneVtx->matrixWeights.y == 0.f ) //첫번째 가중치가 설정 되어 있으면.. { pCurBleneVtx->matrixWeights.y = fWeight; //두번째는 여기. pCurBleneVtx->matrixIndices |= (i)*256; AddUseBoneIndex( i ); } else { _oprint( "Error: more than 3 weights are not supported yet (x: %f; y: %f) \n", pCurBleneVtx->matrixWeights.x, pCurBleneVtx->matrixWeights.y); } // sprintf( szBuf, "UseBone Index : %d %d\n", i, pBleneVtx->matrixIndices ); // OutputDebugString(szBuf); } } //사용하는 뼈 인덱스로 변경.. //우선 Sort std::sort( m_vUseBoneList.begin( ), m_vUseBoneList.end( ) ); //_oprint( "!!!최적화 : Bone Count : %d\n", m_vUseBoneList.size() ); //기존에 들어 있는 인덱스 변경. for(DWORD i = 0; i < numVertex; ++i ) { K3DBLENDEDBUMPVERTEX * pCurBleneVtx = &(pBlendVtxArray[i]); for( unsigned int j(0); m_vUseBoneList.size(); ++j ) { //같은 인덱스, 인덱스를 변경 한다. //256보다 큰 것들은 변경 한다. if( pCurBleneVtx->matrixIndices >= 256 ) { //Weight 값이 2개 인것들.. int nTemp1 = pCurBleneVtx->matrixIndices/256; int nTemp2 = nTemp1*256; //나중에 추가 된것. int nTemp3 = pCurBleneVtx->matrixIndices - nTemp2; //원래 값 pCurBleneVtx->matrixIndices = GetNewBoneIndex(nTemp3); pCurBleneVtx->matrixIndices |= GetNewBoneIndex(nTemp1)*256; } else { //Weight 값이 1개 인것들 pCurBleneVtx->matrixIndices = GetNewBoneIndex(pCurBleneVtx->matrixIndices); } break; } } } void KNX3MeshFrame::_MakeWeightInfo( trf::MTemplateArrayPtr pWeightArray, K3DBLENDEDBUMPVERTEX* pBlendVtxArray, DWORD numVertex) { //Weight 작업중. Blended 버텍스 넣어 주기 위해, 미리 로드 한다. for( DWORD i = 0; m_dwBoneSize > i; ++i) { KNX3WeightElement * pWeightElement = new KNX3WeightElement; pWeightElement->LoadTRF( pWeightArray->getTemplateAt(i) ); m_vWeightList.push_back(pWeightElement); } //Weight 와 Bone Index를 설정. std::vector useBone; for( unsigned int i(0); m_dwBoneSize>i; i++ ) { DWORD nVtxCount = m_vWeightList[i]->GetWeightSize(); for( DWORD j(0); nVtxCount>j; j++ ) { float * pVtxIndexArray = m_vWeightList[i]->GetVertexIndex(); float * pWeightArray = m_vWeightList[i]->GetVertexWeight(); int nVtxIdx = (int)pVtxIndexArray[j]; //버텍스 인덱스 float fWeight = pWeightArray[j]; //가중치 K3DBLENDEDBUMPVERTEX * pCurBleneVtx = &(pBlendVtxArray[nVtxIdx]); if( pCurBleneVtx->matrixWeights.x == 0.f ) //가중치가 설정이 안되어 있으면.. { pCurBleneVtx->matrixWeights.x = fWeight; pCurBleneVtx->matrixIndices = i; AddUseBoneIndex( i ); //사용하는 본으로 추가 } else if( pCurBleneVtx->matrixWeights.y == 0.f ) //첫번째 가중치가 설정 되어 있으면.. { pCurBleneVtx->matrixWeights.y = fWeight; //두번째는 여기. pCurBleneVtx->matrixIndices |= (i)*256; AddUseBoneIndex( i ); } else { _oprint("Error: more than 3 weights are not supported yet (x: %f; y: %f) \n", pCurBleneVtx->matrixWeights.x, pCurBleneVtx->matrixWeights.y); } // sprintf( szBuf, "UseBone Index : %d %d\n", i, pBleneVtx->matrixIndices ); // OutputDebugString(szBuf); } } //사용하는 뼈 인덱스로 변경.. //우선 Sort std::sort( m_vUseBoneList.begin( ), m_vUseBoneList.end( ) ); //_oprint( "!!!최적화 : Bone Count : %d\n", m_vUseBoneList.size() ); //기존에 들어 있는 인덱스 변경. for(DWORD i = 0; i < numVertex; ++i ) { K3DBLENDEDBUMPVERTEX * pCurBleneVtx = &(pBlendVtxArray[i]); for( unsigned int j(0); m_vUseBoneList.size(); ++j ) { //같은 인덱스, 인덱스를 변경 한다. //256보다 큰 것들은 변경 한다. if( pCurBleneVtx->matrixIndices >= 256 ) { //Weight 값이 2개 인것들.. int nTemp1 = pCurBleneVtx->matrixIndices/256; int nTemp2 = nTemp1*256; //나중에 추가 된것. int nTemp3 = pCurBleneVtx->matrixIndices - nTemp2; //원래 값 pCurBleneVtx->matrixIndices = GetNewBoneIndex(nTemp3); pCurBleneVtx->matrixIndices |= GetNewBoneIndex(nTemp1)*256; } else { //Weight 값이 1개 인것들 pCurBleneVtx->matrixIndices = GetNewBoneIndex(pCurBleneVtx->matrixIndices); } break; } } } KNX3WeightElement::KNX3WeightElement() { m_dwWeightSize = 0; m_pVertexIndex = NULL; //버텍스 인덱스 m_pVertexWeight= NULL; //버텍스 가중치 m_pOffsetVector= NULL; //버텍스 OffSet } KNX3WeightElement::~KNX3WeightElement() { if( m_pVertexIndex ) { delete [] m_pVertexIndex; m_pVertexIndex = NULL; } if( m_pVertexWeight) { delete [] m_pVertexWeight; m_pVertexWeight= NULL; } if( m_pOffsetVector) { delete [] m_pOffsetVector; m_pOffsetVector= NULL; } } BOOL KNX3WeightElement::Load(KTemplateDataObject * pObject) { DWORD dwTime = GetSafeTickCount(); KSimpleDataObject * pWeightSize = pObject->GetSimpleDataMemberObject("weight_size"); pWeightSize->GetDWORD(&m_dwWeightSize); KSimpleDataArrayObject * pWeightArray = pObject->GetSimpleDataArrayMemberObject("weight_array"); KSimpleDataObject * pOffsetVectorSize = pObject->GetSimpleDataMemberObject("offset_vector_size"); pOffsetVectorSize->GetDWORD(&m_dwOffsetVectorSize); KSimpleDataArrayObject * pOffsetVectorArray = pObject->GetSimpleDataArrayMemberObject("offset_vector_array"); int iStrLen = 64; KSimpleDataObject * pBoneName = pObject->GetSimpleDataMemberObject("bone_name"); pBoneName->GetString(m_szBoneName, iStrLen); if( m_dwWeightSize <= 0 ) return TRUE; m_pVertexIndex = new float[m_dwWeightSize/2]; m_pVertexWeight = new float[m_dwWeightSize/2]; memset( m_pVertexIndex , 0, sizeof(float)*m_dwWeightSize/2 ); memset( m_pVertexWeight, 0, sizeof(float)*m_dwWeightSize/2 ); int n(0); for( DWORD dw(0); (m_dwWeightSize/2) > dw; dw++ ) { pWeightArray->GetDataFloat( n++, &m_pVertexIndex[dw], sizeof( m_pVertexIndex[dw] ), 1 ); pWeightArray->GetDataFloat( n++, &m_pVertexWeight[dw], sizeof( m_pVertexWeight[dw] ), 1 ); } #ifdef _USE_OFFSETVECTOR_ if( m_dwOffsetVectorSize && pOffsetVectorArray ) { n = 0; m_pOffsetVector = new K3DVector[m_dwOffsetVectorSize/3]; for( DWORD dw(0); (m_dwOffsetVectorSize/3) > dw; dw++ ) { K3DVector offsetvector; pOffsetVectorArray->GetDataFloat( n++, &offsetvector.x, sizeof( offsetvector.x ), 1 ); pOffsetVectorArray->GetDataFloat( n++, &offsetvector.y, sizeof( offsetvector.y ), 1 ); pOffsetVectorArray->GetDataFloat( n++, &offsetvector.z, sizeof( offsetvector.z ), 1 ); m_pOffsetVector[dw] = offsetvector; } } #endif m_dwWeightSize = m_dwWeightSize/2; // _oprint( "Load Time : KNX3WeightElement::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } bool KNX3WeightElement::LoadTRF( trf::MTemplatePtr pObject) { DWORD dwTime = GetSafeTickCount(); trf::MArrayPtr pWeightArray = pObject->getArrayBy("weight_array"); m_dwWeightSize = pWeightArray->count(); trf::MArrayPtr pOffsetVectorArray = pObject->getArrayBy("offset_vector_array"); m_dwOffsetVectorSize = pOffsetVectorArray->count(); strncpy( m_szBoneName, SafeStr( pObject->getStringBy( "bone_name" ) ), 64 ); if( m_dwWeightSize <= 0 ) return true; m_pVertexIndex = new float[m_dwWeightSize/2]; m_pVertexWeight = new float[m_dwWeightSize/2]; memset( m_pVertexIndex , 0, sizeof(float)*m_dwWeightSize/2 ); memset( m_pVertexWeight, 0, sizeof(float)*m_dwWeightSize/2 ); int n(0); for( DWORD dw(0); (m_dwWeightSize/2) > dw; dw++ ) { m_pVertexIndex[dw] = pWeightArray->getFloatAt( n++ ); m_pVertexWeight[dw] = pWeightArray->getFloatAt( n++ ); } #ifdef _USE_OFFSETVECTOR_ n = 0; m_pOffsetVector = new K3DVector[m_dwOffsetVectorSize/3]; for( DWORD dw(0); (m_dwOffsetVectorSize/3) > dw; dw++ ) { K3DVector offsetvector; offsetvector.x = pOffsetVectorArray->getFloatAt( n++ ); offsetvector.y = pOffsetVectorArray->getFloatAt( n++ ); offsetvector.z = pOffsetVectorArray->getFloatAt( n++ ); m_pOffsetVector[dw] = offsetvector; } #endif m_dwWeightSize = m_dwWeightSize/2; // _oprint( "Load Time : KNX3WeightElement::Load - %d\n", GetSafeTickCount()-dwTime ); return true; } KNX3FXElement::KNX3FXElement() { m_dwFrameTime = 0; m_bIsFX = false; } KNX3FXElement::~KNX3FXElement() { m_dwFrameTime = 0; m_vecData.clear(); } bool KNX3FXElement::getKey( std::string &key, int &pos ) { const char *str = m_sNote.c_str(); int len = static_cast(m_sNote.size()); std::string strkey; for ( int i = pos ; i < len ; ++i ) { if ( str[i] == '\n' || str[i] == '\r' || str[i] == '\t' || str[i] == ' ' ) { continue; } if ( str[i] == '=' ) { if ( strkey.size() == 0 ) return false; key = strkey; pos = i + 1; return true; } strkey += str[i]; } return false; } void KNX3FXElement::getKeyValue( std::string &value, int &pos ) { const char *str = m_sNote.c_str(); int len = static_cast(m_sNote.size()); std::string strvalue; int i; for ( i = pos ; i < len ; ++i ) { if ( isalnum( str[i] ) ) { if( i > 0 ) { if( str[ i - 1 ] == '+' || str[ i - 1 ] == '-' ) { i--; } } pos = i; break; } } for ( i = pos ; i < len ; ++i ) { if ( str[i] == '\t' || str[i] == ' ' ) { continue; } if ( (str[i] == '\r' || str[i] == '\n') && strvalue.size() > 0 ) { value = strvalue; pos = i + 1; return; } strvalue += str[i]; } if ( strvalue.size() > 0 ) { value = strvalue; pos = i + 1; return; } } void KNX3FXElement::parse() { DATA data; int pos = 0; while( true ) { if ( getKey( data.key, pos ) ) { getKeyValue( data.value, pos ); m_vecData.push_back( data ); data.key = ""; data.value = ""; } else break; } } const char *KNX3FXElement::GetValue( const char *fname ) { std::vector::iterator it = m_vecData.begin(); for ( ; it != m_vecData.end() ; ++it ) { if ( _stricmp( (*it).key.c_str(), fname ) == 0 ) { return (*it).value.c_str(); } } return NULL; } int KNX3FXElement::GetNumValue( const char *key, int nDef ) { const char *value = GetValue( key ); if ( value == NULL ) return nDef; return atoi( value ); } float KNX3FXElement::GetFloatValue( const char *key, float fDef ) { const char *value = GetValue( key ); if ( value == NULL ) return fDef; return (float)atof( value ); } K3DVector KNX3FXElement::GetVectorValue( const char *key, const K3DVector &vecDef ) { const char *vstr = GetValue( key ); if ( vstr == NULL ) return vecDef; K3DVector v; sscanf( vstr, "%f,%f,%f", &v.x, &v.y, &v.z ); return v; } K3DVector KNX3FXElement::Get2DVectorValue( const char *key, const K3DVector &vecDef ) { const char *vstr = GetValue( key ); if ( vstr == NULL ) return vecDef; K3DVector v; sscanf( vstr, "%f,%f", &v.x, &v.y ); v.z = vecDef.z; return v; } void KNX3FXElement::GetVariNumValue( const char *key, int *base_num, int *vari_num ) { const char *vstr = GetValue( key ); if ( vstr == NULL ) return; sscanf( vstr, "%d,%d", base_num, vari_num ); } BOOL KNX3FXElement::Load(KTemplateDataObject * pObject) { DWORD dwTime = GetSafeTickCount(); KSimpleDataObject * pTime = pObject->GetSimpleDataMemberObject("time"); pTime->GetDWORD(&m_dwFrameTime); char lpszNote[512]; int maxLen = 512; KSimpleDataObject * pNote = pObject->GetSimpleDataMemberObject("note"); pNote->GetString(lpszNote,maxLen); m_sNote.assign(lpszNote); parse(); const char *value = GetValue( "NXFX" ); if ( value != NULL ) { m_bIsFX = true; } else m_bIsFX = false; // _oprint( "Load Time : KNX3FXElement::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } bool KNX3FXElement::LoadTRF( trf::MTemplatePtr pObject) { DWORD dwTime = GetSafeTickCount(); m_dwFrameTime = pObject->getDWordBy("time"); m_sNote = SafeStr( pObject->getStringBy("note") ); parse(); const char *value = GetValue( "NXFX" ); if ( value != NULL ) { m_bIsFX = true; } else m_bIsFX = false; // _oprint( "Load Time : KNX3FXElement::Load - %d\n", GetSafeTickCount()-dwTime ); return true; } BOOL KNX3FX::Load(KTemplateDataObject * pObject) { DWORD dwTime = GetSafeTickCount(); KTemplateDataArrayObject * pFxBlockArray = pObject->GetTemplateDataArrayMemberObject("fx_block_array"); for(int i(0); i < pFxBlockArray->GetDataCount(); ++i) { KNX3FXElement element; element.Load(pFxBlockArray->GetData(i)); if ( i == 0 && element.IsFX() == true ) m_bIsFX = true; m_vtFXElement.push_back(element); } // _oprint( "Load Time : KNX3FX::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } bool KNX3FX::LoadTRF( trf::MTemplatePtr pObject ) { DWORD dwTime = GetSafeTickCount(); trf::MTemplateArrayPtr pFxBlockArray = pObject->getTemplateArrayBy("fx_block_array"); for(int i(0); i < pFxBlockArray->count(); ++i) { KNX3FXElement element; element.LoadTRF(pFxBlockArray->getTemplateAt(i)); if ( i == 0 && element.IsFX() == true ) m_bIsFX = true; m_vtFXElement.push_back(element); } // _oprint( "Load Time : KNX3FX::Load - %d\n", GetSafeTickCount()-dwTime ); return true; } KNX3FXElement * KNX3FX::GetFXElement(DWORD dwFrameTime) { if(m_vtFXElement.size() == 0) { return NULL; } for(unsigned int i(0); i < m_vtFXElement.size() - 1; ++i) { if( m_vtFXElement.at(i).GetFrameTime() <= dwFrameTime && m_vtFXElement.at(i + 1).GetFrameTime() > dwFrameTime) { return &m_vtFXElement.at(i); } } return &m_vtFXElement.back(); } KNX3FXElement * KNX3FX::GetFxElementByIndeX(int iIndex) { if(iIndex < 0 || iIndex >= (int)m_vtFXElement.size() ) return NULL; return &m_vtFXElement.at(iIndex); } DWORD KNX3FX::GetFXElementSize() { return static_cast(m_vtFXElement.size()); } BOOL KNX3CameraChannel::Load(KTemplateDataObject * pObject) { DWORD dwTime = GetSafeTickCount(); KTemplateDataArrayObject * pCameraArray = pObject->GetTemplateDataArrayMemberObject("camera_block_array"); m_spCameraRes = new K3DResCamera; K3DResCamera::Key *key = new K3DResCamera::Key[pCameraArray->GetDataCount()]; float fArray[12]; for(int i(0); i < pCameraArray->GetDataCount(); ++i) { KTemplateDataObject *pObject = pCameraArray->GetData(i); char bHasTarget; KSimpleDataObject * pHasTarget = pObject->GetSimpleDataMemberObject("has_target"); pHasTarget->GetChar(reinterpret_cast(&bHasTarget) ); if ( bHasTarget ) { KSimpleDataArrayObject * pMatObject = pObject->GetSimpleDataArrayMemberObject("mat_object"); pMatObject->GetDataFloat(0,fArray,sizeof(fArray),12); key[i].up.x = fArray[3]; key[i].up.y = fArray[4]; key[i].up.z = fArray[5]; key[i].pos.x = fArray[9]; key[i].pos.y = fArray[10]; key[i].pos.z = fArray[11]; KSimpleDataArrayObject * pMatTarget = pObject->GetSimpleDataArrayMemberObject("mat_target"); pMatTarget->GetDataFloat(0,fArray,sizeof(fArray),12); key[i].view.x = fArray[9] - key[i].pos.x; key[i].view.y = fArray[10] - key[i].pos.y; key[i].view.z = fArray[11] - key[i].pos.z; } else { KSimpleDataArrayObject * pMatObject = pObject->GetSimpleDataArrayMemberObject("mat_object"); pMatObject->GetDataFloat(0,fArray,sizeof(fArray),12); key[i].view.x = fArray[0]; key[i].view.y = fArray[1]; key[i].view.z = fArray[2]; key[i].up.x = fArray[3]; key[i].up.y = fArray[4]; key[i].up.z = fArray[5]; key[i].pos.x = fArray[9]; key[i].pos.y = fArray[10]; key[i].pos.z = fArray[11]; } KSimpleDataObject * pTime = pObject->GetSimpleDataMemberObject("time_value"); pTime->GetDWORD(reinterpret_cast(&key[i].time)); KSimpleDataObject * pFov = pObject->GetSimpleDataMemberObject("fov"); pFov->GetFloat(&key[i].fov); } m_spCameraRes->SetWholeKey( key, pCameraArray->GetDataCount() ); delete[] key; // _oprint( "Load Time : KNX3CameraChannel::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } bool KNX3CameraChannel::LoadTRF( trf::MTemplatePtr pObject ) { DWORD dwTime = GetSafeTickCount(); trf::MTemplateArrayPtr pCameraArray = pObject->getTemplateArrayBy( "camera_block_array" ); m_spCameraRes = new K3DResCamera; K3DResCamera::Key *key = new K3DResCamera::Key[ pCameraArray->count() ]; // float fArray[12]; for(int i(0); i < pCameraArray->count(); ++i) { trf::MTemplatePtr pObject = pCameraArray->getTemplateAt(i); char bHasTarget = pObject->getCharBy( "has_target" ); if ( bHasTarget ) { const float* fArray = pObject->getArrayBy("mat_object")->getFloatArray(); key[i].up.x = fArray[3]; key[i].up.y = fArray[4]; key[i].up.z = fArray[5]; key[i].pos.x = fArray[9]; key[i].pos.y = fArray[10]; key[i].pos.z = fArray[11]; fArray = pObject->getArrayBy("mat_target")->getFloatArray(); key[i].view.x = fArray[9] - key[i].pos.x; key[i].view.y = fArray[10] - key[i].pos.y; key[i].view.z = fArray[11] - key[i].pos.z; } else { const float* fArray = pObject->getArrayBy("mat_object")->getFloatArray(); key[i].view.x = fArray[0]; key[i].view.y = fArray[1]; key[i].view.z = fArray[2]; key[i].up.x = fArray[3]; key[i].up.y = fArray[4]; key[i].up.z = fArray[5]; key[i].pos.x = fArray[9]; key[i].pos.y = fArray[10]; key[i].pos.z = fArray[11]; } key[i].time = pObject->getDWordBy("time_value"); key[i].fov = pObject->getFloatBy("fov"); } m_spCameraRes->SetWholeKey( key, pCameraArray->count() ); delete[] key; // _oprint( "Load Time : KNX3CameraChannel::Load - %d\n", GetSafeTickCount()-dwTime ); return true; } void KNX3LightChannel::Clear() { SAFE_DELETE_VECTOR(m_vtLightList); } BOOL KNX3LightChannel::Load(KTemplateDataObject * pObject) { DWORD dwTime = GetSafeTickCount(); KTemplateDataArrayObject * pLightArray = pObject->GetTemplateDataArrayMemberObject("light_array"); for(int i(0); i < pLightArray->GetDataCount(); ++i) { KNX3Light * pLight = new KNX3Light(m_pGraphics); pLight->Load(pLightArray->GetData(i)); m_vtLightList.push_back(pLight); } // _oprint( "Load Time : KNX3LightChannel::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } bool KNX3LightChannel::LoadTRF( trf::MTemplatePtr pObject) { DWORD dwTime = GetSafeTickCount(); trf::MTemplateArrayPtr pLightArray = pObject->getTemplateArrayBy( "light_array" ); for(int i(0); i < pLightArray->count(); ++i) { KNX3Light * pLight = new KNX3Light(m_pGraphics); pLight->LoadTRF(pLightArray->getTemplateAt(i)); m_vtLightList.push_back(pLight); } // _oprint( "Load Time : KNX3LightChannel::Load - %d\n", GetSafeTickCount()-dwTime ); return true; } BOOL KNX3Light::Load(KTemplateDataObject * pObject) { DWORD dwTime = GetSafeTickCount(); DWORD dwLightType; DWORD dwAmbient; KSimpleDataObject *pLightType = pObject->GetSimpleDataMemberObject("light_type"); pLightType->GetDWORD(&dwLightType); KSimpleDataObject * pAmbientColor = pObject->GetSimpleDataMemberObject("ambient_light"); pAmbientColor->GetDWORD(&dwAmbient); m_spLightRes = new K3DResLight; KTemplateDataArrayObject * pLightBlockArray = pObject->GetTemplateDataArrayMemberObject("light_block_array"); K3DResLight::Key *key = new K3DResLight::Key[pLightBlockArray->GetDataCount()]; for(int i(0); i < pLightBlockArray->GetDataCount(); ++i) { KTemplateDataObject *pElementObject = pLightBlockArray->GetData(i); K3DMatrix pos, target; DWORD dwColor; float fIntens, fAttStart, fAttEnd; char bOn; float fArray[12]; KSimpleDataArrayObject * pMatObject = pElementObject->GetSimpleDataArrayMemberObject("mat_object"); pMatObject->GetDataFloat(0,fArray,sizeof(fArray),12); pos._11 = fArray[0]; pos._12 = fArray[1]; pos._13 = fArray[2]; pos._21 = fArray[3]; pos._22 = fArray[4]; pos._23 = fArray[5]; pos._31 = fArray[6]; pos._32 = fArray[7]; pos._33 = fArray[8]; pos._41 = fArray[9]; pos._42 = fArray[10]; pos._43 = fArray[11]; KSimpleDataArrayObject * pMatTarget = pElementObject->GetSimpleDataArrayMemberObject("mat_target"); pMatTarget->GetDataFloat(0,fArray,sizeof(fArray),12); target._11 = fArray[0]; target._12 = fArray[1]; target._13 = fArray[2]; target._21 = fArray[3]; target._22 = fArray[4]; target._23 = fArray[5]; target._31 = fArray[6]; target._32 = fArray[7]; target._33 = fArray[8]; target._41 = fArray[9]; target._42 = fArray[10]; target._43 = fArray[11]; KSimpleDataObject * pTime = pElementObject->GetSimpleDataMemberObject("time_value"); pTime->GetDWORD(reinterpret_cast(&key[i].time)); KSimpleDataObject * pColorLight = pElementObject->GetSimpleDataMemberObject("clr_light"); pColorLight->GetDWORD(&dwColor); KSimpleDataObject * pIntens = pElementObject->GetSimpleDataMemberObject("intens"); pIntens->GetFloat(&fIntens); KSimpleDataObject * pAttenStart = pElementObject->GetSimpleDataMemberObject("atten_start"); pAttenStart->GetFloat(&fAttStart); KSimpleDataObject * pAttenEnd = pElementObject->GetSimpleDataMemberObject("atten_end"); pAttenEnd->GetFloat(&fAttEnd); KSimpleDataObject * pOnOff = pElementObject->GetSimpleDataMemberObject("onoff"); pOnOff->GetChar( reinterpret_cast(&bOn) ); if ( bOn == false ) dwColor = 0; //라이트 설정하는 방법 바꿔야 함. K3DColor diffuse(dwColor); K3DColor ambient(dwAmbient); K3DColor specular(.3f, .3f, .3f); diffuse *= fIntens; switch(dwLightType) { case NX3LIGHT_OMNI: case NX3LIGHT_SIMPLE_OMNI: key[i].light = K3DLight( diffuse, specular, ambient, K3DVector(pos._41, pos._42, pos._43), fAttEnd * 1.0f, .0f, 1.0f, 1.0f ); break; case NX3LIGHT_TARGET_DIRECTIONAL: key[i].light = K3DLight( diffuse, specular, ambient, K3DVector(target._41 - pos._41, target._42 - pos._42, target._43 - pos._43) ); key[i].light.position = K3DVector(pos._41, pos._42, pos._43); break; case NX3LIGHT_FREE_DIRECTIONAL: key[i].light = K3DLight( diffuse, specular, ambient, K3DVector(pos._41 - pos._31, pos._42 - pos._32, pos._43 - pos._33) ); key[i].light.position = K3DVector(pos._41, pos._42, pos._43); break; } } m_spLightRes->SetWholeKey( key, pLightBlockArray->GetDataCount() ); delete[] key; // _oprint( "Load Time : KNX3Light::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } bool KNX3Light::LoadTRF( trf::MTemplatePtr pObject ) { DWORD dwTime = GetSafeTickCount(); DWORD dwLightType = pObject->getDWordBy( "light_type" ); DWORD dwAmbient = pObject->getDWordBy( "ambient_light" ); m_spLightRes = new K3DResLight; trf::MTemplateArrayPtr pLightBlockArray = pObject->getTemplateArrayBy( "light_block_array" ); K3DResLight::Key *key = new K3DResLight::Key[ pLightBlockArray->count() ]; for(int i(0); i < pLightBlockArray->count(); ++i) { trf::MTemplatePtr pElementObject = pLightBlockArray->getTemplateAt( i ); K3DMatrix pos, target; DWORD dwColor; float fIntens, fAttStart, fAttEnd; char bOn; const float* fArray = pElementObject->getArrayBy( "mat_object" )->getFloatArray(); pos._11 = fArray[0]; pos._12 = fArray[1]; pos._13 = fArray[2]; pos._21 = fArray[3]; pos._22 = fArray[4]; pos._23 = fArray[5]; pos._31 = fArray[6]; pos._32 = fArray[7]; pos._33 = fArray[8]; pos._41 = fArray[9]; pos._42 = fArray[10]; pos._43 = fArray[11]; fArray = pElementObject->getArrayBy( "mat_target" )->getFloatArray(); target._11 = fArray[0]; target._12 = fArray[1]; target._13 = fArray[2]; target._21 = fArray[3]; target._22 = fArray[4]; target._23 = fArray[5]; target._31 = fArray[6]; target._32 = fArray[7]; target._33 = fArray[8]; target._41 = fArray[9]; target._42 = fArray[10]; target._43 = fArray[11]; key[i].time = pElementObject->getDWordBy( "time_value" ); dwColor = pElementObject->getDWordBy( "clr_light" ); fIntens = (float)(pElementObject->getDWordBy( "intens" )); fAttStart = (float)(pElementObject->getDWordBy( "atten_start" )); fAttEnd = (float)(pElementObject->getDWordBy( "atten_end" )); bOn = pElementObject->getCharBy( "onoff" ); if ( bOn == false ) dwColor = 0; //라이트 설정하는 방법 바꿔야 함. K3DColor diffuse(dwColor); K3DColor ambient(dwAmbient); K3DColor specular(.3f, .3f, .3f); diffuse *= fIntens; switch(dwLightType) { case NX3LIGHT_OMNI: case NX3LIGHT_SIMPLE_OMNI: key[i].light = K3DLight( diffuse, specular, ambient, K3DVector(pos._41, pos._42, pos._43), fAttEnd * 1.0f, .0f, 1.0f, 1.0f ); break; case NX3LIGHT_TARGET_DIRECTIONAL: key[i].light = K3DLight( diffuse, specular, ambient, K3DVector(target._41 - pos._41, target._42 - pos._42, target._43 - pos._43) ); key[i].light.position = K3DVector(pos._41, pos._42, pos._43); break; case NX3LIGHT_FREE_DIRECTIONAL: key[i].light = K3DLight( diffuse, specular, ambient, K3DVector(pos._41 - pos._31, pos._42 - pos._32, pos._43 - pos._33) ); key[i].light.position = K3DVector(pos._41, pos._42, pos._43); break; } } m_spLightRes->SetWholeKey( key, pLightBlockArray->count() ); delete[] key; // _oprint( "Load Time : KNX3Light::Load - %d\n", GetSafeTickCount()-dwTime ); return true; } void KNX3ChannelControl::Clear() { SAFE_DELETE(m_pMtlChannel); SAFE_DELETE(m_pMeshChannel); SAFE_DELETE(m_pLightChannel); SAFE_DELETE(m_pCameraChannel); SAFE_DELETE(m_pBoneChannel); } BOOL KNX3ChannelControl::Load( const NX3LoadPack * pLoadPack, K3DRenderDevice *pGraphics, /*KSoundDevice * pSound,*/ KFiler *pFiler, const char * szName ) { DWORD dwTime = GetSafeTickCount(); Clear(); for(int i(0); i GetDataObjectCount(); ++i) { KTemplateDataObject * pObject = pFiler->GetDataObjectAt(i); const char *lpszName = pObject->GetTemplateName(); if(strcmp(lpszName, "nx3_version_header") == 0) { KSimpleDataObject* pVersionObj = pObject->GetSimpleDataMemberObject("version"); pVersionObj->GetDWORD(&m_dwVersion); } if(strcmp(lpszName, "nx3_mtl_header") == 0) { m_pMtlChannel = new KNX3MtlChannel(pGraphics); m_pMtlChannel->Load( pObject, pLoadPack ); } else if(strcmp(lpszName, "nx3_mesh_header") == 0) { m_pMeshChannel = new KNX3MeshChannel(pGraphics, m_pMtlChannel); m_pMeshChannel->Load( pLoadPack, pObject, KNX3MeshChannel::LT_OLD_MESH ); } else if(strcmp(lpszName,"nx3_new_mesh_header") == 0) // 새로 추가 { m_pMeshChannel = new KNX3MeshChannel(pGraphics, m_pMtlChannel); m_pMeshChannel->Load( pLoadPack, pObject, KNX3MeshChannel::LT_NEW_MESH ); } else if(strcmp(lpszName, "nx3_light_header") == 0) { m_pLightChannel = new KNX3LightChannel(pGraphics); m_pLightChannel->Load(pObject); } else if(strcmp(lpszName, "nx3_camera") == 0) { m_pCameraChannel = new KNX3CameraChannel(pGraphics); m_pCameraChannel->Load(pObject); } else if(strcmp(lpszName, "nx3_bone_ani_header") == 0) { m_pBoneChannel = new KNX3BoneChannel(pGraphics); m_pBoneChannel->Load(pObject, szName, m_dwVersion); } } DWORD dwEndTime = (GetSafeTickCount() - dwTime); if( dwEndTime > 50 ) // _performance_print( "%04dms NX3 Load : %s ThreadId:%d\n", dwEndTime, szName, GetCurrentThreadId() ); _oprint( "Load Time : KNX3ChannelControl::Load - %d\n", GetSafeTickCount()-dwTime ); return TRUE; } bool KNX3ChannelControl::LoadTRF( const NX3LoadPack * pLoadPack, K3DRenderDevice *pGraphics, /*KSoundDevice * pSound,*/ trf::MDictPtr pDict, const char * szName ) { DWORD dwTime = GetSafeTickCount(); Clear(); for(int i(0); i < pDict->count(); ++i) { trf::MTemplatePtr pObject = pDict->getTemplateAt( i ); const char *lpszName = pObject->className(); if(strcmp(lpszName, "nx3_version_header") == 0) { m_dwVersion = pObject->getDWordBy( "version" ); } if( strcmp( lpszName, "nx3_property" ) == 0 ) { m_strProperty = pObject->getStringBy( "property_string" ); } if(strcmp(lpszName, "nx3_mtl_header") == 0) { m_pMtlChannel = new KNX3MtlChannel(pGraphics); m_pMtlChannel->LoadTRF( pObject, pLoadPack ); } else if(strcmp(lpszName, "nx3_mesh_header") == 0) { m_pMeshChannel = new KNX3MeshChannel(pGraphics, m_pMtlChannel); m_pMeshChannel->LoadTRF( pLoadPack, pObject, KNX3MeshChannel::LT_OLD_MESH ); } else if(strcmp(lpszName,"nx3_new_mesh_header") == 0) // 새로 추가 { m_pMeshChannel = new KNX3MeshChannel(pGraphics, m_pMtlChannel); m_pMeshChannel->LoadTRF( pLoadPack, pObject, KNX3MeshChannel::LT_NEW_MESH ); } else if(strcmp(lpszName, "nx3_light_header") == 0) { m_pLightChannel = new KNX3LightChannel(pGraphics); m_pLightChannel->LoadTRF(pObject); } else if(strcmp(lpszName, "nx3_camera") == 0) { m_pCameraChannel = new KNX3CameraChannel(pGraphics); m_pCameraChannel->LoadTRF(pObject); } //Bone 작업중.. else if(strcmp(lpszName, "nx3_bone_ani_header") == 0) { m_pBoneChannel = new KNX3BoneChannel(pGraphics); m_pBoneChannel->LoadTRF(pObject, szName, m_dwVersion); } } DWORD dwEndTime = (GetSafeTickCount() - dwTime); if( dwEndTime > 50 ) { // _performance_print( "%04dms TRF Load : %s ThreadId:%d\n", dwEndTime, szName, GetCurrentThreadId() ); _oprint( "Load Time : KNX3ChannelControl::LoadTRF - %d\n", GetSafeTickCount()-dwTime ); } return TRUE; }