📄 d3d_app.cpp
字号:
bOldWindowedState = m_pDeviceInfo->bWindowed;
}
// Inform the framework class of the driver change. It will internally
// re-create valid surfaces, a d3ddevice, etc.
if( FAILED( hr = Initialize3DEnvironment() ) )
{
DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
return hr;
}
// If the app is paused, trigger the rendering of the current frame
if( FALSE == m_bFrameMoving )
{
m_bSingleStep = TRUE;
m_dwBaseTime += timeGetTime() - m_dwStopTime;
m_dwStopTime = timeGetTime();
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Render3DEnvironment()
// Desc: Draws the scene.
//-----------------------------------------------------------------------------
HRESULT D3D_APP::Render3DEnvironment()
{
HRESULT hr;
// Check the cooperative level before rendering
if( FAILED( hr = m_pDD->TestCooperativeLevel() ) )
{
switch( hr )
{
case DDERR_EXCLUSIVEMODEALREADYSET:
case DDERR_NOEXCLUSIVEMODE:
// Do nothing because some other app has exclusive mode
return S_OK;
case DDERR_WRONGMODE:
// The display mode changed on us. Resize accordingly
if( m_pDeviceInfo->bWindowed )
return Change3DEnvironment();
break;
}
return hr;
}
// Get the relative time, in seconds
FLOAT fTime = ( timeGetTime() - m_dwBaseTime ) * 0.001f;
// FrameMove (animate) the scene
if( m_bFrameMoving || m_bSingleStep )
{
if( FAILED( hr = FrameMove( fTime ) ) )
return hr;
m_bSingleStep = FALSE;
}
// If the display is in a stereo mode, render the scene from the left eye
// first, then the right eye.
if( m_bAppUseStereo && m_pDeviceInfo->bStereo && !m_pDeviceInfo->bWindowed )
{
// Render the scene from the left eye
m_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &m_matLeftView );
if( FAILED( hr = m_pd3dDevice->SetRenderTarget( m_pddsRenderTargetLeft, 0 ) ) )
return hr;
if( FAILED( hr = Render() ) )
return hr;
//Render the scene from the right eye
m_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &m_matRightView );
if( FAILED( hr = m_pd3dDevice->SetRenderTarget( m_pddsRenderTarget, 0 ) ) )
return hr;
if( FAILED( hr = Render() ) )
return hr;
}
else
{
// Set center viewing matrix if app is stereo-enabled
if( m_bAppUseStereo )
m_pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &m_matView );
// Render the scene as normal
if( FAILED( hr = Render() ) )
return hr;
}
// Show the frame rate, etc.
if( m_bShowStats )
ShowStats();
// Show the frame on the primary surface.
if( FAILED( hr = m_pFramework->ShowFrame() ) )
{
if( DDERR_SURFACELOST != hr )
return hr;
m_pFramework->RestoreSurfaces();
RestoreSurfaces();
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Cleanup3DEnvironment()
// Desc: Cleanup scene objects
//-----------------------------------------------------------------------------
VOID D3D_APP::Cleanup3DEnvironment()
{
m_bActive = FALSE;
m_bReady = FALSE;
if( m_pFramework )
{
DeleteDeviceObjects();
FinalCleanup();
}
D3DEnum_FreeResources();
}
//-----------------------------------------------------------------------------
// Name: Pause()
// Desc: Called in to toggle the pause state of the app. This function
// brings the GDI surface to the front of the display, so drawing
// output like message boxes and menus may be displayed.
//-----------------------------------------------------------------------------
VOID D3D_APP::Pause( BOOL bPause )
{
static DWORD dwAppPausedCount = 0L;
dwAppPausedCount += ( bPause ? +1 : -1 );
m_bReady = ( dwAppPausedCount ? FALSE : TRUE );
// Handle the first pause request (of many, nestable pause requests)
if( bPause && ( 1 == dwAppPausedCount ) )
{
// Get a surface for the GDI
if( m_pFramework )
m_pFramework->FlipToGDISurface( TRUE );
// Stop the scene from animating
if( m_bFrameMoving )
m_dwStopTime = timeGetTime();
}
if( 0 == dwAppPausedCount )
{
// Restart the scene
if( m_bFrameMoving )
m_dwBaseTime += timeGetTime() - m_dwStopTime;
}
}
//-----------------------------------------------------------------------------
// Name: ShowStats()
// Desc: Shows frame rate and dimensions of the rendering device.
//-----------------------------------------------------------------------------
#include "graph.h"
VOID D3D_APP::ShowStats()
{
static FLOAT fFPS = 0.0f;
static FLOAT fLastTime = 0.0f;
static DWORD dwFrames = 0L;
POINT pt;
GetCursorPos(&pt);
ScreenToClient(m_hWnd , &pt);
g_iMouseX = (int)pt.x;
g_iMouseY = (int)pt.y;
// Keep track of the time lapse and frame count
FLOAT fTime = timeGetTime() * 0.001f; // Get current time in seconds
++dwFrames;
// Update the frame rate once per second
if( fTime - fLastTime > 1.0f )
{
fFPS = dwFrames / (fTime - fLastTime);
fLastTime = fTime;
dwFrames = 0L;
}
// Setup the text buffer to write out dimensions
TCHAR buffer[84];
sprintf( buffer, _T("FPS = %7.02f (%dx%dx%d) cursor[%d %d]"), fFPS,
m_ddsdRenderTarget.dwWidth, m_ddsdRenderTarget.dwHeight,
m_ddsdRenderTarget.ddpfPixelFormat.dwRGBBitCount , g_iMouseX , g_iMouseY );
OutputText( 10 , 0 , buffer );
}
//-----------------------------------------------------------------------------
// Name: OutputText()
// Desc: Draws text on the window.
//-----------------------------------------------------------------------------
VOID D3D_APP::OutputText( DWORD x, DWORD y, TCHAR* str )
{
HDC hDC;
// Get a DC for the surface. Then, write out the buffer
if( m_pddsRenderTarget )
{
if( SUCCEEDED( m_pddsRenderTarget->GetDC(&hDC) ) )
{
SetTextColor( hDC, RGB(255,255,0) );
SetBkMode( hDC, TRANSPARENT );
ExtTextOut( hDC, x, y, 0, NULL, str, lstrlen(str), NULL );
m_pddsRenderTarget->ReleaseDC(hDC);
}
}
// Do the same for the left surface (in case of stereoscopic viewing).
if( m_pddsRenderTargetLeft )
{
if( SUCCEEDED( m_pddsRenderTargetLeft->GetDC( &hDC ) ) )
{
// Use a different color to help distinguish left eye view
SetTextColor( hDC, RGB(255,0,255) );
SetBkMode( hDC, TRANSPARENT );
ExtTextOut( hDC, x, y, 0, NULL, str, lstrlen(str), NULL );
m_pddsRenderTargetLeft->ReleaseDC(hDC);
}
}
}
VOID D3D_APP::DisplayFrameworkError( HRESULT hr, DWORD dwType )
{
TCHAR strMsg[512];
switch( hr )
{
case D3DENUMERR_NODIRECTDRAW:
lstrcpy( strMsg, _T("Could not create DirectDraw!") );
break;
case D3DENUMERR_NOCOMPATIBLEDEVICES:
lstrcpy( strMsg, _T("Could not find any compatible Direct3D\n"
"devices.") );
break;
case D3DENUMERR_SUGGESTREFRAST:
lstrcpy( strMsg, _T("Could not find any compatible devices.\n\n"
"Try enabling the reference rasterizer using\n"
"EnableRefRast.reg.") );
break;
case D3DENUMERR_ENUMERATIONFAILED:
lstrcpy( strMsg, _T("Enumeration failed. Your system may be in an\n"
"unstable state and need to be rebooted") );
break;
case D3DFWERR_INITIALIZATIONFAILED:
lstrcpy( strMsg, _T("Generic initialization error.\n\nEnable "
"debug output for detailed information.") );
break;
case D3DFWERR_NODIRECTDRAW:
lstrcpy( strMsg, _T("No DirectDraw") );
break;
case D3DFWERR_NODIRECT3D:
lstrcpy( strMsg, _T("No Direct3D") );
break;
case D3DFWERR_INVALIDMODE:
lstrcpy( strMsg, _T("This sample requires a 16-bit (or higher) "
"display mode\nto run in a window.\n\nPlease "
"switch your desktop settings accordingly.") );
break;
case D3DFWERR_COULDNTSETCOOPLEVEL:
lstrcpy( strMsg, _T("Could not set Cooperative Level") );
break;
case D3DFWERR_NO3DDEVICE:
lstrcpy( strMsg, _T("Could not create the Direct3DDevice object.") );
if( MSGWARN_SWITCHEDTOSOFTWARE == dwType )
lstrcat( strMsg, _T("\nThe 3D hardware chipset may not support"
"\nrendering in the current display mode.") );
break;
case D3DFWERR_NOZBUFFER:
lstrcpy( strMsg, _T("No ZBuffer") );
break;
case D3DFWERR_INVALIDZBUFFERDEPTH:
lstrcpy( strMsg, _T("Invalid Z-buffer depth. Try switching modes\n"
"from 16- to 32-bit (or vice versa)") );
break;
case D3DFWERR_NOVIEWPORT:
lstrcpy( strMsg, _T("No Viewport") );
break;
case D3DFWERR_NOPRIMARY:
lstrcpy( strMsg, _T("No primary") );
break;
case D3DFWERR_NOCLIPPER:
lstrcpy( strMsg, _T("No Clipper") );
break;
case D3DFWERR_BADDISPLAYMODE:
lstrcpy( strMsg, _T("Bad display mode") );
break;
case D3DFWERR_NOBACKBUFFER:
lstrcpy( strMsg, _T("No backbuffer") );
break;
case D3DFWERR_NONZEROREFCOUNT:
lstrcpy( strMsg, _T("A DDraw object has a non-zero reference\n"
"count (meaning it was not properly cleaned up)." ) );
break;
case D3DFWERR_NORENDERTARGET:
lstrcpy( strMsg, _T("No render target") );
break;
case E_OUTOFMEMORY:
lstrcpy( strMsg, _T("Not enough memory!") );
break;
case DDERR_OUTOFVIDEOMEMORY:
lstrcpy( strMsg, _T("There was insufficient video memory "
"to use the\nhardware device.") );
break;
default:
lstrcpy( strMsg, _T("Generic application error.\n\nEnable "
"debug output for detailed information.") );
}
if( MSGERR_APPMUSTEXIT == dwType )
{
lstrcat( strMsg, _T("\n\nThis sample will now exit.") );
MessageBox( NULL, strMsg, m_strWindowTitle, MB_ICONERROR|MB_OK );
}
else
{
if( MSGWARN_SWITCHEDTOSOFTWARE == dwType )
lstrcat( strMsg, _T("\n\nSwitching to software rasterizer.") );
MessageBox( NULL, strMsg, m_strWindowTitle, MB_ICONWARNING|MB_OK );
}
}
//-----------------------------------------------------------------------------
// Name: SetViewParams()
// Desc: Sets the parameters to be used by the SetViewMatrix() function. You
// must call this function rather than setting the D3D view matrix
// yourself in order for stereo modes to work properly.
//-----------------------------------------------------------------------------
VOID D3D_APP::SetViewParams( D3DVECTOR* vEyePt , D3DVECTOR* vLookatPt , D3DVECTOR* vUpVec, FLOAT fEyeDistance)
{
// Adjust camera position for left or right eye along the axis
// perpendicular to the view direction vector and the up vector.
D3DVECTOR vView = (*vLookatPt) - (*vEyePt);
vView = CrossProduct( vView, (*vUpVec) );
vView = Normalize( vView ) * fEyeDistance;
D3DVECTOR vLeftEyePt = (*vEyePt) + vView;
D3DVECTOR vRightEyePt = (*vEyePt) - vView;
// Set the view matrices
D3DUtil_SetViewMatrix( m_matLeftView, vLeftEyePt, *vLookatPt, *vUpVec );
D3DUtil_SetViewMatrix( m_matRightView, vRightEyePt, *vLookatPt, *vUpVec );
D3DUtil_SetViewMatrix( m_matView, *vEyePt, *vLookatPt, *vUpVec );
}
/*
========================
d3d_app 公用函数
========================
*/
VOID Coord_3DWorldToScreen(float *px , float *py , D3DVECTOR uV ,
D3DMATRIX &matProj ,
D3DMATRIX &matView ,
D3DMATRIX &matWorld )
{
D3DVECTOR uVOut;
D3DVIEWPORT7 vp;
g_pd3dDevice->GetViewport( &vp );
D3DXVec3TransformCoord((D3DXVECTOR3*)&uVOut , (D3DXVECTOR3*)&uV , (D3DXMATRIX*)&matWorld);
D3DXVec3TransformCoord((D3DXVECTOR3*)&uVOut , (D3DXVECTOR3*)&uVOut , (D3DXMATRIX*)&matView);
D3DXVec3TransformCoord((D3DXVECTOR3*)&uVOut , (D3DXVECTOR3*)&uVOut , (D3DXMATRIX*)&matProj);
uVOut.x = (vp.dwWidth / 2 ) + (vp.dwWidth / 2 ) * uVOut.x;
uVOut.y = (vp.dwHeight / 2 ) - (vp.dwHeight / 2 ) * uVOut.y;
*px = uVOut.x;
*py = uVOut.y;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -