Files
2026-06-01 12:46:52 +02:00

1813 lines
49 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "stdafx.h"
#include "KRenderDefine.h"
#include "krenderobjectMesh.h"
#include "K3DCamera.h"
#include "KRenderDeviceDX.h"
#include "KDeviceManager.h"
#include "KResourceManager.h"
//#include "K3DFrustum.h"
#include "GameDefine.h"
#include "KResource.h"
#include "KViewport.h"
#include "k3dpccp.h"
#include "KRenderObjectBone.h"
#include <toolkit/SafeTickCount.h>
namespace {
DWORD interpolateColor(DWORD color0, DWORD color1, float div)
// return = color1*div + color0*(1-div)
{
float a0,r0,g0,b0;
float a1,r1,g1,b1;
float invdiv=1.f-div;
a0=(float)((color0>>24)&0xff);
r0=(float)((color0>>16)&0xff);
g0=(float)((color0>>8)&0xff);
b0=(float)(color0&0xff);
a1=(float)((color1>>24)&0xff);
r1=(float)((color1>>16)&0xff);
g1=(float)((color1>>8)&0xff);
b1=(float)(color1&0xff);
DWORD a, r, g, b;
a = (DWORD)(a0*invdiv + a1*div);
r = (DWORD)(r0*invdiv + r1*div);
g = (DWORD)(g0*invdiv + g1*div);
b = (DWORD)(b0*invdiv + b1*div);
if (a>0xff) a=0xff;
if (r>0xff) r=0xff;
if (g>0xff) g=0xff;
if (b>0xff) b=0xff;
return (a<<24) | (r<<16) | (g<<8) | b;
}
const short KEEP_TIME_WINK = 50;
const int OLDMORPH_MESH_CHCKTIME = 1000;
const int EFFECT_LIFE_TIME = 1000.f;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// KMeshSeqObject Implement
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool KMeshSeqObject::m_sVisbleCube = false;
KMeshSeqObject::KMeshSeqObject()
{
K3DMatrixIdentity(m_matLocal);
K3DMatrixIdentity(m_matRoot);
K3DMatrixIdentity(m_matResult);
K3DMatrixIdentity(m_matUV);
m_pAlterMtl = NULL;
m_dwColors[0] = m_dwColors[1] = m_dwColors[2] = m_dwColors[3] = 0;
m_fVisResult = 1.0f;
m_nBoneMatCount = 0;
m_pBoneMatList = NULL;
m_nPrMeshCount = 0;
m_pPrMesh = NULL;
m_bForceTransparent = false;
m_bIsMakeBoundCube = false;
numFrames=0;
m_bUseTextureAlpha = true;
m_nMorphPrimitiveCount = 0;
_morphInit();
checkTime = 0;
previousTime = 0;
m_bUseWink = false;
m_bFlipWink = false;
m_spWinkTexture = NULL;
m_bUseDefaultTexture = true; // sonador 1.8.10 아바타 텍스쳐 그룹 적용(페이스 컷 포함)
//#ifndef NDEBUG
// _oprint( "KMeshSeqObject !! 0x%08X\n", &m_prMesh );
//#endif
}
KMeshSeqObject::~KMeshSeqObject()
{
_oldmorphClear();
if( !morph_primitivelist.empty() )
{
for( unsigned int i(0); morph_primitivelist.size()>i; i++ )
{
delete [] morph_primitivelist[i];
}
morph_primitivelist.clear();
}
SAFE_DELETE_VECTOR(m_vCacheKeyList);
delete[] m_pPrMesh;
}
void KMeshSeqObject::SetMeshRes( K3DMeshResource *pMesh )
{
assert( m_spResMesh == NULL );
if(m_pPrMesh != NULL)
{
delete[] m_pPrMesh;
m_pPrMesh = NULL;
}
m_spResMesh = pMesh;
if(m_spResMesh != NULL)
{
m_interval.Expand( m_spResMesh->GetInterval() );
m_nPrMeshCount = m_spResMesh->GetResCount();
m_pPrMesh = new KMeshPrimitive[m_nPrMeshCount];
for(int i = 0; i < m_nPrMeshCount; ++i)
{
K3DResVertexAnimation* pVA = m_spResMesh->GetRes( i );
m_pPrMesh[i].SetIndexBuffer( pVA->GetIndexBuffer() );
m_pPrMesh[i].SetPrimitivesCount( pVA->GetPrimitiveCount() );
m_pPrMesh[i].SetTexture( pVA->GetTexturePack() );
m_pPrMesh[i].SetBlendMode( pVA->GetBlendMode() );
m_pPrMesh[i].SetMaterial( pVA->GetMaterial() );
if( m_spResMesh->GetWeightResCount() > 0 )
{
K3DWeight* pWeight = m_spResMesh->GetWeightRes(i);
m_pPrMesh[i].SetWeight( pWeight );
m_pPrMesh[i].SetVSMode( true );
}
// m_pPrMesh[i].SetBoundOcclusion( &m_boundOcclusion );
}
m_boundSphere = m_spResMesh->GetBoundSphere();
m_boundCube = m_spResMesh->GetBoundCube();
}
}
bool ExistCheckVector( std::vector<const char*> & vList, K3DTexture * pTex )
{
std::vector<const char*>::iterator it = vList.begin();
for(; it != vList.end(); it++)
{
if( _stricmp( (*it), pTex->GetName() ) == 0 )
return true;
}
return false;
}
K3DBoundRotCube * KMeshSeqObject::GetCube()
{
//TODO : 고쳐야 하는 부분 임.
#ifdef _RAC //게임에서만 적용
m_boundCube.SetTransform(m_matResult);
#endif
return &m_boundCube;
}
K3DBoundSphere* KMeshSeqObject::GetSphere()
{
//TODO : 고쳐야 하는 부분 임.
#ifdef _RAC //게임에서만 적용
m_boundSphere.SetTransform(m_matResult);
#endif
return &m_boundSphere;
}
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; }
static inline void K3DVectorMultiply( K3DVector& out, const K3DMatrix& TM, const K3DVector& in )
{
out.x = (TM.m00*in.x) + (TM.m10*in.y) + (TM.m20*in.z) + TM.m30;
out.y = (TM.m01*in.x) + (TM.m11*in.y) + (TM.m21*in.z) + TM.m31;
out.z = (TM.m02*in.x) + (TM.m12*in.y) + (TM.m22*in.z) + TM.m32;
}
void KMeshSeqObject::_makeBoundCube( KBoneSeqObject * pBoneSeq )
{
K3DMatrix iden;
K3DMatrixIdentity(iden);
K3DBoundRotCube cube, t_cube;
for ( int n=0 ; n<m_spResMesh->GetResCount(); ++n )
{
bool bFirst = true;
K3DVector cube_min(1000,1000,1000), cube_max(-1000,-1000,-1000);
K3DResVertexAnimation *va = m_spResMesh->GetRes(n);
K3DResVertexAnimation::Key *key1 = NULL, *key2 = NULL;
va->GetData( m_dwTime, key1, key2 );
if( key1 == NULL || !key1->m_spVB->IsValidVtx() ) continue;
DWORD dwVtxCount = key1->m_spVB->GetVertexCount();
DWORD dwVtxFormat = key1->m_spVB->GetVertexFormat();
DWORD dwVtxStride = key1->m_spVB->GetVertexStride();
// K3DFVF_XYZ | K3DFVF_NORMAL 은 항상 존재
char *pTempBuf = NULL;
int size = dwVtxCount; //Size 사용 안함.
key1->m_spVB->Lock( (void**)&pTempBuf, size );
if( pTempBuf == NULL ) continue;
K3DWeight* pWeight = m_spResMesh->GetWeightRes(n);
K3DMatrix * pMeshNodeTM = m_spResMesh->GetNodeTM(n);
//한곳에 모음
K3DVector * pOutVtx = new K3DVector[size];
for( int i(0); size>i; ++i )
pOutVtx[i] = K3DVector(0,0,0);
struct BONE_INDEX
{
K3DBone * pBone;
const char * pBoneName;
int nBoneIndex;
BONE_INDEX()
{
pBone = NULL;
pBoneName = NULL;
nBoneIndex = -1;
}
};
std::vector< BONE_INDEX > cache_list;
if( pWeight )
{
//pWeight->m_nTotal는 뼈수와 같다.
for( int j(0); pWeight->m_nTotal>j; ++j )
{
for( int k(0); pWeight[j].m_nWeight>k; ++k )
{
K3DMatrix * pBoneList = (pBoneSeq) ? pBoneSeq->GetBoneCacheTM() : NULL;
K3DBone * pBone = NULL;
K3DMeshTM * pMeshTM = NULL;
for( unsigned int i(0); cache_list.size()>i; ++i )
{
if( !::_strnicmp( cache_list[i].pBoneName, pWeight[j].m_szBoneName, strlen(pWeight[j].m_szBoneName) ) )
{
pBone = cache_list[i].pBone;
break;
}
}
if( pBone == NULL )
{
if( pBoneSeq )
{
BONE_INDEX bone_index;
pBone = pBoneSeq->GetBone( pWeight[j].m_szBoneName, bone_index.nBoneIndex );
bone_index.pBone = pBone;
bone_index.pBoneName = pWeight[j].m_szBoneName;
cache_list.push_back( bone_index );
}
}
pMeshTM = m_spResMesh->GetMeshTM( pWeight[j].m_szBoneName );
if( pBone == NULL || pMeshTM == NULL ) continue;
int nVertexIndex = (int)pWeight[j].m_pVertexIndex[k]; //버텍스를 찾고
float fWeight = pWeight[j].m_pVertexWeight[k]; //가중치를 적용
// K3DVector OffSetVtx = pWeight[j].m_pOffsetVector[k]; //OffSet Vector;
assert(nVertexIndex <= static_cast<int>(dwVtxCount));
//Local 버텍스 임.
K3DVector *vtx = (K3DVector*)(&pTempBuf[nVertexIndex*dwVtxStride]);
K3DVector *Outvtx = &pOutVtx[nVertexIndex];
K3DVector baseVtx, vec;
baseVtx = K3DVector(0,0,0);
vec = K3DVector(0,0,0);
K3DMatrix smat;
K3DMatrixIdentity(smat);
K3DMatrixMultiply( smat, pMeshTM->mTM, *pBone->GetCacheTM() );
K3DVectorMultiply( vec, smat, *vtx );
K3DVectorScale( vec, vec, fWeight );
K3DVectorAdd( *Outvtx, *Outvtx, vec );
if( bFirst )
{
cube_min = K3DVector(Outvtx->x, Outvtx->y, Outvtx->z);
cube_max = K3DVector(Outvtx->x, Outvtx->y, Outvtx->z);
bFirst = false;
}
// make axis aligned cube
cube_min.x = _min(cube_min.x , Outvtx->x);
cube_min.y = _min(cube_min.y , Outvtx->y);
cube_min.z = _min(cube_min.z , Outvtx->z);
cube_max.x = _max(cube_max.x , Outvtx->x);
cube_max.y = _max(cube_max.y , Outvtx->y);
cube_max.z = _max(cube_max.z , Outvtx->z);
}
}
t_cube = K3DBoundRotCube( cube_min.x, cube_max.x, cube_min.y, cube_max.y, cube_min.z, cube_max.z );
t_cube.SetTransform(iden);
if( n==0 )
cube = t_cube;
else
cube.AddCube(t_cube);
}
delete [] pOutVtx;
key1->m_spVB->Unlock();
m_boundCube = cube;
}
}
void StringFormat( std::string & str, const char *fmt, ... )
{
char p[1024];
va_list ap;
va_start(ap, fmt);
_vsnprintf(p, 1024, fmt, ap);
va_end(ap);
str = p;
}
void GetTexInfo( K3DTexture* pTex, std::string& strInfo )
{
if( pTex )
{
StringFormat( strInfo, "|Fmt:%d Size:(%d %d) Mip:%d|", pTex->GetFormat(), pTex->GetWidth(), pTex->GetHeight(), pTex->GetMipsLevels() );
}
}
void *KMeshSeqObject::Perform( KID id, KArg& msg )
{
_CID( SETDEFORM_BONE );
_CID( GETMESH_ANIINFO );
_CID( GETMESH_NAME );
_CID( GETMESH_INFO );
_CID( CHANGE_MESH_TEXTURE );
_CID( GETMESH_TRI );
_CID( GETMESH_VERTEXBUFFERS );
_CID( GETMESH_INDEXBUFFERS );
_CID( GETMESH_POLYCOUNT );
_CID( GETMESH_TEXNAME );
_CID( SETRENDER_FLAG );
_CID( SETFORCERENDER_FLAG );
_CID( REQ_BOUNDBOX );
_CID( REQ_BOUNDBOXEX );
_CID( REQ_BOUNDSPHERE );
_CID( SET_LIGHT_MAP );
_CID( GET_SEQOBJECT );
_CID( SET_MORPHMESH );
_CID( GET_MORPHMESH );
_CID( SET_FIX_TEXTURE);
_CID( SET_COLORIZE );
_CID( SET_USE_TEXALPHA );
_CID( SET_UV_MODIFY );
_CID( SET_WINK_TEXTURE );
_CID( GET_MATRIX );
_CID( GET_PERFORMANCEINFO );
_CID( SET_BLENDMODE ); // sonador 4.1.2 아바타 머리카락 알바 버그 재수정(ALPHABLENDTWOPASS)
_CID( SET_MTETEX ); //gmpbigsun( 2012_11_30 ) : mte
if ( id == id_SETDEFORM_BONE )
{
KMsgSET_DEFORM *deform = static_cast<KMsgSET_DEFORM*>(&msg);
setBone( deform->nBoneCount, deform->pMatBoneList );
//같은 화일의 메쉬 그룹 안에 피직이 안 된 것이 존재 할 수 있음.
//Make Bound
if( m_spResMesh->GetWeightResCount() != m_spResMesh->GetResCount() )
{
_oprint( "Not MakeBoundCube : %s\n", deform->pBoneSeq->GetResourceName() );
return (void*)0;
}
if( !m_bIsMakeBoundCube )
{
_makeBoundCube( deform->pBoneSeq );
m_bIsMakeBoundCube = true;
}
return (void*)1;
}
else if ( id == id_GETMESH_ANIINFO )
{
KMsgGET_MESHANI_INFO * meshani_info = static_cast<KMsgGET_MESHANI_INFO*>(&msg);
if(m_spResMesh != NULL)
{
// if( _stricmp( meshani_info->strFindName.c_str(), m_spResMesh->GetName() ) == 0 )
{
if( meshani_info->nStart < m_spResMesh->GetInterval().GetStart() )
meshani_info->nStart = m_spResMesh->GetInterval().GetStart();
if( meshani_info->nEnd < m_spResMesh->GetInterval().GetEnd() )
meshani_info->nEnd = m_spResMesh->GetInterval().GetEnd();
}
}
}
else if ( id == id_GETMESH_NAME )
{
KMsgGET_MESHNAME *meshname = static_cast<KMsgGET_MESHNAME*>(&msg);
if(m_spResMesh != NULL)
{
for( int i(0); m_spResMesh->GetResCount()>i; i++ )
{
meshname->vNameList.push_back( m_spResMesh->GetName() );
}
}
}
else if( id == id_GETMESH_INFO )
{
KMsgGET_MESHINFO* meshinfo = static_cast<KMsgGET_MESHINFO*>(&msg);
if(m_spResMesh != NULL)
{
if( m_spResMesh->GetResCount() > 0 )
{
KMsgGET_MESHINFO::MESH_INFO mesh;
mesh.szMeshName = m_spResMesh->GetName();
if( m_pPrMesh )
{
for( int x = 0; x < m_nPrMeshCount; ++x )
{
// sonador #2.2.2.1 프랍 텍스쳐 바리에이션 문제 리포팅 처리
mesh.vTextureList.push_back( ( m_pPrMesh[x].GetDiffuseTexture() != NULL ? m_pPrMesh[x].GetDiffuseTexture()->GetName() : "" ) );
}
}
meshinfo->vMeshList.push_back( mesh );
}
}
}
else if( id == id_CHANGE_MESH_TEXTURE )
{
static NX3LoadPack pack;
pack.Init();
KMsgCHANGE_MESH_TEXTURE* mesh_info = static_cast<KMsgCHANGE_MESH_TEXTURE*>(&msg);
if(m_spResMesh == NULL ) return (void*)0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 아이템 텍스쳐 변경 관련
if (mesh_info->bForceChange)
{
if( ( m_nPrMeshCount < (int)mesh_info->vTextureList.size() ) || mesh_info->vTextureList.empty() )
{
//기본 텍스처로 돌려 놓은다
for( int x = 0; x < m_nPrMeshCount; ++x )
{
if( m_pPrMesh[x].GetDiffuseTexture() != NULL )
{
K3DResVertexAnimation* pVA = m_spResMesh->GetRes( x );
if( m_pPrMesh[x].GetDiffuseTexture() != pVA->GetTexturePack()->spTexture )
m_pPrMesh[x].SetTexture( pVA->GetTexturePack() );
}
}
// sonador 1.8.10 아바타 텍스쳐 그룹 적용(페이스 컷 포함)
m_bUseDefaultTexture = true;
return (void*)0;
}
m_bUseDefaultTexture = false;
for( int x = 0; x < m_nPrMeshCount; ++x )
{
m_pPrMesh[x].SetDiffuseTexture( KTextureManager::GetManager()->GetTexture( mesh_info->vTextureList[0], &pack ) );
// 얼굴 텍스처 설정.
// 망토 텍스처에 문제가 있을 수도... kappamind, 2009.12.16
K3DResVertexAnimation* pVA = m_spResMesh->GetRes( x );
pVA->GetTexturePack()->spTexture = KTextureManager::GetManager()->GetTexture( mesh_info->vTextureList[0], &pack );
}
return (void*)0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if( strcmp( m_spResMesh->GetName(), mesh_info->szMeshName ) != 0 ) return (void*)0;
if( ( m_nPrMeshCount < (int)mesh_info->vTextureList.size() ) || mesh_info->vTextureList.empty() )
{
//기본 텍스처로 돌려 놓은다
for( int x = 0; x < m_nPrMeshCount; ++x )
{
if( m_pPrMesh[x].GetDiffuseTexture() != NULL )
{
K3DResVertexAnimation* pVA = m_spResMesh->GetRes( x );
if( m_pPrMesh[x].GetDiffuseTexture() != pVA->GetTexturePack()->spTexture )
m_pPrMesh[x].SetTexture( pVA->GetTexturePack() );
}
}
// sonador 1.8.10 아바타 텍스쳐 그룹 적용(페이스 컷 포함)
m_bUseDefaultTexture = true;
return (void*)0;
}
std::string strTextureName;
std::string strFxTextureName;
std::vector< const char* >::iterator itTextureList = mesh_info->vTextureList.begin();
for( int x = 0; itTextureList != mesh_info->vTextureList.end(); ++itTextureList, ++x )
{
strTextureName = (*itTextureList);
if( strcmp( strTextureName.c_str(), "" ) != 0 )
{
if( m_pPrMesh[x].GetDiffuseTexture() != NULL )
m_pPrMesh[x].SetDiffuseTexture( KTextureManager::GetManager()->GetTexture( strTextureName.c_str(), &pack ) );
std::string::size_type pos = strTextureName.rfind( ".dds" );
if( pos != std::string::npos )
{
strTextureName.erase( pos, strTextureName.length()-pos );
if( m_pPrMesh[x].GetSpecularTexture() != NULL )
{
strFxTextureName = strTextureName;
strFxTextureName += "_spec.dds";
m_pPrMesh[x].SetSpecularTexture( KTextureManager::GetManager()->GetTexture( strFxTextureName.c_str(), &pack ) );
}
if( m_pPrMesh[x].GetBumpTexture() != NULL )
{
strFxTextureName = strTextureName;
strFxTextureName += "_bump.dds";
m_pPrMesh[x].SetBumpTexture( KTextureManager::GetManager()->GetTexture( strFxTextureName.c_str(), &pack ) );
}
}
}
else
{
if( m_pPrMesh[x].GetDiffuseTexture() != NULL )
{
K3DResVertexAnimation* pVA = m_spResMesh->GetRes( x );
m_pPrMesh[x].SetTexture( pVA->GetTexturePack() );
}
}
}
// sonador 1.8.10 아바타 텍스쳐 그룹 적용(페이스 컷 포함)
m_bUseDefaultTexture = false;
}
else if ( id == id_GETMESH_TRI )
{
KMsgGET_GETMESH_TRI *triangle = static_cast<KMsgGET_GETMESH_TRI*>(&msg);
if(m_spResMesh != NULL)
{
realizeTime();
for(int i = 0; i < m_spResMesh->GetResCount(); i++)
{
K3DResVertexAnimation *rmesh = m_spResMesh->GetRes(i);
K3DResVertexAnimation::Key *key1, *key2;
rmesh->GetData(0, key1, key2);
if( rmesh != NULL )
{
K3DMatrix mat;
K3DMatrixIdentity( mat );
K3DMatrixMultiply( mat, m_matLocal, triangle->mat );
if( rmesh->GetIndexArray() )
{
for(int t = 0; t < (int)rmesh->GetIndexArray()->GetCnt(); ++t)
{
K3DVector pos;
K3DVectorTransform(pos, key1->m_spVB_array->GetArray()[rmesh->GetIndexArray()->GetArray()[t]], mat);
triangle->pListTriangles->push_back(pos);
}
}
}
}
}
}
else if ( id == id_GETMESH_VERTEXBUFFERS )
{
KMsgGET_MESHVERTEXBUFFERS* msgGMVB = static_cast<KMsgGET_MESHVERTEXBUFFERS*>(&msg);
if(m_spResMesh != NULL)
{
MESHVERTEXBUFFERSTRUCT* pVbStruct = new MESHVERTEXBUFFERSTRUCT;
int size = m_spResMesh->GetResCount();
pVbStruct->nVBCount = size;
pVbStruct->pVBs = (K3DVertexBuffer**) new K3DVertexBufferDX*[size];
for(int i = 0; i < size; i++)
{
K3DResVertexAnimation::Key *key1, *key2;
m_spResMesh->GetRes(i)->GetData(0, key1, key2);
pVbStruct->pVBs[i] = key1->m_spVB;
}
pVbStruct->matLocal = m_matLocal;
msgGMVB->vVbStruct.push_back(pVbStruct);
}
}
else if ( id == id_GETMESH_INDEXBUFFERS )
{
KMsgGET_MESHINDEXBUFFERS* msgGMIB = static_cast<KMsgGET_MESHINDEXBUFFERS*>(&msg);
if(m_spResMesh != NULL)
{
MESHINDEXBUFFERSTRUCT* pIbStruct = new MESHINDEXBUFFERSTRUCT;
int size = m_spResMesh->GetResCount();
pIbStruct->nIBCount = size;
pIbStruct->pIBs = (K3DIndexBuffer**) new K3DIndexBufferDX*[size];
for(int i = 0; i < size; i++)
{
pIbStruct->pIBs[i] = m_spResMesh->GetRes(i)->GetIndexBuffer();
}
msgGMIB->vIbStruct.push_back(pIbStruct);
}
}
else if ( id == id_GETMESH_POLYCOUNT )
{
KMsgGET_MESHPOLYCOUNT *polycount = static_cast<KMsgGET_MESHPOLYCOUNT*>(&msg);
if(m_spResMesh != NULL)
{
for(int i = 0; i < m_spResMesh->GetResCount(); i++)
{
polycount->nPolyCount += m_spResMesh->GetRes(i)->GetIndexBuffer()->GetIndexCount() / 3;
}
}
}
else if ( id == id_GETMESH_TEXNAME )
{
KMsgGET_MESHTEXNAME* texname = static_cast<KMsgGET_MESHTEXNAME*>(&msg);
if(m_spResMesh != NULL)
{
for(int i = 0; i < m_spResMesh->GetResCount(); i++)
{
TEXPACK* pTexpack = m_spResMesh->GetRes(i)->GetTexturePack();
if( pTexpack->spTexture != NULL)
{
if( ExistCheckVector( texname->vNameList, pTexpack->spTexture ) == false )
{
texname->vNameList.push_back(pTexpack->spTexture->GetName());
}
}
if(pTexpack->spTexture_Bump != NULL)
{
if( ExistCheckVector( texname->vNameList, pTexpack->spTexture_Bump ) == false )
{
texname->vNameList.push_back(pTexpack->spTexture_Bump->GetName());
}
}
if(pTexpack->spTexture_Illumin != NULL)
{
if( ExistCheckVector( texname->vNameList, pTexpack->spTexture_Illumin ) == false )
{
texname->vNameList.push_back(pTexpack->spTexture_Illumin->GetName());
}
}
if(pTexpack->spTexture_Specular != NULL)
{
if( ExistCheckVector( texname->vNameList, pTexpack->spTexture_Specular ) == false )
{
texname->vNameList.push_back(pTexpack->spTexture_Specular->GetName());
}
}
if(pTexpack->spTexture_SpecularColor != NULL)
{
if( ExistCheckVector( texname->vNameList, pTexpack->spTexture_SpecularColor ) == false )
{
texname->vNameList.push_back(pTexpack->spTexture_SpecularColor->GetName());
}
}
}
}
}
else if ( id == id_SETRENDER_FLAG )
{
KMsgSET_RENDERFLAG * renderflagmsg = static_cast<KMsgSET_RENDERFLAG*>(&msg);
if(m_spResMesh != NULL)
{
if( renderflagmsg->pName == NULL )
{
m_bRenderFlag = renderflagmsg->bRenderFlag;
}
else
{
for( int i(0); m_spResMesh->GetResCount()>i; i++ )
{
if( strstr( m_spResMesh->GetName(), renderflagmsg->pName ) != NULL )
{
m_bRenderFlag = renderflagmsg->bRenderFlag;
}
}
}
}
}
else if ( id == id_SETFORCERENDER_FLAG )
{
if(m_spResMesh != NULL)
{
m_bRenderFlag = FALSE;
}
}
else if ( id == id_REQ_BOUNDBOX )
{
realizeTransform();
KMsgREQ_BOUNDBOX *boundReq = static_cast<KMsgREQ_BOUNDBOX*>(&msg);
boundReq->AddBound( GetCube() );
return (void*)1;
}
else if ( id == id_REQ_BOUNDBOXEX )
{
realizeTransform();
KMsgREQ_BOUNDBOXEX * boundReqEx = static_cast<KMsgREQ_BOUNDBOXEX*>(&msg);
if( strcmp( boundReqEx->pSearchName, m_spResMesh->GetName() ) == 0 )
{
boundReqEx->AddBound( GetCube() );
return (void*)1;
}
}
else if ( id == id_REQ_BOUNDSPHERE )
{
realizeTransform();
KMsgREQ_BOUNDSPHERE *boundReq = static_cast<KMsgREQ_BOUNDSPHERE*>(&msg);
boundReq->AddBound( GetSphere() );
return (void*)1;
}
else if ( id == id_SET_LIGHT_MAP )
{
KMsgSET_LIGHTMAP *pLightMapSet = static_cast<KMsgSET_LIGHTMAP*>(&msg);
int count = m_spResMesh->GetResCount();
for(int i = 0; i < count; ++i)
{
K3DResVertexAnimation* pRes = m_spResMesh->GetRes(i);
if(strlen(pLightMapSet->GetPrefixTexName() ) == 0)
{
m_pPrMesh[i].SetLightMapTexture(NULL);
}
else
{
DWORD idx = pRes->GetLightMapIndex();
static char name[_MAX_PATH];
_snprintf_s(name, _MAX_PATH, "%s_Light_%d_%d_%d.tga", pLightMapSet->GetPrefixTexName(),idx, pLightMapSet->GetSegmentIdx(),
pLightMapSet->GetPropIdx());
static NX3LoadPack pack; // 어이없는 인-_-자 이지만 lod 지원을 위해서 어쩔수 없이 넣어주는 센스
if( KTextureManager::GetManager()->IsExistTexture( name, &pack ) )
{
m_pPrMesh[i].SetLightMapTexture(KTextureManager::GetManager()->GetTexture( name, &pack ) );
}
}
}
}
else if ( id == id_GET_SEQOBJECT )
{
KMsgGET_SEQOBJECT * getSeqMsg = static_cast<KMsgGET_SEQOBJECT*>(&msg);
if(m_spResMesh != NULL)
{
for( int i(0); m_spResMesh->GetResCount()>i; i++ )
{
if( strstr( m_spResMesh->GetName(), getSeqMsg->pName ) != NULL )
{
getSeqMsg->pSeqObject = this;
break;
}
}
}
}
else if( id == id_GET_MORPHMESH )
{
KMsgGET_MORPHMESH * getMorph = static_cast<KMsgGET_MORPHMESH*>(&msg);
getMorph->bIsValid = true;
getMorph->numFrames = numFrames;
getMorph->loopWindowSize = loopWindowSize;
getMorph->markFrame = markFrame;
getMorph->animationDelay = animationDelay;
getMorph->startColor0 = startColor0;
getMorph->startColor1 = startColor1;
getMorph->markColor0 = markColor0;
getMorph->markColor1 = markColor1;
getMorph->endColor0 = endColor0;
getMorph->endColor1 = endColor1;
getMorph->startSizeOffset = startSizeOffset;
getMorph->markSizeOffset = markSizeOffset;
getMorph->endSizeOffset = endSizeOffset;
getMorph->strTexture = strFxTexture;
}
else if( id == id_SET_MORPHMESH )
{
KMsgSET_MORPHMESH * setMorph = static_cast<KMsgSET_MORPHMESH*>(&msg);
if( setMorph->bShow == false )
{
_morphInit();
return NULL;
}
if( setMorph->nSetFlag == 0 )
{
_morphInit();
_morphDefaultSet(); //Test
}
else
{
_morphClear();
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_FRAME ) numFrames = setMorph->numFrames;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_LOOP ) loopWindowSize = setMorph->loopWindowSize;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_DELAY ) animationDelay = setMorph->animationDelay;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_MARK ) markFrame = setMorph->markFrame;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_ADDITIVE ) additive = setMorph->additive;
//기본 값 설정
if( numFrames <= 0 ) numFrames = 32;
if( loopWindowSize <= 0 ) loopWindowSize = 6;
if( animationDelay <= 0 ) animationDelay = 100;
if( markFrame <= 0 ) markFrame = 8;
markFrame = setMorph->markFrame;
if( markFrame > numFrames )
{
assert( 0 && "markFrame Invalid" );
markFrame = numFrames;
}
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_SC0 ) startColor0 = setMorph->startColor0;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_SC1 ) startColor1 = setMorph->startColor1;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_MC0 ) markColor0 = setMorph->markColor0;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_MC1 ) markColor1 = setMorph->markColor1;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_EC0 ) endColor0 = setMorph->endColor0;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_EC1 ) endColor1 = setMorph->endColor1;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_SSIZE ) startSizeOffset = setMorph->startSizeOffset;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_MSIZE ) markSizeOffset = setMorph->markSizeOffset;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_ESIZE ) endSizeOffset = setMorph->endSizeOffset;
if( setMorph->nSetFlag & KMsgSET_MORPHMESH::FLAG_TEXTURE) strFxTexture = setMorph->strTexture;
}
_morphMeshMake();
}
else if( id == id_SET_FIX_TEXTURE )
{
if( stricmp( m_spResMesh->GetName(), "grid" ) == 0 )
return NULL;
KMsgSET_FIXTEXTURE * setFixTexture = static_cast<KMsgSET_FIXTEXTURE*>(&msg);
m_bForceTransparent = setFixTexture->bForceTransparent;
int count = m_spResMesh->GetResCount();
if( count > 0 )
{
if( setFixTexture->bUseFix )
{
for(int i = 0; i < count; ++i)
{
m_pPrMesh[i].SetFixMapTexture( setFixTexture->pTexture );
}
}
else
{
for(int i = 0; i < count; ++i)
{
m_pPrMesh[i].SetFixMapTexture(NULL);
}
}
}
}
//눈 깜박임 제거
//2009-04-14 : hunee
/*else if( id == id_SET_WINK_TEXTURE )
{
KMsgSET_WINKTEXTURE* setWinkTexture = static_cast<KMsgSET_WINKTEXTURE*>(&msg);
m_bUseWink = setWinkTexture->bUseWink;
m_spWinkTexture = setWinkTexture->pTexture;
checkTime = setWinkTexture->nWinkTime;
m_bFlipWink = false;
}*/
else if( id == id_SET_COLORIZE )
{
KMsgSET_COLORIZE* setColorize = static_cast<KMsgSET_COLORIZE*>(&msg);
_oprint("[id_SET_COLORIZE] setColorize->color[0]: %u, setColorize->color[1]: %u, setColorize->color[2]: %u, setColorize->color[3]: %u\n", setColorize->color[0], setColorize->color[1], setColorize->color[2], setColorize->color[3]);
SetColor( setColorize->color[0], setColorize->color[1], setColorize->color[2], setColorize->color[3], setColorize->nMode );
}
else if( id == id_SET_USE_TEXALPHA )
{
KMsgSET_USE_TEXALPHA* setUseAlpha = static_cast<KMsgSET_USE_TEXALPHA*>(&msg);
m_bUseTextureAlpha = setUseAlpha->bIsUseTexAlpha;
}
else if( id == id_SET_UV_MODIFY )
{ //
if( stricmp( m_spResMesh->GetName(), "grid" ) == 0 )
return NULL;
KMsgSET_UV_MODIFY* setUVModify = static_cast<KMsgSET_UV_MODIFY*>(&msg);
int nHalfWidth = setUVModify->nW/2;
int nHalfHeight = setUVModify->nH/2;
int nTargetHalfWidth = setUVModify->nTargetW/2;
int nTargetHalfHeight = setUVModify->nTargetH/2;
float uv[4][2];
uv[0][0] = (float)((nHalfWidth -nTargetHalfWidth )+0.5f)/setUVModify->nW;
uv[0][1] = (float)((nHalfHeight-nTargetHalfHeight)+0.5f)/setUVModify->nH;
uv[1][0] = (float)((nHalfWidth -nTargetHalfWidth )+0.5f)/setUVModify->nW;
uv[1][1] = (float)((nHalfHeight+nTargetHalfHeight)-0.5f)/setUVModify->nH;
uv[2][0] = (float)((nHalfWidth +nTargetHalfWidth )-0.5f)/setUVModify->nW;
uv[2][1] = (float)((nHalfHeight+nTargetHalfHeight)-0.5f)/setUVModify->nH;
uv[3][0] = (float)((nHalfWidth +nTargetHalfWidth )-0.5f)/setUVModify->nW;
uv[3][1] = (float)((nHalfHeight-nTargetHalfHeight)+0.5f)/setUVModify->nH;
int count = m_spResMesh->GetResCount();
for ( int n=0 ; n<count; ++n )
{
K3DResVertexAnimation *va = m_spResMesh->GetRes(n);
K3DResVertexAnimation::Key *key1 = NULL;
int nKeyCount = va->GetKeyCount();
for( int i(0); nKeyCount>i; i++ )
{
K3DResVertexAnimation::Key& key = va->GetKey( i );
if( !key.m_spVB->IsValidVtx() ) continue;
DWORD dwVtxCount = key.m_spVB->GetVertexCount();
DWORD dwVtxFormat = key.m_spVB->GetVertexFormat();
DWORD dwVtxStride = key.m_spVB->GetVertexStride();
if( dwVtxCount != 4 ) continue;
// K3DFVF_XYZ | K3DFVF_NORMAL 은 항상 존재
K3DBLENDEDBUMPVERTEX * pTempBuf = NULL;
int size = dwVtxCount; //Size 사용 안함.
key.m_spVB->Lock( (void**)&pTempBuf, size );
if( pTempBuf == NULL ) continue;
for( int n=0; 4>n; n++ )
{
pTempBuf[n].texcoord.x = uv[0][0];
pTempBuf[n].texcoord.y = uv[0][1];
n++;
pTempBuf[n].texcoord.x = uv[1][0];
pTempBuf[n].texcoord.y = uv[1][1];
n++;
pTempBuf[n].texcoord.x = uv[2][0];
pTempBuf[n].texcoord.y = uv[2][1];
n++;
pTempBuf[n].texcoord.x = uv[3][0];
pTempBuf[n].texcoord.y = uv[3][1];
n++;
}
key.m_spVB->Unlock();
}
}
}
else if( id == id_GET_MATRIX )
{
KMsgGET_MATRIX* getMatrix = static_cast<KMsgGET_MATRIX*>(&msg);
CalcMatrix();
getMatrix->matLocal = &m_matLocal;
getMatrix->matRoot = &m_matRoot;
getMatrix->bSuc = true;
}
else if( id == id_GET_PERFORMANCEINFO )
{
KMsgGET_PERFORMANCEINFO* getPerformanceinfo = static_cast<KMsgGET_PERFORMANCEINFO*>(&msg);
getPerformanceinfo->nSeqCount++;
getPerformanceinfo->nMeshCount++;
for ( int i=0 ; i<m_spResMesh->GetResCount() ; ++i )
{
K3DResVertexAnimation* va = m_spResMesh->GetRes(i);
TEXPACK* pTexPack = va->GetTexturePack();
std::string strInfo;
GetTexInfo( pTexPack->spTexture , strInfo );
GetTexInfo( pTexPack->spTexture_Bump , strInfo );
GetTexInfo( pTexPack->spTexture_Illumin , strInfo );
GetTexInfo( pTexPack->spTexture_Specular , strInfo );
GetTexInfo( pTexPack->spTexture_SpecularColor, strInfo );
GetTexInfo( pTexPack->spTexture_Light , strInfo );
GetTexInfo( pTexPack->spTexture_Fix , strInfo );
if( strInfo.length() > 0 )
getPerformanceinfo->vTexList.push_back( strInfo );
for( int j(0); va->GetKeyCount()>j; j++ )
{
std::string strVertexInfo;
K3DResVertexAnimation::Key& key = va->GetKey( j );
StringFormat( strVertexInfo, "|Fmt:%d Stride:%d Cnt:%d|", key.m_spVB->GetVertexFormat(), key.m_spVB->GetVertexStride(), key.m_spVB->GetVertexCount() );
if( strVertexInfo.length() > 0 )
getPerformanceinfo->vVertexList.push_back( strVertexInfo );
}
}
}
// sonador 4.1.2 아바타 머리카락 알바 버그 재수정(ALPHABLENDTWOPASS)
else if( id == id_SET_BLENDMODE )
{
KMsgSET_BLENDMODE* commandSetBlendMode = static_cast< KMsgSET_BLENDMODE* >( &msg );
m_pPrMesh->SetBlendMode( commandSetBlendMode->blendMode );
}
else if( id == id_SET_MTETEX )
{
KMsgSET_MTETEX* setMteTex = static_cast< KMsgSET_MTETEX* >( &msg );
SetMTETexture( setMteTex->pTexture );
}
return NULL;
}
void KMeshSeqObject::setBone( int nCount, K3DMatrix *pMatList )
{
m_nBoneMatCount = nCount;
m_pBoneMatList = pMatList;
K3DMatrix * pOffSetMat = m_spResMesh->GetMeshTMArray();
for(int i = 0; i < m_nPrMeshCount; ++i)
{
m_pPrMesh[i].SetBlendedInfo( m_nBoneMatCount, pOffSetMat, m_pBoneMatList );
}
bool bMorphRender = !morph_primitivelist.empty();
if( bMorphRender && m_nMorphPrimitiveCount == m_spResMesh->GetResCount() )
{
for(int i = 0; i < m_nPrMeshCount; ++i)
{
for (int n=0; n < numFrames; n++) {
morph_primitivelist[i][n].SetBlendedInfo( m_nBoneMatCount, pOffSetMat, m_pBoneMatList );
}
}
}
}
void KMeshSeqObject::SetMatrixRes( K3DResMeshMatrixAnimation *pResMatrix )
{
assert( m_spResMatrix == NULL );
m_spResMatrix = pResMatrix;
if(m_spResMatrix != NULL)
{
m_interval.Expand( m_spResMatrix->GetInterval() );
}
}
void KMeshSeqObject::SetVisibilityRes( K3DResMeshVisibilityAnimation *pResVis )
{
assert( m_spResVis == NULL);
m_spResVis = pResVis;
if(m_spResVis != NULL)
{
m_interval.Expand( m_spResVis->GetInterval() );
}
}
void KMeshSeqObject::SetUVAniRes( K3DResMeshUVAnimation *pResUV )
{
assert( m_spResUV == NULL);
m_spResUV = pResUV;
if( m_spResUV != NULL )
{
int nUvMode = m_spResUV->GetMode();
if( m_spResMesh != NULL )
{
for( int i = 0; i < m_nPrMeshCount; i++ )
{
int nBlendMode = m_pPrMesh[ i ].GetBlendMode();
if( nBlendMode == K3DMaterial::MBM_ALPHABLEND || nBlendMode == K3DMaterial::MBM_ADDITIVE )
nBlendMode += nUvMode;
m_pPrMesh[ i ].SetBlendMode( nBlendMode );
}
}
m_interval.Expand( m_spResUV->GetInterval() );
}
}
void KMeshSeqObject::SetAlterMaterial( K3DMaterial* pMtl)
{
m_pAlterMtl = pMtl;
if(NULL == m_spResMesh)
return;
for(int i = 0; i < m_nPrMeshCount; ++i)
{
if(m_pAlterMtl != NULL)
m_pPrMesh[i].SetMaterial(m_pAlterMtl);
else
m_pPrMesh[i].SetMaterial(m_spResMesh->GetRes(i)->GetMaterial() );
}
}
void KMeshSeqObject::updateColors()
{
// TODO: Add resource option loading (in progress)
NX3LoadPack loadpack;
loadpack.Init();
for ( int i = 0 ; i < m_spResMesh->GetResCount() ; ++i )
{
K3DResVertexAnimation *va = m_spResMesh->GetRes(i);
K3DTexture *oldtex = va->GetTexturePack()->spTexture;
if( oldtex )
{
K3DTexture* curtex = m_pPrMesh[i].GetDiffuseTexture();
// 2010.06.18 Without filename checking, colorizing may use a previously loaded (different) texture prodongi
if (strcmp(oldtex->GetName(), curtex->GetName()) != 0)
oldtex = curtex;
if( m_nColorizedMode == K3DTexture::COLORIZED_DEF || m_nColorizedMode == K3DTexture::COLORIZED_KEEP_ALPHA
|| m_nColorizedMode == K3DTexture::COLORIZED_GRAY )
{
K3DTexture *newtex = KTextureManager::GetManager()->GetTexture( oldtex, &loadpack,
m_dwColors[0], m_dwColors[1], m_dwColors[2], m_dwColors[3], 0, m_nColorizedMode );
if(oldtex != newtex)
{
K3DTexture* diffTex = m_pPrMesh[i].GetDiffuseTexture();
TEXPACK texpack = *va->GetTexturePack();
texpack.spTexture = newtex; //SmartPoint 에서 oldtex는 Release 된다.
va->SetTexturePack( &texpack );
m_pPrMesh[i].SetTexture( va->GetTexturePack() );
}
}
else if( m_nColorizedMode == K3DTexture::COLORIZED_USEALPHA )
{
if( strstr( oldtex->GetName(), "_color" ) )
{
K3DTexture *newtex = KTextureManager::GetManager()->GetTexture( oldtex, &loadpack,
m_dwColors[0], m_dwColors[1], m_dwColors[2], m_dwColors[3], 0, m_nColorizedMode );
if(oldtex != newtex)
{
TEXPACK texpack = *va->GetTexturePack();
texpack.spTexture = newtex; //SmartPoint 에서 oldtex는 Release 된다.
va->SetTexturePack( &texpack );
m_pPrMesh[i].SetTexture( va->GetTexturePack() );
}
}
}
}
}
}
void KMeshSeqObject::SetColor( DWORD c1, DWORD c2 /* = 0 */, DWORD c3 /* = 0 */, DWORD c4 /* = 0 */, short nMode /*= 0*/ )
{
if ( m_dwColors[0] != c1 || m_dwColors[1] != c2 || m_dwColors[2] != c3 || m_dwColors[3] != c4 || m_nColorizedMode != nMode )
{
m_nColorizedMode = nMode;
m_dwColors[0] = c1;
m_dwColors[1] = c2;
m_dwColors[2] = c3;
m_dwColors[3] = c4;
_oprint("[KMeshSeqObject::SetColor] (after id_SET_COLORIZE): m_dwColors[0]: %u, m_dwColors[1]: %u, m_dwColors[2]: %u, m_dwColors[3]: %u\n", m_dwColors[0], m_dwColors[1], m_dwColors[2], m_dwColors[3]);
updateColors();
}
}
void KMeshSeqObject::realizeTransform()
{
realizeTime();
if ( m_pMatAttach != NULL && m_pMatParent != NULL )
{
K3DMatrix matTemp;
K3DMatrixMultiply( matTemp, *m_pMatAttach, *m_pMatParent );
K3DMatrixMultiply( m_matResult, m_matLocal, matTemp );
}
else if ( m_pMatParent != NULL )
K3DMatrixMultiply( m_matResult, m_matLocal, *m_pMatParent );
else
m_matResult = m_matLocal;
}
void KMeshSeqObject::ClipTest( const K3DVector* pFrustum)
{
realizeTransform();
m_boundCube.SetTransform( m_matResult );
//m_bIsClip = pFrustrum->ISContainCube(m_boundCube) == K3DFrustum::FRUSTUM_OUT;
m_bIsClip = KPCCP::nonuniformcube_collide_nonuniformcube(pFrustum, m_boundCube.GetVertices()) == false;
//m_boundSphere.SetTransform( m_matResult );
//m_bIsClip = pFrustrum->IsContaineSphere(m_boundSphere) == K3DFrustum::FRUSTUM_OUT;
}
void KMeshSeqObject::CalcMatrix()
{
if(m_pMatParent != NULL)
{
if(m_pMatAttach != NULL)
{
//m_matRoot = *m_pMatParent;
K3DMatrix matTemp;
if( m_bRotationLock )
{
//위치만 얻는다.
//K3DMatrixIdentity( m_matLocal );
//m_matLocal._41 = m_pMatAttach->_41;
//m_matLocal._42 = m_pMatAttach->_42;
//m_matLocal._43 = m_pMatAttach->_43;
K3DMatrixIdentity( matTemp );
matTemp._41 = m_pMatAttach->_41;
matTemp._42 = m_pMatAttach->_42;
matTemp._43 = m_pMatAttach->_43;
}
else
{
//m_matLocal = *m_pMatAttach;
matTemp = *m_pMatAttach;
}
K3DMatrixMultiply( m_matRoot, matTemp, *m_pMatParent );
}
else
{
if( m_bRotationLock )
{
K3DMatrixIdentity( m_matRoot );
m_matRoot._41 = m_pMatParent->_41;
m_matRoot._42 = m_pMatParent->_42;
m_matRoot._43 = m_pMatParent->_43;
}
else
{
m_matRoot = *m_pMatParent;
}
}
//K3DMatrixMultiply( m_matResult, m_matLocal, *m_pMatParent );
K3DMatrixMultiply( m_matResult, m_matLocal, m_matRoot );
}
else
{
K3DMatrixIdentity( m_matRoot );
m_matResult = m_matLocal;
}
}
void KMeshSeqObject::SetMTETexture( K3DTexture* pTex )
{
for( int i = 0; i < m_nPrMeshCount; ++i )
{
m_pPrMesh[i].SetMTETexture( pTex );
}
}
void KMeshSeqObject::Render( KViewportObject *viewport, DWORD flag, const K3DMatrix * pAttachMat )
{
realizeTime();
float vis = m_fVisResult * m_fMasterVisibility;
if ( vis > .9f )
m_bIsTransparent = false;
else
m_bIsTransparent = true;
//강제 알파 설정
if( m_bForceTransparent )
m_bIsTransparent = true;
if( vis <= 0.f )
return; //투명한 놈이므로 안 그림
CalcMatrix();
if( m_bRenderFlag == false ) return; //Render 하지 않는다.
#ifdef _RAC
if( /*m_pBoneMatList == NULL ||*/ m_spResMesh->GetWeightResCount() == 0 )
#else
if( m_pBoneMatList == NULL || m_spResMesh->GetWeightResCount() == 0 )
#endif
{
_defSetTransform( flag );
int i=0 ;
for ( int i=0 ; i<m_spResMesh->GetResCount() ; ++i )
{
K3DResVertexAnimation *va = m_spResMesh->GetRes(i);
if( _defRender( i, va, flag, vis ) )
{
if( m_sVisbleCube )
{
m_boundCube.Render( viewport );
viewport->RegisterWire( &m_prCenterWire );
}
// m_boundOcclusion.SetVertices( m_boundCube.GetOriginVertices() );
viewport->Register( &m_pPrMesh[i], flag );
}
}
bool bMorphRender = !morph_primitivelist.empty();
if( bMorphRender && m_nMorphPrimitiveCount == m_spResMesh->GetResCount() )
{
for ( int i=0 ; i<m_spResMesh->GetResCount() ; ++i )
{
for (int n=currentFrame; n < numFrames; n+=loopWindowSize) {
viewport->Register( &morph_primitivelist[i][n], 0 );
}
}
}
}
else //BoneSeq으로 스킨
{
if( m_spResMesh->GetWeightResCount() != m_spResMesh->GetResCount() )
{
//주의 : 매쉬 덩어리와, 가중치 덩어리는 항상 같아야 한다.
_oprint( "If the bone and flesh are not the same, it's a big problem~ Weight: %d, Res: %d \n", m_spResMesh->GetWeightResCount(), m_spResMesh->GetResCount() );
return;
}
//VS HW
// assert( m_pBoneSeq->GetBoneCount() == m_spResMesh->GetMeshTMCount() && "뼈와 살이 같지 않다~" );
_defSetTransform( flag );
//Shader Const
for ( int i=0 ; i<m_spResMesh->GetResCount(); ++i )
{
K3DResVertexAnimation *va = m_spResMesh->GetRes(i);
if( _defRender( i, va, flag, vis ) )
{
if( m_sVisbleCube )
{
m_boundCube.Render( viewport );
viewport->RegisterWire( &m_prCenterWire );
}
// m_boundOcclusion.SetVertices( m_boundCube.GetOriginVertices() );
viewport->Register( &m_pPrMesh[i], flag );
}
}
bool bMorphRender = !morph_primitivelist.empty();
if( bMorphRender && m_nMorphPrimitiveCount == m_spResMesh->GetResCount() )
{
for ( int i=0 ; i<m_spResMesh->GetResCount(); ++i )
{
for (int n=currentFrame; n < numFrames; n+=loopWindowSize) {
viewport->Register( &morph_primitivelist[i][n], 0 );
}
}
}
}
}
void KMeshSeqObject::_defSetTransform( DWORD flag )
{
for(int i = 0; i < m_nPrMeshCount; ++i)
{
m_pPrMesh[i].SetTransform( &m_matLocal, &m_matRoot );
m_pPrMesh[i].SetUVTransform( &m_matUV );
m_pPrMesh[i].SetRenderState( m_nRenderState );
}
bool bMorphRender = !morph_primitivelist.empty();
if( bMorphRender && m_nMorphPrimitiveCount == m_spResMesh->GetResCount() )
{
for(int i = 0; i < m_nPrMeshCount; ++i)
{
for (int n=currentFrame; n < numFrames; n+=loopWindowSize) {
morph_primitivelist[i][n].SetTransform(&m_matLocal, &m_matRoot);
}
}
}
}
//공통 랜더 설정
bool KMeshSeqObject::_defRender( int i, K3DResVertexAnimation *va, DWORD flag, float vis )
{
// Vertex Animation이 사용되지 않는다면 밑의 코드도 불필요!!
////////////////////////////////////////////////////////////////////////////
K3DResVertexAnimation::Key *key1 = NULL, *key2 = NULL;
va->GetData( m_dwTime, key1, key2 );
m_pPrMesh[i].SetVertexBuffer( key1->m_spVB );
////////////////////////////////////////////////////////////////////////////
m_pPrMesh[i].SetVisibility( vis );
m_pPrMesh[i].SetDiffuseAlpha( vis > .9f ? false : true ); //스페큘러 때문에 DiffuseAlpha 감지가 필요함.
if( m_bUseTextureAlpha )
m_pPrMesh[i].SetTransparent( m_bIsTransparent || va->IsTransparent() );
else
m_pPrMesh[i].SetTransparent( m_bIsTransparent );
m_pPrMesh[i].SetSkinDiffuse( m_SkinDiffuse );
m_boundCube.SetTransform( m_matResult );
const K3DVector *cube = m_boundCube.GetVertices();
K3DVector vCenterPos = K3DVector(0.f, 0.f, 0.f);
K3DVector pos = K3DVector(0.f, 0.f, 0.f);
if( m_pMatParent && m_pMatAttach )
{
K3DMatrix matResult;
K3DMatrixMultiply( matResult, *m_pMatAttach, *m_pMatParent );
pos = K3DVector(0.f, 0.f, 0.f);
K3DMatrixGetPosVector( pos, matResult );
vCenterPos = cube[0] + (0.5f*(cube[7] - cube[0]));
m_pPrMesh[i].SetCenterPosition( vCenterPos );
}
else if( m_pMatParent )
{
pos = K3DVector(0.f, 0.f, 0.f);
K3DMatrixGetPosVector( pos, *m_pMatParent );
vCenterPos = cube[0] + (0.5f*(cube[7] - cube[0]));
m_pPrMesh[i].SetCenterPosition( vCenterPos );
}
else
{
vCenterPos = 0.5f*(cube[7] - cube[0]);
m_pPrMesh[i].SetCenterPosition( vCenterPos );
}
bool bMorphRender = !morph_primitivelist.empty();
if( bMorphRender && m_nMorphPrimitiveCount == m_spResMesh->GetResCount() )
{
K3DVector vmin, vmax;
vmax = cube[7];
vmin = cube[0];
for (int n=currentFrame; n < numFrames; n+=loopWindowSize) {
vCenterPos = vmin + (0.5f*(vmax - vmin));
morph_primitivelist[i][n].SetCenterPosition( vCenterPos );
vmax += ((i * 1.f)+0.2f);
vmin -= ((i * 1.f)+0.2f);
}
}
if( m_sVisbleCube )
{
m_prCenterWire.Clear();
K3DVector vVectorX, vVectorY, vVectorZ;
vVectorX = vCenterPos;
vVectorY = vCenterPos;
vVectorZ = vCenterPos;
vVectorX.x += 3.f;
vVectorY.y += 3.f;
vVectorZ.z += 3.f;
//CenterPos
m_prCenterWire.AddLine( vCenterPos, vVectorX, KColor(255,0,0,255) );
m_prCenterWire.AddLine( vCenterPos, vVectorY, KColor(0,255,0,255) );
m_prCenterWire.AddLine( vCenterPos, vVectorZ, KColor(0,0,255,255) );
vVectorX = pos;
vVectorY = pos;
vVectorZ = pos;
vVectorX.x += 3.f;
vVectorY.y += 3.f;
vVectorZ.z += 3.f;
//Ori Pos
m_prCenterWire.AddLine( pos, vVectorX, KColor(255,0,0,255) );
m_prCenterWire.AddLine( pos, vVectorY, KColor(255,0,0,255) );
m_prCenterWire.AddLine( pos, vVectorZ, KColor(255,0,0,255) );
}
return (key1->m_spVB && key1->m_spVB->IsValidVtx() && !key1->m_spVB->IsLock() );
}
KSeqObject* KMeshSeqObject::Clone()
{
KMeshSeqObject *obj = new KMeshSeqObject;
obj->SetMeshRes( m_spResMesh );
obj->SetMatrixRes( m_spResMatrix );
obj->SetVisibilityRes( m_spResVis );
obj->SetUVAniRes( m_spResUV );
// sonador 1.8.10 아바타 텍스쳐 그룹 적용(페이스 컷 포함)
if( !m_bUseDefaultTexture )
{
for( int n( 0 ); n < obj->m_nPrMeshCount; ++n )
obj->m_pPrMesh[ n ].SetTexture( this->m_pPrMesh[ n ].GetTexPack() );
obj->m_bUseDefaultTexture = false;
}
return obj;
}
const short aIntWinkTime[] = { 27, 23, 15, 37, 19, 20, 43, 35, 49, 9 };
void KMeshSeqObject::realizeTime()
{
if ( m_dwRealizedTime == m_dwTime )
return;
// Ignore dwTime and use system-time instead
DWORD dwTime=GetSafeTickCount();
if (!morph_primitivelist.empty())
{
currentFrame = (dwTime / (animationDelay+1)) % loopWindowSize;
previousTime = dwTime;
if( checkTime == 0 )
checkTime = dwTime;
if( (dwTime - checkTime) > OLDMORPH_MESH_CHCKTIME )
{
_oldmorphClear();
checkTime = dwTime;
}
}
else
{ //위의 타임 변수를 공유 하기 때문에 위 기능과 동시에 안됨.(같이 되게 하려면, 변수 분리)
if( m_bUseWink )
{
if( previousTime == 0 )
previousTime = dwTime;
int count = m_spResMesh->GetResCount();
if( count > 0 )
{
if( m_bFlipWink )
{
if( (dwTime - previousTime) > KEEP_TIME_WINK )
{
for(int i = 0; i < count; ++i)
m_pPrMesh[i].SetDiffuseTexture( m_spBackUpDiffTexture );
m_bFlipWink = false;
previousTime = dwTime;
}
}
else
{
if( (dwTime - previousTime) > checkTime )
{
short nRandIndex = rand()%10;
short nValue = rand()%100;
if( aIntWinkTime[nRandIndex] > nValue )
{
for(int i = 0; i < count; ++i)
{
m_spBackUpDiffTexture = m_pPrMesh[i].GetDiffuseTexture();
m_pPrMesh[i].SetDiffuseTexture( m_spWinkTexture );
}
m_bFlipWink = true;
}
previousTime = dwTime;
}
}
}
}
}
m_dwRealizedTime = m_dwTime;
if( m_pBoneMatList == NULL || m_spResMesh->GetWeightResCount() == 0 )
{
//Effect 등 뼈없는 넘들이 사용 한다.
//나중에 Bone을 사용하는 Effect를 추가 하자~
if ( m_spResVis != NULL )
{
m_spResVis->GetVisibility(static_cast<int>(m_dwTime), &m_fVisResult);
}
if ( m_spResMatrix != NULL )
{
m_spResMatrix->GetLerpMatrix(static_cast<int>(m_dwTime), &m_matLocal);
}
if ( m_spResUV != NULL )
{
m_spResUV->GetLerpMatrix(static_cast<int>(m_dwTime), &m_matUV);
}
}
}
KMeshPrimitive* KMeshSeqObject::getMeshPrimitive(int nIndex)
{
if (nIndex<0 || nIndex>=m_nPrMeshCount) return NULL;
return &(m_pPrMesh[nIndex]);
}
void KMeshSeqObject::_morphMeshMake()
{
assert(morph_primitivelist.empty());
int i;
float f, h;
for( int j=0; m_nPrMeshCount>j; j++ )
{
K3DResVertexAnimation *va = m_spResMesh->GetRes(j);
K3DResVertexAnimation::Key *key1 = NULL, *key2 = NULL;
va->GetData( m_dwTime, key1, key2 );
if( key1 == NULL || !key1->m_spVB->IsValidVtx() )
continue;
m_pPrMesh[j].SetVertexBuffer( key1->m_spVB );
FxResizedPrimitive* primitiveArray = new FxResizedPrimitive[numFrames];
assert(primitiveArray!=NULL);
//const char * p_FX = strstr( m_spResMesh->GetName(), "_fx" );
//if( p_FX == NULL )
//{
// for (i=0; i<numFrames; i++)
// primitiveArray[i].SetEnable( false );
//}
//else
{
//// 0프레임에서 (markFrame-1)프레임까지 primitive생성
h=(float)markFrame;
for (i=0; i<markFrame; i++) {
f=((float)i)/h; // [0, markFrame-1] 구간에 대해
primitiveArray[i].init(&m_pPrMesh[j], startSizeOffset*(1.f-f) + markSizeOffset*f
, interpolateColor(startColor0, markColor0, f)
, interpolateColor(startColor1, markColor1, f)
, strFxTexture.c_str(), additive
);
}
//// markFrame부터 (numFrames-1)프레임까지 primitive생성
h=(float)(numFrames-markFrame);
for (i=markFrame; i<numFrames; i++) {
f=((float)(i-markFrame))/h; // [markFrame, numFrames-1] 구간에 대해
primitiveArray[i].init(&m_pPrMesh[j], markSizeOffset*(1.f-f) + endSizeOffset*f
, interpolateColor(markColor0, endColor0, f)
, interpolateColor(markColor1, endColor1, f)
);
}
}
morph_primitivelist.push_back( primitiveArray );
m_nMorphPrimitiveCount = (int)morph_primitivelist.size();
}
}
void KMeshSeqObject::_morphClear()
{
if( !morph_primitivelist.empty() )
{
for( unsigned int i(0); morph_primitivelist.size()>i; i++ )
{
clear_morph_primitivelist.push_back( morph_primitivelist[i] );
}
morph_primitivelist.clear();
}
}
void KMeshSeqObject::_oldmorphClear()
{
if( !clear_morph_primitivelist.empty() )
{
for( unsigned int i(0); clear_morph_primitivelist.size()>i; i++ )
{
delete [] clear_morph_primitivelist[i];
}
clear_morph_primitivelist.clear();
}
}
void KMeshSeqObject::_morphInit()
{
_morphClear();
numFrames =0;
loopWindowSize=0;
markFrame =0;
animationDelay=0;
startColor0=startColor1=0xffffffff;
markColor0=markColor1 =0x80808080;
endColor0=endColor1 =0x00000000;
startSizeOffset=0.f;
markSizeOffset =0.f;
endSizeOffset =0.f;
currentFrame=0;
previousTime=0xffffffff;
additive = 0;
//땜방 텍스쳐 임
strFxTexture="LensFlare_01.dds";
}
void KMeshSeqObject::_morphDefaultSet()
{
const DWORD color0_mark=0x40e00000;
const DWORD color1_mark=0x20400000;
const DWORD color0_end=0x00000000;
const DWORD color1_end=0x004040c0;
/* // Red to green
const DWORD color0_mark=0x40e04040;
const DWORD color1_mark=0x20804040;
const DWORD color0_end=0x00000000;
const DWORD color1_end=0x00408040;
*/
//
// Set default parameters
//
numFrames = 32; // 전체 애니메이션 프레임 수. 대충 16~32
loopWindowSize = 6; // 반복될 애니메이션 간의 간격. 대충 4~8
animationDelay = 100; // 프레임 애니메이션 속도 (애니메이션 프레임 간의 시간간격)
markFrame = 8; // markFrame : 중간의 어떤 적절한 프레임. 애니메이션 경계를 주기 위해 사용
startColor0 = 0x00000000;
startColor1 = 0x00000000; // 0번 프레임의 컬러
markColor0 = color0_mark;
markColor1 = color1_mark;// (markFrame)번 프레임의 컬러
endColor0 = color0_end;
endColor1 = color1_end; // (numFrames-1)번 프레임의 컬러
startSizeOffset = 0.01f; // 0번 프레임의 메쉬 확대 크기. 대충 +0.01정도?
markSizeOffset = 0.10f; // (markFrame)번 프레임의 메쉬 크기.
endSizeOffset = 0.6f; // (numFrames-1)번 프레임의 메쉬 크기. 대충 +0.6정도?
}