3422 lines
102 KiB
C++
3422 lines
102 KiB
C++
#include "stdafx.h"
|
|
#include "KNX3Loader.h"
|
|
#include "K3DBound.h"
|
|
#include "KResourceManager.h"
|
|
#include "nx10.h"
|
|
#include <mmo/ArTime.h>
|
|
|
|
#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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<DWORD>(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<DWORD>(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<KNX3FXElement*> vFXEle;
|
|
for ( unsigned int i=0; i<pFX->GetFXElementSize() ; ++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<DWORD *>(&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<DWORD*>(&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 ; i<m_vtMeshElement.size() ; ++i )
|
|
{
|
|
KNX3MeshElement* pElement = m_vtMeshElement[i];
|
|
pElement->GetWritableEventCube().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<DWORD*>(&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<DWORD*>(&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 ; i<m_vtMeshElement.size() ; ++i )
|
|
{
|
|
KNX3MeshElement* pElement = m_vtMeshElement[i];
|
|
pElement->GetWritableEventCube().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<DWORD*>(&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 ; i<m_vtMeshElement.size() ; ++i )
|
|
{
|
|
KNX3MeshElement* pElement = m_vtMeshElement[i];
|
|
pElement->GetWritableEventCube().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 ; i<m_vtMeshElement.size() ; ++i )
|
|
{
|
|
KNX3MeshElement* pElement = m_vtMeshElement[i];
|
|
pElement->GetWritableEventCube().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<float *>(&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<float *> (&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<float *> (&(pCurBlendVtx->position)), sizeof( pCurBlendVtx->position ), 3 );
|
|
|
|
if(pVtxArray != NULL)
|
|
pVtxArray[i] = pCurBlendVtx->position;
|
|
|
|
pNormalArray->GetDataFloat(i * 3, reinterpret_cast<float *> (&(pCurBlendVtx->normal)), sizeof( pCurBlendVtx->normal ), 3 );
|
|
|
|
if(NULL != pTexelArray)
|
|
{
|
|
pTexelArray->GetDataFloat(i * 2, reinterpret_cast<float *> (&(pCurBlendVtx->texcoord)), sizeof( pCurBlendVtx->texcoord ), 2 );
|
|
|
|
// 우선 Lightmap쓰는 놈은 Skinning을 절대 하지 않으므로 Weight에 넣어볼까? -_- (뜯어 고치기 귀찮3)
|
|
if(bLoadLightMapUV)
|
|
pTexelArray->GetDataFloat(numVertex * 2 + i * 2, reinterpret_cast<float *> (&(pCurBlendVtx->matrixWeights)), sizeof( pCurBlendVtx->matrixWeights ), 2 );
|
|
|
|
}
|
|
|
|
if(NULL != pColorArray)
|
|
pColorArray->GetDataDWORD( i, reinterpret_cast<DWORD *> (&(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<void**>(&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<float *> (&(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<void**>(&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<int> 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<int> 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<int>(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<int>(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<DATA>::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<DWORD>(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<char *>(&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<DWORD*>(&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<DWORD*>(&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<char *>(&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 <pFiler->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;
|
|
}
|