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>
373 lines
12 KiB
C++
373 lines
12 KiB
C++
#include ".\imposterscene.h"
|
|
#include "BaseGraphicsLayer.h"
|
|
#include "SceneManager.h"
|
|
#include "NTexture.h"
|
|
#include "GMMemory.h"
|
|
|
|
using namespace CROSSM;
|
|
|
|
struct ImposterVertex
|
|
{
|
|
enum { FVF = D3DFVF_XYZ|D3DFVF_TEX1 };
|
|
D3DXVECTOR3 p;
|
|
float u, v;
|
|
};
|
|
|
|
CImposterScene* CImposterScene::ms_pScenesPool[IMP_TOTALSCENE_NUM];
|
|
CImposterScene::COUNT_QUEUE CImposterScene::ms_UnusedSceneQueue;
|
|
LPDIRECT3DTEXTURE8 CImposterScene::ms_pSceneTexture[IMP_LTEXTURE_NUM];
|
|
LPDIRECT3DSURFACE8 CImposterScene::ms_pSceneZBuffer[IMP_LTEXTURE_NUM];
|
|
LPDIRECT3DSURFACE8 CImposterScene::ms_pSceneSurface[IMP_LTEXTURE_NUM];
|
|
LPDIRECT3DSURFACE8 CImposterScene::ms_pTempZBuffer;
|
|
LPDIRECT3DSURFACE8 CImposterScene::ms_pTempSurface;
|
|
D3DVIEWPORT8 CImposterScene::ms_TempViewport;
|
|
float CImposterScene::ms_fViewRatio = 550.0f; //값이 클수록 보이는 비주얼이 커짐
|
|
float CImposterScene::ms_fViewDist = 20000.0f; //거리 제한값
|
|
bool CImposterScene::ms_bActivate;
|
|
|
|
CImposterScene::CImposterScene( int nIndex ) : m_nIndex(nIndex), m_vOldCamToScene(D3DXVECTOR3(0, 0, 0)), m_pSrcScene(NULL)
|
|
{
|
|
m_nTextureIndex = nIndex / IMP_PERTEXTURE_SCENE_NUM;
|
|
int nTemp = m_nIndex % IMP_PERTEXTURE_SCENE_NUM;
|
|
m_ViewPort.Width = IMP_STEXTURE_SIZE;
|
|
m_ViewPort.Height = IMP_STEXTURE_SIZE;
|
|
m_ViewPort.MinZ = 0;
|
|
m_ViewPort.MaxZ = 1;
|
|
m_ViewPort.X = (nTemp % (IMP_LTEXTURE_SIZE/IMP_STEXTURE_SIZE)) * IMP_STEXTURE_SIZE;
|
|
m_ViewPort.Y = (nTemp / (IMP_LTEXTURE_SIZE/IMP_STEXTURE_SIZE)) * IMP_STEXTURE_SIZE;
|
|
}
|
|
|
|
CImposterScene::~CImposterScene()
|
|
{
|
|
}
|
|
|
|
bool CImposterScene::Init()
|
|
{
|
|
LPDIRECT3DDEVICE8 pDevice = BaseGraphicsLayer::GetDevice();
|
|
|
|
int i;
|
|
HRESULT hr;
|
|
|
|
for( i = 0; i < IMP_LTEXTURE_NUM; i++ )
|
|
{
|
|
hr = pDevice->CreateTexture( IMP_LTEXTURE_SIZE, IMP_LTEXTURE_SIZE, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, //BaseGraphicsLayer::m_d3dpp.BackBufferFormat,
|
|
D3DPOOL_DEFAULT, &ms_pSceneTexture[i] );
|
|
if( FAILED(hr) )
|
|
{
|
|
// MessageBox( 0, "텍스처 생성 실패 : imposter", "Error", 0 );
|
|
return false;
|
|
}
|
|
|
|
hr = ms_pSceneTexture[i]->GetSurfaceLevel( 0, &ms_pSceneSurface[i] );
|
|
if( FAILED(hr) )
|
|
{
|
|
Shutdown();
|
|
MessageBox( 0, "서페이스 생성 실패 : imposter", "Error", 0 );
|
|
return false;
|
|
}
|
|
|
|
pDevice->CreateDepthStencilSurface( IMP_LTEXTURE_SIZE, IMP_LTEXTURE_SIZE, BaseGraphicsLayer::m_d3dpp.AutoDepthStencilFormat,
|
|
D3DMULTISAMPLE_NONE, &ms_pSceneZBuffer[i] );
|
|
if( FAILED(hr) )
|
|
{
|
|
Shutdown();
|
|
MessageBox( 0, "Z버퍼 생성 실패 : imposter", "Error", 0 );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
for( i = 0; i < IMP_TOTALSCENE_NUM; i++ )
|
|
{
|
|
ms_pScenesPool[i] = new CImposterScene(i);
|
|
}
|
|
|
|
while( !ms_UnusedSceneQueue.empty() )
|
|
{
|
|
ms_UnusedSceneQueue.pop();
|
|
}
|
|
|
|
for( i = 0; i < IMP_TOTALSCENE_NUM; i++ )
|
|
{
|
|
ms_UnusedSceneQueue.push(i);
|
|
}
|
|
|
|
ms_bActivate = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
void CImposterScene::Shutdown()
|
|
{
|
|
for( int i = 0; i < IMP_LTEXTURE_NUM; i++ )
|
|
{
|
|
SAFE_RELEASE( ms_pSceneTexture[i] );
|
|
SAFE_RELEASE( ms_pSceneZBuffer[i] );
|
|
SAFE_RELEASE( ms_pSceneSurface[i] );
|
|
}
|
|
|
|
for(int i = 0; i < IMP_TOTALSCENE_NUM; i++ )
|
|
{
|
|
SAFE_DELETE( ms_pScenesPool[i] );
|
|
}
|
|
|
|
ms_bActivate = false;
|
|
}
|
|
|
|
CImposterScene* CImposterScene::GetScene( CHouseObjectScene* pScene )
|
|
{
|
|
if( ms_bActivate == false || ms_UnusedSceneQueue.empty() )
|
|
return NULL;
|
|
|
|
int nCount = ms_UnusedSceneQueue.front();
|
|
ms_UnusedSceneQueue.pop();
|
|
|
|
CImposterScene* pImposter = ms_pScenesPool[nCount];
|
|
pImposter->m_pSrcScene = pScene;
|
|
|
|
return pImposter;
|
|
}
|
|
|
|
void CImposterScene::DeleteScene( CImposterScene* pScene )
|
|
{
|
|
if( pScene && ms_bActivate )
|
|
{
|
|
pScene->Clear();
|
|
ms_UnusedSceneQueue.push( pScene->m_nIndex );
|
|
}
|
|
}
|
|
|
|
void CImposterScene::SetViewRatio( float f )
|
|
{
|
|
ms_fViewRatio = f;
|
|
}
|
|
|
|
float CImposterScene::GetViewRatio()
|
|
{
|
|
return ms_fViewRatio;
|
|
}
|
|
|
|
void CImposterScene::Render( D3DXVECTOR3& vCamPos, D3DXVECTOR3& vScenePos )
|
|
{
|
|
//텍스쳐를 갱신했을경우 바로 그리지 않고 다음프레임에 그린다
|
|
if( GenerateRenderTexture(vCamPos, vScenePos) ) return;
|
|
|
|
LPDIRECT3DDEVICE8 pDevice = BaseGraphicsLayer::GetDevice();
|
|
|
|
//Set RenderState !!
|
|
pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
|
|
pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
|
|
pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
|
|
pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTA_TEXTURE );
|
|
pDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
|
|
pDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
|
|
|
|
pDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
|
|
pDevice->SetRenderState( D3DRS_ALPHAREF, 0xee );
|
|
pDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
|
|
pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
|
|
|
|
pDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
|
|
pDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
|
|
|
|
ImposterVertex Quad[4];
|
|
Quad[0].p = D3DXVECTOR3( -m_pSrcScene->m_fRad, m_pSrcScene->m_fRad, 0 );
|
|
Quad[0].u = (float)m_ViewPort.X / (float)IMP_LTEXTURE_SIZE;
|
|
Quad[0].v = (float)m_ViewPort.Y / (float)IMP_LTEXTURE_SIZE;
|
|
Quad[1].p = D3DXVECTOR3( m_pSrcScene->m_fRad, m_pSrcScene->m_fRad, 0 );
|
|
Quad[1].u = ((float)m_ViewPort.X + (float)m_ViewPort.Width) / (float)IMP_LTEXTURE_SIZE;
|
|
Quad[1].v = (float)m_ViewPort.Y / (float)IMP_LTEXTURE_SIZE;
|
|
Quad[2].p = D3DXVECTOR3( -m_pSrcScene->m_fRad, -m_pSrcScene->m_fRad, 0 );
|
|
Quad[2].u = (float)m_ViewPort.X / (float)IMP_LTEXTURE_SIZE;
|
|
Quad[2].v = ((float)m_ViewPort.Y + (float)m_ViewPort.Height) / (float)IMP_LTEXTURE_SIZE;
|
|
Quad[3].p = D3DXVECTOR3( m_pSrcScene->m_fRad, -m_pSrcScene->m_fRad, 0 );
|
|
Quad[3].u = ((float)m_ViewPort.X + (float)m_ViewPort.Width) / (float)IMP_LTEXTURE_SIZE;
|
|
Quad[3].v = ((float)m_ViewPort.Y + (float)m_ViewPort.Height) / (float)IMP_LTEXTURE_SIZE;
|
|
|
|
//Set RenderState
|
|
pDevice->SetTexture( 0, ms_pSceneTexture[m_nTextureIndex] );
|
|
|
|
//DrawPrimitive
|
|
D3DXMATRIX mBillboard;
|
|
D3DXMatrixIdentity( &mBillboard );
|
|
mBillboard._11 = CSceneManager::m_ViewCamera->GetMatView()->_11;
|
|
mBillboard._13 = CSceneManager::m_ViewCamera->GetMatView()->_13;
|
|
mBillboard._31 = CSceneManager::m_ViewCamera->GetMatView()->_31;
|
|
mBillboard._33 = CSceneManager::m_ViewCamera->GetMatView()->_33;
|
|
D3DXMatrixInverse( &mBillboard, NULL, &mBillboard );
|
|
mBillboard._41 = m_pSrcScene->m_AccumulateTM._41;
|
|
mBillboard._42 = m_pSrcScene->m_AccumulateTM._42;
|
|
mBillboard._43 = m_pSrcScene->m_AccumulateTM._43;
|
|
pDevice->SetVertexShader( ImposterVertex::FVF );
|
|
pDevice->SetTransform( D3DTS_WORLD, &mBillboard );
|
|
pDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, Quad, sizeof(ImposterVertex) );
|
|
pDevice->SetVertexShader(NULL);
|
|
|
|
//Back RenderState
|
|
pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
|
|
pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
|
|
pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
|
|
pDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
|
|
pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
|
pDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
|
|
pDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
|
pDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
|
|
pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
|
|
pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
|
|
pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR );
|
|
pDevice->SetRenderState( D3DRS_LIGHTING,TRUE);
|
|
}
|
|
|
|
void CImposterScene::BeginImposter()
|
|
{
|
|
LPDIRECT3DDEVICE8 pDevice = BaseGraphicsLayer::GetDevice();
|
|
pDevice->GetViewport( &ms_TempViewport );
|
|
pDevice->GetRenderTarget( &ms_pTempSurface );
|
|
pDevice->GetDepthStencilSurface( &ms_pTempZBuffer );
|
|
pDevice->SetRenderTarget( ms_pSceneSurface[m_nTextureIndex], ms_pSceneZBuffer[m_nTextureIndex] );
|
|
pDevice->EndScene();
|
|
|
|
D3DRECT rect;
|
|
rect.x1 = m_ViewPort.X;
|
|
rect.y1 = m_ViewPort.Y;
|
|
rect.x2 = m_ViewPort.X + m_ViewPort.Width;
|
|
rect.y2 = m_ViewPort.Y + m_ViewPort.Height;
|
|
pDevice->Clear( 1, &rect, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00, 1.0f, 0 );
|
|
pDevice->BeginScene();
|
|
}
|
|
|
|
void CImposterScene::EndImposter()
|
|
{
|
|
LPDIRECT3DDEVICE8 pDevice = BaseGraphicsLayer::GetDevice();
|
|
pDevice->EndScene();
|
|
|
|
pDevice->SetRenderTarget( ms_pTempSurface, ms_pTempZBuffer );
|
|
pDevice->SetViewport( &ms_TempViewport );
|
|
SAFE_RELEASE( ms_pTempZBuffer );
|
|
SAFE_RELEASE( ms_pTempSurface );
|
|
|
|
pDevice->BeginScene();
|
|
}
|
|
|
|
bool CImposterScene::GenerateRenderTexture( D3DXVECTOR3& vCamPos, D3DXVECTOR3& vScenePos )
|
|
{
|
|
D3DXVECTOR3 vCamToScene = vScenePos - vCamPos;
|
|
D3DXVec3Normalize( &vCamToScene, &vCamToScene );
|
|
if( D3DXVec3Dot(&m_vOldCamToScene, &vCamToScene) > 0.5f ) return false;
|
|
|
|
static int nLoadSchedule;
|
|
++nLoadSchedule;
|
|
if( nLoadSchedule % 5 != 0 ) return false;
|
|
|
|
//벌거숭이 메쉬를 찍지 않기 위해 쓰레드로딩이 다될때까지 기다린다
|
|
int nCompleteLoad = 0;
|
|
|
|
// 2005/01/06 yundi. CHouseObjectScene::m_HouseObject 가 NULL 일 경우 처리
|
|
if( NULL == m_pSrcScene->m_HouseObject ||
|
|
NULL == m_pSrcScene->m_HouseObject->m_pOutHouseObject ||
|
|
false == m_pSrcScene->m_HouseObject->m_pOutHouseObject->IsLoaded() )
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
for( int i = 0; i < (int)m_pSrcScene->m_HouseObject->m_pOutHouseObject->m_pMat.size(); ++i )
|
|
{
|
|
CNTexture* pTex = m_pSrcScene->m_HouseObject->m_pOutHouseObject->m_pMat[i];
|
|
if( pTex->IsLoaded() )
|
|
{
|
|
++nCompleteLoad;
|
|
}
|
|
}
|
|
if( nCompleteLoad < (int)m_pSrcScene->m_HouseObject->m_pOutHouseObject->m_pMat.size() )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
m_vOldCamToScene = vCamToScene;
|
|
|
|
LPDIRECT3DDEVICE8 pd3dDevice = BaseGraphicsLayer::GetDevice();
|
|
D3DXMATRIX mView, mSaveView;
|
|
D3DXMatrixIdentity( &mView );
|
|
D3DXMatrixLookAtLH( &mView, &vCamPos, &vScenePos, &D3DXVECTOR3(0, 1, 0) );
|
|
pd3dDevice->GetTransform( D3DTS_VIEW, &mSaveView );
|
|
pd3dDevice->SetTransform( D3DTS_VIEW, &mView );
|
|
pd3dDevice->SetTransform(D3DTS_WORLD,(D3DMATRIX*)&m_pSrcScene->m_AccumulateTM);
|
|
|
|
D3DXMATRIX mProj, mSaveProj;
|
|
D3DXMatrixOrthoLH( &mProj, m_pSrcScene->m_fRad*2, m_pSrcScene->m_fRad*2, 1.0f, 100000.0f);
|
|
pd3dDevice->GetTransform( D3DTS_PROJECTION, &mSaveProj );
|
|
pd3dDevice->SetTransform( D3DTS_PROJECTION, &mProj );
|
|
|
|
BeginImposter();
|
|
pd3dDevice->SetViewport( &m_ViewPort );
|
|
|
|
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
|
|
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
|
|
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
|
pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
|
|
pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
|
|
pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR );
|
|
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
|
|
pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
|
|
pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 0xee );
|
|
pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
|
|
pd3dDevice->SetRenderState( D3DRS_LIGHTING,TRUE );
|
|
pd3dDevice->SetRenderState( D3DRS_TEXTUREFACTOR, 0xFFFFFFFF );
|
|
pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
|
|
pd3dDevice->SetRenderState( D3DRS_COLORWRITEENABLE, 0x0000000F );
|
|
pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
|
|
pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
|
|
pd3dDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
|
|
m_pSrcScene->m_HouseObject->Render( pd3dDevice );
|
|
EndImposter();
|
|
|
|
pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
|
|
pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
|
|
pd3dDevice->SetTransform( D3DTS_VIEW, &mSaveView );
|
|
pd3dDevice->SetTransform( D3DTS_PROJECTION, &mSaveProj );
|
|
pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
|
|
pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
|
|
pd3dDevice->SetRenderState( D3DRS_FOGENABLE, TRUE );
|
|
|
|
return true;
|
|
}
|
|
|
|
int CImposterScene::GetSceneNum()
|
|
{
|
|
return IMP_TOTALSCENE_NUM - ms_UnusedSceneQueue.size();
|
|
}
|
|
|
|
void CImposterScene::Clear()
|
|
{
|
|
memset( m_vOldCamToScene, 0, sizeof(D3DXVECTOR3) );
|
|
m_pSrcScene = NULL;
|
|
}
|
|
|
|
void CImposterScene::SetViewDistance( float f )
|
|
{
|
|
ms_fViewDist = f;
|
|
}
|
|
|
|
float CImposterScene::GetViewDistance()
|
|
{
|
|
return ms_fViewDist;
|
|
}
|
|
|
|
bool CImposterScene::IsRenderEnable( float fDist, CHouseObjectScene* pScene )
|
|
{
|
|
if( ms_bActivate == false )
|
|
return false;
|
|
|
|
if( fDist > ms_fViewDist &&
|
|
pScene->m_fRad*pScene->m_fRad/fDist < ms_fViewRatio )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CImposterScene::IsActivated()
|
|
{
|
|
return ms_bActivate;
|
|
}
|