www.pudn.com > D3D9Cartoon.rar > D3D9Cartoon.cpp


//----------------------------------------------------------------------------- 
// File: D3D9Cartoon.cpp 
// 
// Desc: DirectX window application created by the DirectX AppWizard 
//----------------------------------------------------------------------------- 
#define STRICT 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include "DXUtil.h" 
#include "D3DEnumeration.h" 
#include "D3DSettings.h" 
#include "D3DApp.h" 
#include "D3DFont.h" 
#include "D3DFile.h" 
#include "D3DUtil.h" 
#include "resource.h" 
#include "D3D9Cartoon.h" 
 
//----------------------------------------------------------------------------- 
// Global access to the app (needed for the global WndProc()) 
//----------------------------------------------------------------------------- 
CMyD3DApplication* g_pApp  = NULL; 
HINSTANCE          g_hInst = NULL; 
 
//----------------------------------------------------------------------------- 
// Name: WinMain() 
// Desc: Entry point to the program. Initializes everything, and goes into a 
//       message-processing loop. Idle time is used to render the scene. 
//----------------------------------------------------------------------------- 
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ) 
{ 
    CMyD3DApplication d3dApp; 
 
    g_pApp  = &d3dApp; 
    g_hInst = hInst; 
 
    InitCommonControls(); 
    if( FAILED( d3dApp.Create( hInst ) ) ) 
        return 0; 
 
    return d3dApp.Run(); 
} 
 
//----------------------------------------------------------------------------- 
// Name: CMyD3DApplication() 
// Desc: Application constructor.   Paired with ~CMyD3DApplication() 
//       Member variables should be initialized to a known state here.   
//       The application window has not yet been created and no Direct3D device  
//       has been created, so any initialization that depends on a window or  
//       Direct3D should be deferred to a later stage.  
//----------------------------------------------------------------------------- 
CMyD3DApplication::CMyD3DApplication() 
{ 
    m_dwCreationWidth           = 500; 
    m_dwCreationHeight          = 375; 
    m_strWindowTitle            = TEXT( "D3D9Cartoon" ); 
    m_d3dEnumeration.AppUsesDepthBuffer   = TRUE; 
	m_bStartFullscreen			= false; 
	m_bShowCursorWhenFullscreen	= false; 
 
    // Create a D3D font using d3dfont.cpp 
    m_pFont                     = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD ); 
    m_bLoadingApp               = TRUE; 
    m_pD3DXMesh                 = NULL; 
 
    ZeroMemory( &m_UserInput, sizeof(m_UserInput) ); 
    m_fWorldRotX                = 0.0f; 
    m_fWorldRotY                = 0.0f; 
 
	/////////////////////////////////////////////////////////////// 
	m_pSilhouetteVertexShader=0; 
	m_pSilhouetteVertexDecl=0; 
	m_pSurfaceVertexShader=0; 
	m_pSurfaceVertexDecl=0; 
	m_pFloorVertexShader=0; 
	m_pFloorVertexDecl=0; 
 
	m_pObject=new CD3DMesh(); 
	m_pFloor=new CD3DMesh(); 
} 
 
//----------------------------------------------------------------------------- 
// Name: ~CMyD3DApplication() 
// Desc: Application destructor.  Paired with CMyD3DApplication() 
//----------------------------------------------------------------------------- 
CMyD3DApplication::~CMyD3DApplication() 
{ 
} 
 
//----------------------------------------------------------------------------- 
// Name: OneTimeSceneInit() 
// Desc: Paired with FinalCleanup(). 
//       The window has been created and the IDirect3D9 interface has been 
//       created, but the device has not been created yet.  Here you can 
//       perform application-related initialization and cleanup that does 
//       not depend on a device. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::OneTimeSceneInit() 
{ 
    // TODO: perform one time initialization 
 
    // Drawing loading status message until app finishes loading 
    SendMessage( m_hWnd, WM_PAINT, 0, 0 ); 
 
    m_bLoadingApp = FALSE; 
 
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: ConfirmDevice() 
// Desc: Called during device initialization, this code checks the display device 
//       for some minimum set of capabilities 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior, 
                                          D3DFORMAT Format ) 
{ 
    UNREFERENCED_PARAMETER( Format ); 
    UNREFERENCED_PARAMETER( dwBehavior ); 
    UNREFERENCED_PARAMETER( pCaps ); 
     
    BOOL bCapsAcceptable; 
 
    // TODO: Perform checks to see if these display caps are acceptable. 
    bCapsAcceptable = TRUE; 
 
    if( bCapsAcceptable )          
        return S_OK; 
    else 
        return E_FAIL; 
} 
 
