Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
408 lines
11 KiB
C++
408 lines
11 KiB
C++
#include "DrawElement.h"
|
||
#include <algorithm>
|
||
|
||
|
||
namespace Caldron
|
||
{
|
||
namespace Scene
|
||
{
|
||
IDirect3DDevice8* CDrawElementMgr::ms_pDevice;
|
||
|
||
std::vector< DRAW_ELEMENT > CDrawElementMgr::ms_avecDynamicDrawElement[MAX_DRAW_ELEMENT_LAYER];
|
||
// std::vector< DRAW_ELEMENT > CDrawElementMgr::ms_avecStaticDrawElement[MAX_DRAW_ELEMENT_LAYER];
|
||
|
||
int CDrawElementMgr::ms_nDynamicVertexBufferCount;
|
||
DWORD CDrawElementMgr::ms_dwDynamicVertexBufferSize;
|
||
|
||
int CDrawElementMgr::ms_nDynamicIndexBufferCount;
|
||
DWORD CDrawElementMgr::ms_dwDynamicIndexBufferSize;
|
||
|
||
// int CDrawElementMgr::ms_nStaticVertexBufferCount;
|
||
// DWORD CDrawElementMgr::ms_dwStaticVertexBufferSize;
|
||
|
||
// int CDrawElementMgr::ms_nStaticIndexBufferCount;
|
||
// DWORD CDrawElementMgr::ms_dwStaticIndexBufferSize;
|
||
|
||
// IDirect3DVertexBuffer8** CDrawElementMgr::ms_apDynamicVertexBuffer;
|
||
// IDirect3DIndexBuffer8** CDrawElementMgr::ms_apDynaicIndexBuffer;
|
||
IDirect3DVertexBuffer8* CDrawElementMgr::ms_pDynamicVertexBuffer;
|
||
IDirect3DIndexBuffer8* CDrawElementMgr::ms_pDynamicIndexBuffer;
|
||
|
||
std::map< CBaseMesh*, UINT > CDrawElementMgr::ms_mapVBAllocationInfo;
|
||
std::map< CBaseMesh*, UINT > CDrawElementMgr::ms_mapIBAllocationInfo;
|
||
int CDrawElementMgr::ms_nVBUsedInByte;
|
||
int CDrawElementMgr::ms_nIBUsedInByte;
|
||
|
||
|
||
// IDirect3DVertexBuffer8** CDrawElementMgr::ms_apStaticVertexBuffer;
|
||
// IDirect3DIndexBuffer8** CDrawElementMgr::ms_apStaticIndexBuffer;
|
||
|
||
DRAW_ELEMENT CDrawElementMgr::ms_LastTimeDE;
|
||
|
||
|
||
bool CDrawElementMgr::_Init( IDirect3DDevice8* pDevice, DRAW_ELEMENT_MGR_INIT_PARAM* pInitParam )
|
||
{
|
||
ms_pDevice = pDevice;
|
||
|
||
HRESULT hr;
|
||
|
||
// dynamic VB ÇÒ´ç
|
||
hr = pDevice->CreateVertexBuffer( pInitParam->dwDynamicVertexBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY,
|
||
0, D3DPOOL_DEFAULT, &ms_pDynamicVertexBuffer );
|
||
if( FAILED(hr) )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// dynamic IB ÇÒ´ç
|
||
hr = pDevice->CreateIndexBuffer( pInitParam->dwDynamicIndexBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY,
|
||
D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ms_pDynamicIndexBuffer );
|
||
if( FAILED(hr) )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// static VB ÇÒ´ç
|
||
// ÇöÀç¾øÀ½
|
||
|
||
// static IB ÇÒ´ç
|
||
// ÇöÀç¾øÀ½
|
||
|
||
|
||
ms_nDynamicVertexBufferCount = 1;//pInitParam->nDynamicVertexBufferCount;
|
||
ms_dwDynamicVertexBufferSize = pInitParam->dwDynamicVertexBufferSize;
|
||
|
||
ms_nDynamicIndexBufferCount = 1;//pInitParam->nDynamicIndexBufferCount;
|
||
ms_dwDynamicIndexBufferSize = pInitParam->dwDynamicIndexBufferSize;
|
||
|
||
|
||
// ms_nStaticVertexBufferCount = pInitParam->nStaticVertexBufferCount;
|
||
// ms_dwStaticVertexBufferSize = pInitParam->dwStaticVertexBufferSize;
|
||
|
||
// ms_nStaticIndexBufferCount = pInitParam->nStaticIndexBufferCount;
|
||
// ms_dwStaticIndexBufferSize = pInitParam->dwStaticIndexBufferSize;
|
||
|
||
|
||
ms_LastTimeDE.pMesh = NULL;
|
||
ms_LastTimeDE.pTM = NULL;
|
||
ms_LastTimeDE.pTextureTM = NULL;
|
||
ms_LastTimeDE.textureSlot.apTexture[0] = NULL;
|
||
ms_LastTimeDE.textureSlot.nUsed = 1;
|
||
ms_LastTimeDE.hVertexShader = NULL;
|
||
ms_LastTimeDE.hPixelShader = NULL;
|
||
ms_LastTimeDE.pStateSet = NULL;
|
||
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
bool CDrawElementMgr::_RegisterDrawElement( int nLayer, DRAW_ELEMENT& rDE )
|
||
{
|
||
if( nLayer >= MAX_DRAW_ELEMENT_LAYER )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
if( false == rDE.ValidityCheck() )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// D/E °¢ ¿ä¼Òµé¿¡ ´ëÇÑ lock ÀÌ ÇÊ¿äÇÒµí.. ±×·±µ¥ ÀÌ·¸°Ô ÇÏ·Á¸é °¢ ¿ä¼Òµé ¸ðµÎ lockable ÇÑ °´Ã¼·Î ¹Ù²ãÁà¾ßÇÑ´Ù.
|
||
rDE.pMesh->Lock();
|
||
|
||
ms_avecDynamicDrawElement[nLayer].push_back( rDE );
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
// bool CDrawElementMgr::_RegisterStaticDrawElement( int nLayer, DRAW_ELEMENT& rDE )
|
||
// {
|
||
// //
|
||
// // ÇöÀç´Â dynamic À϶§¿Í ±¸ÇöÀÌ °°À¸³ª Â÷ÈÄ ¹Ù²ð ¼ö ÀÖÀ½
|
||
// //
|
||
//
|
||
// if( nLayer >= MAX_DRAW_ELEMENT_LAYER )
|
||
// {
|
||
// return false;
|
||
// }
|
||
//
|
||
// if( false ==rDE.ValidityCheck() )
|
||
// {
|
||
// return false;
|
||
// }
|
||
//
|
||
// // D/E °¢ ¿ä¼Òµé¿¡ ´ëÇÑ lock ÀÌ ÇÊ¿äÇÒµí.. ±×·±µ¥ ÀÌ·¸°Ô ÇÏ·Á¸é °¢ ¿ä¼Òµé ¸ðµÎ lockable ÇÑ °´Ã¼·Î ¹Ù²ãÁà¾ßÇÑ´Ù.
|
||
//
|
||
// ms_avecDynamicDrawElement[nLayer].push_back( rDE );
|
||
//
|
||
// return true;
|
||
// }
|
||
|
||
void CDrawElementMgr::_Process()
|
||
{
|
||
VIB_PACKET packet;
|
||
|
||
// sort
|
||
_Sort();
|
||
|
||
// optimize
|
||
_Optimize();
|
||
|
||
|
||
|
||
for( int i = 0; i < MAX_DRAW_ELEMENT_LAYER; ++i )
|
||
{
|
||
// per-layer setting ( ex) Render Target Change )
|
||
// render target, view matrix, projection matrix º¯°æ Àû¿ë
|
||
|
||
|
||
|
||
std::vector< DRAW_ELEMENT > & rvecDE = ms_avecDynamicDrawElement[i]; // shortcut to i-th layer of D/E vector
|
||
|
||
for( int j = 0; j < rvecDE.size(); ++j )
|
||
{
|
||
DRAW_ELEMENT &rCurrentDrawElement = rvecDE[j];
|
||
|
||
// mesh data uploading (to VB/IB )
|
||
_UploadMesh( rCurrentDrawElement, packet );
|
||
|
||
// draw primitive(include state setting)
|
||
_Render( rCurrentDrawElement, packet );
|
||
|
||
// unlock D/E related components
|
||
// Áö±ÝÀº CMesh ¸¸ Lock/Unlock ±¸ÇöµÇ¾îÀÖÀ½
|
||
rCurrentDrawElement.pMesh->Unlock();
|
||
}
|
||
|
||
// flush D/E list 'cause this is DYNAMIC D/E list
|
||
rvecDE.clear();
|
||
}
|
||
|
||
ms_pDevice->SetStreamSource( 0, NULL, 0 );
|
||
ms_pDevice->SetIndices( NULL, 0 );
|
||
}
|
||
|
||
void CDrawElementMgr::_Close()
|
||
{
|
||
// VB/IB ÇØÁ¦
|
||
SafeRelease( ms_pDynamicVertexBuffer );
|
||
SafeRelease( ms_pDynamicIndexBuffer );
|
||
}
|
||
|
||
// D/E sort comparison processor
|
||
bool DE_Ascend( DRAW_ELEMENT rDE1, DRAW_ELEMENT rDE2 )
|
||
{
|
||
if( rDE1.textureSlot.apTexture[0] > rDE2.textureSlot.apTexture[0] ) return false;
|
||
if( rDE1.pTM > rDE2.pTM ) return false;
|
||
if( rDE1.hVertexShader > rDE2.hVertexShader ) return false;
|
||
if( rDE1.hPixelShader > rDE2.hPixelShader ) return false;
|
||
if( rDE1.pStateSet > rDE2.pStateSet ) return false;
|
||
if( rDE1.pMesh > rDE2.pMesh ) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
void CDrawElementMgr::_Sort()
|
||
{
|
||
for( int i = 0; i < MAX_DRAW_ELEMENT_LAYER; ++i )
|
||
{
|
||
std::stable_sort( ms_avecDynamicDrawElement[i].begin(), ms_avecDynamicDrawElement[i].end(), DE_Ascend );
|
||
}
|
||
|
||
}
|
||
|
||
|
||
void CDrawElementMgr::_Optimize()
|
||
{
|
||
// nothing now..
|
||
}
|
||
|
||
|
||
void CDrawElementMgr::_UploadMesh( DRAW_ELEMENT &rDE, VIB_PACKET &rPacket )
|
||
{
|
||
std::map< CBaseMesh*, UINT >::iterator it;
|
||
BYTE* pByteDataInBuffer = NULL;
|
||
UINT uSizeInByte; // ÇÒ´çµÉ mesh data ÀÇ byte »çÀÌÁî
|
||
UINT uAllocOffset; // buffer »ó¿¡ upload µÉ À§Ä¡
|
||
UINT uRemain; // buffer »ó¿¡ ³²¾ÆÀÖ´Â °ø°£
|
||
HRESULT hr;
|
||
|
||
// VB »ó¿¡ ÀÌ¹Ì upload µÇ¾îÀÖ´Â mesh Àΰ¡?
|
||
it = ms_mapVBAllocationInfo.find( rDE.pMesh );
|
||
if( it != ms_mapVBAllocationInfo.end() )
|
||
{
|
||
// ±×·¸´Ù¸é ±âÁ¸ Á¤º¸¸¸ VIB packet ¿¡ ±â·Ï
|
||
rPacket.uPositionInVB = it->second;
|
||
}
|
||
else
|
||
{
|
||
// ¾Æ´Ï¸é ÇÒ´ç °úÁ¤
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// DrawPrimitive °è¿ÀÇ offset °ü·Ã ÆÄ¶ó¹ÌÅ͵éÀÌ vertex °¹¼ö ´ÜÀ§À̹ǷÎ
|
||
// mesh vertex data°¡ upload µÉ °æ¿ì ±× À§Ä¡¸¦ vertex size¿¡ ¸Â°Ô align
|
||
// ÇØ ÁØ´Ù.
|
||
//
|
||
|
||
uSizeInByte = rDE.pMesh->GetVertexCount() * rDE.pMesh->GetVertexSize();
|
||
|
||
UINT uUsedAlignFixed = (ms_nVBUsedInByte % rDE.pMesh->GetVertexSize() ) ?
|
||
( ( ms_nVBUsedInByte/rDE.pMesh->GetVertexSize() ) + 1 ) * rDE.pMesh->GetVertexSize() :
|
||
ms_nVBUsedInByte; // vertex size °æ°è¿¡ ¸ÂÃç ¿Ã¸²
|
||
uRemain = ms_dwDynamicVertexBufferSize - uUsedAlignFixed;
|
||
|
||
// Lock VB
|
||
if( uRemain < uSizeInByte )
|
||
{
|
||
// °ø°£ÀÌ ºÎÁ·ÇÒ¶§ -> discard all & reset alloc info
|
||
uAllocOffset = 0;
|
||
hr = ms_pDynamicVertexBuffer->Lock( uAllocOffset, uSizeInByte, &pByteDataInBuffer, D3DLOCK_DISCARD );
|
||
if( FAILED(hr) )
|
||
{
|
||
return; // Lock ½ÇÆÐ½Ã °Á ¸®ÅÏ..-_-
|
||
}
|
||
|
||
// VB flush, ÇÒ´çÁ¤º¸ clear
|
||
ms_mapVBAllocationInfo.clear();
|
||
ms_nVBUsedInByte = 0;
|
||
}
|
||
else
|
||
{
|
||
// °ø°£ÀÌ ÃæºÐÇÒ¶§ -> °Á Lock
|
||
uAllocOffset = uUsedAlignFixed;
|
||
hr = ms_pDynamicVertexBuffer->Lock( uAllocOffset, uSizeInByte, &pByteDataInBuffer, D3DLOCK_NOOVERWRITE );
|
||
if( FAILED(hr) )
|
||
{
|
||
return; // Lock ½ÇÆÐ½Ã °Á ¸®ÅÏ..-_-
|
||
}
|
||
}
|
||
|
||
// upload, ÇÒ´çÁ¤º¸ °»½Å
|
||
rDE.pMesh->UploadVertexData( pByteDataInBuffer );
|
||
ms_pDynamicVertexBuffer->Unlock();
|
||
|
||
ms_mapVBAllocationInfo[rDE.pMesh] = uAllocOffset;
|
||
ms_nVBUsedInByte = uUsedAlignFixed + uSizeInByte;
|
||
}
|
||
|
||
// indexed mesh °¡ ¾Æ´Ï¸é -> Á¾·á
|
||
if( !( rDE.pMesh->IsIndexed() ) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
// IB ¿¡µµ VB ¿Í °°Àº °úÁ¤ ¹Ýº¹
|
||
|
||
// IB »ó¿¡ ÀÌ¹Ì upload µÇ¾îÀÖ´Â mesh Àΰ¡?
|
||
it = ms_mapIBAllocationInfo.find( rDE.pMesh );
|
||
if( it != ms_mapIBAllocationInfo.end() )
|
||
{
|
||
// ±×·¸´Ù¸é ±âÁ¸ Á¤º¸¸¸ VIB packet ¿¡ ±â·Ï
|
||
rPacket.uPositionInIB = it->second;
|
||
}
|
||
else
|
||
{
|
||
// ¾Æ´Ï¸é ÇÒ´ç °úÁ¤
|
||
|
||
uSizeInByte = rDE.pMesh->GetIndexCount() * sizeof(WORD);
|
||
uRemain = ms_dwDynamicIndexBufferSize - ms_nIBUsedInByte;
|
||
|
||
// Lock IB
|
||
if( uRemain < uSizeInByte )
|
||
{
|
||
// °ø°£ÀÌ ºÎÁ·ÇÒ¶§ -> discard all & reset alloc info
|
||
uAllocOffset = 0;
|
||
hr = ms_pDynamicIndexBuffer->Lock( uAllocOffset, uSizeInByte, &pByteDataInBuffer, D3DLOCK_DISCARD );
|
||
if( FAILED(hr) )
|
||
{
|
||
return; // Lock ½ÇÆÐ½Ã °Á ¸®ÅÏ..-_-
|
||
}
|
||
|
||
// IB flush, ÇÒ´çÁ¤º¸ clear
|
||
ms_mapIBAllocationInfo.clear();
|
||
ms_nIBUsedInByte = 0;
|
||
}
|
||
else
|
||
{
|
||
// °ø°£ÀÌ ÃæºÐÇÒ¶§ -> °Á Lock
|
||
uAllocOffset = ms_nIBUsedInByte;
|
||
hr = ms_pDynamicIndexBuffer->Lock( uAllocOffset, uSizeInByte, &pByteDataInBuffer, D3DLOCK_NOOVERWRITE );
|
||
if( FAILED(hr) )
|
||
{
|
||
return; // Lock ½ÇÆÐ½Ã °Á ¸®ÅÏ..-_-
|
||
}
|
||
}
|
||
|
||
// upload, ÇÒ´çÁ¤º¸ °»½Å
|
||
rDE.pMesh->UploadIndexData( pByteDataInBuffer );
|
||
ms_pDynamicIndexBuffer->Unlock();
|
||
|
||
ms_mapIBAllocationInfo[rDE.pMesh] = uAllocOffset;
|
||
ms_nIBUsedInByte += uSizeInByte;
|
||
}
|
||
}
|
||
|
||
|
||
void CDrawElementMgr::_Render( DRAW_ELEMENT &rDE, VIB_PACKET &rPacket )
|
||
{
|
||
// ÀÓ½ÃÄÚµå
|
||
ms_pDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
|
||
ms_pDevice->LightEnable( 0, TRUE );
|
||
|
||
|
||
// ms_LastTimeDE ¿Í rDE °¢ ÄÄÆ÷³ÍÆ®º° ºñ±³ ÈÄ ´Ù¸¥ ÄÄÆ÷³ÍÆ®ÀÇ Àû¿ë
|
||
|
||
// rPacket ¿¡ VB/IB °¡ last time °ú ´Ù¸¦ °æ¿ì stream source ¸¦ ¹Ù²ãÁà¾ß..ÇÏÁö¸¸
|
||
// ÇöÀç´Â VB/IB °¡ Çϳª»ÓÀ̹ǷΠ»ý·«
|
||
// ...ÇÏ·Á°í ÇßÀ¸³ª, SSS¿¡ stride °¡ ÆÄ¶ó¹ÌÅÍ·Î µé¾î°¡¹Ç·Î ¸Å¹ø ÇØÁִ°ÍÀ¸·Î °áÁ¤-_-;
|
||
ms_pDevice->SetStreamSource( 0, ms_pDynamicVertexBuffer, rDE.pMesh->GetVertexSize() );
|
||
|
||
ms_pDevice->SetTransform( D3DTS_WORLD, rDE.pTM );
|
||
|
||
if( NULL == rDE.hVertexShader )
|
||
{
|
||
DWORD dwFVF = rDE.pMesh->GetFVF();
|
||
ms_pDevice->SetVertexShader( dwFVF );
|
||
}
|
||
else
|
||
{
|
||
ms_pDevice->SetVertexShader( rDE.hVertexShader );
|
||
}
|
||
ms_pDevice->SetPixelShader( rDE.hPixelShader );
|
||
|
||
if( NULL == rDE.textureSlot.apTexture[0] )
|
||
{
|
||
ms_pDevice->SetTexture( 0, NULL );
|
||
}
|
||
else
|
||
{
|
||
ms_pDevice->SetTexture( 0, rDE.textureSlot.apTexture[0]->GetTexture() );
|
||
}
|
||
|
||
|
||
if( rDE.pMesh->IsIndexed() )
|
||
{
|
||
ms_pDevice->SetIndices( ms_pDynamicIndexBuffer, rPacket.uPositionInVB / rDE.pMesh->GetVertexSize() );
|
||
|
||
ms_pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, rDE.pMesh->GetVertexCount(),
|
||
rPacket.uPositionInIB / sizeof(WORD), rDE.pMesh->GetIndexCount() / 3 );
|
||
}
|
||
else
|
||
{
|
||
ms_pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, rPacket.uPositionInVB / rDE.pMesh->GetVertexSize(),
|
||
rDE.pMesh->GetVertexCount()/3 );
|
||
}
|
||
|
||
// last time µ¥ÀÌÅÍ ¾÷µ¥ÀÌÆ®
|
||
ms_LastTimeDE = rDE;
|
||
}
|
||
|
||
|
||
|
||
|
||
}
|
||
} |