Files
Client/Engine/Caldron/Src/Scene/DrawElement.cpp
LGram16 e067522598 Initial commit: ROW Client source code
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>
2025-11-29 16:24:34 +09:00

408 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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;
}
}
}