Files
Client/GameTools/Zallad3D SceneClass/Z3DMultipartPortion.cpp
LGram16 dd97ddec92 Restructure repository to include all source folders
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>
2025-11-29 20:17:20 +09:00

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