www.pudn.com > Samples-latest.zip > BasicSH.cpp
//----------------------------------------------------------------------------- // File: BasicSH.cpp // // Desc: This sample shows the basic usage of the SH-Utils // by using the ZFXMath::SphericalHarmonics::Device. // This includes the creation of a custom light function, // its compression, rotation and visual reconstruction. //----------------------------------------------------------------------------- #include#include #include #include "resource.h" #include #include #include #include "ReconstructSH.h" using namespace ZFXMath; typedef float SHPrecisionType; typedef float SHFuncValueType; // Our custom light source, which implements the spherical function interface. // This is the way to compress an arbitrary lighting situation into SH-Coefficients. struct TestLight : public TReconstructSH< SHPrecisionType, SHFuncValueType > { SHFuncValueType EvalFunction(const SphericalHarmonics::TSample & s) const { return SHFuncValueType( ( Max (0, 5 * Cos(s.theta) - 4) + Max (0, -4 * Sin(s.theta - (SHPrecisionType)PI) * Cos(s.phi - 2.5f) - 3) ) * 1.3f ); } }; typedef TReconstructSH< SHPrecisionType, SHFuncValueType > ReconstructSH; typedef SphericalHarmonics::TDevice< SHPrecisionType, SHFuncValueType > SHDevice; typedef SphericalHarmonics::TCoeffs Coeffs; typedef SphericalHarmonics::TRotateMatrix< SHPrecisionType, SHFuncValueType > SHRotateMatrix; const int NUM_RECONSTRUCT_SAMPLES = 30; D3DXVECTOR3 LightDir = (*D3DXVec3Normalize( &LightDir, &D3DXVECTOR3(1.0f, 1.0f, -1.0f) )); //----------------------------------------------------------------------------- // Name: class CMyD3DApplication // Desc: Main class to run this application. Most functionality is inherited // from the CD3DApplication base class. //----------------------------------------------------------------------------- class CMyD3DApplication : public CD3DApplication { private: ID3DXFont* m_pFont; // Font for drawing text bool m_bShowHelp; // If true, it renders the UI control text bool m_WireFrame; CModelViewerCamera m_Camera; // A model viewing camera LPD3DXEFFECT m_pEffect; // D3DX effect interface LPD3DXMESH m_pMesh; // Mesh object LPDIRECT3DTEXTURE9 m_pMeshTexture; // Mesh texture D3DXHANDLE m_hTime; // Handle to var in the effect D3DXHANDLE m_hWorld; // Handle to var in the effect D3DXHANDLE m_hMeshTexture; // Handle to var in the effect D3DXHANDLE m_hWorldViewProjection; // Handle to var in the effect D3DXHANDLE m_hTechniqueRenderScene; // Handle to technique in the effect float* m_pVertexBufferStaticSH; float* m_pVertexBufferDynamicSH; float* m_pVBOriginalFunction; // SH STUFF // bool m_ReconstructToSphere; int m_NumBands; int m_NumSamples; // SH-Tool SHDevice* m_pSHDevice; // Unrotated SH coefficients Coeffs m_InitialCoeffs; // Function containing coeff rotation destination ReconstructSH* m_pFunction; TestLight* m_pTestLight; SHRotateMatrix m_SHRotateMatrix; protected: HRESULT OneTimeSceneInit(); HRESULT InitDeviceObjects(); HRESULT RestoreDeviceObjects(); HRESULT InvalidateDeviceObjects(); HRESULT DeleteDeviceObjects(); HRESULT FinalCleanup(); HRESULT Render(); HRESULT FrameMove(); HRESULT ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior, D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat ); void CreateSHStuff(); HRESULT LoadMesh( TCHAR* strFileName, LPD3DXMESH* ppMesh ); HRESULT RenderText(); public: CMyD3DApplication(); LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); }; //----------------------------------------------------------------------------- // 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; 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_pSHDevice(NULL), m_NumBands(4), m_NumSamples(100), m_InitialCoeffs(m_NumBands), m_pFunction(NULL), m_pTestLight(NULL), m_SHRotateMatrix(m_NumBands), m_pVertexBufferStaticSH(NULL), m_pVertexBufferDynamicSH(NULL), m_pVBOriginalFunction(NULL) { m_strWindowTitle = _T("BasicSH"); m_d3dEnumeration.AppUsesDepthBuffer = TRUE; m_dwCreationWidth = 800; m_dwCreationHeight = 600; m_pFont = NULL; m_WireFrame = false; m_ReconstructToSphere = false; m_pEffect = NULL; m_hWorld = NULL; m_hMeshTexture = NULL; m_hWorldViewProjection = NULL; m_hTechniqueRenderScene = NULL; m_pMesh = NULL; m_pMeshTexture = NULL; } //----------------------------------------------------------------------------- // 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() { return S_OK; } //----------------------------------------------------------------------------- // 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() { HRESULT hr; // Initialize the font HDC hDC = GetDC( NULL ); int nHeight = -MulDiv( 9, GetDeviceCaps(hDC, LOGPIXELSY), 72 ); ReleaseDC( NULL, hDC ); if( FAILED( hr = D3DXCreateFont( m_pd3dDevice, nHeight, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &m_pFont ) ) ) return DXTRACE_ERR( TEXT("D3DXCreateFont"), hr ); // Load the mesh LoadMesh( "teapot.x", &m_pMesh ); // Read the D3DX effect file hr = D3DXCreateEffectFromFile( m_pd3dDevice, "BasicSH.fx", NULL, NULL, 0, NULL, &m_pEffect, NULL ); // If this fails, there should be debug output as to // they the .fx file failed to compile if( FAILED( hr ) ) return DXTRACE_ERR( TEXT("D3DXCreateEffectFromFile"), hr ); // Setup the camera's projection parameters float fAspectRatio = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height; m_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f ); m_Camera.SetWindow( m_d3dsdBackBuffer.Width, m_d3dsdBackBuffer.Height ); // Setup the camera's view parameters D3DXVECTOR3 vecEye(0.0f, 0.0f, 0.0f); D3DXVECTOR3 vecAt (0.0f, 0.0f, 0.0f); m_Camera.SetViewParams( &vecEye, &vecAt ); m_Camera.SetRadius( 6.0f ); m_Camera.SetButtonMasks( MOUSE_LEFT_BUTTON, MOUSE_WHEEL, MOUSE_MIDDLE_BUTTON ); CreateSHStuff(); return S_OK; } void CMyD3DApplication::CreateSHStuff() { // init the SHDevice m_pSHDevice = new SHDevice( m_NumBands, m_NumSamples ); m_pTestLight = new TestLight; // Project the test light onto SH coefficients m_pSHDevice->Project( *m_pTestLight, m_InitialCoeffs ); // SHDevice is no longer required delete m_pSHDevice; // Create the 3D representation of the reconstructed test light function m_pFunction = new ReconstructSH(m_InitialCoeffs); m_pVertexBufferStaticSH = new float[ NUM_RECONSTRUCT_SAMPLES * NUM_RECONSTRUCT_SAMPLES * 6 * 7 ]; // 6 Vertices * Stride m_pVertexBufferDynamicSH = new float[ NUM_RECONSTRUCT_SAMPLES * NUM_RECONSTRUCT_SAMPLES * 6 * 7 ]; m_pVBOriginalFunction = new float[ NUM_RECONSTRUCT_SAMPLES * NUM_RECONSTRUCT_SAMPLES * 6 * 7 ]; m_pFunction->Reconstruct( m_pVertexBufferStaticSH, NUM_RECONSTRUCT_SAMPLES, m_ReconstructToSphere ); m_pTestLight->Reconstruct( m_pVBOriginalFunction, NUM_RECONSTRUCT_SAMPLES, m_ReconstructToSphere ); } //----------------------------------------------------------------------------- // Name: LoadMesh() // Desc: Load the mesh and ensure the mesh has normals, and optimize // the mesh for this graphics card's vertex cache so the triangle list // inside in the mesh will cache miss less which improves perf. //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::LoadMesh( TCHAR* strFileName, LPD3DXMESH* ppMesh ) { LPD3DXMESH pMesh = NULL; HRESULT hr; if( ppMesh == NULL ) return E_INVALIDARG; hr = D3DXLoadMeshFromX(strFileName, D3DXMESH_MANAGED, m_pd3dDevice, NULL, NULL, NULL, NULL, &pMesh); if( FAILED(hr) || (pMesh == NULL) ) return DXTRACE_ERR( TEXT("D3DXLoadMeshFromX"), hr ); DWORD *rgdwAdjacency = NULL; //----------------------------------------------------------------------- // Redefine Mesh //----------------------------------------------------------------------- D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END() }; LPD3DXMESH pTempMesh; hr = pMesh->CloneMesh( pMesh->GetOptions(), decl, m_pd3dDevice, &pTempMesh ); if( FAILED(hr) ) return DXTRACE_ERR( TEXT("CloneMeshFVF"), hr ); D3DXComputeNormals( pTempMesh, NULL ); SAFE_RELEASE( pMesh ); pMesh = pTempMesh; //----------------------------------------------------------------------- // //----------------------------------------------------------------------- UINT uStride = pMesh->GetNumBytesPerVertex(); UINT VertexCount = pMesh->GetNumVertices(); BYTE* pV = NULL; WORD* pI = NULL; pMesh->LockVertexBuffer( 0, (void**) &pV ); pMesh->LockIndexBuffer( 0, (void**) &pI ); float* pBuffer = (float*)pV; for ( UINT n = 0; n < VertexCount; n++ ) { pBuffer[6] = 1.0f; pBuffer += uStride / 4; } pMesh->UnlockIndexBuffer(); pMesh->UnlockVertexBuffer(); // Optimize the mesh for this graphics card's vertex cache // so when rendering the mesh's triangle list the vertices will // cache hit more often so it won't have to re-execute the vertex shader // on those vertices so it will improves perf. rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3]; pMesh->ConvertPointRepsToAdjacency(NULL, rgdwAdjacency); pMesh->OptimizeInplace( D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL); delete[] rgdwAdjacency; *ppMesh = pMesh; 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() { if( m_pFont ) m_pFont->OnResetDevice(); if( m_pEffect ) m_pEffect->OnResetDevice(); // To read or write to D3DX effect variables we can use the string name // instead of using handles, however it improves perf to use handles since then // D3DX won't have to spend time doing string compares m_hTechniqueRenderScene = m_pEffect->GetTechniqueByName( "RenderScene" ); m_hTime = m_pEffect->GetParameterByName( NULL, "g_fTime" ); m_hWorld = m_pEffect->GetParameterByName( NULL, "g_mWorld" ); m_hWorldViewProjection = m_pEffect->GetParameterByName( NULL, "g_mWorldViewProjection" ); m_hMeshTexture = m_pEffect->GetParameterByName( NULL, "g_MeshTexture" ); return D3D_OK; } //----------------------------------------------------------------------------- // Name: FrameMove() // Desc: Called once per frame, the call is the entry point for animating // the scene. //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::FrameMove() { // Update the camera's postion based on user input m_Camera.FrameMove( m_fElapsedTime ); return S_OK; } //----------------------------------------------------------------------------- // 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() { D3DXMATRIXA16 mWorld; D3DXMATRIXA16 mView; D3DXMATRIXA16 mProj; D3DXMATRIXA16 mWorldViewProjection; UINT iPass, cPasses; if ( m_WireFrame ) m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, 2 ); else m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, 3 ); // Clear the render target and the zbuffer m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00005F5F, 1.0f, 0); // Render the scene if( SUCCEEDED( m_pd3dDevice->BeginScene() ) ) { // Set world drawing technique m_pEffect->SetTechnique( m_hTechniqueRenderScene ); // Get the projection & view matrix from the camera class mWorld = *m_Camera.GetWorldMatrix(); mProj = *m_Camera.GetProjMatrix(); mView = *m_Camera.GetViewMatrix(); D3DXMATRIX mInverseWMatrix; float det = D3DXMatrixDeterminant( &mWorld ); D3DXMatrixInverse( &mInverseWMatrix, &det, &mWorld ); float s = 0.2f; mWorld._11 *= s; mWorld._12 *= s; mWorld._13 *= s; mWorld._22 *= s; mWorld._21 *= s; mWorld._23 *= s; mWorld._33 *= s; mWorld._31 *= s; mWorld._32 *= s; mWorld._42 = -1.5f; mWorldViewProjection = mWorld * mView * mProj; // Update the effect's variables m_pEffect->SetMatrix( m_hWorldViewProjection, &mWorldViewProjection ); m_pEffect->SetMatrix( m_hWorld, &mWorld ); m_pEffect->SetFloat( m_hTime, m_fTime ); m_pEffect->SetTexture( m_hMeshTexture, m_pMeshTexture); D3DXVECTOR4 LightObjectSpace4 = LightDir; D3DXVec3Transform( &LightObjectSpace4, &LightDir, &mInverseWMatrix ); D3DXVECTOR3 LightObjectSpace3 = LightObjectSpace4; D3DXVec3Normalize( &LightObjectSpace3, &LightObjectSpace3 ); m_pEffect->SetVector( "g_LightDir", &D3DXVECTOR4( LightObjectSpace3.x, LightObjectSpace3.y, LightObjectSpace3.z, 0.0f ) ); m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, false ); //----------------------------------------------------------------------- // Draw the teapot (set the VertexDeclaration) //----------------------------------------------------------------------- m_pEffect->Begin(&cPasses, 0); for (iPass = 0; iPass < cPasses; iPass++) { m_pEffect->BeginPass(iPass); m_pMesh->DrawSubset(0); m_pEffect->EndPass(); } m_pEffect->End(); //----------------------------------------------------------------------- // Draw Matrix-Rotated function //----------------------------------------------------------------------- mWorld = *m_Camera.GetWorldMatrix(); mWorld._41 = -2.1f; mWorldViewProjection = mWorld * mView * mProj; m_pEffect->SetMatrix( m_hWorldViewProjection, &mWorldViewProjection ); m_pEffect->SetMatrix( m_hWorld, &mWorld ); m_pEffect->Begin(&cPasses, 0); for (iPass = 0; iPass < cPasses; iPass++) { m_pEffect->BeginPass(iPass); m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, NUM_RECONSTRUCT_SAMPLES*NUM_RECONSTRUCT_SAMPLES*2, m_pVertexBufferStaticSH, 28 ); m_pEffect->EndPass(); } m_pEffect->End(); //----------------------------------------------------------------------- // Draw SH-rotated function //----------------------------------------------------------------------- TMatrix3x3 rotMatrix( mWorld._11, mWorld._12, mWorld._13, mWorld._21, mWorld._22, mWorld._23, mWorld._31, mWorld._32, mWorld._33 ); SphericalHarmonics::SHRotate( m_SHRotateMatrix, rotMatrix ); m_SHRotateMatrix.Transform( m_InitialCoeffs, m_pFunction->m_Coeffs ); D3DXMatrixIdentity( &mWorld ); mWorld._41 = 2.1f; mWorldViewProjection = mWorld * mView * mProj; m_pEffect->SetMatrix( m_hWorldViewProjection, &mWorldViewProjection ); D3DXVECTOR4 LightObjectSpace4D = LightDir; m_pEffect->SetVector( "g_LightDir", &LightObjectSpace4D ); m_pEffect->Begin(&cPasses, 0); for (iPass = 0; iPass < cPasses; iPass++) { m_pEffect->BeginPass(iPass); m_pFunction->Reconstruct( m_pVertexBufferDynamicSH, NUM_RECONSTRUCT_SAMPLES, m_ReconstructToSphere ); m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, NUM_RECONSTRUCT_SAMPLES*NUM_RECONSTRUCT_SAMPLES*2, m_pVertexBufferDynamicSH, 28 ); m_pEffect->EndPass(); } m_pEffect->End(); //----------------------------------------------------------------------- // Draw the original uncompressed function //----------------------------------------------------------------------- mWorld = *m_Camera.GetWorldMatrix(); mWorldViewProjection = mWorld * mView * mProj; m_pEffect->SetMatrix( m_hWorldViewProjection, &mWorldViewProjection ); m_pEffect->SetVector( "g_LightDir", &D3DXVECTOR4( LightObjectSpace3.x, LightObjectSpace3.y, LightObjectSpace3.z, 0.0f ) ); m_pEffect->Begin(&cPasses, 0); for (iPass = 0; iPass < cPasses; iPass++) { m_pEffect->BeginPass(iPass); m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, NUM_RECONSTRUCT_SAMPLES*NUM_RECONSTRUCT_SAMPLES*2, m_pVBOriginalFunction, 28 ); m_pEffect->EndPass(); } m_pEffect->End(); RenderText(); m_pd3dDevice->EndScene(); } return S_OK; } //----------------------------------------------------------------------------- // Name: RenderText() // Desc: Draw the help & statistics for running sample //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::RenderText() { HRESULT hr; RECT rc; if( NULL == m_pFont ) return S_OK; // Output statistics int iLineY = 0; SetRect( &rc, 2, iLineY, 0, 0 ); iLineY += 15; hr = m_pFont->DrawText( NULL, m_strFrameStats, -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f )); if( FAILED(hr) ) return DXTRACE_ERR( TEXT("DrawText"), hr ); SetRect( &rc, 2, iLineY, 0, 0 ); iLineY += 15; hr = m_pFont->DrawText( NULL, m_strDeviceStats, -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) ); if( FAILED(hr) ) return DXTRACE_ERR( TEXT("DrawText"), hr ); // Draw help if( m_bShowHelp ) { // Object Description SetRect( &rc, 2, m_d3dsdBackBuffer.Height / 4, 0, 0 ); m_pFont->DrawText( NULL, _T("D3D Matrix Rotated SH Function:"), -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) ); SetRect( &rc, int(m_d3dsdBackBuffer.Width / 2.5), m_d3dsdBackBuffer.Height / 4, 0, 0 ); m_pFont->DrawText( NULL, _T("Original Light Function:"), -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) ); SetRect( &rc, m_d3dsdBackBuffer.Width - 200, m_d3dsdBackBuffer.Height / 4, 0, 0 ); m_pFont->DrawText( NULL, _T("SH Matrix Rotated SH Function:"), -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) ); iLineY = m_d3dsdBackBuffer.Height-15*6; SetRect( &rc, 2, iLineY, 0, 0 ); iLineY += 15; hr = m_pFont->DrawText( NULL, _T("Controls:"), -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) ); if( FAILED(hr) ) return DXTRACE_ERR( TEXT("DrawText"), hr ); SetRect( &rc, 20, iLineY, 0, 0 ); hr = m_pFont->DrawText( NULL, _T("Rotate model: Left mouse button\n") _T("Rotate light: Right mouse button\n") _T("Rotate camera: Middle mouse button\n") _T("Zoom camera: Mouse wheel scroll\n") _T("Hide help: F1\n"), -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) ); if( FAILED(hr) ) return DXTRACE_ERR( TEXT("DrawText"), hr ); SetRect( &rc, 250, iLineY, 0, 0 ); hr = m_pFont->DrawText( NULL, _T("Change Device: F2\n") _T("View readme: F9\n") _T("Change function evaluation: c\n") _T("Toggle wireframe: w\n") _T("Quit: ESC"), -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) ); if( FAILED(hr) ) return DXTRACE_ERR( TEXT("DrawText"), hr ); } else { SetRect( &rc, 2, iLineY, 0, 0 ); iLineY += 15; hr = m_pFont->DrawText( NULL, _T("Press F1 to help"), -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) ); if( FAILED(hr) ) return DXTRACE_ERR( TEXT("DrawText"), hr ); } return S_OK; } //----------------------------------------------------------------------------- // Name: InvalidateDeviceObjects() // Desc: Invalidates device objects. Paired with RestoreDeviceObjects() //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::InvalidateDeviceObjects() { if( m_pFont ) m_pFont->OnLostDevice(); if( m_pEffect ) m_pEffect->OnLostDevice(); SAFE_RELEASE(m_pMeshTexture); 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() { SAFE_RELEASE(m_pEffect); SAFE_RELEASE(m_pFont); SAFE_RELEASE(m_pMesh); delete m_pFunction; delete m_pTestLight; delete[] m_pVertexBufferStaticSH; delete[] m_pVertexBufferDynamicSH; delete[] m_pVBOriginalFunction; 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() { return S_OK; } //----------------------------------------------------------------------------- // Name: ConfirmDevice() // Desc: Called during device initialization, this code checks the device // for some minimum set of capabilities //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior, D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat ) { // Debugging vertex shaders requires either REF or software vertex processing // and debugging pixel shaders requires REF. #ifdef DEBUG_VS if( pCaps->DeviceType != D3DDEVTYPE_REF && (dwBehavior & D3DCREATE_SOFTWARE_VERTEXPROCESSING) == 0 ) return E_FAIL; #endif if( dwBehavior & D3DCREATE_PUREDEVICE ) return E_FAIL; // If device doesn't support 1.1 vertex shaders in HW, switch to SWVP. if( pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) ) { if( (dwBehavior & D3DCREATE_SOFTWARE_VERTEXPROCESSING ) == 0 ) { return E_FAIL; } } return S_OK; } POINT LastMPos; D3DXVECTOR2 delta( 0.0f, 0.0f ); //----------------------------------------------------------------------------- // 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 uMsg, WPARAM wParam, LPARAM lParam ) { m_Camera.HandleMessages( hWnd, uMsg, wParam, lParam ); POINT CurMPos; GetCursorPos( &CurMPos ); if ( m_Camera.IsMouseRButtonDown() ) { delta.x += float( CurMPos.x - LastMPos.x ) * 0.01f; delta.y -= float( CurMPos.y - LastMPos.y ) * 0.02f; LightDir.x = sinf( delta.y ) * cosf( delta.x ); LightDir.y = sinf( delta.y ) * sinf( delta.x ); LightDir.z = cosf( delta.y ); } LastMPos = CurMPos; switch( uMsg ) { case WM_COMMAND: { switch( LOWORD(wParam) ) { case IDM_TOGGLEHELP: m_bShowHelp = !m_bShowHelp; break; } break; } case WM_KEYUP: { switch(wParam) { case 0x57: { m_WireFrame = !m_WireFrame; break; } case 0x43: { m_ReconstructToSphere = !m_ReconstructToSphere; delete m_pFunction; m_pFunction = new ReconstructSH(m_InitialCoeffs); m_pFunction->Reconstruct( m_pVertexBufferStaticSH, NUM_RECONSTRUCT_SAMPLES, m_ReconstructToSphere ); m_pTestLight->Reconstruct( m_pVBOriginalFunction, NUM_RECONSTRUCT_SAMPLES, m_ReconstructToSphere ); break; } } break; } } return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam ); }