Files
Client/Library/dxx8/samples/Multimedia/DirectPlay/Maze/MazeClient/D3DGraphics.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

1372 lines
48 KiB
C++

//----------------------------------------------------------------------------
// File: d3dgraphics.cpp
//
// Desc: see main.cpp
//
// Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
//-----------------------------------------------------------------------------
#define STRICT
#define D3D_OVERLOADS
#include <windows.h>
#include <D3DX8.h>
#include <dplay8.h>
#include <stdio.h>
#include <math.h>
#include <mmsystem.h>
#include <process.h>
#include <dxerr8.h>
#include <tchar.h>
#include <dplay8.h>
#include "SyncObjects.h"
#include "DummyConnector.h"
#include "IMazeGraphics.h"
#include "SmartVB.h"
#include "MazeServer.h"
#include "MazeApp.h"
#include "IMazeGraphics.h"
#include "d3dSaver.h"
#include "D3DFont.h"
#include "D3DFile.h"
#include "D3DUtil.h"
#include "D3DGraphics.h"
#include "resource.h"
#include "DXUtil.h"
static CD3DGraphics* s_pGraphics = NULL;
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
CD3DGraphics::CD3DGraphics()
{
s_pGraphics = this;
m_pMazeApp = NULL;
m_pSphere = NULL;
m_pWallTexture = NULL;
m_pFloorTexture = NULL;
m_pCeilingTexture = NULL;
m_pNetIconTexture = NULL;
m_pLocalIconTexture = NULL;
// Tell the d3dsaver framework to run on one monitor only
m_bOneScreenOnly = TRUE;
m_bUseDepthBuffer = TRUE;
// Create fonts
m_pFont = new CD3DFont( _T("Courier"), 12, D3DFONT_BOLD );
m_pStatsFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
m_pPlayerMesh = new CD3DFile();
lstrcpy( m_strRegPath, MAZE_REGKEYNAME );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
CD3DGraphics::~CD3DGraphics()
{
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
VOID CD3DGraphics::Init( CMazeApp* pMazeApp, CDPlay8Client* pDP8Client,
CMazeClient* pMazeClient )
{
m_pMazeApp = pMazeApp;
m_pMazeClient = pMazeClient;
m_pDP8Client = pDP8Client;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DGraphics::Create( HINSTANCE hInstance )
{
return CD3DScreensaver::Create( hInstance );
}
//-----------------------------------------------------------------------------
// Name: PostCreate()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DGraphics::PostCreate()
{
HRESULT hr;
// Create the screen saver window
if( m_SaverMode == sm_test ||
m_SaverMode == sm_full )
{
if( FAILED( hr = CreateSaverWindow() ) )
{
m_bErrorMode = TRUE;
m_hrError = hr;
}
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Run()
// Desc:
//-----------------------------------------------------------------------------
INT CD3DGraphics::Run()
{
HRESULT hr;
BOOL bIsScreenSaver = TRUE;
TCHAR* strCmdLine = GetCommandLine();
// Parse the command line and do the appropriate thing
m_SaverMode = ParseCommandLine( strCmdLine );
// Skip along to the first option delimiter "/" or "-"
while ( *strCmdLine && *strCmdLine != '/' && *strCmdLine != '-' )
strCmdLine++;
// If there weren't any params, then it must have run from a exe form
if ( *strCmdLine == 0 )
{
m_SaverMode = sm_config;
bIsScreenSaver = FALSE;
}
m_pMazeApp->SetAllowLoopback( TRUE );
switch ( m_SaverMode )
{
case sm_config:
ScreenSaverDoConfig( bIsScreenSaver );
if( m_dwStartMode == 0 )
break;
// Don't do AutoDisconnnect or Stress Connect in 3D client
m_pConfig = m_pMazeApp->GetConfig();
m_pConfig->bAutoDisconnnect = FALSE;
m_pConfig->dwStressConnect = 0;
if( m_pConfig->bFullScreen )
m_SaverMode = sm_full;
else
m_SaverMode = sm_test;
m_pMazeApp->SetAllowConnect( TRUE );
PostCreate();
if( FAILED( hr = DoSaver() ) )
DisplayErrorMsg( hr, 0 );
break;
case sm_preview:
/*
// This is temp code to allow stepping thru code in the preview case
WNDCLASS cls;
cls.hCursor = NULL;
cls.hIcon = NULL;
cls.lpszMenuName = NULL;
cls.lpszClassName = "Parent";
cls.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
cls.hInstance = m_hInstance;
cls.style = CS_VREDRAW|CS_HREDRAW|CS_SAVEBITS|CS_DBLCLKS;
cls.lpfnWndProc = DefWindowProc;
cls.cbWndExtra = 0;
cls.cbClsExtra = 0;
RegisterClass( &cls );
// Create the window
RECT rect;
HWND hwnd;
rect.left = rect.top = 40;
rect.right = rect.left+100;
rect.bottom = rect.top+100;
AdjustWindowRect( &rect , WS_VISIBLE|WS_OVERLAPPED|WS_CAPTION|WS_POPUP , FALSE );
hwnd= CreateWindow( "Parent", "FakeShell" ,
WS_VISIBLE|WS_OVERLAPPED|WS_CAPTION|WS_POPUP , rect.left , rect.top ,
rect.right-rect.left , rect.bottom-rect.top , NULL ,
NULL , m_hInstance , NULL );
m_hWndParent = hwnd;
*/
case sm_test:
case sm_full:
if( m_SaverMode == sm_preview )
m_pMazeApp->SetAllowConnect( FALSE );
else
m_pMazeApp->SetAllowConnect( TRUE );
// Don't do AutoDisconnnect or StressConnect in 3D client
m_pConfig = m_pMazeApp->GetConfig();
m_pConfig->bAutoDisconnnect = FALSE;
m_pConfig->dwStressConnect = 0;
if( m_SaverMode != sm_preview && m_pConfig->bFullScreen )
m_SaverMode = sm_full;
else
{
m_SaverMode = sm_test;
}
if( FAILED( hr = DoSaver() ) )
DisplayErrorMsg( hr, 0 );
break;
case sm_passwordchange:
ChangePassword();
break;
}
return 0;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CD3DGraphics::Shutdown()
{
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
int CD3DGraphics::ScreenSaverDoConfig( BOOL bIsScreenSaverSettings )
{
m_bIsScreenSaverSettings = bIsScreenSaverSettings;
m_pMazeApp->ReadConfig();
HKEY hKey = NULL;
RegOpenKeyEx( HKEY_CURRENT_USER, MAZE_REGKEYNAME, 0, KEY_READ, &hKey );
ReadScreenSettings( hKey );
RegCloseKey( hKey );
m_pConfig = m_pMazeApp->GetConfig();
if( DialogBox( m_hInstance, MAKEINTRESOURCE(IDD_SAVERCONFIG),
NULL, StaticSaverConfigDlgProc ) == IDOK )
{
m_pMazeApp->WriteConfig();
HKEY hKey = NULL;
RegOpenKeyEx( HKEY_CURRENT_USER, MAZE_REGKEYNAME, 0, KEY_READ, &hKey );
WriteScreenSettings( hKey );
RegCloseKey( hKey );
}
return 0;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CD3DGraphics::StaticSaverConfigDlgProc( HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam )
{
return s_pGraphics->SaverConfigDlgProc( hDlg, uMsg, wParam, lParam );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CD3DGraphics::SaverConfigDlgProc( HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
PopulateSaverConfigDlg( hDlg );
return TRUE;
case WM_CLOSE:
EndDialog( hDlg, IDCANCEL );
break;
case WM_COMMAND:
switch( HIWORD(wParam) )
{
case BN_CLICKED:
switch( LOWORD(wParam) )
{
case IDOK:
ExtractSaverConfigDlgSettings( hDlg );
m_dwStartMode = 0;
EndDialog( hDlg, IDOK );
break;
case IDC_LAUNCH:
ExtractSaverConfigDlgSettings( hDlg );
m_dwStartMode = 1;
EndDialog( hDlg, IDOK );
break;
case IDC_SCREENSETTINGS:
DoScreenSettingsDialog( hDlg );
break;
case IDCANCEL:
EndDialog( hDlg, IDCANCEL );
return TRUE;
}
break;
}
break;
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CD3DGraphics::PopulateSaverConfigDlg( HWND hDlg )
{
if( m_bIsScreenSaverSettings )
ShowWindow( GetDlgItem( hDlg, IDOK ), SW_SHOW );
else
ShowWindow( GetDlgItem( hDlg, IDOK ), SW_HIDE );
CheckDlgButton( hDlg, IDC_MICROSOFT, m_pConfig->bConnectToMicrosoftSite );
CheckDlgButton( hDlg, IDC_LOCAL_SERVER, m_pConfig->bConnectToLocalServer );
CheckDlgButton( hDlg, IDC_REMOTE_SERVER, m_pConfig->bConnectToRemoteServer );
SetDlgItemInt( hDlg, IDC_RETRY_DELAY, m_pConfig->dwNetworkRetryDelay, FALSE );
CheckDlgButton( hDlg, IDC_FRAMERATE, m_pConfig->bShowFramerate );
CheckDlgButton( hDlg, IDC_INDICATORS, m_pConfig->bShowIndicators );
CheckDlgButton( hDlg, IDC_FULLSCREEN, m_pConfig->bFullScreen );
CheckDlgButton( hDlg, IDC_MINIMAP, m_pConfig->bDrawMiniMap );
CheckDlgButton( hDlg, IDC_REFLECTIONS, m_pConfig->bReflections );
CheckDlgButton( hDlg, IDC_FILELOGGING, m_pConfig->bFileLogging );
SetDlgItemText( hDlg, IDC_IPADDRESS, m_pConfig->szIPAddress );
SendDlgItemMessage( hDlg, IDC_IPADDRESS, EM_SETLIMITTEXT, sizeof(m_pConfig->szIPAddress)-1, 0 );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CD3DGraphics::ExtractSaverConfigDlgSettings( HWND hDlg )
{
m_pConfig->bConnectToMicrosoftSite = IsDlgButtonChecked( hDlg, IDC_MICROSOFT );
m_pConfig->bConnectToLocalServer = IsDlgButtonChecked( hDlg, IDC_LOCAL_SERVER );
m_pConfig->bConnectToRemoteServer = IsDlgButtonChecked( hDlg, IDC_REMOTE_SERVER );
m_pConfig->dwNetworkRetryDelay = GetDlgItemInt( hDlg, IDC_RETRY_DELAY, NULL, FALSE );
m_pConfig->bShowFramerate = IsDlgButtonChecked( hDlg, IDC_FRAMERATE );
m_pConfig->bShowIndicators = IsDlgButtonChecked( hDlg, IDC_INDICATORS );
m_pConfig->bFullScreen = IsDlgButtonChecked( hDlg, IDC_FULLSCREEN );
m_pConfig->bDrawMiniMap = IsDlgButtonChecked( hDlg, IDC_MINIMAP );
m_pConfig->bReflections = IsDlgButtonChecked( hDlg, IDC_REFLECTIONS );
m_pConfig->bFileLogging = IsDlgButtonChecked( hDlg, IDC_FILELOGGING );
GetDlgItemText( hDlg, IDC_IPADDRESS, m_pConfig->szIPAddress, sizeof(m_pConfig->szIPAddress) );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CD3DGraphics::HandleOutputMsg( EnumLineType enumLineType, TCHAR* strLine )
{
// Nothing needs to be done here
return;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
LRESULT CD3DGraphics::SaverProc( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam )
{
switch( message )
{
case WM_KEYDOWN:
if( wParam == 'R' )
m_pConfig->bReflections = !m_pConfig->bReflections;
else if( wParam == 'A' )
m_pMazeClient->EngageAutopilot( !m_pMazeClient->IsAutopilot() );
break;
case WM_POWERBROADCAST:
switch( wParam )
{
#ifndef PBT_APMQUERYSUSPEND // Defines are here for old compilers
#define PBT_APMQUERYSUSPEND 0x0000
#endif
#ifndef BROADCAST_QUERY_DENY
#define BROADCAST_QUERY_DENY 0x424D5144
#endif
case PBT_APMQUERYSUSPEND:
// Tell the OS not to suspend, otherwise we
// will loose the network connection.
return BROADCAST_QUERY_DENY;
#ifndef PBT_APMRESUMESUSPEND
#define PBT_APMRESUMESUSPEND 0x0007
#endif
case PBT_APMRESUMESUSPEND:
return TRUE;
}
break;
}
return CD3DScreensaver::SaverProc( hWnd, message, wParam, lParam );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DGraphics::ConfirmDevice(D3DCAPS8* pCaps, DWORD dwBehavior,
D3DFORMAT Format )
{
if( dwBehavior & D3DCREATE_PUREDEVICE )
return E_FAIL; // GetTransform doesn't work on PUREDEVICE
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DGraphics::OneTimeSceneInit()
{
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DGraphics::CreateTextureFromResource( INT nResource, LPDIRECT3DTEXTURE8* ppTexture )
{
if( FAILED( D3DXCreateTextureFromResourceEx( m_pd3dDevice, NULL, MAKEINTRESOURCE( nResource ),
D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_A8R8G8B8,
D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE|D3DX_FILTER_MIRROR,
D3DX_FILTER_TRIANGLE|D3DX_FILTER_MIRROR, 0xFF000000, NULL, NULL, ppTexture ) ) )
return D3DAPPERR_MEDIANOTFOUND;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DGraphics::InitDeviceObjects()
{
HRESULT hr;
m_dwTesselation = 3;
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
// Restore the fonts
m_pFont->InitDeviceObjects( m_pd3dDevice );
m_pStatsFont->InitDeviceObjects( m_pd3dDevice );
if( FAILED( CreateTextureFromResource( IDB_WALLTEXTURE, &m_pWallTexture ) ) )
return DXTRACE_ERR_NOMSGBOX( TEXT("IDB_WALLTEXTURE"), D3DAPPERR_MEDIANOTFOUND );
if( FAILED( CreateTextureFromResource( IDB_FLOORTEXTURE, &m_pFloorTexture ) ) )
return DXTRACE_ERR_NOMSGBOX( TEXT("IDB_FLOORTEXTURE"), D3DAPPERR_MEDIANOTFOUND );
if( FAILED( CreateTextureFromResource( IDB_CEILINGTEXTURE, &m_pCeilingTexture ) ) )
return DXTRACE_ERR_NOMSGBOX( TEXT("IDB_CEILINGTEXTURE"), D3DAPPERR_MEDIANOTFOUND );
if( FAILED( CreateTextureFromResource( IDB_NETICON, &m_pNetIconTexture ) ) )
return DXTRACE_ERR_NOMSGBOX( TEXT("IDB_NETICON"), D3DAPPERR_MEDIANOTFOUND );
if( FAILED( CreateTextureFromResource( IDB_LOCALICON, &m_pLocalIconTexture ) ) )
return DXTRACE_ERR_NOMSGBOX( TEXT("IDB_LOCALICON"), D3DAPPERR_MEDIANOTFOUND );
// Create airplane for rendering players
if( FAILED( m_pPlayerMesh->CreateFromResource( m_pd3dDevice, MAKEINTRESOURCE(IDB_TANK), TEXT("XFILE") ) ) )
return DXTRACE_ERR( TEXT("tank.x"), D3DAPPERR_MEDIANOTFOUND );
// Create sphere for rendering clients
if( FAILED( hr = D3DXCreateSphere( m_pd3dDevice, 0.2f, 8, 8, &m_pSphere, NULL ) ) )
return DXTRACE_ERR_NOMSGBOX( TEXT("D3DXCreateSphere"), hr );
if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( sizeof(VERTEX_TL_DIFFUSE) * 4,
D3DUSAGE_WRITEONLY, FVF_TL_DIFFUSE,
D3DPOOL_MANAGED, &m_pMiniMapBackgroundVB ) ) )
return DXTRACE_ERR_NOMSGBOX( TEXT("CreateVertexBuffer"), hr );
if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( sizeof(VERTEX_TL_TEXTURED) * 4,
D3DUSAGE_WRITEONLY, FVF_TL_TEXTURED,
D3DPOOL_MANAGED, &m_pIndicatorVB ) ) )
return DXTRACE_ERR_NOMSGBOX( TEXT("CreateVertexBuffer"), hr );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DGraphics::RestoreDeviceObjects()
{
HRESULT hr;
// Restore the fonts
m_pFont->RestoreDeviceObjects();
m_pStatsFont->RestoreDeviceObjects();
m_pPlayerMesh->RestoreDeviceObjects( m_pd3dDevice );
// Initialise the SmartVB for the walls
if( FAILED( hr = m_SmartVB.Init( m_pD3D, m_pd3dDevice, 2048 ) ) )
return DXTRACE_ERR_NOMSGBOX( TEXT("m_SmartVB.Init"), hr );
if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( sizeof(VERTEX_DIFFUSE) * 1024,
D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, FVF_DIFFUSE,
D3DPOOL_DEFAULT, &m_pMiniMapVB ) ) )
return DXTRACE_ERR_NOMSGBOX( TEXT("CreateVertexBuffer"), hr );
// Set projection matrix
const float fov = 1.8f;
const float znear = 0.1f;
const float zfar = 30.0f;
const float viewwidth = float(tan(fov*0.5f) ) * znear;
const float viewheight = viewwidth * float(m_d3dsdBackBuffer.Height)/float(m_d3dsdBackBuffer.Width);
D3DXMatrixPerspectiveLH( &m_Projection, viewwidth, viewheight, znear, zfar );
m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_Projection );
// Set renderstates and lighting
D3DXMATRIX matIden; D3DXMatrixIdentity( &matIden );
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matIden );
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x333333 );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );
m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
m_pd3dDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
D3DMATERIAL8 mtrl;
D3DUtil_InitMaterial( mtrl, 1.0f, 1.0f, 1.0f );
m_pd3dDevice->SetMaterial( &mtrl );
// Init light
D3DUtil_InitLight( m_Light, D3DLIGHT_POINT, m_vCameraPos.x, m_vCameraPos.y, m_vCameraPos.z );
m_Light.Direction = D3DXVECTOR3(0,0,0);
m_Light.Range = 80.0f;
m_Light.Attenuation0 = 1.0f;
m_Light.Attenuation1 = 0.0f;
m_Light.Attenuation2 = 1.0f;
m_pd3dDevice->SetLight( 0, &m_Light );
m_pd3dDevice->LightEnable( 0, TRUE );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DGraphics::FrameMove()
{
m_pMazeApp->FrameMove( m_fElapsedTime );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DGraphics::Render()
{
// Clear the viewport
m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L );
// Begin the scene
if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
{
m_vCameraPos = m_pMazeClient->GetCameraPos();
m_fCameraYaw = AngleToFloat(m_pMazeClient->GetCameraYaw() );
// Compute and set view matrix
D3DXMATRIX matTrans,matRot;
D3DXMatrixTranslation( &matTrans, -m_vCameraPos.x, -m_vCameraPos.y, -m_vCameraPos.z );
D3DXMatrixRotationY( &matRot, m_fCameraYaw );
m_Camera = matTrans * matRot;
m_pd3dDevice->SetTransform( D3DTS_VIEW, &m_Camera );
// Move light
m_Light.Position = m_vCameraPos;
m_pd3dDevice->SetLight( 0, &m_Light );
// Get visibility set of maze
D3DXVECTOR2 dir;
dir.y = float(cos(m_fCameraYaw) );
dir.x = float(-sin(m_fCameraYaw) );
m_dwNumVisibleCells = m_pMazeClient->m_Maze.GetVisibleCells( D3DXVECTOR2(m_vCameraPos.x, m_vCameraPos.z) ,
dir, 1.8f, m_mcrVisList, MAX_VISLIST );
// Draw reflection of walls and ceiling in floor
if( m_pConfig->bReflections )
{
D3DXMATRIX reflectcamera = m_Camera;
reflectcamera.m[1][0] = -reflectcamera.m[1][0];
reflectcamera.m[1][1] = -reflectcamera.m[1][1];
reflectcamera.m[1][2] = -reflectcamera.m[1][2];
reflectcamera.m[1][3] = -reflectcamera.m[1][3];
m_pd3dDevice->SetTransform( D3DTS_VIEW, &reflectcamera );
m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
m_Light.Diffuse = D3DXCOLOR(0.7f,0.7f,0.7f,0);
m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x222222 );
m_pd3dDevice->SetLight( 0, &m_Light );
DrawWalls();
DrawCeiling();
// DrawPlayers();
m_Light.Diffuse = D3DXCOLOR(1,1,1,0);
m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x333333 );
m_pd3dDevice->SetLight( 0, &m_Light );
m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
m_pd3dDevice->SetTransform( D3DTS_VIEW, &m_Camera );
}
// Draw floor
if( m_pConfig->bReflections )
{
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
}
DrawFloor();
if( m_pConfig->bReflections )
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
// Draw walls and ceiling
DrawWalls();
DrawCeiling();
// Draw Players
DrawPlayers();
// Draw mini-map
if( m_pConfig->bDrawMiniMap )
DrawMiniMap();
// Draw indicators
if( m_pConfig->bShowIndicators )
DrawIndicators();
// Show frame rate
m_pStatsFont->DrawText( 2, 0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
m_pStatsFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
// End the scene.
m_pd3dDevice->EndScene();
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CD3DGraphics::DrawPlayers()
{
D3DXMATRIX matWorld;
D3DXMATRIX matScale;
D3DXMATRIX matTrans;
D3DXMATRIX matRot;
D3DXMatrixScaling( &matScale, 0.25f, 0.25f, 0.25f );
MazeCellRef* pCell = m_mcrVisList;
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTexture( 0, m_pCeilingTexture );
m_pMazeClient->LockWorld();
for( DWORD i = 0; i < m_dwNumVisibleCells; i++, pCell++ )
{
PlayerObject* pPlayerObject = m_pMazeClient->GetFirstPlayerObjectInCell( pCell->x, pCell->y );
while( pPlayerObject )
{
D3DXMatrixTranslation( &matTrans, pPlayerObject->vPos.x, pPlayerObject->vPos.y - 0.5f, pPlayerObject->vPos.z );
D3DXMatrixRotationYawPitchRoll( &matRot, -AngleToFloat(pPlayerObject->aCameraYaw), -D3DX_PI/2.0f, 0.0f );
matWorld = matScale * matRot * matTrans;
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
// m_pSphere->DrawSubset( 0 );
m_pPlayerMesh->Render( m_pd3dDevice );
pPlayerObject = pPlayerObject->pNext;
}
}
m_pd3dDevice->SetTexture( 0, NULL );
D3DMATERIAL8 mtrl;
D3DUtil_InitMaterial( mtrl, 1.0f, 1.0f, 1.0f );
m_pd3dDevice->SetMaterial( &mtrl );
m_pMazeClient->UnlockWorld();
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CD3DGraphics::DrawFloor()
{
MazeCellRef* pCell = m_mcrVisList;
VERTEX_TEXURED* pVert;
WORD* pIndex;
WORD offset;
D3DXVECTOR3 normal(0,1,0);
DWORD verts_per_side = (m_dwTesselation+1)*(m_dwTesselation+1);
DWORD indicies_per_side = m_dwTesselation*m_dwTesselation*6;
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTexture( 0, m_pFloorTexture );
m_SmartVB.Begin();
for( DWORD i = 0; i < m_dwNumVisibleCells; i++, pCell++ )
{
D3DXVECTOR3 pos( float(pCell->x), 0, float(pCell->y) );
m_SmartVB.MakeRoom( verts_per_side, indicies_per_side, &pVert, &pIndex, &offset );
LoadQuad( pVert, pIndex, offset, pos, D3DXVECTOR3(1,0,0), D3DXVECTOR3(0,0,1) ,
D3DXVECTOR3(0,1,0) );
}
m_SmartVB.End();
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CD3DGraphics::DrawCeiling()
{
MazeCellRef* pCell = m_mcrVisList;
VERTEX_TEXURED* pVert;
WORD* pIndex;
WORD offset;
D3DXVECTOR3 normal(0,1,0);
DWORD verts_per_side = (m_dwTesselation+1)*(m_dwTesselation+1);
DWORD indicies_per_side = m_dwTesselation*m_dwTesselation*6;
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTexture( 0, m_pCeilingTexture );
m_SmartVB.Begin();
for( DWORD i = 0; i < m_dwNumVisibleCells; i++, pCell++ )
{
D3DXVECTOR3 pos( float(pCell->x), 1, float(1+pCell->y) );
m_SmartVB.MakeRoom( verts_per_side, indicies_per_side, &pVert, &pIndex, &offset );
LoadQuad( pVert, pIndex, offset, pos, D3DXVECTOR3(1,0,0), D3DXVECTOR3(0,0,-1) ,
D3DXVECTOR3(0,-1,0) );
}
m_SmartVB.End();
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CD3DGraphics::DrawWalls()
{
MazeCellRef* pCell = m_mcrVisList;
VERTEX_TEXURED* pVert;
WORD* pIndex;
WORD offset;
DWORD verts_per_side = (m_dwTesselation+1)*(m_dwTesselation+1);
DWORD indicies_per_side = m_dwTesselation*m_dwTesselation*6;
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTexture( 0, m_pWallTexture );
m_SmartVB.Begin();
for( DWORD i = 0; i < m_dwNumVisibleCells; i++, pCell++ )
{
BYTE cell = m_pMazeClient->m_Maze.GetCell(pCell->x,pCell->y);
if( cell & MAZE_WALL_NORTH )
{
D3DXVECTOR3 pos( float(pCell->x), 1, float(pCell->y) );
m_SmartVB.MakeRoom( verts_per_side, indicies_per_side, &pVert, &pIndex, &offset );
LoadQuad( pVert, pIndex, offset, pos, D3DXVECTOR3(1,0,0), D3DXVECTOR3(0,-1,0) ,
D3DXVECTOR3(0,0,1) );
}
if( cell & MAZE_WALL_SOUTH )
{
D3DXVECTOR3 pos( float(1+pCell->x), 1, float(1+pCell->y) );
m_SmartVB.MakeRoom( verts_per_side, indicies_per_side, &pVert, &pIndex, &offset );
LoadQuad( pVert, pIndex, offset, pos, D3DXVECTOR3(-1,0,0), D3DXVECTOR3(0,-1,0) ,
D3DXVECTOR3(0,0,-1) );
}
if( cell & MAZE_WALL_WEST )
{
D3DXVECTOR3 pos( float(pCell->x), 1, float(1+pCell->y) );
m_SmartVB.MakeRoom( verts_per_side, indicies_per_side, &pVert, &pIndex, &offset );
LoadQuad( pVert, pIndex, offset, pos, D3DXVECTOR3(0,0,-1), D3DXVECTOR3(0,-1,0) ,
D3DXVECTOR3(1,0,0) );
}
if( cell & MAZE_WALL_EAST )
{
D3DXVECTOR3 pos( float(1+pCell->x), 1, float(pCell->y) );
m_SmartVB.MakeRoom( verts_per_side, indicies_per_side, &pVert, &pIndex, &offset );
LoadQuad( pVert, pIndex, offset, pos, D3DXVECTOR3(0,0,1), D3DXVECTOR3(0,-1,0) ,
D3DXVECTOR3(-1,0,0) );
}
}
m_SmartVB.End();
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CD3DGraphics::LoadQuad( VERTEX_TEXURED* pVerts, WORD* pIndex, WORD wOffset,
const D3DXVECTOR3& vOrigin, const D3DXVECTOR3& vBasis1,
const D3DXVECTOR3& vBasis2, const D3DXVECTOR3& vNormal )
{
// Compute edge steps
float fStep = 1.0f / m_dwTesselation;
D3DXVECTOR3 vStep1 = vBasis1 * fStep;
D3DXVECTOR3 vStep2 = vBasis2 * fStep;
// Fill out grid of vertices
D3DXVECTOR3 rowstart = vOrigin;
float u = 0;
for( DWORD i = 0; i <= m_dwTesselation; i++, rowstart += vStep1, u += fStep )
{
D3DXVECTOR3 pos = rowstart;
float v = 0;
for( DWORD j = 0; j <= m_dwTesselation; j++, pos += vStep2, v += fStep )
{
pVerts->vPos = pos;
pVerts->vNormal = vNormal;
pVerts->fU = u;
pVerts->fV = v;
pVerts++;
}
}
// Fill out grid of indicies
for( i = 0; i < m_dwTesselation; i++ )
{
for( DWORD j = 0; j < m_dwTesselation; j++ )
{
*pIndex++ = wOffset;
*pIndex++ = wOffset+1;
*pIndex++ = wOffset+1+(WORD(m_dwTesselation)+1);
*pIndex++ = wOffset;
*pIndex++ = wOffset+1+(WORD(m_dwTesselation)+1);
*pIndex++ = wOffset+(WORD(m_dwTesselation)+1);
wOffset++;
}
wOffset++;
}
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CD3DGraphics::DrawMiniMap()
{
DWORD y;
DWORD x;
VERTEX_DIFFUSE* verts = NULL;
D3DXVECTOR3 pos;
D3DXVECTOR3 origin;
D3DXMATRIX matWorld;
D3DXMATRIX matTrans;
D3DXMATRIX matRot;
MazeCellRef* pCell = NULL;
// Compute size of mini-map based on display size
DWORD mapsize = m_d3dsdBackBuffer.Width / 4;
int mapx = m_d3dsdBackBuffer.Width - mapsize - 16;
int mapy = m_d3dsdBackBuffer.Height - mapsize - 16;
if( mapx < 0 || mapy < 0 )
return;
// Disable z-buffering
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
D3DXMatrixIdentity( &matWorld );
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
// Draw alpha blended background
VERTEX_TL_DIFFUSE* v;
m_pMiniMapBackgroundVB->Lock( 0, 0, (BYTE**)&v, 0 );
v[0].vPos.x = float(mapx)-0.5f; v[0].vPos.y = float(mapy)-0.5f;
v[1].vPos.x = float(mapx+mapsize)-0.5f; v[1].vPos.y = float(mapy)-0.5f;
v[2].vPos.x = float(mapx+mapsize)-0.5f; v[2].vPos.y = float(mapy+mapsize)-0.5f;
v[3].vPos.x = float(mapx)-0.5f; v[3].vPos.y = float(mapy+mapsize)-0.5f;
v[0].vPos.z = v[1].vPos.z = v[2].vPos.z = v[3].vPos.z = 0.1f;
v[0].fRHW = v[1].fRHW = v[2].fRHW = v[3].fRHW = 1.0f;
v[0].dwDiffuse = v[1].dwDiffuse = v[2].dwDiffuse = v[3].dwDiffuse = 0x80008000;
m_pMiniMapBackgroundVB->Unlock();
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
m_pd3dDevice->SetVertexShader( FVF_TL_DIFFUSE );
m_pd3dDevice->SetStreamSource( 0, m_pMiniMapBackgroundVB, sizeof(VERTEX_TL_DIFFUSE) );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
DWORD dwLineCount = 0;
// Now set matrices for orthogonal top-down line drawing into mini-map area
D3DXMATRIX orthproj;
D3DXMatrixOrthoLH( &orthproj, 8, 8, 1, 2 );
m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &orthproj );
D3DXMATRIX orthcam; D3DXMatrixIdentity( &orthcam );
orthcam.m[3][0] = -m_vCameraPos.x;
orthcam.m[3][1] = -m_vCameraPos.z;
orthcam.m[0][0] = orthcam.m[2][1] = orthcam.m[1][2] = 1;
orthcam.m[1][1] = orthcam.m[2][2] = 0;
D3DXMATRIX rot; D3DXMatrixRotationZ( &rot, -m_fCameraYaw );
orthcam = orthcam * rot;
m_pd3dDevice->SetTransform( D3DTS_VIEW, &orthcam );
// Compute range of cells we're interested in
DWORD centrecellx = DWORD(m_vCameraPos.x);
DWORD centrecelly = DWORD(m_vCameraPos.z);
DWORD mazewidth = m_pMazeClient->m_Maze.GetWidth();
DWORD mazeheight = m_pMazeClient->m_Maze.GetHeight();
DWORD minx = (centrecellx < 6) ? 0 : centrecellx - 6;
DWORD miny = (centrecelly < 6) ? 0 : centrecelly - 6;
DWORD maxx = centrecellx+6 > mazewidth - 1 ? mazewidth - 1 : centrecellx+5;
DWORD maxy = centrecelly+6 > mazeheight - 1 ? mazeheight - 1 : centrecelly+5;
// Change viewport to clip to the map region
D3DVIEWPORT8 oldvp;
oldvp.X = 0;
oldvp.Y = 0;
oldvp.Width = m_d3dsdBackBuffer.Width;
oldvp.Height = m_d3dsdBackBuffer.Height;
oldvp.MinZ = 0.0f;
oldvp.MaxZ = 1.0f;
D3DVIEWPORT8 mapvp;
mapvp.X = mapx;
mapvp.Y = mapy;
mapvp.Width = mapsize;
mapvp.Height = mapsize;
mapvp.MinZ = 0.0f;
mapvp.MaxZ = 1.0f;
m_pd3dDevice->SetViewport( &mapvp );
// Lock mini-map VB
m_pMiniMapVB->Lock( 0, 0, (BYTE**)&verts, D3DLOCK_DISCARD );
// Loop through cells
origin = D3DXVECTOR3( float(minx),1,float(miny) );
for( x = minx; x <= maxx; x++ )
{
pos = origin;
for( DWORD y = miny; y <= maxy; y++ )
{
// Grab wall bitmask
BYTE cell = m_pMazeClient->m_Maze.GetCell(x,y);
// Check for north wall
if( cell & MAZE_WALL_NORTH )
{
verts->vPos = pos; verts->dwDiffuse = 0xffffff; verts++;
verts->vPos = pos; verts->vPos.x++; verts->dwDiffuse = 0xffffff; verts++;
dwLineCount++;
}
// Check for west wall
if( cell & MAZE_WALL_WEST )
{
verts->vPos = pos; verts->dwDiffuse = 0xffffff; verts++;
verts->vPos = pos; verts->vPos.z++; verts->dwDiffuse = 0xffffff; verts++;
dwLineCount++;
}
if( y==maxy )
{
// Check for north wall
if( cell & MAZE_WALL_SOUTH )
{
verts->vPos = pos; verts->vPos.z++; verts->dwDiffuse = 0xffffff; verts++;
verts->vPos = pos; verts->vPos.z++; verts->vPos.x++; verts->dwDiffuse = 0xffffff; verts++;
dwLineCount++;
}
}
if( x==maxx )
{
// Check for west wall
if( cell & MAZE_WALL_EAST )
{
verts->vPos = pos; verts->vPos.x++; verts->dwDiffuse = 0xffffff; verts++;
verts->vPos = pos; verts->vPos.x++; verts->vPos.z++; verts->dwDiffuse = 0xffffff; verts++;
dwLineCount++;
}
}
pos.z += 1;
}
origin.x += 1;
}
// Unlock VB and submit for rendering
m_pMiniMapVB->Unlock();
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
m_pd3dDevice->SetVertexShader( FVF_DIFFUSE );
m_pd3dDevice->SetStreamSource( 0, m_pMiniMapVB, sizeof(VERTEX_DIFFUSE) );
m_pd3dDevice->DrawPrimitive( D3DPT_LINELIST, 0, dwLineCount );
// Draw marker for camera
D3DXMatrixRotationY( &rot, -m_fCameraYaw );
rot.m[3][0] = m_vCameraPos.x; rot.m[3][2] = m_vCameraPos.z;
m_pd3dDevice->SetTransform( D3DTS_WORLD, &rot );
m_pMiniMapVB->Lock( 0, 0, (BYTE**)&verts, D3DLOCK_DISCARD );
verts[0].vPos.y = verts[1].vPos.y = verts[2].vPos.y = verts[3].vPos.y = 1.0f;
verts[0].dwDiffuse = verts[1].dwDiffuse = verts[2].dwDiffuse = verts[3].dwDiffuse = 0xb01010;
verts[0].vPos.x = 0.0f; verts[0].vPos.z = 0.4f;
verts[1].vPos.x = 0.2f; verts[1].vPos.z = 0.0f;
verts[2].vPos.x = 0.0f; verts[2].vPos.z = -0.2f;
verts[3].vPos.x = -0.2f; verts[3].vPos.z = 0.0f;
m_pMiniMapVB->Unlock();
m_pd3dDevice->SetVertexShader( FVF_DIFFUSE );
m_pd3dDevice->SetStreamSource( 0, m_pMiniMapVB, sizeof(VERTEX_DIFFUSE) );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
// Draw things in mini-map
m_pMazeClient->LockWorld();
m_pMiniMapVB->Lock( 0, 0, (BYTE**)&verts, D3DLOCK_DISCARD );
verts[0].vPos.y = verts[1].vPos.y = verts[2].vPos.y = verts[3].vPos.y = 1.0f;
verts[0].dwDiffuse = verts[1].dwDiffuse = verts[2].dwDiffuse = verts[3].dwDiffuse = 0x00FFFF00;
verts[0].vPos.x = 0.0f; verts[0].vPos.z = 0.4f;
verts[1].vPos.x = 0.2f; verts[1].vPos.z = 0.0f;
verts[2].vPos.x = 0.0f; verts[2].vPos.z = -0.2f;
verts[3].vPos.x = -0.2f; verts[3].vPos.z = 0.0f;
m_pMiniMapVB->Unlock();
m_pd3dDevice->SetVertexShader( FVF_DIFFUSE );
m_pd3dDevice->SetStreamSource( 0, m_pMiniMapVB, sizeof(VERTEX_DIFFUSE) );
for( x = minx; x <= maxx; x++ )
{
for( y = miny; y <= maxy; y++ )
{
PlayerObject* pPlayerObject = m_pMazeClient->GetFirstPlayerObjectInCell( x, y );
while( pPlayerObject )
{
D3DXMatrixTranslation( &matTrans, pPlayerObject->vPos.x, pPlayerObject->vPos.y, pPlayerObject->vPos.z );
D3DXMatrixRotationYawPitchRoll( &matRot, -AngleToFloat(pPlayerObject->aCameraYaw), 0.0f, 0.0f );
matWorld = matRot * matTrans;
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
pPlayerObject = pPlayerObject->pNext;
}
pos.z += 1;
}
}
m_pMazeClient->UnlockWorld();
D3DXMatrixIdentity( &rot );
m_pd3dDevice->SetTransform( D3DTS_WORLD, &rot );
// Re-enable z-buffering and reset viewport and matrices
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
m_pd3dDevice->SetViewport( &oldvp );
m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_Projection );
m_pd3dDevice->SetTransform( D3DTS_VIEW, &m_Camera );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CD3DGraphics::DrawIndicators()
{
VERTEX_TL_TEXTURED* v;
float xscale = float(m_d3dsdBackBuffer.Width)/640.0f;
float yscale = float(m_d3dsdBackBuffer.Height)/480.0f;
// Draw network/local icon and player icon (if connected)
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
m_pIndicatorVB->Lock( 0, 0, (BYTE**)&v, 0 );
v[0].dwSpecular = v[1].dwSpecular = v[2].dwSpecular = v[3].dwSpecular = 0;
v[0].vPos.z = v[1].vPos.z = v[2].vPos.z = v[3].vPos.z = 0.0f;
v[0].fRHW = v[1].fRHW = v[2].fRHW = v[3].fRHW = 1.0f;
v[0].dwDiffuse = v[1].dwDiffuse = v[2].dwDiffuse = v[3].dwDiffuse = 0xFFFFFFFF;
v[0].fU = 0; v[0].fV = 0;
v[1].fU = 1; v[1].fV = 0;
v[2].fU = 1; v[2].fV = 1;
v[3].fU = 0; v[3].fV = 1;
v[0].vPos.x = (xscale*16)-0.5f; v[0].vPos.y = ((480-68)*yscale)-0.5f;
v[1].vPos.x = (xscale*48)-0.5f; v[1].vPos.y = ((480-68)*yscale)-0.5f;
v[2].vPos.x = (xscale*48)-0.5f; v[2].vPos.y = ((480-36)*yscale)-0.5f;
v[3].vPos.x = (xscale*16)-0.5f; v[3].vPos.y = ((480-36)*yscale)-0.5f;
m_pIndicatorVB->Unlock();
if( m_pDP8Client->IsSessionLost() )
m_pd3dDevice->SetTexture( 0, m_pLocalIconTexture );
else
m_pd3dDevice->SetTexture( 0, m_pNetIconTexture );
m_pd3dDevice->SetVertexShader( FVF_TL_TEXTURED );
m_pd3dDevice->SetStreamSource( 0, m_pIndicatorVB, sizeof(VERTEX_TL_TEXTURED) );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
if( FALSE == m_pDP8Client->IsSessionLost() )
{
DWORD dwNumPlayers, dwNumNearbyPlayers;
m_pMazeClient->GetPlayerStats( &dwNumPlayers, &dwNumNearbyPlayers );
// Show frame rate
POINT ptStart = { (long)(xscale*60.0f), (long)((480-95)*yscale) };
TCHAR strText[MAX_PATH];
wsprintf( strText, TEXT(" Players: %4d"), dwNumPlayers );
m_pFont->DrawText( (float)ptStart.x, (float)ptStart.y, D3DCOLOR_ARGB(255,255,255,0), strText );
wsprintf( strText, TEXT("Nearby Players: %4d"), dwNumNearbyPlayers );
m_pFont->DrawText( (float)ptStart.x, (float)ptStart.y+20, D3DCOLOR_ARGB(255,255,255,0), strText );
wsprintf( strText, TEXT(" Ping: %4d ms"), m_pMazeClient->GetRoundTripLatencyMS() );
m_pFont->DrawText( (float)ptStart.x, (float)ptStart.y+40, D3DCOLOR_ARGB(255,255,255,0), strText );
wsprintf( strText, TEXT(" Data Rate: %4d Bps"), m_pMazeClient->GetThroughputBPS() );
m_pFont->DrawText( (float)ptStart.x, (float)ptStart.y+60, D3DCOLOR_ARGB(255,255,255,0), strText );
}
else
{
if( m_pMazeApp->IsOutOfDateClient() )
{
POINT ptStart = { (long)(xscale*60.0f), (long)((480-75)*yscale) };
TCHAR strText[MAX_PATH];
wsprintf( strText, TEXT("Client is out of date") );
m_pFont->DrawText( (float)ptStart.x, (float)ptStart.y, D3DCOLOR_ARGB(255,255,255,0), strText );
wsprintf( strText, TEXT("Please get update at") );
m_pFont->DrawText( (float)ptStart.x, (float)ptStart.y+20, D3DCOLOR_ARGB(255,255,255,0), strText );
wsprintf( strText, TEXT("http://msdn.microsoft.com/directx/") );
m_pFont->DrawText( (float)ptStart.x, (float)ptStart.y+40, D3DCOLOR_ARGB(255,255,255,0), strText );
}
}
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DGraphics::InvalidateDeviceObjects()
{
m_pFont->InvalidateDeviceObjects();
m_pStatsFont->InvalidateDeviceObjects();
m_pPlayerMesh->InvalidateDeviceObjects();
SAFE_RELEASE( m_pMiniMapVB );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DGraphics::DeleteDeviceObjects()
{
m_pFont->DeleteDeviceObjects();
m_pStatsFont->DeleteDeviceObjects();
SAFE_RELEASE( m_pSphere );
if( m_pPlayerMesh )
m_pPlayerMesh->Destroy();
SAFE_RELEASE( m_pMiniMapBackgroundVB );
SAFE_RELEASE( m_pIndicatorVB );
m_SmartVB.Uninit();
SAFE_RELEASE( m_pWallTexture );
SAFE_RELEASE( m_pFloorTexture );
SAFE_RELEASE( m_pCeilingTexture );
SAFE_RELEASE( m_pNetIconTexture );
SAFE_RELEASE( m_pLocalIconTexture );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DGraphics::FinalCleanup()
{
SAFE_DELETE( m_pFont );
SAFE_DELETE( m_pStatsFont );
SAFE_DELETE( m_pPlayerMesh );
return S_OK;
}