//-------------------------------------------------------------------------------------- // This callback function will be called immediately after the Direct3D device has been // reset, which will happen after a lost device scenario. This is the best location to // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever // the device is lost. Resources created here should be released in the OnLostDevice // callback. //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { HRESULT hr; V_RETURN( g_DialogResourceManager.OnD3D9ResetDevice() ); V_RETURN( g_SettingsDlg.OnD3D9ResetDevice() ); if( g_pFont ) V_RETURN( g_pFont->OnResetDevice() ); if( g_pEffect ) V_RETURN( g_pEffect->OnResetDevice() ); // Store the correct technique handles for each material for( UINT i = 0; i < g_MeshLoader.GetNumMaterials(); i++ ) { Material* pMaterial = g_MeshLoader.GetMaterial( i ); const char* strTechnique = NULL; if( pMaterial->pTexture && pMaterial->bSpecular ) strTechnique = "TexturedSpecular"; else if( pMaterial->pTexture && !pMaterial->bSpecular ) strTechnique = "TexturedNoSpecular"; else if( !pMaterial->pTexture && pMaterial->bSpecular ) strTechnique = "Specular"; else if( !pMaterial->pTexture && !pMaterial->bSpecular ) strTechnique = "NoSpecular"; pMaterial->hTechnique = g_pEffect->GetTechniqueByName( strTechnique ); } // Create a sprite to help batch calls when drawing many lines of text V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) ); // Setup the camera's projection parameters float fAspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height; g_Camera.SetProjParams( D3DX_PI / 4, fAspectRatio, 0.1f, 1000.0f ); g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height ); g_HUD.SetLocation( pBackBufferSurfaceDesc->Width - 170, 0 ); g_HUD.SetSize( 170, 170 ); g_HUD.Refresh(); g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height - 350 ); g_SampleUI.SetSize( 170, 300 ); g_SampleUI.Refresh(); return S_OK; }
//-------------------------------------------------------------------------------------- void RenderSubset( UINT iSubset ) { HRESULT hr; UINT iPass, cPasses; // Retrieve the ID3DXMesh pointer and current material from the MeshLoader helper ID3DXMesh* pMesh = g_MeshLoader.GetMesh(); Material* pMaterial = g_MeshLoader.GetMaterial( iSubset ); // Set the lighting variables and texture for the current material V( g_pEffect->SetValue( g_hAmbient, pMaterial->vAmbient, sizeof( D3DXVECTOR3 ) ) ); V( g_pEffect->SetValue( g_hDiffuse, pMaterial->vDiffuse, sizeof( D3DXVECTOR3 ) ) ); V( g_pEffect->SetValue( g_hSpecular, pMaterial->vSpecular, sizeof( D3DXVECTOR3 ) ) ); V( g_pEffect->SetTexture( g_hTexture, pMaterial->pTexture ) ); V( g_pEffect->SetFloat( g_hOpacity, pMaterial->fAlpha ) ); V( g_pEffect->SetInt( g_hSpecularPower, pMaterial->nShininess ) ); V( g_pEffect->SetTechnique( pMaterial->hTechnique ) ); V( g_pEffect->Begin( &cPasses, 0 ) ); for( iPass = 0; iPass < cPasses; iPass++ ) { V( g_pEffect->BeginPass( iPass ) ); // The effect interface queues up the changes and performs them // with the CommitChanges call. You do not need to call CommitChanges if // you are not setting any parameters between the BeginPass and EndPass. // V( g_pEffect->CommitChanges() ); // Render the mesh with the applied technique V( pMesh->DrawSubset( iSubset ) ); V( g_pEffect->EndPass() ); } V( g_pEffect->End() ); }
//-------------------------------------------------------------------------------------- // Saves the mesh to X-file //-------------------------------------------------------------------------------------- void SaveMeshToXFile() { HRESULT hr; // Fill out D3DXMATERIAL structures UINT numMaterials = g_MeshLoader.GetNumMaterials(); D3DXMATERIAL* pMaterials = new D3DXMATERIAL[numMaterials]; char* pStrTexture = new char[MAX_PATH * numMaterials]; if( ( pMaterials != NULL ) && ( pStrTexture != NULL ) ) { for( UINT i = 0; i < g_MeshLoader.GetNumMaterials(); i++ ) { Material* pMat = g_MeshLoader.GetMaterial( i ); if( pMat != NULL ) { pMaterials[i].MatD3D.Ambient.r = pMat->vAmbient.x; pMaterials[i].MatD3D.Ambient.g = pMat->vAmbient.y; pMaterials[i].MatD3D.Ambient.b = pMat->vAmbient.z; pMaterials[i].MatD3D.Ambient.a = pMat->fAlpha; pMaterials[i].MatD3D.Diffuse.r = pMat->vDiffuse.x; pMaterials[i].MatD3D.Diffuse.g = pMat->vDiffuse.y; pMaterials[i].MatD3D.Diffuse.b = pMat->vDiffuse.z; pMaterials[i].MatD3D.Diffuse.a = pMat->fAlpha; pMaterials[i].MatD3D.Specular.r = pMat->vSpecular.x; pMaterials[i].MatD3D.Specular.g = pMat->vSpecular.y; pMaterials[i].MatD3D.Specular.b = pMat->vSpecular.z; pMaterials[i].MatD3D.Specular.a = pMat->fAlpha; pMaterials[i].MatD3D.Emissive.r = 0; pMaterials[i].MatD3D.Emissive.g = 0; pMaterials[i].MatD3D.Emissive.b = 0; pMaterials[i].MatD3D.Emissive.a = 0; pMaterials[i].MatD3D.Power = ( float )pMat->nShininess; WideCharToMultiByte( CP_ACP, 0, pMat->strTexture, -1, ( pStrTexture + i * MAX_PATH ), MAX_PATH, NULL, NULL ); pMaterials[i].pTextureFilename = ( pStrTexture + i * MAX_PATH ); } } // Write to file in same directory where the .obj file was found WCHAR strBuf[ MAX_PATH ]; swprintf_s( strBuf, MAX_PATH - 1, L"%s\\%s", g_MeshLoader.GetMediaDirectory(), L"MeshFromOBJ.x" ); hr = D3DXSaveMeshToX( strBuf, g_MeshLoader.GetMesh(), NULL, pMaterials, NULL, numMaterials, D3DXF_FILEFORMAT_TEXT ); if( SUCCEEDED( hr ) ) { swprintf_s( g_strFileSaveMessage, MAX_PATH - 1, L"Created %s", strBuf ); } else { DXTRACE_ERR( L"SaveMeshToXFile()::D3DXSaveMeshToX", hr ); swprintf_s( g_strFileSaveMessage, MAX_PATH - 1, L"Error creating %s, check debug output", strBuf ); } } SAFE_DELETE_ARRAY( pMaterials ); SAFE_DELETE_ARRAY( pStrTexture ); }
//-------------------------------------------------------------------------------------- // This callback function will be called immediately after the Direct3D device has been // created, which will happen during application initialization and windowed/full screen // toggles. This is the best location to create D3DPOOL_MANAGED resources since these // resources need to be reloaded whenever the device is destroyed. Resources created // here should be released in the OnDestroyDevice callback. //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { HRESULT hr; WCHAR str[MAX_PATH]; V_RETURN( g_DialogResourceManager.OnD3D9CreateDevice( pd3dDevice ) ); V_RETURN( g_SettingsDlg.OnD3D9CreateDevice( pd3dDevice ) ); // Initialize the font V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial", &g_pFont ) ); // Create the mesh and load it with data already gathered from a file V_RETURN( g_MeshLoader.Create( pd3dDevice, L"media\\cup.obj" ) ); // Add the identified material subsets to the UI CDXUTComboBox* pComboBox = g_SampleUI.GetComboBox( IDC_SUBSET ); pComboBox->RemoveAllItems(); pComboBox->AddItem( L"All", ( void* )( INT_PTR )-1 ); for( UINT i = 0; i < g_MeshLoader.GetNumMaterials(); i++ ) { Material* pMaterial = g_MeshLoader.GetMaterial( i ); pComboBox->AddItem( pMaterial->strName, ( void* )( INT_PTR )i ); } // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the // shader debugger. Debugging vertex shaders requires either REF or software vertex // processing, and debugging pixel shaders requires REF. The // D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the // shader debugger. It enables source level debugging, prevents instruction // reordering, prevents dead code elimination, and forces the compiler to compile // against the next higher available software target, which ensures that the // unoptimized shaders do not exceed the shader model limitations. Setting these // flags will cause slower rendering since the shaders will be unoptimized and // forced into software. See the DirectX documentation for more information about // using the shader debugger. DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE; #if defined( DEBUG ) || defined( _DEBUG ) // Set the D3DXSHADER_DEBUG flag to embed debug information in the shaders. // Setting this flag improves the shader debugging experience, but still allows // the shaders to be optimized and to run exactly the way they will run in // the release configuration of this program. dwShaderFlags |= D3DXSHADER_DEBUG; #endif #ifdef DEBUG_VS dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT; #endif #ifdef DEBUG_PS dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT; #endif // Read the D3DX effect file V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"MeshFromOBJ.fx" ) ); // If this fails, there should be debug output as to // they the .fx file failed to compile V_RETURN( D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags, NULL, &g_pEffect, NULL ) ); // Cache the effect handles g_hAmbient = g_pEffect->GetParameterBySemantic( 0, "Ambient" ); g_hDiffuse = g_pEffect->GetParameterBySemantic( 0, "Diffuse" ); g_hSpecular = g_pEffect->GetParameterBySemantic( 0, "Specular" ); g_hOpacity = g_pEffect->GetParameterBySemantic( 0, "Opacity" ); g_hSpecularPower = g_pEffect->GetParameterBySemantic( 0, "SpecularPower" ); g_hLightColor = g_pEffect->GetParameterBySemantic( 0, "LightColor" ); g_hLightPosition = g_pEffect->GetParameterBySemantic( 0, "LightPosition" ); g_hCameraPosition = g_pEffect->GetParameterBySemantic( 0, "CameraPosition" ); g_hTexture = g_pEffect->GetParameterBySemantic( 0, "Texture" ); g_hTime = g_pEffect->GetParameterBySemantic( 0, "Time" ); g_hWorld = g_pEffect->GetParameterBySemantic( 0, "World" ); g_hWorldViewProjection = g_pEffect->GetParameterBySemantic( 0, "WorldViewProjection" ); // Setup the camera's view parameters D3DXVECTOR3 vecEye( 2.0f, 1.0f, 0.0f ); D3DXVECTOR3 vecAt ( 0.0f, 0.0f, -0.0f ); g_Camera.SetViewParams( &vecEye, &vecAt ); return S_OK; }