// Z3DMultipartSkin.cpp: implementation of the CZ3DMultipartSkin class. // ////////////////////////////////////////////////////////////////////// //#include "FunctionPerformanceCheck.h" #include "Z3DMultipartSkin.h" #include "Vertex.h" //#include "BaseDataDefine.h" #include "RenderOption.h" #include "GMMemory.h" ////////////////////////////////////////////////////////////////////// // LOD ·¹º§´ç ¸î ÇÁ·¹ÀÓ¿¡ Çѹø¾¿ blending °è»êÀ» ÇÒ °ÍÀÎÁö °áÁ¤ÇÒ¶§ ¾²ÀÌ´Â Å×À̺í long CZ3DMultipartSkin::ms_alAniLODFrameTable[Z3D_LOD_LEVEL] = { 1, 3, 5, 10 }; bool CZ3DMultipartSkin::SetMesh( const char* szMeshName ) { if( this != m_rpThis ) { return true; } int id; int nPartId; //H3DMeshTag tagMesh; //g_ContLODMesh.GetObject( tagMesh, szMeshName ); //nPartId = tagMesh.GetObject()->GetId(); Z3DLODMesh* pMesh; pMesh = g_ContLODMesh.GetObject( szMeshName ); nPartId = pMesh->GetId(); id = GetPortionIndex( nPartId ); if( -1 == id ) // À߸øµÈ id { // ÇöÀç CBaseCacheMgr Àº release °ü·Ã ¸Þ¼Òµå°¡ ¾ø´Ù //tagMesh.Release(); return false; } if( m_apPortion[id]->SetMesh( nPartId, pMesh ) ) //if( m_apPortion[id]->SetMesh( nPartId, tagMesh ) ) { if( !m_bIsBatchMode ) { m_lAniLODCounter = 0; // ¸Þ½¬°¡ ¹Ù²î¾úÀ» °æ¿ì blending Àç°è»êÀÌ ÇÊ¿äÇϹǷΠm_apPortion[id]->BuildMesh( GetDevice() ); } return true; } return false; } bool CZ3DMultipartSkin::SetTex( const char* szTexName, const char* szTex2Name ) { if( this != m_rpThis ) { return true; } int id; int nPartId; H3DTexPieceTag tagTexPiece; g_ContTexturePiece.GetObject( tagTexPiece, szTexName ); nPartId = tagTexPiece.GetObject()->GetId(); id = GetPortionIndex( nPartId ); if( -1 == id ) // À߸øµÈ id { tagTexPiece.Release(); return false; } if( !m_bIsBatchMode ) { // ÅØ½ºÃ³°¡ ºñ¾î ÀÖÀ»¶§ null ÅØ½ºÃ³ »ý¼º if( true == m_apPortion[id]->m_pTexture->IsEmpty() ) { if( 0 == id ) { // if( false == m_apPortion[id]->m_pTexture->Load( "NULL_512x512.dds" ) ) // { // _ASSERT(false); // error reading default texture! // return false; // } // } // else // { // if( false == m_apPortion[id]->m_pTexture->Load( "NULL_256x512.dds" ) ) // { // _ASSERT(false); // error reading default texture! // return false; // } } } } if( m_apPortion[id]->SetTexPiece( nPartId, tagTexPiece ) ) { if( !m_bIsBatchMode ) { tagTexPiece.GetObject()->Blt2Texture( m_apPortion[id]->m_pTexture->GetD3dTexture() ); } } // secondary texture ó¸® if( NULL == szTex2Name ) { return true; } g_ContTexturePiece.GetObject( tagTexPiece, szTex2Name ); nPartId = tagTexPiece.GetObject()->GetId(); id = GetPortionIndex( nPartId ); if( -1 == id ) // À߸øµÈ id { tagTexPiece.Release(); return false; } if( !m_bIsBatchMode ) { // ÅØ½ºÃ³°¡ ºñ¾î ÀÖÀ»¶§ null ÅØ½ºÃ³ »ý¼º if( true == m_apPortion[id]->m_pTexture2->IsEmpty() ) { if( 0 == id ) { // if( false == m_apPortion[id]->m_pTexture2->Load( "BUMP_512x512.dds" ) ) // { // _ASSERT(false); // error reading default texture! // return false; // } // } // else // { // if( false == m_apPortion[id]->m_pTexture2->Load( "BUMP_256x512.dds" ) ) // { // _ASSERT(false); // error reading default texture! // return false; // } } } } if( m_apPortion[id]->SetTexPiece2( nPartId, tagTexPiece ) ) { if( !m_bIsBatchMode ) { tagTexPiece.GetObject()->Blt2Texture( m_apPortion[id]->m_pTexture2->GetD3dTexture() ); } return true; } return false; } int CZ3DMultipartSkin::GetIdFromMeshName( char* szMeshName ) { char* pNumberBegin = strrchr( szMeshName, '_' ); if( NULL == pNumberBegin ) { return 0; } ++pNumberBegin; // ¼ýÀÚ´Â '_' ¹Ù·Î ´ÙÀ½ ¹®ÀÚºÎÅÍ ½ÃÀÛÀ̹ǷΠchar* pNumberEnd = strrchr( szMeshName, '.' ); if( NULL == pNumberEnd ) { return 0; } int nNumLen = pNumberEnd - pNumberBegin; if( nNumLen < 0 ) { return 0; } char szTmp[10]; strncpy( szTmp, pNumberBegin, nNumLen ); szTmp[nNumLen] = '\0'; return atoi( szTmp ); } bool CZ3DMultipartSkin::SetMeshTexture( const char* szMeshName, const char* szTextureName, const char* szTexture2Name, long lGradeEffectIndex, long lGlowIndex ) { if( this != m_rpThis ) { return true; } //DeclareBlockTimingCheck("mesh GetObject", aa); //DeclareBlockTimingCheck("tex1 GetObject", bb); //DeclareBlockTimingCheck("tex2 GetObject", cc); int id; int nPartId; Z3DLODMesh* pMesh; // H3DMeshTag tagMesh; //BlockTimingCheckStart(aa); //g_ContLODMesh.GetObject( tagMesh, szMeshName ); pMesh = g_ContLODMesh.GetObject( szMeshName ); //BlockTimingCheckStop(aa); //nPartId = tagMesh.GetObject()->GetId(); nPartId = GetIdFromMeshName(const_cast(szMeshName)); id = GetPortionIndex( nPartId ); if( -1 == id ) // À߸øµÈ id { // ¸±¸®Áî //tagMesh.Release(); return false; } m_apPortion[id]->SetGradeEffectIndex( nPartId, lGradeEffectIndex ); m_apPortion[id]->SetGlowIndex( nPartId, lGlowIndex ); if( m_apPortion[id]->SetMesh( nPartId, pMesh ) ) //if( m_apPortion[id]->SetMesh( nPartId, tagMesh ) ) { if( !m_bIsBatchMode ) { m_lAniLODCounter = 0; // ¸Þ½¬°¡ ¹Ù²î¾úÀ» °æ¿ì blending Àç°è»êÀÌ ÇÊ¿äÇϹǷΠm_apPortion[id]->BuildMesh( GetDevice() ); } } Z3DTexture* pTexture; // H3DTextureTag tagTexture; if( NULL == szTextureName ) { m_apPortion[id]->DeleteTexture( nPartId ); } else { //BlockTimingCheckStart(bb); pTexture = g_ContTexture.GetObject( szTextureName ); //g_ContTexture.GetObject( tagTexture, szTextureName ); //BlockTimingCheckStop(bb); m_apPortion[id]->SetTexture( nPartId, pTexture ); /* if( NULL == tagTexture.GetObject() ) { WRONG_WAY( "Texture file not found!" ); } m_apPortion[id]->SetTexture( nPartId, tagTexture );*/ } if( NULL == szTexture2Name ) { m_apPortion[id]->DeleteTexture2( nPartId ); return true; } //BlockTimingCheckStart(cc); pTexture = g_ContTexture.GetObject( szTexture2Name ); //BlockTimingCheckStop(cc); return m_apPortion[id]->SetTexture2( nPartId, pTexture ); /* //BlockTimingCheckStart(cc); g_ContTexture.GetObject( tagTexture, szTexture2Name ); //BlockTimingCheckStop(cc); if( NULL == tagTexture.GetObject() ) { WRONG_WAY( "Texture file not found!" ); } return m_apPortion[id]->SetTexture2( nPartId, tagTexture );*/ } bool CZ3DMultipartSkin::DeleteMesh( int nPartId ) { if( this != m_rpThis ) { return true; } int id = GetPortionIndex( nPartId ); if( -1 == id ) { return false; } if( m_apPortion[id]->DeleteMesh( nPartId ) ) { if( !m_bIsBatchMode ) { m_apPortion[id]->BuildMesh( GetDevice() ); m_lAniLODCounter = 0; // ¸Þ½¬°¡ ¹Ù²î¾úÀ» °æ¿ì blending Àç°è»êÀÌ ÇÊ¿äÇϹǷΠ} return true; } return false; } bool CZ3DMultipartSkin::DeleteTex( int nPartId ) { if( this != m_rpThis ) { return true; } int id = GetPortionIndex( nPartId ); if( -1 == id ) { return false; } if( m_apPortion[id]->DeleteTexPiece( nPartId ) ) { if( !m_bIsBatchMode ) { if( m_apPortion[id]->m_map_IdTexPieceTag.empty() ) { m_apPortion[id]->m_pTexture->Flush(); } } return true; } return false; } bool CZ3DMultipartSkin::BatchOpen() { if( this != m_rpThis ) { return true; } //_ASSERTE( !m_bIsBatchMode ); if( m_bIsBatchMode ) { return false; } // batchopenÀ¸·Î °ª ¸®¼ÂÇÏ´Â ºÎºÐÀº build mesh¿¡ ¸ðµÎ Æ÷ÇԵǹǷÎ, µû·Î È£ÃâÇÏÁö ¾Ê´Â´Ù. /*for( int i = 0; i < Z3D_MULTIPART_PORTION_COUNT; i++ ) { m_apPortion[i]->BatchOpen(); }*/ m_bIsBatchMode = true; return true; } bool CZ3DMultipartSkin::BatchClose() { if( this != m_rpThis ) { return true; } //_ASSERTE( m_bIsBatchMode ); if( false == m_bIsBatchMode ) { return false; } for( int i = 0; i < Z3D_MULTIPART_PORTION_COUNT; i++ ) { if( Z3D_MPT_TEXPIECE == m_MPT ) { if( m_apPortion[i]->m_map_IdTexPieceTag.empty() ) { m_apPortion[i]->m_pTexture->Flush(); } else if( m_apPortion[i]->m_pTexture->IsEmpty() ) { // if( 0 == i ) // { // if( false == m_apPortion[i]->m_pTexture->Load( "NULL_512x512.dds" ) ) // { // return false; // } // } // else // { // if( false == m_apPortion[i]->m_pTexture->Load( "NULL_256x512.dds" ) ) // { // return false; // } // } } if( m_apPortion[i]->m_map_IdTexPieceTag2.empty() ) { m_apPortion[i]->m_pTexture2->Flush(); } else if( m_apPortion[i]->m_pTexture2->IsEmpty() ) { // if( 0 == i ) // { // if( false == m_apPortion[i]->m_pTexture2->Load( "BUMP_512x512.dds" ) ) // { // return false; // } // } // else // { // if( false == m_apPortion[i]->m_pTexture2->Load( "BUMP_256x512.dds" ) ) // { // return false; // } // } } } m_apPortion[i]->BatchClose( GetDevice() ); } m_lAniLODCounter = 0; // ¸Þ½¬°¡ ¹Ù²î¾î blending Àç°è»êÀÌ ÇÊ¿äÇϹǷΠm_bIsBatchMode = false; return true; } vector3 ComputeTangentVector(BumpVertex pVtxA, BumpVertex pVtxB,BumpVertex pVtxC ) { vector3 vAB=pVtxB.v-pVtxA.v; vector3 vAC=pVtxC.v-pVtxA.v; vector3 n=pVtxA.n; vector3 vProjAB=vAB-( (n*vAB)*n ); vector3 vProjAC=vAC-( (n*vAC)*n ); float duAB=pVtxB.tu-pVtxA.tu; float duAC=pVtxC.tu-pVtxA.tu; float dvAB=pVtxB.tv-pVtxA.tv; float dvAC=pVtxC.tv-pVtxA.tv; if( duAC*dvAB > duAB*dvAC ) { duAC=-duAC; duAB=-duAB; } vector3 vTangent=duAC*vProjAB-duAB*vProjAC; vTangent.Normalize(); return vTangent; } void CalcTagentSpaceVector(BumpVertex *pVertices,WORD *pIndices,int cVertex,int cIndices,vector3 *pU) { memset(pU,0,sizeof(vector3)*cVertex); for(int i=0;iCheckLoadedStatus( GetDevice() ); } // allocation safety check for(int i = 0; i < Z3D_MULTIPART_PORTION_COUNT; ++i ) { if( NULL == m_apPortion[i]->m_pVertexBuffer ) { return; } } // bounding box ÃÖ¼Ò°ªÀº °¡Àå Å« °ªÀ¸·Î, ÃÖ´ë°ªÀº °¡Àå ÀÛÀº °ªÀ¸·Î ÃʱâÈ­ m_vBoundingBoxMin = vector3( 4.2e9f, 4.2e9f, 4.2e9f ); m_vBoundingBoxMax = vector3( -4.2e9f, -4.2e9f, -4.2e9f ); if( CRenderOption::m_CharacterPerPixelLighting ) { //static bFirstRender=true; //static vector3 vecU[2000]; BumpVertex* pVertices; // shortcut to render vertex pool of portion Z3DBlend2Vertex* pBlVertex; matrix* pMat1,* pMat2; // fixed as 2 for now float factor1, factor2; int i, j, k, l; Z3DLODMesh* pMesh; float f1, f2, f3, f4; // LOD level ±¸ÇÔ : »À´Ù±¸ÀÇ rootÀ§Ä¡¸¦ ±âÁØÀ¸·Î - Â÷ÈÄ¿¡ ´Ù¸¥ ¹æ¹ýÀ¸·Î ¹Ù²ÜÁöµµ? // ¿ÜºÎ¿¡¼­ LOD ·¹º§ ¼³Á¤ÇØÁִ°ÍÀ¸·Î ¹Ù²ñ. //pMat1 = m_rpSkeleton[0].GetTM(); int nLODLevel = GetLODLevel(); if( 1 )//CheckRecalcByAniLOD() ) { // ¿øTMÀÇ ¿ªÇà·ÄÀ» ±¸ÇØÁø ani TM¿¡ °öÇØÁØ´Ù. for( i = 0; i < m_lSkelCount; i++ ) { if( m_bTestMode ) { m_pMatrixPalette[i].MakeIdent(); } else { m_rpSkeleton[i].GetLocalizedTM( m_pMatrixPalette[i], m_rpSkeletonLocalizer[i] ); } } for( i = 0; i < Z3D_MULTIPART_PORTION_COUNT; i++ ) { if( 0 == m_apPortion[i]->m_vec_pMesh.size() ) { continue; } j = 0; //pVertices = m_apPortion[i]->m_pVertices; // m_apPortion[i]->m_pVertexBuffer->Lock( 0, 0, (BYTE**)(&pVertices), D3DLOCK_DISCARD ); m_apPortion[i]->m_pVertexBuffer->Lock( 0, 0, (BYTE**)(&pVertices), 0 ); for( l = 0; l < (int)m_apPortion[i]->m_vec_pMesh.size(); l++ ) { pMesh = m_apPortion[i]->m_vec_pMesh[l]; for( k = 0; k < pMesh->lVertexCount; k++ ) { if( pMesh->pVertices[k].lodLevel >= nLODLevel ) { pBlVertex = &(pMesh->pVertices[k]); /* // edith 2008.06.19 ½ºÄÌ·¹Å» ó¸® if(m_lSkelCount <= pBlVertex->mtrx_id[0]) continue; else if(m_lSkelCount <= pBlVertex->mtrx_id[1]) continue; */ pMat1 = &(m_pMatrixPalette[pBlVertex->mtrx_id[0]]); pMat2 = &(m_pMatrixPalette[pBlVertex->mtrx_id[1]]); factor1 = pBlVertex->bfactor; factor2 = 1.0f - factor1; f1 = (factor1*pMat1->_11) + (factor2*pMat2->_11); f2 = (factor1*pMat1->_21) + (factor2*pMat2->_21); f3 = (factor1*pMat1->_31) + (factor2*pMat2->_31); f4 = (factor1*pMat1->_41) + (factor2*pMat2->_41); pVertices[j].v.x = (pBlVertex->pos.x*f1 + pBlVertex->pos.y*f2 + pBlVertex->pos.z*f3 + f4) * m_fScaleFactor; pVertices[j].u.x = (pBlVertex->u.x*f1 + pBlVertex->u.y*f2 + pBlVertex->u.z*f3); pVertices[j].n.x = pBlVertex->normal.x*f1 + pBlVertex->normal.y*f2 + pBlVertex->normal.z*f3; f1 = (factor1*pMat1->_12) + (factor2*pMat2->_12); f2 = (factor1*pMat1->_22) + (factor2*pMat2->_22); f3 = (factor1*pMat1->_32) + (factor2*pMat2->_32); f4 = (factor1*pMat1->_42) + (factor2*pMat2->_42); pVertices[j].v.y = (pBlVertex->pos.x*f1 + pBlVertex->pos.y*f2 + pBlVertex->pos.z*f3 + f4) * m_fScaleFactor; pVertices[j].u.y = (pBlVertex->u.x*f1 + pBlVertex->u.y*f2 + pBlVertex->u.z*f3); pVertices[j].n.y = pBlVertex->normal.x*f1 + pBlVertex->normal.y*f2 + pBlVertex->normal.z*f3; f1 = (factor1*pMat1->_13) + (factor2*pMat2->_13); f2 = (factor1*pMat1->_23) + (factor2*pMat2->_23); f3 = (factor1*pMat1->_33) + (factor2*pMat2->_33); f4 = (factor1*pMat1->_43) + (factor2*pMat2->_43); pVertices[j].v.z = (pBlVertex->pos.x*f1 + pBlVertex->pos.y*f2 + pBlVertex->pos.z*f3 + f4) * m_fScaleFactor; pVertices[j].u.z = (pBlVertex->u.x*f1 + pBlVertex->u.y*f2 + pBlVertex->u.z*f3); pVertices[j].n.z = pBlVertex->normal.x*f1 + pBlVertex->normal.y*f2 + pBlVertex->normal.z*f3; pVertices[j].tu = pBlVertex->tu; pVertices[j].tv = pBlVertex->tv; // bounding box min/max °ª ±¸ÇÔ m_vBoundingBoxMin.x = min( pVertices[j].v.x, m_vBoundingBoxMin.x ); m_vBoundingBoxMin.y = min( pVertices[j].v.y, m_vBoundingBoxMin.y ); m_vBoundingBoxMin.z = min( pVertices[j].v.z, m_vBoundingBoxMin.z ); m_vBoundingBoxMax.x = max( pVertices[j].v.x, m_vBoundingBoxMax.x ); m_vBoundingBoxMax.y = max( pVertices[j].v.y, m_vBoundingBoxMax.y ); m_vBoundingBoxMax.z = max( pVertices[j].v.z, m_vBoundingBoxMax.z ); } j++; } } m_apPortion[i]->m_pVertexBuffer->Unlock(); } } } else { // blending °è»ê ¹× ÅØ½ºÃ³ ¼¼ÆÃ, ·»´õ¸µ D3DVERTEX* pVertices; // shortcut to render vertex pool of portion Z3DBlend2Vertex* pBlVertex; matrix* pMat1,* pMat2; // fixed as 2 for now float factor1, factor2; int i, j, k, l; Z3DLODMesh* pMesh; matrix m; float f1, f2, f3, f4; // LOD level ±¸ÇÔ : »À´Ù±¸ÀÇ rootÀ§Ä¡¸¦ ±âÁØÀ¸·Î - Â÷ÈÄ¿¡ ´Ù¸¥ ¹æ¹ýÀ¸·Î ¹Ù²ÜÁöµµ? // ¿ÜºÎ¿¡¼­ LOD ·¹º§ ¼³Á¤ÇØÁִ°ÍÀ¸·Î ¹Ù²ñ. //pMat1 = m_rpSkeleton[0].GetTM(); int nLODLevel = GetLODLevel(); if( 1 )//CheckRecalcByAniLOD() ) { // ¿øTMÀÇ ¿ªÇà·ÄÀ» ±¸ÇØÁø ani TM¿¡ °öÇØÁØ´Ù. for( i = 0; i < m_lSkelCount; i++ ) { if( m_bTestMode ) { m_pMatrixPalette[i].MakeIdent(); } else { m_rpSkeleton[i].GetLocalizedTM( m_pMatrixPalette[i], m_rpSkeletonLocalizer[i] ); } } for( i = 0; i < Z3D_MULTIPART_PORTION_COUNT; i++ ) { if( 0 == m_apPortion[i]->m_vec_pMesh.size() ) { continue; } j = 0; // m_apPortion[i]->m_pVertexBuffer->Lock( 0, 0, (BYTE**)(&pVertices), D3DLOCK_DISCARD ); m_apPortion[i]->m_pVertexBuffer->Lock( 0, 0, (BYTE**)(&pVertices), 0 ); for( l = 0; l < (int)m_apPortion[i]->m_vec_pMesh.size(); l++ ) { pMesh = m_apPortion[i]->m_vec_pMesh[l]; for( k = 0; k < pMesh->lVertexCount; k++ ) { if( pMesh->pVertices[k].lodLevel >= nLODLevel ) { pBlVertex = &(pMesh->pVertices[k]); /* // edith ½ºÅ² // edith 2008.06.19 ½ºÄÌ·¹Å» ó¸® if(m_lSkelCount <= pBlVertex->mtrx_id[0]) continue; else if(m_lSkelCount <= pBlVertex->mtrx_id[1]) continue; */ pMat1 = &(m_pMatrixPalette[pBlVertex->mtrx_id[0]]); pMat2 = &(m_pMatrixPalette[pBlVertex->mtrx_id[1]]); factor1 = pBlVertex->bfactor; factor2 = 1.0f - factor1; f1 = (factor1*pMat1->_11) + (factor2*pMat2->_11); f2 = (factor1*pMat1->_21) + (factor2*pMat2->_21); f3 = (factor1*pMat1->_31) + (factor2*pMat2->_31); f4 = (factor1*pMat1->_41) + (factor2*pMat2->_41); pVertices[j].x = (pBlVertex->pos.x*f1 + pBlVertex->pos.y*f2 + pBlVertex->pos.z*f3 + f4) * m_fScaleFactor; pVertices[j].nx = pBlVertex->normal.x*f1 + pBlVertex->normal.y*f2 + pBlVertex->normal.z*f3; f1 = (factor1*pMat1->_12) + (factor2*pMat2->_12); f2 = (factor1*pMat1->_22) + (factor2*pMat2->_22); f3 = (factor1*pMat1->_32) + (factor2*pMat2->_32); f4 = (factor1*pMat1->_42) + (factor2*pMat2->_42); pVertices[j].y = (pBlVertex->pos.x*f1 + pBlVertex->pos.y*f2 + pBlVertex->pos.z*f3 + f4) * m_fScaleFactor; pVertices[j].ny = pBlVertex->normal.x*f1 + pBlVertex->normal.y*f2 + pBlVertex->normal.z*f3; f1 = (factor1*pMat1->_13) + (factor2*pMat2->_13); f2 = (factor1*pMat1->_23) + (factor2*pMat2->_23); f3 = (factor1*pMat1->_33) + (factor2*pMat2->_33); f4 = (factor1*pMat1->_43) + (factor2*pMat2->_43); pVertices[j].z = (pBlVertex->pos.x*f1 + pBlVertex->pos.y*f2 + pBlVertex->pos.z*f3 + f4) * m_fScaleFactor; pVertices[j].nz = pBlVertex->normal.x*f1 + pBlVertex->normal.y*f2 + pBlVertex->normal.z*f3; pVertices[j].tu = pBlVertex->tu; pVertices[j].tv = pBlVertex->tv; // bounding box min/max °ª ±¸ÇÔ m_vBoundingBoxMin.x = min( pVertices[j].x, m_vBoundingBoxMin.x ); m_vBoundingBoxMin.y = min( pVertices[j].y, m_vBoundingBoxMin.y ); m_vBoundingBoxMin.z = min( pVertices[j].z, m_vBoundingBoxMin.z ); m_vBoundingBoxMax.x = max( pVertices[j].x, m_vBoundingBoxMax.x ); m_vBoundingBoxMax.y = max( pVertices[j].y, m_vBoundingBoxMax.y ); m_vBoundingBoxMax.z = max( pVertices[j].z, m_vBoundingBoxMax.z ); } j++; } } m_apPortion[i]->m_pVertexBuffer->Unlock(); } } } m_vBoundingBoxMin += m_vPivotPos; m_vBoundingBoxMax += m_vPivotPos; } void CZ3DMultipartSkin::Render() { if( this != m_rpThis ) { return; } int i, j; int nLODLevel = GetLODLevel(); for( i = 0; i < Z3D_MULTIPART_PORTION_COUNT; ++i ) { if( NULL == m_apPortion[i]->m_pVertexBuffer ) { return; } if( NULL == m_apPortion[i]->m_apIndexBuffer[nLODLevel] ) { return; } } if( m_bIsBatchMode ) { return; } long lVertexOffset, lIndexOffset; Z3DLODMesh* pMesh = NULL; if(CRenderOption::m_CharacterPerPixelLighting) { //GetDevice()->SetVertexShader( BUMPVERTEXFVF ); } else { GetDevice()->SetVertexShader( D3DFVF_VERTEX ); } matrix m; m.MakeIdent(); m._41 = m_vPivotPos.x; m._42 = m_vPivotPos.y; m._43 = m_vPivotPos.z; GetDevice()->SetTransform( D3DTS_WORLD, m ); for( i = 0; i < Z3D_MULTIPART_PORTION_COUNT; i++ ) { if( m_apPortion[i]->m_alIndexCount[nLODLevel] ) { if( Z3D_MPT_TEXPIECE == m_apPortion[i]->m_MPT ) { GetDevice()->SetTexture( 0, m_apPortion[i]->m_pTexture->GetD3dTexture() ); GetDevice()->SetTexture( 1, m_apPortion[i]->m_pTexture2->GetD3dTexture() ); } if(CRenderOption::m_CharacterPerPixelLighting) { GetDevice()->SetStreamSource( 0, m_apPortion[i]->m_pVertexBuffer, sizeof(BumpVertex) ); } else { GetDevice()->SetStreamSource( 0, m_apPortion[i]->m_pVertexBuffer, sizeof(D3DVERTEX) ); } GetDevice()->SetIndices( m_apPortion[i]->m_apIndexBuffer[nLODLevel], 0 ); lVertexOffset = 0; lIndexOffset = 0; for( j = 0; j < (int)m_apPortion[i]->m_vec_pMesh.size(); ++j ) { pMesh = m_apPortion[i]->m_vec_pMesh[j]; if( pMesh->aIndex[nLODLevel].lIndexCount ) { if( Z3D_MPT_TEXTURE == m_apPortion[i]->m_MPT ) { if( m_apPortion[i]->m_vec_pTexture[j] ) { GetDevice()->SetTexture( 0, m_apPortion[i]->m_vec_pTexture[j]->GetD3dTexture() ); } else { GetDevice()->SetTexture( 0, NULL ); } // if( m_apPortion[i]->m_vec_pTexture2[j] ) // { // GetDevice()->SetTexture( 1, *(m_apPortion[i]->m_vec_pTexture2[j]) ); // } // else // { // GetDevice()->SetTexture( 1, NULL ); // } } //static int nTexTransformCounter = 0; //int cTemp = (nTexTransformCounter < 1200) ? 384*sinf(3.1415926535f*nTexTransformCounter/1200.0f) : 0; //if( cTemp > 255 ) cTemp = 255; //GetDevice()->SetRenderState( D3DRS_TEXTUREFACTOR, D3DCOLOR_ARGB( cTemp, 0, cTemp, 0 ) ); ////GetDevice()->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); ////GetDevice()->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); //if( ++nTexTransformCounter == 2000 ) //{ // nTexTransformCounter = 0; //} m_apPortion[i]->m_vec_pGradeEffectHandler[j]->ApplySetting( GetDevice() ); HRESULT hr = GetDevice()->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, lVertexOffset, pMesh->lVertexCount, lIndexOffset, (pMesh->aIndex[nLODLevel].lIndexCount)/3 ); } lVertexOffset += pMesh->lVertexCount; lIndexOffset += pMesh->aIndex[nLODLevel].lIndexCount; } } } IncreaseAniLODCounter(); } void CZ3DMultipartSkin::RenderShadow( IDirect3DDevice8* pDevice, DWORD vertexShader, int nLevel ) { if( this != m_rpThis ) { return; } int i, j; // int nLODLevel = ( -1 == nLevel ) ? ( (m_lLODLevel+Z3D_LOD_LEVEL-1)/2 ) : min( Z3D_LOD_LEVEL, nLevel ); int nLODLevel = ( -1 == nLevel ) ? m_lLODLevel : min( Z3D_LOD_LEVEL, nLevel ); for( i = 0; i < Z3D_MULTIPART_PORTION_COUNT; ++i ) { if( NULL == m_apPortion[i]->m_pVertexBuffer ) { return; } if( NULL == m_apPortion[i]->m_apIndexBuffer[nLODLevel] ) { return; } } //_ASSERTE( !m_bIsBatchMode ); if( NULL != vertexShader ) { if( 0xFFFFFFFF == vertexShader ) { if(CRenderOption::m_CharacterPerPixelLighting) { GetDevice()->SetVertexShader( BUMPVERTEXFVF ); } else { GetDevice()->SetVertexShader( D3DFVF_VERTEX ); } } else { GetDevice()->SetVertexShader( vertexShader ); } } matrix m; m.MakeIdent(); m._41 = m_vPivotPos.x; m._42 = m_vPivotPos.y; m._43 = m_vPivotPos.z; GetDevice()->SetTransform( D3DTS_WORLD, m ); Z3DLODMesh* pMesh; long lVertexOffset, lIndexOffset; for( i = 0; i < Z3D_MULTIPART_PORTION_COUNT; i++ ) { if( m_apPortion[i]->m_alIndexCount[nLODLevel] ) { if(CRenderOption::m_CharacterPerPixelLighting) { GetDevice()->SetStreamSource( 0, m_apPortion[i]->m_pVertexBuffer, sizeof(BumpVertex) ); } else { GetDevice()->SetStreamSource( 0, m_apPortion[i]->m_pVertexBuffer, sizeof(D3DVERTEX) ); } lVertexOffset = 0; lIndexOffset = 0; for( j = 0; j < (int)m_apPortion[i]->m_vec_pMesh.size(); ++j ) { pMesh = m_apPortion[i]->m_vec_pMesh[j]; if( pMesh->aIndex[nLODLevel].lIndexCount ) { GetDevice()->SetIndices( m_apPortion[i]->m_apIndexBuffer[nLODLevel], 0 ); GetDevice()->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, lVertexOffset, pMesh->lVertexCount, lIndexOffset, (pMesh->aIndex[nLODLevel].lIndexCount)/3 ); } lVertexOffset += pMesh->lVertexCount; lIndexOffset += pMesh->aIndex[nLODLevel].lIndexCount; } GetDevice()->SetStreamSource( 0, NULL, 0 ); GetDevice()->SetIndices( NULL, 0 ); } } } void CZ3DMultipartSkin::RenderGlowShape( IDirect3DDevice8* pDevice ) { if( this != m_rpThis ) { return; } int i, j; for( i = 0; i < Z3D_MULTIPART_PORTION_COUNT; ++i ) { if( NULL == m_apPortion[i]->m_pVertexBuffer ) { return; } if( NULL == m_apPortion[i]->m_apIndexBuffer[m_lLODLevel] ) { return; } } //_ASSERTE( !m_bIsBatchMode ); GetDevice()->SetVertexShader( D3DFVF_VERTEX ); matrix m; m.MakeIdent(); m._41 = m_vPivotPos.x; m._42 = m_vPivotPos.y; m._43 = m_vPivotPos.z; GetDevice()->SetTransform( D3DTS_WORLD, m ); Z3DLODMesh* pMesh; long lVertexOffset, lIndexOffset; for( i = 0; i < Z3D_MULTIPART_PORTION_COUNT; i++ ) { if( m_apPortion[i]->m_alIndexCount[m_lLODLevel] ) { GetDevice()->SetStreamSource( 0, m_apPortion[i]->m_pVertexBuffer, sizeof(D3DVERTEX) ); lVertexOffset = 0; lIndexOffset = 0; for( j = 0; j < (int)m_apPortion[i]->m_vec_pMesh.size(); ++j ) { pMesh = m_apPortion[i]->m_vec_pMesh[j]; m_apPortion[i]->m_vec_pGlowHandler[j]->ApplySetting( GetDevice() ); if( pMesh->aIndex[m_lLODLevel].lIndexCount ) { GetDevice()->SetIndices( m_apPortion[i]->m_apIndexBuffer[m_lLODLevel], 0 ); GetDevice()->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, lVertexOffset, pMesh->lVertexCount, lIndexOffset, (pMesh->aIndex[m_lLODLevel].lIndexCount)/3 ); } lVertexOffset += pMesh->lVertexCount; lIndexOffset += pMesh->aIndex[m_lLODLevel].lIndexCount; } GetDevice()->SetStreamSource( 0, NULL, 0 ); GetDevice()->SetIndices( NULL, 0 ); } } } void CZ3DMultipartSkin::GetBoundingBox( vector3& r_vmin, vector3& r_vmax ) { if( this != m_rpThis ) { return; } int i, j; r_vmin = vector3( 0, 0, 0 ); r_vmax = vector3( 0, 0, 0 ); D3DVERTEXBUFFER_DESC vd; if(CRenderOption::m_CharacterPerPixelLighting) { BumpVertex* pVertices; for( i = 0; i < Z3D_MULTIPART_PORTION_COUNT; i++ ) { if( 0 == m_apPortion[i]->m_vec_pMesh.size() ) { continue; } // allocation safety check if( NULL == m_apPortion[i]->m_pVertexBuffer ) { continue; } m_apPortion[i]->m_pVertexBuffer->GetDesc( &vd ); // m_apPortion[i]->m_pVertexBuffer->Lock( 0, 0, (BYTE**)(&pVertices), D3DLOCK_DISCARD ); m_apPortion[i]->m_pVertexBuffer->Lock( 0, 0, (BYTE**)(&pVertices), 0 ); for( j = 0; j < (int)(vd.Size/sizeof(BumpVertex)); ++j ) { if( pVertices[j].v.x < r_vmin.x ) { r_vmin.x = pVertices[j].v.x; } if( pVertices[j].v.y < r_vmin.y ) { r_vmin.y = pVertices[j].v.y; } if( pVertices[j].v.z < r_vmin.z ) { r_vmin.z = pVertices[j].v.z; } if( pVertices[j].v.x > r_vmax.x ) { r_vmax.x = pVertices[j].v.x; } if( pVertices[j].v.y > r_vmax.y ) { r_vmax.y = pVertices[j].v.y; } if( pVertices[j].v.z > r_vmax.z ) { r_vmax.z = pVertices[j].v.z; } } m_apPortion[i]->m_pVertexBuffer->Unlock(); } } else { D3DVERTEX* pVertices; for( i = 0; i < Z3D_MULTIPART_PORTION_COUNT; i++ ) { if( 0 == m_apPortion[i]->m_vec_pMesh.size() ) { continue; } // allocation safety check if( NULL == m_apPortion[i]->m_pVertexBuffer ) { continue; } m_apPortion[i]->m_pVertexBuffer->GetDesc( &vd ); // m_apPortion[i]->m_pVertexBuffer->Lock( 0, 0, (BYTE**)(&pVertices), D3DLOCK_DISCARD ); m_apPortion[i]->m_pVertexBuffer->Lock( 0, 0, (BYTE**)(&pVertices), 0 ); for( j = 0; j < (int)(vd.Size/sizeof(D3DVERTEX)); ++j ) { if( pVertices[j].x < r_vmin.x ) { r_vmin.x = pVertices[j].x; } if( pVertices[j].y < r_vmin.y ) { r_vmin.y = pVertices[j].y; } if( pVertices[j].z < r_vmin.z ) { r_vmin.z = pVertices[j].z; } if( pVertices[j].x > r_vmax.x ) { r_vmax.x = pVertices[j].x; } if( pVertices[j].y > r_vmax.y ) { r_vmax.y = pVertices[j].y; } if( pVertices[j].z > r_vmax.z ) { r_vmax.z = pVertices[j].z; } } m_apPortion[i]->m_pVertexBuffer->Unlock(); } } } void CZ3DMultipartSkin::GetProcessedVertex( Z3DBlend2Vertex& v_in, vector3& v_out ) const { if( this != m_rpThis ) { return; } matrix m2[2]; m_rpSkeleton[v_in.mtrx_id[0]].GetLocalizedTM( m2[0], m_rpSkeletonLocalizer[v_in.mtrx_id[0]] ); m_rpSkeleton[v_in.mtrx_id[1]].GetLocalizedTM( m2[1], m_rpSkeletonLocalizer[v_in.mtrx_id[1]] ); float factor1 = v_in.bfactor; float factor2 = 1.0f - factor1; float f1 = (factor1*m2[0]._11) + (factor2*m2[1]._11); float f2 = (factor1*m2[0]._21) + (factor2*m2[1]._21); float f3 = (factor1*m2[0]._31) + (factor2*m2[1]._31); float f4 = (factor1*m2[0]._41) + (factor2*m2[1]._41); v_out.x = (v_in.pos.x*f1 + v_in.pos.y*f2 + v_in.pos.z*f3 + f4); f1 = (factor1*m2[0]._12) + (factor2*m2[1]._12); f2 = (factor1*m2[0]._22) + (factor2*m2[1]._22); f3 = (factor1*m2[0]._32) + (factor2*m2[1]._32); f4 = (factor1*m2[0]._42) + (factor2*m2[1]._42); v_out.y = (v_in.pos.x*f1 + v_in.pos.y*f2 + v_in.pos.z*f3 + f4); f1 = (factor1*m2[0]._13) + (factor2*m2[1]._13); f2 = (factor1*m2[0]._23) + (factor2*m2[1]._23); f3 = (factor1*m2[0]._33) + (factor2*m2[1]._33); f4 = (factor1*m2[0]._43) + (factor2*m2[1]._43); v_out.z = (v_in.pos.x*f1 + v_in.pos.y*f2 + v_in.pos.z*f3 + f4); } long CZ3DMultipartSkin::GetPolyCount( int nLODLevel ) const { if( this != m_rpThis ) { return 0; } if( -1 == nLODLevel ) { nLODLevel = m_lLODLevel; } if( nLODLevel >= Z3D_LOD_LEVEL ) { return 0; } long lSum = 0; for( int i = 0; i < Z3D_MULTIPART_PORTION_COUNT; ++i ) { lSum += m_apPortion[i]->m_alIndexCount[nLODLevel]; } lSum /= 3; return lSum; }