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