//----------------------------------------------------------------------------- 
// Name: InitDeviceObjects() 
// Desc: Paired with DeleteDeviceObjects() 
//       The device has been created.  Resources that are not lost on 
//       Reset() can be created here -- resources in D3DPOOL_MANAGED, 
//       D3DPOOL_SCRATCH, or D3DPOOL_SYSTEMMEM.  Image surfaces created via 
//       CreateImageSurface are never lost and can be created here.  Vertex 
//       shaders and pixel shaders can also be created here as they are not 
//       lost on Reset(). 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::InitDeviceObjects() 
{ 
    // TODO: create device objects 
 
    HRESULT hr; 
 
    // Init the font 
    m_pFont->InitDeviceObjects( m_pd3dDevice ); 
 
    // Create a teapot mesh using D3DX 
    if( FAILED( hr = D3DXCreateTeapot( m_pd3dDevice, &m_pD3DXMesh, NULL ) ) ) 
        return DXTRACE_ERR( "D3DXCreateTeapot", hr ); 
 
	///////////////////////////////////////////////////////////////////////// 
	//在 d3dapp.cpp 的 Initialize3DEnvironment 中设置为软件模拟VS2.0(第725行) 
	LPDIRECT3DVERTEXBUFFER9 pVB; 
	LPVOID pVertices; 
 
	hr=m_pObject->Create(m_pd3dDevice,"tiger.x"); 
	hr=m_pObject->SetFVF(m_pd3dDevice,FVF); 
 
	hr=m_pObject->m_pSysMemMesh->GetVertexBuffer(&pVB); 
	hr=pVB->Lock(0,0,&pVertices,0); 
	hr=D3DXComputeBoundingSphere((D3DXVECTOR3*)pVertices,m_pObject->m_pSysMemMesh->GetNumVertices(), 
		D3DXGetFVFVertexSize(m_pObject->m_pSysMemMesh->GetFVF()),&m_vCenter,&m_ObjRadius); 
	pVB->Unlock(); 
    SAFE_RELEASE(pVB); 
 
	hr=m_pFloor->Create(m_pd3dDevice,"seaFloor.x"); 
	hr=m_pFloor->SetFVF(m_pd3dDevice,FVF); 
 
	hr=BuildShaders(); 
	hr=ModifyTextures(); 
 
    return S_OK; 
} 
 
HRESULT CMyD3DApplication::BuildShaders() 
{ 
	LPD3DXBUFFER pError=0;    
	LPD3DXBUFFER pCode=0; 
	HRESULT hr; 
 
	D3DVERTEXELEMENT9 declSilhouette[] = 
    { 
    	{ 0,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_POSITION, 0},  
        { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_NORMAL,   0},  
        { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_TEXCOORD, 0}, 
		{ 0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_COLOR,    0}, 
		D3DDECL_END() 
    }; 
 
	hr=m_pd3dDevice->CreateVertexDeclaration(declSilhouette,&m_pSilhouetteVertexDecl); 
    hr=D3DXAssembleShaderFromFile("zzSilhouette.vsh",0,0,0,&pCode,&pError); 
    hr=m_pd3dDevice->CreateVertexShader((DWORD*)pCode->GetBufferPointer(),&m_pSilhouetteVertexShader); 
	 
	D3DVERTEXELEMENT9 declSurface[] = 
    { 
    	{ 0,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_POSITION, 0},  
        { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_NORMAL,   0},  
        { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_TEXCOORD, 0}, 
		{ 0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_COLOR,    0}, 
		D3DDECL_END() 
    }; 
 
	hr=m_pd3dDevice->CreateVertexDeclaration(declSurface,&m_pSurfaceVertexDecl); 
    hr=D3DXAssembleShaderFromFile("zzSurface.vsh",0,0,0,&pCode,&pError); 
    hr=m_pd3dDevice->CreateVertexShader((DWORD*)pCode->GetBufferPointer(),&m_pSurfaceVertexShader); 
	 
	D3DVERTEXELEMENT9 declFloor[] = 
    { 
    	{ 0,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_POSITION, 0},  
        { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_NORMAL,   0},  
        { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_TEXCOORD, 0}, 
		{ 0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_COLOR,    0}, 
		D3DDECL_END() 
    }; 
 
	hr=m_pd3dDevice->CreateVertexDeclaration(declFloor,&m_pFloorVertexDecl); 
    hr=D3DXAssembleShaderFromFile("zzFloor.vsh",0,0,0,&pCode,&pError); 
    hr=m_pd3dDevice->CreateVertexShader((DWORD*)pCode->GetBufferPointer(),&m_pFloorVertexShader); 
 
	return(S_OK); 
} 
 
HRESULT	CMyD3DApplication::ModifyTextures() 
{ 
	LPDIRECT3DSURFACE9 pSurface; 
	LPBYTE pMemSurface,pMemData; 
	D3DSURFACE_DESC desc; 
	RECT rect; 
	HRESULT	hr; 
	DWORD i,j; 
 
	(*m_pObject->m_pTextures)->Release(); 
	hr=D3DXCreateTexture(m_pd3dDevice,256,8,D3DX_DEFAULT,0,D3DFMT_L8, 
		D3DPOOL_MANAGED,m_pObject->m_pTextures); 
	(*m_pObject->m_pTextures)->GetSurfaceLevel(0,&pSurface); 
	pSurface->GetDesc(&desc); 
	 
	pMemSurface=new BYTE[desc.Width*desc.Height]; 
	pMemData=pMemSurface; 
	for(i=0;iRelease(); 
 
	return(S_OK); 
} 
 
//----------------------------------------------------------------------------- 
// Name: RestoreDeviceObjects() 
// Desc: Paired with InvalidateDeviceObjects() 
//       The device exists, but may have just been Reset().  Resources in 
//       D3DPOOL_DEFAULT and any other device state that persists during 
//       rendering should be set here.  Render states, matrices, textures, 
//       etc., that don't change during rendering can be set once here to 
//       avoid redundant state setting during Render() or FrameMove(). 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::RestoreDeviceObjects() 
{ 
    // TODO: setup render states 
 
    // Setup a material 
    D3DMATERIAL9 mtrl; 
    D3DUtil_InitMaterial( mtrl, 1.0f, 0.0f, 0.0f ); 
    m_pd3dDevice->SetMaterial( &mtrl ); 
 
    // Set up the textures 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE ); 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE ); 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); 
    m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); 
    m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); 
 
    // Set miscellaneous render states 
    m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE,   FALSE ); 
    m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE ); 
    m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,        TRUE ); 
    m_pd3dDevice->SetRenderState( D3DRS_AMBIENT,        0x000F0F0F ); 
 
    // Restore the font 
    m_pFont->RestoreDeviceObjects(); 
 
	/////////////////////////////////////////////////////////////// 
	D3DXVECTOR3 vEye=D3DXVECTOR3(0.0f,0.0f,-2.0f*m_ObjRadius); 
    D3DXVECTOR3 vAt=D3DXVECTOR3(0.0f,0.0f,0.0f); 
    D3DXVECTOR3 vUp=D3DXVECTOR3(0.0f,1.0f,0.0f); 
	FLOAT fAspect; 
	HRESULT hr; 
	 
    D3DXMatrixIdentity(&m_matWorld); 
	D3DXMatrixLookAtLH(&m_matView,&vEye,&vAt,&vUp); 
    fAspect=(FLOAT)m_d3dsdBackBuffer.Width/(FLOAT)m_d3dsdBackBuffer.Height; 
    D3DXMatrixPerspectiveFovLH(&m_matProj,D3DXToRadian(60.0f),fAspect,0.1f,100.0f); 
	 
	m_pd3dDevice->SetTransform(D3DTS_WORLD,&m_matWorld); 
    m_pd3dDevice->SetTransform(D3DTS_VIEW,&m_matView); 
    m_pd3dDevice->SetTransform(D3DTS_PROJECTION,&m_matProj); 
 
	m_ArcBall.SetWindow(m_d3dsdBackBuffer.Width,m_d3dsdBackBuffer.Height,0.8f); 
    m_ArcBall.SetRadius(m_ObjRadius); 
 
	hr=m_pObject->RestoreDeviceObjects(m_pd3dDevice); 
	hr=m_pFloor->RestoreDeviceObjects(m_pd3dDevice); 
 
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: FrameMove() 
// Desc: Called once per frame, the call is the entry point for animating 
//       the scene. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::FrameMove() 
{ 
    // TODO: update world 
	/////////////////////////////////////////////////////////////// 
	D3DXMATRIX matT,matX,matY,matZ; 
 
	D3DXMatrixTranslation(&matT,0.01f,0.01f,0.01f); 
	D3DXMatrixRotationX(&matX,10.0f*D3DX_PI/180.0f); 
	D3DXMatrixRotationY(&matY,110.0f*D3DX_PI/180.0f); 
	D3DXMatrixRotationZ(&matZ,15.0f*D3DX_PI/180.0f); 
	D3DXMatrixMultiply(&m_matWorld,&matX,&matY); 
	D3DXMatrixMultiply(&m_matWorld,&m_matWorld,&matZ); 
	D3DXMatrixMultiply(&m_matWorld,&m_matWorld,&matT); 
 
    D3DXMatrixMultiply(&m_matWorld,&m_matWorld,m_ArcBall.GetRotationMatrix()); 
    D3DXMatrixMultiply(&m_matWorld,&m_matWorld,m_ArcBall.GetTranslationMatrix()); 
	 
	D3DXMATRIX matWVPTranspose,matWVTranspose,matViewTranspose,matProjTranspose; 
	D3DXMATRIX matWVP,matWV; 
	HRESULT hr; 
	 
	D3DXMatrixMultiply(&matWV,&m_matWorld,&m_matView); 
	D3DXMatrixMultiply(&matWVP,&matWV,&m_matProj); 
	D3DXMatrixTranspose(&matWVPTranspose,&matWVP); 
	D3DXMatrixTranspose(&matWVTranspose,&matWV); 
	D3DXMatrixTranspose(&matViewTranspose,&m_matView); 
    D3DXMatrixTranspose(&matProjTranspose,&m_matProj); 
	 
	FLOAT fLight[4]={-1.0f,-1.0f,1.0f,0.0f}; 
	FLOAT fDiffuse[4]={1.0f,1.0f,0.0f,1.0f}; 
	FLOAT fAmbient[4]={0.25f,0.25f,0.25f,1.0f}; 
	 
	hr=m_pd3dDevice->SetVertexShaderConstantF(1,(FLOAT*)&matWVTranspose,4); 
	hr=m_pd3dDevice->SetVertexShaderConstantF(5,(FLOAT*)&matWVPTranspose,4); 
	hr=m_pd3dDevice->SetVertexShaderConstantF(18,(FLOAT*)&matViewTranspose,4); 
	hr=m_pd3dDevice->SetVertexShaderConstantF(22,(FLOAT*)&matProjTranspose,4); 
 
	hr=m_pd3dDevice->SetVertexShaderConstantF(9,(FLOAT*)&fDiffuse,1); 
	hr=m_pd3dDevice->SetVertexShaderConstantF(10,(FLOAT*)&fLight,1); 
	hr=m_pd3dDevice->SetVertexShaderConstantF(11,(FLOAT*)&fAmbient,1); 
   
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: UpdateInput() 
// Desc: Update the user input.  Called once per frame  
//----------------------------------------------------------------------------- 
void CMyD3DApplication::UpdateInput( UserInput* pUserInput ) 
{ 
    pUserInput->bRotateUp    = ( m_bActive && (GetAsyncKeyState( VK_UP )    & 0x8000) == 0x8000 ); 
    pUserInput->bRotateDown  = ( m_bActive && (GetAsyncKeyState( VK_DOWN )  & 0x8000) == 0x8000 ); 
    pUserInput->bRotateLeft  = ( m_bActive && (GetAsyncKeyState( VK_LEFT )  & 0x8000) == 0x8000 ); 
    pUserInput->bRotateRight = ( m_bActive && (GetAsyncKeyState( VK_RIGHT ) & 0x8000) == 0x8000 ); 
} 
 
//----------------------------------------------------------------------------- 
// Name: Render() 
// Desc: Called once per frame, the call is the entry point for 3d 
//       rendering. This function sets up render states, clears the 
//       viewport, and renders the scene. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::Render() 
{ 
    // Clear the viewport 
    m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 
                         0x000000ff, 1.0f, 0L ); 
 
    // Begin the scene 
    if( SUCCEEDED( m_pd3dDevice->BeginScene() ) ) 
    { 
        // TODO: render world 
         
        // Render the teapot mesh 
        //m_pD3DXMesh->DrawSubset(0); 
 
		/////////////////////////////////////////////////////////// 
		HRESULT hr; 
 
		hr=m_pd3dDevice->SetVertexDeclaration(m_pFloorVertexDecl); 
		hr=m_pd3dDevice->SetVertexShader(m_pFloorVertexShader); 
		hr=m_pFloor->Render(m_pd3dDevice); 
 
		hr=m_pd3dDevice->SetVertexDeclaration(m_pSurfaceVertexDecl); 
		hr=m_pd3dDevice->SetVertexShader(m_pSurfaceVertexShader); 
		hr=m_pObject->Render(m_pd3dDevice); 
		 
		m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE,1); 
		m_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL); 
		m_pd3dDevice->SetRenderState(D3DRS_ALPHAREF,200); 
 
		hr=m_pd3dDevice->SetVertexDeclaration(m_pSilhouetteVertexDecl); 
		hr=m_pd3dDevice->SetVertexShader(m_pSilhouetteVertexShader); 
		hr=m_pObject->Render(m_pd3dDevice); 
 
        // Render stats and help text   
        RenderText(); 
 
        // End the scene. 
        m_pd3dDevice->EndScene(); 
    } 
 
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: RenderText() 
// Desc: Renders stats and help text to the scene. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::RenderText() 
{ 
    D3DCOLOR fontColor        = D3DCOLOR_ARGB(255,255,255,0); 
    TCHAR szMsg[MAX_PATH] = TEXT(""); 
 
    // Output display stats 
    FLOAT fNextLine = 40.0f;  
 
    lstrcpy( szMsg, m_strDeviceStats ); 
    fNextLine -= 20.0f; 
    m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
    lstrcpy( szMsg, m_strFrameStats ); 
    fNextLine -= 20.0f; 
    m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: MsgProc() 
// Desc: Overrrides the main WndProc, so the sample can do custom message 
//       handling (e.g. processing mouse, keyboard, or menu commands). 
//----------------------------------------------------------------------------- 
LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT msg, WPARAM wParam, 
                                    LPARAM lParam ) 
{ 
	/////////////////////////////////////////////////////////////// 
	m_ArcBall.HandleMouseMessages(hWnd,msg,wParam,lParam); 
 
    return CD3DApplication::MsgProc( hWnd, msg, wParam, lParam ); 
} 
 
