Files
Leviathan/Client/Game/engine/Renderer/KNX3Loader.cpp
T
2026-06-01 12:46:52 +02:00

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;
}