Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1213 lines
27 KiB
C++
1213 lines
27 KiB
C++
// Z3DMultipartPortion.cpp: implementation of the Z3DMultipartPortion class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "Z3DMultipartPortion.h"
|
|
#include "Vertex.h"
|
|
#include "RenderOption.h"
|
|
#include "Shader_Rain.h"
|
|
#include "TextureUtils.h"
|
|
|
|
|
|
|
|
const long Z3DMultipartPortion::ms_lMaxVBCacheCount = 20;
|
|
long Z3DMultipartPortion::ms_lVBCacheCount = 0;
|
|
Z3DVBCacheNode* Z3DMultipartPortion::ms_pVBCacheChainHeader = NULL;
|
|
|
|
const long Z3DMultipartPortion::ms_alMaxIBCacheCount[Z3D_LOD_LEVEL] = { 20, 20, 20, 20 };
|
|
long Z3DMultipartPortion::ms_alIBCacheCount[Z3D_LOD_LEVEL] = { 0, 0, 0, 0 };
|
|
Z3DIBCacheNode* Z3DMultipartPortion::ms_apIBCacheChainHeader[Z3D_LOD_LEVEL] = { NULL, NULL, NULL, NULL };
|
|
|
|
|
|
// 실제로는 LOD단계별 index자료 설정및 vertex를 위한 공간할당
|
|
void Z3DMultipartPortion::BuildMesh( IDirect3DDevice8* pDevice )
|
|
{
|
|
std::map<int, H3DMeshTag>::iterator it, itToBeLast;
|
|
int i, j, k;
|
|
|
|
// clear previous set
|
|
m_vec_pMesh.clear();
|
|
m_vecBumpTexture.clear();
|
|
m_vecDiffuseTexture.clear();
|
|
|
|
m_vec_pTexture.clear();
|
|
m_vec_pTexture2.clear();
|
|
m_vec_pSpecTexture.clear();
|
|
m_lVertexCount = 0;
|
|
for( i = 0; i < Z3D_LOD_LEVEL; i++ )
|
|
{
|
|
m_alIndexCount[i] = 0;
|
|
}
|
|
|
|
Z3DLODMesh* pMesh;
|
|
// sum index count for each LOD level
|
|
// 그리고 각 파트의 누적순서(=렌더링순서) 리스트도 만든다.
|
|
itToBeLast = m_map_IdMeshTag.end(); // 마지막으로 돌려야될 파트의 id
|
|
for( it = m_map_IdMeshTag.begin(); it != m_map_IdMeshTag.end(); it++ )
|
|
{
|
|
pMesh = (it->second).GetObject();
|
|
|
|
_ASSERT( pMesh );
|
|
|
|
for( i = 0; i < Z3D_LOD_LEVEL; i++ )
|
|
{
|
|
m_alIndexCount[i] += pMesh->aIndex[i].lIndexCount;
|
|
}
|
|
|
|
// 머리카락 파트일 경우, 인덱스 합 계산은 위에서 하고
|
|
// 리스트에는 마지막에 넣기위해 빠짐
|
|
/* if( Z3D_MPID_EAR == it->first )
|
|
{
|
|
itToBeLast = it;
|
|
continue;
|
|
}
|
|
*/
|
|
m_vec_pMesh.push_back( pMesh );
|
|
if( Z3D_MPT_TEXTURE == m_MPT )
|
|
{
|
|
m_vec_pTexture.push_back( (m_map_IdTextureTag[it->first]).GetObject() );
|
|
|
|
if( m_map_IdTextureTag2.end() == m_map_IdTextureTag2.find( it->first ) )
|
|
{
|
|
m_vec_pTexture2.push_back( NULL );
|
|
}
|
|
else
|
|
{
|
|
m_vec_pTexture2.push_back( (m_map_IdTextureTag2[it->first]).GetObject() );
|
|
}
|
|
|
|
if( m_map_IdSpecTextureTag.end() == m_map_IdSpecTextureTag.find( it->first ) )
|
|
{
|
|
m_vec_pSpecTexture.push_back( NULL );
|
|
}
|
|
else
|
|
{
|
|
m_vec_pSpecTexture.push_back( (m_map_IdSpecTextureTag[it->first]).GetObject() );
|
|
}
|
|
if((m_map_IdTextureTag[it->first]).GetObject())
|
|
{
|
|
Z3DTexture *pTex = (m_map_IdTextureTag[it->first]).GetObject();
|
|
|
|
char strName[256];
|
|
char strTarName[256];
|
|
char strTarName2[256];
|
|
char strTarName3[256];
|
|
|
|
strcpy(strName,pTex->m_strName);
|
|
strcpy(strTarName,strName);
|
|
strcpy(strTarName2,strName);
|
|
strcpy(strTarName3,strName);
|
|
char *ptr = strchr(strTarName,'.');
|
|
*(ptr) = '_';
|
|
ptr++;
|
|
*(ptr) = 's';
|
|
ptr++;
|
|
*(ptr) = '.';
|
|
ptr++;
|
|
*(ptr) = 'b';
|
|
ptr++;
|
|
*(ptr) = 'm';
|
|
ptr++;
|
|
*(ptr) = 'p';
|
|
ptr++;
|
|
*(ptr) = '\0';
|
|
|
|
ptr = strchr(strTarName2,'.');
|
|
*(ptr) = '_';
|
|
ptr++;
|
|
*(ptr) = 'b';
|
|
ptr++;
|
|
*(ptr) = '.';
|
|
ptr++;
|
|
*(ptr) = 'b';
|
|
ptr++;
|
|
*(ptr) = 'm';
|
|
ptr++;
|
|
*(ptr) = 'p';
|
|
ptr++;
|
|
*(ptr) = '\0';
|
|
|
|
ptr = strchr(strTarName3,'.');
|
|
*(ptr) = '_';
|
|
ptr++;
|
|
*(ptr) = 'g';
|
|
ptr++;
|
|
*(ptr) = '.';
|
|
ptr++;
|
|
*(ptr) = 'b';
|
|
ptr++;
|
|
*(ptr) = 'm';
|
|
ptr++;
|
|
*(ptr) = 'p';
|
|
ptr++;
|
|
*(ptr) = '\0';
|
|
|
|
LPDIRECT3DTEXTURE8 lpDiffuse;
|
|
LPDIRECT3DTEXTURE8 lpBump;
|
|
|
|
|
|
FILE *fp1 = fopen(strName,"rb");
|
|
FILE *fp2 = fopen(strTarName,"rb");
|
|
FILE *fp3 = fopen(strTarName2,"rb");
|
|
FILE *fp4 = fopen(strTarName3,"rb");
|
|
|
|
if(fp1 == NULL || fp2 == NULL)
|
|
{
|
|
lpDiffuse = TextureUtils::CreateTextureAlpha("c:/mp-project/texture/shader/ssDiffuseMap.tga","c:/mp-project/texture/shader/dumyspec.bmp",pDevice);
|
|
|
|
//lpDiffuse = TextureUtils::CreateTextureAlpha("c:/mp-project/texture/shader/m_Sacred_armor.dds","c:/mp-project/texture/shader/m_Sacred_armor_a.dds",pDevice);
|
|
}
|
|
else
|
|
lpDiffuse = TextureUtils::CreateTextureAlpha(strName,strTarName,pDevice);
|
|
m_vecDiffuseTexture.push_back(lpDiffuse);
|
|
|
|
if(fp3 == NULL || fp4 == NULL)
|
|
{
|
|
//lpBump = TextureUtils::CreateNormalMapAlpha(10.0f,"c:/mp-project/texture/shader/m_Sacred_armor_b.dds","c:/mp-project/texture/shader/m_Sacred_armor_l.dds",pDevice);;
|
|
D3DXIMAGE_INFO imageinfo;
|
|
D3DXIMAGE_INFO imageinfo2;
|
|
|
|
D3DXGetImageInfoFromFile( "c:/mp-project/texture/shader/ssNormalsMap.tga", &imageinfo );
|
|
|
|
D3DXCreateTextureFromFileEx( pDevice,"c:/mp-project/texture/shader/ssNormalsMap.tga" ,
|
|
imageinfo.Width, imageinfo.Height, imageinfo.MipLevels, 0,
|
|
imageinfo.Format, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, 0,
|
|
&imageinfo2, NULL, (LPDIRECT3DTEXTURE8*)&lpBump );
|
|
|
|
|
|
|
|
}
|
|
else
|
|
lpBump = TextureUtils::CreateNormalMapAlpha(CRenderOption::m_fBumpScale,strTarName2,strTarName3,pDevice);
|
|
m_vecBumpTexture.push_back(lpBump);
|
|
if(fp1)
|
|
fclose(fp1);
|
|
if(fp2)
|
|
fclose(fp2);
|
|
if(fp3)
|
|
fclose(fp3);
|
|
if(fp4)
|
|
fclose(fp4);
|
|
|
|
}
|
|
else
|
|
{
|
|
LPDIRECT3DTEXTURE8 lpDiffuse = NULL;
|
|
LPDIRECT3DTEXTURE8 lpBump = NULL;
|
|
|
|
m_vecDiffuseTexture.push_back(lpDiffuse);
|
|
m_vecBumpTexture.push_back(lpBump);
|
|
}
|
|
}
|
|
}
|
|
// 마지막으로 돌려야 될 파트가 있으면..( itToBeLast의 값이 바뀌었다면)
|
|
/* if( m_map_IdMeshTag.end() != itToBeLast )
|
|
{
|
|
// 리스트에 마저 집어넣어주지롱(합은 루프안에서 이미 구해져있다)
|
|
m_vec_pMesh.push_back( (itToBeLast->second).GetObject() );
|
|
}
|
|
*/
|
|
if( 0 == m_vec_pMesh.size() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// alloc. index buffer space
|
|
for( i = 0; i < Z3D_LOD_LEVEL; i++ )
|
|
{
|
|
if( m_alIndexBufferIndexCount[i] < m_alIndexCount[i] )
|
|
{
|
|
m_alIndexBufferIndexCount[i] = GetSizeByBank( m_alIndexCount[i], Z3D_PORTION_BUFFER_BANK_SIZE*4 );
|
|
|
|
_ReleaseIndexBufferInterface( i, m_apIndexBuffer[i] );
|
|
|
|
m_apIndexBuffer[i] = _GetIndexBufferInterface( i, pDevice, m_alIndexBufferIndexCount[i] );
|
|
}
|
|
}
|
|
|
|
// fill up data
|
|
int nCount[Z3D_LOD_LEVEL] = { 0, };
|
|
|
|
WORD* apIndices[Z3D_LOD_LEVEL] = { NULL, };
|
|
for( i = 0; i < Z3D_LOD_LEVEL; ++i )
|
|
{
|
|
|
|
m_apIndexBuffer[i]->Lock( 0, 0, (BYTE**)(&apIndices[i]), D3DLOCK_DISCARD );
|
|
}
|
|
|
|
for( k = 0; k < (int)m_vec_pMesh.size(); k++ )
|
|
{
|
|
pMesh = m_vec_pMesh[k];
|
|
|
|
for( i = 0; i < Z3D_LOD_LEVEL; i++ )
|
|
{
|
|
for( j = 0; j < pMesh->aIndex[i].lIndexCount; j++ )
|
|
{
|
|
apIndices[i][nCount[i]] =
|
|
pMesh->aIndex[i].pIndices[j] + (WORD)m_lVertexCount;
|
|
|
|
(nCount[i])++;
|
|
}
|
|
}
|
|
m_lVertexCount += pMesh->lVertexCount;
|
|
}
|
|
|
|
for( i = 0; i < Z3D_LOD_LEVEL; ++i )
|
|
{
|
|
m_apIndexBuffer[i]->Unlock();
|
|
}
|
|
|
|
// vertex buffer 크기부족시 확장재할당
|
|
if( m_lVertexBufferVertexCount < m_lVertexCount )
|
|
{
|
|
m_lVertexBufferVertexCount = GetSizeByBank( m_lVertexCount, Z3D_PORTION_BUFFER_BANK_SIZE );
|
|
|
|
_ReleaseVertexBufferInterface( m_pVertexBuffer );
|
|
|
|
m_pVertexBuffer = _GetVertexBufferInterface( pDevice, m_lVertexBufferVertexCount );
|
|
|
|
|
|
}
|
|
|
|
m_bSTVertexMode = false;
|
|
SAFE_RELEASE( m_pSTVertexBuffer );
|
|
for( i = 0; i < m_vecpSTVectors.size(); ++i )
|
|
{
|
|
SAFE_DELETEA( m_vecpSTVectors[i] );
|
|
}
|
|
m_vecpSTVectors.clear();
|
|
//Rain
|
|
SAFE_RELEASE( m_lpRainVertexBuffer );
|
|
|
|
}
|
|
|
|
|
|
static void ComputeST( Z3DBlend2Vertex &rv0, Z3DBlend2Vertex &rv1, Z3DBlend2Vertex &rv2,
|
|
STVectorStorage &st0, STVectorStorage &st1, STVectorStorage &st2 )
|
|
{
|
|
// static float F_TEMP_EPSILON = 1e-6f;
|
|
static float F_TEMP_EPSILON = 0.00001f;
|
|
|
|
vector3 vEdge1, vEdge2, vCross;
|
|
|
|
vector3 vecDumyS1(0.0f,0.0f,0.0f),vecDumyT1(0.0f,0.0f,0.0f);
|
|
vector3 vecDumyS2(0.0f,0.0f,0.0f),vecDumyT2(0.0f,0.0f,0.0f);
|
|
vector3 vecDumyS3(0.0f,0.0f,0.0f),vecDumyT3(0.0f,0.0f,0.0f);
|
|
|
|
|
|
////
|
|
// x
|
|
STVectorStorage vecTangent[3];
|
|
|
|
vEdge1.x = rv1.pos.x - rv0.pos.x;
|
|
vEdge1.y = rv1.tu - rv0.tu;
|
|
vEdge1.z = rv1.tv - rv0.tv;
|
|
|
|
vEdge2.x = rv2.pos.x - rv0.pos.x;
|
|
vEdge2.y = rv2.tu - rv0.tu;
|
|
vEdge2.z = rv2.tv - rv0.tv;
|
|
|
|
vCross = vEdge1 ^ vEdge2;
|
|
vCross.Normalize();
|
|
|
|
|
|
if( fabs(vCross.x) > F_TEMP_EPSILON )
|
|
{
|
|
vecTangent[0].s.x = -vCross.y/vCross.x;
|
|
vecTangent[0].t.x = -vCross.z/vCross.x;
|
|
|
|
vecTangent[1].s.x = -vCross.y/vCross.x;
|
|
vecTangent[1].t.x = -vCross.z/vCross.x;
|
|
|
|
vecTangent[2].s.x = -vCross.y/vCross.x;
|
|
vecTangent[2].t.x = -vCross.z/vCross.x;
|
|
|
|
}
|
|
|
|
// y
|
|
vEdge1.x = rv1.pos.y - rv0.pos.y;
|
|
vEdge1.y = rv1.tu - rv0.tu;
|
|
vEdge1.z = rv1.tv - rv0.tv;
|
|
|
|
vEdge2.x = rv2.pos.y - rv0.pos.y;
|
|
vEdge2.y = rv2.tu - rv0.tu;
|
|
vEdge2.z = rv2.tv - rv0.tv;
|
|
|
|
vCross = vEdge1 ^ vEdge2;
|
|
vCross.Normalize();
|
|
|
|
|
|
if( fabs(vCross.x) > F_TEMP_EPSILON )
|
|
{
|
|
vecTangent[0].s.y = -vCross.y/vCross.x;
|
|
vecTangent[0].t.y = -vCross.z/vCross.x;
|
|
|
|
vecTangent[1].s.y = -vCross.y/vCross.x;
|
|
vecTangent[1].t.y = -vCross.z/vCross.x;
|
|
|
|
vecTangent[2].s.y = -vCross.y/vCross.x;
|
|
vecTangent[2].t.y = -vCross.z/vCross.x;
|
|
|
|
}
|
|
|
|
// z
|
|
vEdge1.x = rv1.pos.z - rv0.pos.z;
|
|
vEdge1.y = rv1.tu - rv0.tu;
|
|
vEdge1.z = rv1.tv - rv0.tv;
|
|
|
|
vEdge2.x = rv2.pos.z - rv0.pos.z;
|
|
vEdge2.y = rv2.tu - rv0.tu;
|
|
vEdge2.z = rv2.tv - rv0.tv;
|
|
|
|
vCross = vEdge1 ^ vEdge2;
|
|
vCross.Normalize();
|
|
|
|
|
|
if( fabs(vCross.x) > F_TEMP_EPSILON )
|
|
{
|
|
vecTangent[0].s.z = -vCross.y/vCross.x;
|
|
vecTangent[0].t.z = -vCross.z/vCross.x;
|
|
|
|
vecTangent[1].s.z = -vCross.y/vCross.x;
|
|
vecTangent[1].t.z = -vCross.z/vCross.x;
|
|
|
|
vecTangent[2].s.z = -vCross.y/vCross.x;
|
|
vecTangent[2].t.z = -vCross.z/vCross.x;
|
|
}
|
|
vecTangent[0].s.Normalize();
|
|
vecTangent[0].t.Normalize();
|
|
|
|
vecTangent[1].s.Normalize();
|
|
vecTangent[1].t.Normalize();
|
|
|
|
vecTangent[2].s.Normalize();
|
|
vecTangent[2].t.Normalize();
|
|
|
|
st0.s += vecTangent[0].s;
|
|
st0.t += vecTangent[0].t;
|
|
|
|
st1.s += vecTangent[1].s;
|
|
st1.t += vecTangent[1].t;
|
|
|
|
st2.s += vecTangent[2].s;
|
|
st2.t += vecTangent[2].t;
|
|
|
|
/*
|
|
vEdge1.x = rv1.pos.x - rv0.pos.x;
|
|
vEdge1.y = rv1.pos.y - rv0.pos.y;
|
|
vEdge1.z = rv1.pos.z - rv0.pos.z;
|
|
|
|
vEdge2.x = rv2.pos.x - rv0.pos.x;
|
|
vEdge2.y = rv2.pos.y - rv0.pos.y;
|
|
vEdge2.z = rv2.pos.z - rv0.pos.z;
|
|
|
|
float DeltaU1 = rv1.tu - rv0.tu;
|
|
float DeltaU2 = rv2.tu - rv0.tu;
|
|
|
|
vector3 vecV,vecU,vecW;
|
|
|
|
vecV = DeltaU2 * vEdge1 - DeltaU1 * vEdge2;
|
|
vecV.Normalize();
|
|
|
|
st0.s += vecV;
|
|
st1.s += vecV;
|
|
st2.s += vecV;
|
|
|
|
vecU = vecV ^ rv0.normal;
|
|
vecU.Normalize();
|
|
st0.t += vecU;
|
|
vecU = vecV ^ rv1.normal;
|
|
vecU.Normalize();
|
|
st1.t += vecU;
|
|
vecU = vecV ^ rv2.normal;
|
|
vecU.Normalize();
|
|
st2.t += vecU;*/
|
|
/*
|
|
|
|
// Compute edge vectors.
|
|
D3DXVECTOR3 vecNormal,vecEdge1,vecEdge2;
|
|
|
|
D3DXVECTOR2 vecTv1,vecTv2;
|
|
vEdge1.x = rv1.pos.x - rv0.pos.x;
|
|
vEdge1.y = rv1.pos.y - rv0.pos.y;
|
|
vEdge1.z = rv1.pos.z - rv0.pos.z;
|
|
|
|
vEdge2.x = rv2.pos.x - rv0.pos.x;
|
|
vEdge2.y = rv2.pos.y - rv0.pos.y;
|
|
vEdge2.z = rv2.pos.z - rv0.pos.z;
|
|
|
|
vecEdge1 = D3DXVECTOR3(vEdge1.x,vEdge1.y,vEdge1.z);
|
|
vecEdge2 = D3DXVECTOR3(vEdge2.x,vEdge2.y,vEdge2.z);
|
|
|
|
D3DXVec3Cross(&vecNormal,&vecEdge1,&vecEdge2);
|
|
D3DXVec3Normalize(&vecNormal,&vecNormal);
|
|
|
|
|
|
vecTv1.x = rv1.tu - rv0.tu;
|
|
vecTv1.y = rv1.tv - rv0.tv;
|
|
|
|
vecTv2.x = rv2.tu - rv0.tu;
|
|
vecTv2.y = rv2.tv - rv0.tv;
|
|
|
|
float a = vecTv1.x - vecTv1.y * vecTv2.x / vecTv2.y;
|
|
if (a != 0.0)
|
|
a = 1.0f/a;
|
|
|
|
float b = vecTv2.x - vecTv2.y * vecTv2.x / vecTv1.y;
|
|
if (b != 0.0)
|
|
b = 1.0f/b;
|
|
|
|
D3DXVECTOR3 vecUTmp;
|
|
vecUTmp.x = a * vEdge1.x + b * vEdge2.x;
|
|
vecUTmp.y = a * vEdge1.y + b * vEdge2.y;
|
|
vecUTmp.z = a * vEdge1.z + b * vEdge2.z;
|
|
|
|
D3DXVec3Normalize(&vecUTmp,&vecUTmp);
|
|
|
|
// Calculate v vector
|
|
a = vecTv1.y - vecTv1.x * vecTv2.y / vecTv2.x;
|
|
if (a != 0.0)
|
|
a = 1.0f/a;
|
|
|
|
b = vecTv2.y- vecTv2.x * vecTv1.y / vecTv1.x;
|
|
if (b != 0.0)
|
|
b = 1.0f/b;
|
|
|
|
D3DXVECTOR3 vecVTmp;
|
|
vecVTmp.x = a * vEdge1.x + b * vEdge2.x;
|
|
vecVTmp.y = a * vEdge1.y + b * vEdge2.y;
|
|
vecVTmp.z = a * vEdge1.z + b * vEdge2.z;
|
|
D3DXVec3Normalize(&vecUTmp,&vecUTmp);
|
|
|
|
D3DXVECTOR3 vecVertexN = D3DXVECTOR3(rv0.normal.x,rv0.normal.y,rv0.normal.z);
|
|
float fTmp = (vecUTmp.x * vecVertexN.x) + (vecUTmp.y * vecVertexN.y) + (vecUTmp.z * vecVertexN.z);
|
|
st0.s.x += vecUTmp.x - (fTmp * vecVertexN.x);
|
|
st0.s.y += vecUTmp.y - (fTmp * vecVertexN.y);
|
|
st0.s.z += vecUTmp.z - (fTmp * vecVertexN.z);
|
|
// st0.s.Normalize();
|
|
|
|
fTmp = (vecVTmp.x * vecVertexN.x) + (vecVTmp.y * vecVertexN.y) + (vecVTmp.z * vecVertexN.z);
|
|
st0.t.x += vecVTmp.x - (fTmp * vecVertexN.x);
|
|
st0.t.y += vecVTmp.y - (fTmp * vecVertexN.y);
|
|
st0.t.z += vecVTmp.z - (fTmp * vecVertexN.z);
|
|
// st0.t.Normalize();
|
|
|
|
vecVertexN = D3DXVECTOR3(rv1.normal.x,rv1.normal.y,rv1.normal.z);
|
|
fTmp = (vecUTmp.x * vecVertexN.x) + (vecUTmp.y * vecVertexN.y) + (vecUTmp.z * vecVertexN.z);
|
|
st1.s.x += vecUTmp.x - (fTmp * vecVertexN.x);
|
|
st1.s.y += vecUTmp.y - (fTmp * vecVertexN.y);
|
|
st1.s.z += vecUTmp.z - (fTmp * vecVertexN.z);
|
|
// st1.s.Normalize();
|
|
|
|
fTmp = (vecVTmp.x * vecVertexN.x) + (vecVTmp.y * vecVertexN.y) + (vecVTmp.z * vecVertexN.z);
|
|
st1.t.x += vecVTmp.x - (fTmp * vecVertexN.x);
|
|
st1.t.y += vecVTmp.y - (fTmp * vecVertexN.y);
|
|
st1.t.z += vecVTmp.z - (fTmp * vecVertexN.z);
|
|
// st1.t.Normalize();
|
|
|
|
|
|
vecVertexN = D3DXVECTOR3(rv2.normal.x,rv2.normal.y,rv2.normal.z);
|
|
fTmp = (vecUTmp.x * vecVertexN.x) + (vecUTmp.y * vecVertexN.y) + (vecUTmp.z * vecVertexN.z);
|
|
st2.s.x += vecUTmp.x - (fTmp * vecVertexN.x);
|
|
st2.s.y += vecUTmp.y - (fTmp * vecVertexN.y);
|
|
st2.s.z += vecUTmp.z - (fTmp * vecVertexN.z);
|
|
// st2.s.Normalize();
|
|
|
|
fTmp = (vecVTmp.x * vecVertexN.x) + (vecVTmp.y * vecVertexN.y) + (vecVTmp.z * vecVertexN.z);
|
|
st2.t.x += vecVTmp.x - (fTmp * vecVertexN.x);
|
|
st2.t.y += vecVTmp.y - (fTmp * vecVertexN.y);
|
|
st2.t.z += vecVTmp.z - (fTmp * vecVertexN.z);
|
|
// st2.t.Normalize();
|
|
|
|
|
|
*/
|
|
|
|
|
|
}
|
|
|
|
|
|
struct BasisFixVCST // V = pos, C = count, ST = s and t vector
|
|
{
|
|
vector3 v;
|
|
long c;
|
|
vector3 s;
|
|
vector3 t;
|
|
};
|
|
|
|
|
|
static long FindSamePositionIndexInBucket( vector3 &rv, STVectorStorage &rsts, std::vector<BasisFixVCST> &rvecVCST )
|
|
{
|
|
//static float F_TEMP_EPSILON = 1e-6f;
|
|
static float F_TEMP_EPSILON = 0.0001f;
|
|
|
|
float fx, fy, fz, fDist;
|
|
for( int i = 0; i < rvecVCST.size(); ++i )
|
|
{
|
|
fx = rvecVCST[i].v.x - rv.x;
|
|
fy = rvecVCST[i].v.y - rv.y;
|
|
fz = rvecVCST[i].v.z - rv.z;
|
|
|
|
fDist = fx*fx + fy*fy + fz*fz;
|
|
|
|
if( fDist < F_TEMP_EPSILON )
|
|
{
|
|
rvecVCST[i].c++;
|
|
rvecVCST[i].s += rsts.s;
|
|
rvecVCST[i].t += rsts.t;
|
|
|
|
return i;
|
|
}
|
|
}
|
|
|
|
// no same-positioned vertex in. add new one.
|
|
BasisFixVCST vcst;
|
|
vcst.v = rv;
|
|
vcst.c = 1;
|
|
vcst.s = rsts.s;
|
|
vcst.t = rsts.t;
|
|
|
|
rvecVCST.push_back( vcst );
|
|
|
|
return rvecVCST.size()-1;
|
|
}
|
|
|
|
|
|
static void FixVertexBasis( Z3DBlend2Vertex* pVertices, STVectorStorage* pST, long lVertexCount )
|
|
{
|
|
long* pIndex2Bucket;
|
|
|
|
pIndex2Bucket = new long[lVertexCount];
|
|
std::vector<BasisFixVCST> vecVCST;
|
|
|
|
for( int i = 0; i < lVertexCount; ++i )
|
|
{
|
|
pIndex2Bucket[i] = FindSamePositionIndexInBucket( pVertices[i].pos, pST[i], vecVCST );
|
|
}
|
|
|
|
for( i = 0; i < vecVCST.size(); ++i )
|
|
{
|
|
vecVCST[i].s.Normalize();
|
|
vecVCST[i].t.Normalize();
|
|
}
|
|
|
|
for( i = 0; i < lVertexCount; ++i )
|
|
{
|
|
pST[i].s = vecVCST[pIndex2Bucket[i]].s;
|
|
pST[i].t = vecVCST[pIndex2Bucket[i]].t;
|
|
}
|
|
|
|
SAFE_DELETEA( pIndex2Bucket );
|
|
}
|
|
|
|
|
|
void Z3DMultipartPortion::BuildSTVertex( IDirect3DDevice8* pDevice )
|
|
{
|
|
int i, j;
|
|
|
|
if( !CRenderOption::m_CharacterPerPixelLighting )
|
|
return;
|
|
//Rain
|
|
SAFE_RELEASE( m_lpRainVertexBuffer);
|
|
//
|
|
SAFE_RELEASE( m_pSTVertexBuffer );
|
|
for( i = 0; i < m_vecpSTVectors.size(); ++i )
|
|
{
|
|
SAFE_DELETEA( m_vecpSTVectors[i] );
|
|
}
|
|
m_vecpSTVectors.clear();
|
|
|
|
// st vector 값만 저장해두는 버퍼 할당
|
|
STVectorStorage* pST;
|
|
for( i = 0; i < m_vec_pMesh.size(); ++i )
|
|
{
|
|
pST = new STVectorStorage[m_vec_pMesh[i]->lVertexCount];
|
|
for( j = 0; j < m_vec_pMesh[i]->lVertexCount; ++j )
|
|
{
|
|
pST[j].s.x = pST[j].s.y = pST[j].s.z = 0.0f;
|
|
pST[j].t.x = pST[j].t.y = pST[j].t.z = 0.0f;
|
|
}
|
|
m_vecpSTVectors.push_back(pST);
|
|
}
|
|
|
|
Z3DBlend2Vertex* pVertices;
|
|
WORD* pIndices;
|
|
|
|
long lTotalCount = 0;
|
|
for( i = 0; i < m_vec_pMesh.size(); ++i )
|
|
{
|
|
pVertices = m_vec_pMesh[i]->pVertices;
|
|
pST = m_vecpSTVectors[i];
|
|
pIndices = m_vec_pMesh[i]->aIndex[0].pIndices;
|
|
|
|
for( j = 0; j < m_vec_pMesh[i]->aIndex[0].lIndexCount; j += 3 )
|
|
{
|
|
WORD i1, i2, i3;
|
|
|
|
i1 = pIndices[j];
|
|
i2 = pIndices[j+1];
|
|
i3 = pIndices[j+2];
|
|
|
|
// st 값만을 계산해 저장
|
|
ComputeST( pVertices[i1], pVertices[i2], pVertices[i3],
|
|
pST[i1], pST[i2], pST[i3] );
|
|
}
|
|
|
|
for( j = 0; j < m_vec_pMesh[i]->lVertexCount; ++j )
|
|
{
|
|
pST[j].s.Normalize();
|
|
|
|
|
|
pST[j].t.Normalize();
|
|
|
|
}
|
|
|
|
FixVertexBasis( pVertices, pST, m_vec_pMesh[i]->lVertexCount );
|
|
}
|
|
|
|
if( FAILED( pDevice->CreateVertexBuffer( m_lVertexCount*sizeof(BumpVertexST),
|
|
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_pSTVertexBuffer ) ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_bSTVertexMode = true;
|
|
|
|
//Rain
|
|
if( FAILED( pDevice->CreateVertexBuffer( m_lVertexCount*sizeof(RainVertex),
|
|
D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_lpRainVertexBuffer ) ) )
|
|
{
|
|
return;
|
|
}
|
|
m_dwRainVertexsNum = m_lVertexCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::SetMesh( const int nPartId, H3DMeshTag tagMesh )
|
|
{
|
|
std::map<int, H3DMeshTag>::iterator it_m;
|
|
|
|
it_m = m_map_IdMeshTag.find( nPartId );
|
|
if( m_map_IdMeshTag.end() != it_m )
|
|
{
|
|
// 슬롯에 세팅될 메시가 이전에 세팅되어있던 메시와 같은가?
|
|
if( (it_m->second) == tagMesh )
|
|
{
|
|
// 중복이므로 현재 불러온 메시 release
|
|
tagMesh.Release();
|
|
|
|
// 메시가 바뀌지 않았으므로, blending재계산 필요가 없으므로 false반환
|
|
return false;
|
|
}
|
|
// 이전에 세팅된 mesh release
|
|
else
|
|
{
|
|
it_m->second.Release();
|
|
}
|
|
}
|
|
|
|
// setting
|
|
m_map_IdMeshTag[nPartId] = tagMesh;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::DeleteMesh( const int nPartId )
|
|
{
|
|
std::map<int, H3DMeshTag>::iterator it_m;
|
|
|
|
it_m = m_map_IdMeshTag.find( nPartId );
|
|
if( m_map_IdMeshTag.end() == it_m )
|
|
{
|
|
return false; // id에 해당하는 mesh가 세팅되어있지 않다.
|
|
}
|
|
|
|
// deleting
|
|
it_m->second.Release();
|
|
m_map_IdMeshTag.erase(it_m);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::SetTexPiece( const int nPartId, H3DTexPieceTag tagTexpiece )
|
|
{
|
|
std::map<int, H3DTexPieceTag>::iterator it_t;
|
|
|
|
it_t = m_map_IdTexPieceTag.find( nPartId );
|
|
if( m_map_IdTexPieceTag.end() != it_t )
|
|
{
|
|
// same as previous
|
|
if( (it_t->second) == tagTexpiece )
|
|
{
|
|
tagTexpiece.Release();
|
|
return false;
|
|
}
|
|
|
|
// 이전에 세팅된 texpiece container instance를 release해준다
|
|
else
|
|
{
|
|
it_t->second.Release();
|
|
}
|
|
}
|
|
|
|
// setting
|
|
m_map_IdTexPieceTag[nPartId] = tagTexpiece;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::SetTexPiece2( const int nPartId, H3DTexPieceTag tagTexpiece )
|
|
{
|
|
std::map<int, H3DTexPieceTag>::iterator it_t;
|
|
|
|
it_t = m_map_IdTexPieceTag2.find( nPartId );
|
|
if( m_map_IdTexPieceTag2.end() != it_t )
|
|
{
|
|
// same as previous
|
|
if( (it_t->second) == tagTexpiece )
|
|
{
|
|
tagTexpiece.Release();
|
|
return false;
|
|
}
|
|
|
|
// 이전에 세팅된 texpiece container instance를 release해준다
|
|
else
|
|
{
|
|
it_t->second.Release();
|
|
}
|
|
}
|
|
|
|
// setting
|
|
m_map_IdTexPieceTag2[nPartId] = tagTexpiece;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::DeleteTexPiece( const int nPartId )
|
|
{
|
|
std::map<int, H3DTexPieceTag>::iterator it_t;
|
|
|
|
it_t = m_map_IdTexPieceTag.find( nPartId );
|
|
if( m_map_IdTexPieceTag.end() == it_t )
|
|
{
|
|
return false; // id에 해당하는 texpiece세팅이 되어있지 않다.
|
|
}
|
|
|
|
it_t->second.Release();
|
|
m_map_IdTexPieceTag.erase(it_t);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::SetTexture( const int nPartId, H3DTextureTag tagTexture )
|
|
{
|
|
std::map<int, H3DTextureTag>::iterator it_t;
|
|
|
|
it_t = m_map_IdTextureTag.find( nPartId );
|
|
if( m_map_IdTextureTag.end() != it_t )
|
|
{
|
|
// same as previous
|
|
if( (it_t->second) == tagTexture )
|
|
{
|
|
tagTexture.Release();
|
|
return false;
|
|
}
|
|
|
|
// 이전에 세팅된 texpiece container instance를 release해준다
|
|
else
|
|
{
|
|
it_t->second.Release();
|
|
}
|
|
}
|
|
|
|
// setting
|
|
m_map_IdTextureTag[nPartId] = tagTexture;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::SetTexture2( const int nPartId, H3DTextureTag tagTexture )
|
|
{
|
|
std::map<int, H3DTextureTag>::iterator it_t;
|
|
|
|
it_t = m_map_IdTextureTag2.find( nPartId );
|
|
if( m_map_IdTextureTag2.end() != it_t )
|
|
{
|
|
// same as previous
|
|
if( (it_t->second) == tagTexture )
|
|
{
|
|
tagTexture.Release();
|
|
return false;
|
|
}
|
|
|
|
// 이전에 세팅된 texpiece container instance를 release해준다
|
|
else
|
|
{
|
|
it_t->second.Release();
|
|
}
|
|
}
|
|
|
|
// setting
|
|
m_map_IdTextureTag2[nPartId] = tagTexture;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::SetSpecTexture( const int nPartId, H3DTextureTag tagTexture )
|
|
{
|
|
std::map<int, H3DTextureTag>::iterator it_t;
|
|
|
|
it_t = m_map_IdSpecTextureTag.find( nPartId );
|
|
if( m_map_IdSpecTextureTag.end() != it_t )
|
|
{
|
|
// same as previous
|
|
if( (it_t->second) == tagTexture )
|
|
{
|
|
tagTexture.Release();
|
|
return false;
|
|
}
|
|
|
|
// 이전에 세팅된 texpiece container instance를 release해준다
|
|
else
|
|
{
|
|
it_t->second.Release();
|
|
}
|
|
}
|
|
|
|
// setting
|
|
m_map_IdSpecTextureTag[nPartId] = tagTexture;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::DeleteTexture( const int nPartId )
|
|
{
|
|
std::map<int, H3DTextureTag>::iterator it_t;
|
|
|
|
it_t = m_map_IdTextureTag.find( nPartId );
|
|
if( m_map_IdTextureTag.end() != it_t )
|
|
{
|
|
it_t->second.Release();
|
|
m_map_IdTextureTag.erase( it_t );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::DeleteTexture2( const int nPartId )
|
|
{
|
|
std::map<int, H3DTextureTag>::iterator it_t;
|
|
|
|
it_t = m_map_IdTextureTag2.find( nPartId );
|
|
if( m_map_IdTextureTag2.end() != it_t )
|
|
{
|
|
it_t->second.Release();
|
|
m_map_IdTextureTag2.erase( it_t );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::DeleteSpecTexture( const int nPartId )
|
|
{
|
|
std::map<int, H3DTextureTag>::iterator it_t;
|
|
|
|
it_t = m_map_IdSpecTextureTag.find( nPartId );
|
|
if( m_map_IdSpecTextureTag.end() != it_t )
|
|
{
|
|
it_t->second.Release();
|
|
m_map_IdSpecTextureTag.erase( it_t );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::BatchOpen()
|
|
{
|
|
/*map<int, Z3DMeshTag>::iterator it_m;
|
|
for( it_m = m_map_IdMeshTag.begin(); it_m != m_map_IdMeshTag.end(); it_m++ )
|
|
{
|
|
g_ContLODMesh.Release(it_m->second);
|
|
}
|
|
m_map_IdMeshTag.clear();*/
|
|
|
|
/*map<int, Z3DTexPieceTag>::iterator it_t;
|
|
for( it_t = m_map_IdTexPieceTag.begin(); it_t != m_map_IdTexPieceTag.end(); it_t++ )
|
|
{
|
|
g_ContTexturePiece.Release(it_t->second);
|
|
}
|
|
m_map_IdTexPieceTag.clear();*/
|
|
|
|
/*m_vec_pMesh.clear();
|
|
|
|
m_lVertexCount = 0;
|
|
SAFE_DELETEA( m_pVertices );
|
|
|
|
for( int i = 0; i < Z3D_LOD_LEVEL; i++ )
|
|
{
|
|
m_aIndices[i].lIndexCount = 0;
|
|
SAFE_DELETEA( m_aIndices[i].pIndices );
|
|
}*/
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Z3DMultipartPortion::BatchClose( IDirect3DDevice8* pDevice )
|
|
{
|
|
BuildMesh( pDevice );
|
|
|
|
std::map<int, H3DTexPieceTag>::iterator it_t;
|
|
for( it_t = m_map_IdTexPieceTag.begin(); it_t != m_map_IdTexPieceTag.end(); it_t++ )
|
|
{
|
|
(it_t->second).GetObject()->Blt2Texture( *m_pTexture );
|
|
}
|
|
|
|
for( it_t = m_map_IdTexPieceTag2.begin(); it_t != m_map_IdTexPieceTag2.end(); it_t++ )
|
|
{
|
|
(it_t->second).GetObject()->Blt2Texture( *m_pTexture2 );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
IDirect3DVertexBuffer8* Z3DMultipartPortion::_GetVertexBufferInterface( IDirect3DDevice8* pDevice, long& rlVertexCount )
|
|
{
|
|
IDirect3DVertexBuffer8* pVB = NULL;
|
|
Z3DVBCacheNode* pChainNode = ms_pVBCacheChainHeader;
|
|
Z3DVBCacheNode* pPrevNode = NULL;
|
|
|
|
while( pChainNode )
|
|
{
|
|
if( rlVertexCount <= pChainNode->lVertexCount )
|
|
{
|
|
pVB = pChainNode->pVB;
|
|
rlVertexCount = pChainNode->lVertexCount;
|
|
|
|
// 삭제될 노드의 앞-뒤 노드간 연결 설정
|
|
if( pPrevNode )
|
|
{
|
|
pPrevNode->pNext = pChainNode->pNext;
|
|
}
|
|
|
|
// 삭제될 노드가 head일경우 head pointer 조정
|
|
if( ms_pVBCacheChainHeader == pChainNode )
|
|
{
|
|
ms_pVBCacheChainHeader = pChainNode->pNext;
|
|
}
|
|
|
|
// 노드 삭제
|
|
SAFE_DELETE( pChainNode );
|
|
--ms_lVBCacheCount;
|
|
|
|
break;
|
|
}
|
|
|
|
pPrevNode = pChainNode;
|
|
pChainNode = pChainNode->pNext;
|
|
}
|
|
|
|
if( pVB )
|
|
{
|
|
return pVB;
|
|
}
|
|
|
|
if(CRenderOption::m_CharacterPerPixelLighting)
|
|
{
|
|
if( FAILED( pDevice->CreateVertexBuffer( rlVertexCount*sizeof(BumpVertex),
|
|
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
|
|
D3DPOOL_DEFAULT, &pVB ) ) )
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( FAILED( pDevice->CreateVertexBuffer( rlVertexCount*sizeof(D3DVERTEX),
|
|
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_VERTEX,
|
|
D3DPOOL_DEFAULT, &pVB ) ) )
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return pVB;
|
|
}
|
|
|
|
|
|
void Z3DMultipartPortion::_ReleaseVertexBufferInterface( IDirect3DVertexBuffer8* pVB )
|
|
{
|
|
if( NULL == pVB )
|
|
{
|
|
return;
|
|
}
|
|
|
|
Z3DVBCacheNode* pNode;
|
|
Z3DVBCacheNode* pPrev = NULL;
|
|
|
|
// 캐시 오버플로시 가장 오래된 노드 삭제
|
|
if( ms_lVBCacheCount == ms_lMaxVBCacheCount )
|
|
{
|
|
pNode = ms_pVBCacheChainHeader;
|
|
|
|
while( pNode->pNext )
|
|
{
|
|
pPrev = pNode;
|
|
pNode = pNode->pNext;
|
|
}
|
|
SAFE_RELEASE( pNode->pVB );
|
|
SAFE_DELETE( pNode );
|
|
if( pPrev )
|
|
{
|
|
pPrev->pNext = NULL;
|
|
}
|
|
--ms_lVBCacheCount;
|
|
}
|
|
|
|
pNode = new Z3DVBCacheNode;
|
|
D3DVERTEXBUFFER_DESC d3dvbd;
|
|
pVB->GetDesc( &d3dvbd );
|
|
pNode->lVertexCount = d3dvbd.Size /
|
|
((CRenderOption::m_CharacterPerPixelLighting) ? sizeof(BumpVertex) : sizeof(D3DVERTEX) );
|
|
pNode->pVB = pVB;
|
|
pNode->pNext = ms_pVBCacheChainHeader;
|
|
ms_pVBCacheChainHeader = pNode;
|
|
++ms_lVBCacheCount;
|
|
}
|
|
|
|
|
|
IDirect3DIndexBuffer8* Z3DMultipartPortion::_GetIndexBufferInterface( long lLODIndex, IDirect3DDevice8* pDevice, long rlIndexCount )
|
|
{
|
|
IDirect3DIndexBuffer8* pIB = NULL;
|
|
Z3DIBCacheNode* pChainNode = ms_apIBCacheChainHeader[lLODIndex];
|
|
Z3DIBCacheNode* pPrevNode = NULL;
|
|
|
|
while( pChainNode )
|
|
{
|
|
if( rlIndexCount <= pChainNode->lIndexCount )
|
|
{
|
|
pIB = pChainNode->pIB;
|
|
rlIndexCount = pChainNode->lIndexCount;
|
|
|
|
// 삭제될 노드의 앞-뒤 노드간 연결 설정
|
|
if( pPrevNode )
|
|
{
|
|
pPrevNode->pNext = pChainNode->pNext;
|
|
}
|
|
|
|
// 삭제될 노드가 head일경우 head pointer 조정
|
|
if( ms_apIBCacheChainHeader[lLODIndex] == pChainNode )
|
|
{
|
|
ms_apIBCacheChainHeader[lLODIndex] = pChainNode->pNext;
|
|
}
|
|
|
|
// 노드 삭제
|
|
SAFE_DELETE( pChainNode );
|
|
--ms_alIBCacheCount[lLODIndex];
|
|
|
|
break;
|
|
}
|
|
|
|
pPrevNode = pChainNode;
|
|
pChainNode = pChainNode->pNext;
|
|
}
|
|
|
|
if( pIB )
|
|
{
|
|
return pIB;
|
|
}
|
|
|
|
if( FAILED( pDevice->CreateIndexBuffer( rlIndexCount * sizeof(WORD),
|
|
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16,
|
|
D3DPOOL_DEFAULT, &(pIB) ) ) )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return pIB;
|
|
}
|
|
|
|
|
|
void Z3DMultipartPortion::_ReleaseIndexBufferInterface( long lLODIndex, IDirect3DIndexBuffer8* pIB )
|
|
{
|
|
if( NULL == pIB )
|
|
{
|
|
return;
|
|
}
|
|
|
|
Z3DIBCacheNode* pNode;
|
|
Z3DIBCacheNode* pPrev = NULL;
|
|
|
|
// 캐시 오버플로시 가장 오래된 노드 삭제
|
|
if( ms_alIBCacheCount[lLODIndex] == ms_alMaxIBCacheCount[lLODIndex] )
|
|
{
|
|
pNode = ms_apIBCacheChainHeader[lLODIndex];
|
|
|
|
while( pNode->pNext )
|
|
{
|
|
pPrev = pNode;
|
|
pNode = pNode->pNext;
|
|
}
|
|
SAFE_RELEASE( pNode->pIB );
|
|
SAFE_DELETE( pNode );
|
|
if( pPrev )
|
|
{
|
|
pPrev->pNext = NULL;
|
|
}
|
|
--ms_alIBCacheCount[lLODIndex];
|
|
}
|
|
|
|
pNode = new Z3DIBCacheNode;
|
|
D3DINDEXBUFFER_DESC d3dibd;
|
|
pIB->GetDesc( &d3dibd );
|
|
pNode->lIndexCount = d3dibd.Size / sizeof(WORD);
|
|
pNode->pIB = pIB;
|
|
pNode->pNext = ms_apIBCacheChainHeader[lLODIndex];
|
|
ms_apIBCacheChainHeader[lLODIndex] = pNode;
|
|
++ms_alIBCacheCount[lLODIndex];
|
|
}
|
|
|
|
|
|
void Z3DMultipartPortion::_Close()
|
|
{
|
|
Z3DVBCacheNode* pVBChainNode = ms_pVBCacheChainHeader;
|
|
Z3DVBCacheNode* pVBTmp;
|
|
|
|
while( pVBChainNode )
|
|
{
|
|
pVBTmp = pVBChainNode;
|
|
pVBChainNode = pVBChainNode->pNext;
|
|
SAFE_RELEASE( pVBTmp->pVB );
|
|
SAFE_DELETE( pVBTmp );
|
|
}
|
|
|
|
Z3DIBCacheNode* pIBChainNode;
|
|
Z3DIBCacheNode* pIBTmp;
|
|
|
|
for( int i = 0; i < Z3D_LOD_LEVEL; ++i )
|
|
{
|
|
pIBChainNode = ms_apIBCacheChainHeader[i];
|
|
|
|
while( pIBChainNode )
|
|
{
|
|
pIBTmp = pIBChainNode;
|
|
pIBChainNode = pIBChainNode->pNext;
|
|
SAFE_RELEASE( pIBTmp->pIB );
|
|
SAFE_DELETE( pIBTmp );
|
|
}
|
|
}
|
|
}
|