//----------------------------------------------------------------------------- 
// Name: InvalidateDeviceObjects() 
// Desc: Invalidates device objects.  Paired with RestoreDeviceObjects() 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::InvalidateDeviceObjects() 
{ 
    // TODO: Cleanup any objects created in RestoreDeviceObjects() 
    m_pFont->InvalidateDeviceObjects(); 
 
	/////////////////////////////////////////////////////////////// 
	m_pObject->InvalidateDeviceObjects(); 
	m_pFloor->InvalidateDeviceObjects(); 
 
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: DeleteDeviceObjects() 
// Desc: Paired with InitDeviceObjects() 
//       Called when the app is exiting, or the device is being changed, 
//       this function deletes any device dependent objects.   
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::DeleteDeviceObjects() 
{ 
    // TODO: Cleanup any objects created in InitDeviceObjects() 
    m_pFont->DeleteDeviceObjects(); 
    SAFE_RELEASE( m_pD3DXMesh ); 
 
	/////////////////////////////////////////////////////////////// 
	m_pObject->Destroy(); 
	m_pFloor->Destroy(); 
 
	SAFE_RELEASE(m_pSilhouetteVertexShader); 
	SAFE_RELEASE(m_pSilhouetteVertexDecl); 
 
	SAFE_RELEASE(m_pSurfaceVertexShader); 
	SAFE_RELEASE(m_pSurfaceVertexDecl); 
 
	SAFE_RELEASE(m_pFloorVertexShader); 
	SAFE_RELEASE(m_pFloorVertexDecl); 
 
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: FinalCleanup() 
// Desc: Paired with OneTimeSceneInit() 
//       Called before the app exits, this function gives the app the chance 
//       to cleanup after itself. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::FinalCleanup() 
{ 
    // TODO: Perform any final cleanup needed 
    // Cleanup D3D font 
    SAFE_DELETE( m_pFont ); 
 
	/////////////////////////////////////////////////////////////// 
	SAFE_DELETE(m_pObject); 
	SAFE_DELETE(m_pFloor); 
 
    return S_OK; 
}