#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 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 & vList, K3DTexture * pTex ) { std::vector::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 ; nGetResCount(); ++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(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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&msg); boundReq->AddBound( GetCube() ); return (void*)1; } else if ( id == id_REQ_BOUNDBOXEX ) { realizeTransform(); KMsgREQ_BOUNDBOXEX * boundReqEx = static_cast(&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(&msg); boundReq->AddBound( GetSphere() ); return (void*)1; } else if ( id == id_SET_LIGHT_MAP ) { KMsgSET_LIGHTMAP *pLightMapSet = static_cast(&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(&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(&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(&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(&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(&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(&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(&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(&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 ; nGetRes(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(&msg); CalcMatrix(); getMatrix->matLocal = &m_matLocal; getMatrix->matRoot = &m_matRoot; getMatrix->bSuc = true; } else if( id == id_GET_PERFORMANCEINFO ) { KMsgGET_PERFORMANCEINFO* getPerformanceinfo = static_cast(&msg); getPerformanceinfo->nSeqCount++; getPerformanceinfo->nMeshCount++; for ( int i=0 ; iGetResCount() ; ++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 ; iGetResCount() ; ++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 ; iGetResCount() ; ++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 ; iGetResCount(); ++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 ; iGetResCount(); ++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(m_dwTime), &m_fVisResult); } if ( m_spResMatrix != NULL ) { m_spResMatrix->GetLerpMatrix(static_cast(m_dwTime), &m_matLocal); } if ( m_spResUV != NULL ) { m_spResUV->GetLerpMatrix(static_cast(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; ii; 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정도? }