/** \file \brief Performs DirectX initialization via DXUT callback functions. \brief Adds some additional helper functions to support screenshot capturing. \author Istvan Lazanyi, TU Budapest \date 2006-04-26 */ #include "dxstdafx.h" #include "resource.h" #include #include #include //#define DEBUG_VS // Uncomment this line to debug vertex shaders //#define DEBUG_PS // Uncomment this line to debug pixel shaders /// File containing the shader code. #define FX_FILENAME L"EnvMap.fx" #include "Cube.h" #include "Mesh.h" #include "Parameters.h" #include "EnvMap.h" const int WIDTH = 800; ///< screen width const int HEIGHT = 800; ///< screen height const int CHARBUFFER_SIZE = 200; ///< length of the buffer (one line to be saved to file) /// This struct was created to easily navigate to Main.cpp. struct DXUT_Manager { }; //-------------------------------------------------------------------------------------- // Global variables //-------------------------------------------------------------------------------------- IDirect3DDevice9* g_pd3dDevice; ///< THE D3D DEVICE ID3DXEffect* g_pEffect; ///< THE EFFECT FILE EnvMap* envmapRenderer; ///< PROBLEM-SPECIFIC CLASS Parameters pp; ///< HELPER CLASS TO MANAGE VARIOUS PARAMETERS CDXUTDialogResourceManager g_DialogResourceManager; ///< Manager for shared resources of dialogs CD3DSettingsDlg g_SettingsDlg; ///< Device settings dialog CDXUTDialog g_HUD; ///< Dialog for sample specific controls ID3DXFont* g_pFont; ///< Font for drawing text ID3DXSprite* g_pTextSprite; ///< Sprite for batching draw text calls IDirect3DSurface9* g_pSaveSurface; ///< surface for screenshot capturing bool bSavingScreenshot = false; ///< boolean for screenshot capturing int counter = 0; ///< counter for screenshots (see GenerateNewFileName()) HRESULT hr; CModelViewerCamera camera; ///< the camera //-------------------------------------------------------------------------------------- // Forward declarations (CALLBACK) //-------------------------------------------------------------------------------------- bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext ); bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext ); HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* g_pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ); HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* g_pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ); void CALLBACK OnFrameMove( IDirect3DDevice9* g_pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ); void CALLBACK OnFrameRender( IDirect3DDevice9* g_pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ); LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext ); void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext ); void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ); void CALLBACK OnLostDevice( void* pUserContext ); void CALLBACK OnDestroyDevice( void* pUserContext ); void InitParams(); void RenderText(); //-------------------------------------------------------------------------------------- // Forward declarations //-------------------------------------------------------------------------------------- void SaveCameraPosition( char* fileName ); void LoadCameraPosition( char* fileName ); int GenerateNewFileName( int& counter ); //-------------------------------------------------------------------------------------- /// \brief 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, HINSTANCE, LPSTR, int ) { // Enable run-time memory check for debug builds. #if defined(DEBUG) | defined(_DEBUG) _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif DXUTSetCallbackDeviceCreated( OnCreateDevice ); DXUTSetCallbackDeviceReset( OnResetDevice ); DXUTSetCallbackDeviceLost( OnLostDevice ); DXUTSetCallbackDeviceDestroyed( OnDestroyDevice ); DXUTSetCallbackMsgProc( MsgProc ); DXUTSetCallbackKeyboard( KeyboardProc ); DXUTSetCallbackFrameRender( OnFrameRender ); DXUTSetCallbackFrameMove( OnFrameMove ); envmapRenderer = new EnvMap(); InitParams(); // Show the cursor and clip it when in full screen DXUTSetCursorSettings( true, true ); DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes DXUTCreateWindow( L"Environment Mapping Demo" ); DXUTCreateDevice( D3DADAPTER_DEFAULT, true, WIDTH, HEIGHT, IsDeviceAcceptable, ModifyDeviceSettings ); camera.SetButtonMasks( 0, MOUSE_WHEEL, MOUSE_LEFT_BUTTON ); DXUTMainLoop(); return DXUTGetExitCode(); } /// \brief DXUT callback (called by the framework in case of GUI events). /// Forwards GUI event to the parameter-manager class #Parameters (see #pp). /// \param nControlID id of the adjusted GUI control void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ) { pp.UpdateFromHUD( nControlID ); } /// (Load, Save, Reset are default buttons.) void OnLoad() { LoadCameraPosition( ".matrix" ); } /// (Load, Save, Reset are default buttons.) void OnSave() { SaveCameraPosition( ".matrix" ); bSavingScreenshot = true; } /// (Load, Save, Reset are default buttons.) void OnReset() {} /// Callback of type #CONVERTER. float Exponent(float f) { return 0.012f * pow(50.0f, 2*f); } /// Actions to be taken when the cubemaps get invalid. Callback of type #ONCHANGE_CALLBACK. void OnChangeCubeMap() { envmapRenderer->InvalidateCubeMap(); } /// Actions to be taken when the central mesh object is changed. Callback of type #ONCHANGE_CALLBACK. void OnChangeMesh() { envmapRenderer->ChooseMesh( pp.GetInt( iWhichMesh )); } /// Actions to be taken when the size of the central mesh is to change. Callback of type #ONCHANGE_CALLBACK. void OnChangeMeshSize() { envmapRenderer->SetMeshSize( pp.Get( fMeshScale )*2); } /// Actions to be taken when the shininess is to change. Callback of type #ONCHANGE_CALLBACK. void OnChangeShininess() { envmapRenderer->InvalidateShininess(); } /// Actions to be taken when the resolution is to change. Callback of type #ONCHANGE_CALLBACK. void OnChangeResolution() { envmapRenderer->InvalidateResolution(); } //-------------------------------------------------------------------------------------- /// \brief Defines application-specific parameters and creates GUI controls (sliders, checkboxes) for them. /// \brief Finally, loads initial values for the parameters from file called .params0 (Reset). /// Use Parameters::Add to create GUI controls. //-------------------------------------------------------------------------------------- void InitParams() { g_SettingsDlg.Init( &g_DialogResourceManager ); g_HUD.Init( &g_DialogResourceManager ); g_HUD.SetCallback( OnGUIEvent ); // Event handling //pp.Setup( &g_HUD ); pp.Setup( &g_HUD, OnReset, OnSave, OnLoad ); // you can add callbacks to these actions // CHECKBOXES pp.Add( bShowHelp, "Help [F1]", VK_F1 ); //pp.Add( bAutoGenCubeMap, "[A]utoGenCubeMap", 'A' ); pp.Add( bShowFireballs, "[F]ireballs", 'F', OnChangeCubeMap ); pp.Add( bMultipleObjects, "Multiple [O]bjects", 'O' ); pp.Add( bConfineToRoom, "Between [W]alls only", 'W' ); // SLIDERS pp.Add( iWhichMethod, "WhichMethod [TAB,Q]", 3, VK_TAB, 'Q', noconvert, OnChangeCubeMap ); pp.Add( iWhichMesh, "WhichMesh [Home,End]", 9, VK_HOME, VK_END, noconvert, OnChangeMesh ); pp.Add( fMeshScale, "Mesh size [Ins,Del]", 100, VK_DELETE, VK_INSERT, noconvert, OnChangeMeshSize ); pp.Add( iResolution, "Resolution [M]", 3, 'N', 'M', noconvert, OnChangeResolution ); pp.Add( iShowCubeMap, "ShowCubeMap [C]", 3, 'C' ); pp.Add( fIntensity, "Intensity [+,-]", 100, VK_SUBTRACT, VK_ADD, Exponent ); pp.Add( iShininess, "shininess [/,*]", 30, VK_DIVIDE, VK_MULTIPLY, noconvert, OnChangeShininess ); pp.UpdateFromHUD( IDC_RESET_BUTTON ); // do a reset } //-------------------------------------------------------------------------------------- /// \brief DXUT callback (Rejects any devices that aren't acceptable by returning false) /// /// DXUT callback. Rejects any devices that aren't acceptable by returning false. //-------------------------------------------------------------------------------------- bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext ) { // Skip backbuffer formats that don't support alpha blending IDirect3D9* pD3D = DXUTGetD3DObject(); if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, BackBufferFormat ) ) ) return false; return true; } //-------------------------------------------------------------------------------------- /// \brief DXUT callback (Before a device is created, modifies the device settings as needed) //-------------------------------------------------------------------------------------- bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext ) { // VSync off pDeviceSettings->pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW // then switch to SWVP. if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 || pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) ) pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING; else pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; // This application is designed to work on a pure device by not using // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP. if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 ) pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE; // Debugging vertex shaders requires either REF or software vertex processing // and debugging pixel shaders requires REF. #ifdef DEBUG_VS if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF ) { pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING; pDeviceSettings->BehaviorFlags &= ~D3DCREATE_PUREDEVICE; pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; } #endif #ifdef DEBUG_PS pDeviceSettings->DeviceType = D3DDEVTYPE_REF; #endif // For the first device created if its a REF device, optionally display a warning dialog box static bool s_bFirstTime = true; if( s_bFirstTime ) { s_bFirstTime = false; if( pDeviceSettings->DeviceType == D3DDEVTYPE_REF ) DXUTDisplaySwitchingToREFWarning(); } return true; } //-------------------------------------------------------------------------------------- /// @brief DXUT callback (You should create any D3DPOOL_MANAGED resources here) /// /// Compiles the effect file (EnvMap.fx) and displays error message if compilation fails. /// Finally, forwards call to EnvMap::OnCreateDevice. //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { ::g_pd3dDevice = pd3dDevice; HRESULT hr; V_RETURN( g_DialogResourceManager.OnCreateDevice( g_pd3dDevice ) ); V_RETURN( g_SettingsDlg.OnCreateDevice( g_pd3dDevice ) ); // Initialize the font V_RETURN( D3DXCreateFont( g_pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial", &g_pFont ) ); // ----------- fx compilation options ----------- DWORD dwShaderFlags = 0; #ifdef DEBUG_VS dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT; #endif #ifdef DEBUG_PS dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT; #endif dwShaderFlags |= D3DXSHADER_SKIPOPTIMIZATION; // ----------- compiling fx file ----------- ID3DXBuffer* errBuff; // buffer for error message if (FAILED(hr = D3DXCreateEffectFromFile( g_pd3dDevice, FX_FILENAME, NULL, NULL, dwShaderFlags, NULL, &g_pEffect, &errBuff ))) // if compilation error occurs { int BufSize = errBuff->GetBufferSize(); wchar_t* wbuf = new wchar_t[BufSize]; mbstowcs( wbuf, (const char*)errBuff->GetBufferPointer(), BufSize ); MessageBox(NULL, wbuf, L".fx Compilation Error", MB_ICONERROR); // error message delete wbuf; exit(-1); } envmapRenderer->OnCreateDevice( g_pd3dDevice, g_pEffect ); float initialEyeDist = 6.82; D3DXVECTOR3 vecEye(0, 0, -initialEyeDist); D3DXVECTOR3 vecAt (0.0f, 0.0f, -0.0f); camera.SetViewParams( &vecEye, &vecAt ); return S_OK; } //-------------------------------------------------------------------------------------- /// \brief DXUT callback (You should release resources created in the OnCreateDevice callback here) /// /// Forwards call to EnvMap::OnDestroyDevice. //-------------------------------------------------------------------------------------- void CALLBACK OnDestroyDevice( void* pUserContext ) { g_DialogResourceManager.OnDestroyDevice(); g_SettingsDlg.OnDestroyDevice(); SAFE_RELEASE(g_pEffect); SAFE_RELEASE(g_pFont); envmapRenderer->OnDestroyDevice(); } //-------------------------------------------------------------------------------------- /// \brief DXUT callback (You should create any D3DPOOL_DEFAULT resources here) /// /// Resets camera and HUD elements. Initializes #g_pSaveSurface according to the /// current screen resolution. /// Then it forwards call to EnvMap::OnResetDevice. //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* g_pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { HRESULT hr; V_RETURN( g_DialogResourceManager.OnResetDevice() ); V_RETURN( g_SettingsDlg.OnResetDevice() ); if( g_pFont ) V_RETURN( g_pFont->OnResetDevice() ); if( g_pEffect ) V_RETURN( g_pEffect->OnResetDevice() ); // Create a sprite to help batch calls when drawing many lines of text V_RETURN( D3DXCreateSprite( g_pd3dDevice, &g_pTextSprite ) ); // Create a surface to save screenshots IDirect3DTexture9* pSaveTexture = NULL; V( D3DXCreateTexture( g_pd3dDevice, pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSaveTexture) ); pSaveTexture->GetSurfaceLevel( 0, &g_pSaveSurface ); SAFE_RELEASE( pSaveTexture ); // Setup the camera's projection parameters float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height; camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1, 100 ); camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height ); envmapRenderer->OnResetDevice(); // Position the on-screen dialog g_HUD.SetLocation( 0, 0 ); g_HUD.SetSize( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height ); return S_OK; } //-------------------------------------------------------------------------------------- /// DXUT callback (You should release resources created in the OnResetDevice callback here) //-------------------------------------------------------------------------------------- void CALLBACK OnLostDevice( void* pUserContext ) { g_DialogResourceManager.OnLostDevice(); g_SettingsDlg.OnLostDevice(); if( g_pFont ) g_pFont->OnLostDevice(); if( g_pEffect ) g_pEffect->OnLostDevice(); SAFE_RELEASE( g_pTextSprite ); SAFE_RELEASE( g_pSaveSurface ); envmapRenderer->OnLostDevice(); } //-------------------------------------------------------------------------------------- /// \brief DXUT callback (Message processing). /// /// Forwards messages to the DirectX settings window, the GUI controls or the camera, respecively. //-------------------------------------------------------------------------------------- LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext ) { // Always allow dialog resource manager calls to handle global messages // so GUI state is updated correctly *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam ); if( *pbNoFurtherProcessing ) return 0; if( g_SettingsDlg.IsActive() ) { g_SettingsDlg.MsgProc( hWnd, uMsg, wParam, lParam ); return 0; } // Give the dialogs a chance to handle the message first *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam ); if( *pbNoFurtherProcessing ) return 0; // Pass all remaining windows messages to camera so it can respond to user input camera.HandleMessages( hWnd, uMsg, wParam, lParam ); return 0; } //-------------------------------------------------------------------------------------- /// \brief DXUT callback (Handle updates to the scene) //-------------------------------------------------------------------------------------- void CALLBACK OnFrameMove( IDirect3DDevice9* g_pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ) { camera.FrameMove( fElapsedTime ); } //-------------------------------------------------------------------------------------- /// \brief DXUT callback (Render the scene). Also responsible for screenshot taking. /// /// If a screenshot is being taken (#bSavingScreenshot), sets #g_pSaveSurface as the render target /// and saves it to a non-existent file (GenerateNewFileName()). Also saves current camera parameters (SaveCameraPosition()). /// /// To perform actual rendering, it forwards call to EnvMap::OnFrameRender with current camera matrices. //-------------------------------------------------------------------------------------- void CALLBACK OnFrameRender( IDirect3DDevice9* g_pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ) { // If the settings dialog is being shown, then // render it instead of rendering the app's scene if( g_SettingsDlg.IsActive() ) { g_SettingsDlg.OnRender( fElapsedTime ); return; } // ------------------------------------------------------------ // if screenshot is being taken - preparation // ------------------------------------------------------------ IDirect3DSurface9* oldRenderTarget = NULL; if (bSavingScreenshot) { V( g_pd3dDevice->GetRenderTarget(0, &oldRenderTarget) ); V( g_pd3dDevice->SetRenderTarget(0, g_pSaveSurface) ); } // ------------------------------------------------------------ // rendering // ------------------------------------------------------------ V( g_pd3dDevice->BeginScene() ); D3DXMATRIXA16 mView = *camera.GetViewMatrix(); D3DXMATRIXA16 mProj = *camera.GetProjMatrix(); envmapRenderer->SetCamera( &camera ); envmapRenderer->OnFrameRender( g_pd3dDevice, mView, mProj ); if (!bSavingScreenshot) { RenderText(); V( g_HUD.OnRender( fElapsedTime ) ); } V( g_pd3dDevice->EndScene() ); // ------------------------------------------------------------ // if screenshot is being taken - saving // ------------------------------------------------------------ if (bSavingScreenshot) { // create file name char buf[CHARBUFFER_SIZE]; wchar_t wbuf[CHARBUFFER_SIZE]; GenerateNewFileName( counter ); sprintf(buf, "shots\\%03i.png", counter); mbstowcs( wbuf, buf, CHARBUFFER_SIZE ); // save surface D3DXSaveSurfaceToFileW(wbuf, D3DXIFF_PNG, g_pSaveSurface, NULL, NULL); // save parameters sprintf(buf, "shots\\%03i", counter); pp.SaveToFile( buf ); // save camera position sprintf(buf, "shots\\%03i.matrix", counter); SaveCameraPosition( buf ); g_pd3dDevice->SetRenderTarget(0, oldRenderTarget); bSavingScreenshot = false; } } //-------------------------------------------------------------------------------------- /// \brief Generates a non-existing filename to store the screenshot in the shots directory. /// /// Generated file names are shots/000.png, shots/001.png, ... //-------------------------------------------------------------------------------------- int GenerateNewFileName( int& counter ) { char buf[CHARBUFFER_SIZE]; FILE* f; do { sprintf(buf, "shots\\%03i.png", counter); if ( (f = fopen(buf, "rt")) != NULL ) { fclose( f ); counter++; } } while (f != NULL); return counter; } //-------------------------------------------------------------------------------------- /// \brief DXUT callback (Keystroke messages) //-------------------------------------------------------------------------------------- void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext ) { envmapRenderer->KeyboardProc( nChar, bKeyDown, bAltDown ); } //-------------------------------------------------------------------------------------- /// \brief Writes current camera settings to file. /// /// Writes current #camera settings (world matrix and camera position) to file. /// Useful when capturing multiple screenshots from the same view. /// \param fileName the name of the file to be created //-------------------------------------------------------------------------------------- void SaveCameraPosition( char* fileName ) { // save parameters to file: // world matrix (4x4) // camera position (3) // save world matrix D3DXMATRIXA16 W = *camera.GetViewMatrix(); FILE* f; if ((f = fopen(fileName, "wt")) == NULL) { wchar_t wbuf[CHARBUFFER_SIZE]; mbstowcs( wbuf, fileName, CHARBUFFER_SIZE ); MessageBox(NULL, wbuf, L"File creation failed!", MB_ICONEXCLAMATION); return; } fprintf(f, "\n"); fprintf(f, "World matrix:\n"); fprintf(f, "%10.4g %10.4g %10.4g %10.4g\n", W._11, W._12, W._13, W._14); fprintf(f, "%10.4g %10.4g %10.4g %10.4g\n", W._21, W._22, W._23, W._24); fprintf(f, "%10.4g %10.4g %10.4g %10.4g\n", W._31, W._32, W._33, W._34); fprintf(f, "%10.4g %10.4g %10.4g %10.4g\n", W._41, W._42, W._43, W._44); // save camera position fprintf(f, "\n"); fprintf(f, "Camera position:\n"); const D3DXVECTOR3* eye = camera.GetEyePt(); fprintf(f, "%10g %10g %10g", eye->x, eye->y, eye->z); fprintf(f, "\n"); // save mesh position fprintf(f, "\n"); fprintf(f, "Mesh position:\n"); D3DXVECTOR3 pos = envmapRenderer->GetMeshPosition(); fprintf(f, "%10g %10g %10g", pos.x, pos.y, pos.z); fprintf(f, "\n"); fclose(f); } //-------------------------------------------------------------------------------------- /// \brief Loads camera settings from file. /// /// Loads #camera settings (world matrix and camera position) from an existing file. /// Useful when capturing multiple screenshots from the same view. /// \param fileName the name of the file to load from. //-------------------------------------------------------------------------------------- void LoadCameraPosition( char* fileName ) { FILE* f; if ((f = fopen(fileName, "rt")) == NULL) { wchar_t wbuf[CHARBUFFER_SIZE]; mbstowcs( wbuf, fileName, CHARBUFFER_SIZE ); MessageBox(NULL, wbuf, L"File not found!", MB_ICONEXCLAMATION); return; } const int BufSize = 500; // size of char buffers char buf[BufSize]; D3DXMATRIXA16 W; fgets(buf, BufSize, f); // skip comment fgets(buf, BufSize, f); // skip comment fgets(buf, BufSize, f); sscanf(buf, "%f %f %f %f", &W._11, &W._12, &W._13, &W._14); fgets(buf, BufSize, f); sscanf(buf, "%f %f %f %f", &W._21, &W._22, &W._23, &W._24); fgets(buf, BufSize, f); sscanf(buf, "%f %f %f %f", &W._31, &W._32, &W._33, &W._34); fgets(buf, BufSize, f); sscanf(buf, "%f %f %f %f", &W._41, &W._42, &W._43, &W._44); // load camera position D3DXVECTOR3 vecAt(0.0f, 0.0f, 0.0f); D3DXVECTOR3 vecEye; fgets(buf, BufSize, f); // skip comment fgets(buf, BufSize, f); // skip comment fgets(buf, BufSize, f); sscanf(buf, "%f %f %f", &vecEye.x, &vecEye.y, &vecEye.z); // load mesh position D3DXVECTOR3 pos(0.0f, 0.0f, 0.0f); fgets(buf, BufSize, f); // skip comment fgets(buf, BufSize, f); // skip comment fgets(buf, BufSize, f); sscanf(buf, "%f %f %f", &pos.x, &pos.y, &pos.z); fclose(f); envmapRenderer->SetMeshPosition( pos ); camera.SetViewParams( &vecEye, &vecAt ); D3DXQUATERNION q; D3DXQuaternionRotationMatrix(&q, &W); camera.SetViewQuat(q); } //-------------------------------------------------------------------------------------- /// \brief Renders help and statistics text and displays algorithmic-specific parameters. /// /// - Statistics: FPS value, screen resolution /// /// - Help: displays avaliable keyboard shortcuts after the user presses F1. /// /// - Algorithmic-specific parameters: describes the currently selected method and /// displays its most important parameters. //-------------------------------------------------------------------------------------- void RenderText() { const D3DSURFACE_DESC* backBufferDesc = DXUTGetBackBufferSurfaceDesc(); CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 ); txtHelper.Begin(); txtHelper.SetInsertionPos( 5, 5 ); txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) ); txtHelper.DrawFormattedTextLine( L"%.2f fps @ %i x %i", DXUTGetFPS(), backBufferDesc->Width, backBufferDesc->Height ); //txtHelper.DrawTextLine( DXUTGetFrameStats() ); txtHelper.DrawTextLine( DXUTGetDeviceStats() ); txtHelper.DrawTextLine( L"" ); txtHelper.SetInsertionPos( 30, 200 ); txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) ); switch (pp.GetInt( iWhichMethod )) { case DIFFUSE_SPECULAR_CLASSIC: if (pp.GetInt( iShininess ) > 0) txtHelper.DrawFormattedTextLine( L"Method : CLASSIC (specular, s=%i)", pp.GetInt( iShininess )); else txtHelper.DrawFormattedTextLine( L"Method : CLASSIC (diffuse)"); break; case DIFFUSE_SPECULAR_LOCALIZED: if (pp.GetInt( iShininess ) > 0) txtHelper.DrawFormattedTextLine( L"Method : Our method (specular, s=%i)", pp.GetInt( iShininess )); else txtHelper.DrawFormattedTextLine( L"Method : Our method (diffuse)"); break; case DIFFUSE_SPECULAR_LOCALIZED_NEW: if (pp.GetInt( iShininess ) > 0) txtHelper.DrawFormattedTextLine( L"Method : Our method New (specular, s=%i)", pp.GetInt( iShininess )); else txtHelper.DrawFormattedTextLine( L"Method : Our method New (diffuse)"); break; case DIFFUSE_SPECULAR_LOCALIZED_5TEX: if (pp.GetInt( iShininess ) > 0) txtHelper.DrawFormattedTextLine( L"Method : Our method (specular, s=%i), 5 TEXEL ONLY", pp.GetInt( iShininess )); else txtHelper.DrawFormattedTextLine( L"Method : Our method (diffuse), 5 TEXEL ONLY"); break; } //txtHelper.DrawFormattedTextLine( L"IOR : %.2f Fresnel : %.2f", pp.Get( refractionIndex ), pp.Get( sFresnel )); txtHelper.DrawFormattedTextLine( L"Intensity multiplier : %.2f", pp.Get( fIntensity )); switch (pp.GetInt( iShowCubeMap )) { case 0: txtHelper.DrawFormattedTextLine( L"" ); break; case 1: txtHelper.DrawFormattedTextLine( L"SHOW HI-RES CUBEMAP on the walls" ); break; case 2: txtHelper.DrawFormattedTextLine( L"SHOW LO-RES CUBEMAP on the walls" ); break; case 3: txtHelper.DrawFormattedTextLine( L"SHOW PRECONVOLVED CUBEMAP on the walls" ); break; } int exp = pp.GetInt( iResolution ) + 1; // 1..4 int LR_CUBEMAP_SIZE = pow( 2, exp ); txtHelper.DrawFormattedTextLine( L"Resolution: %i x %i", LR_CUBEMAP_SIZE, LR_CUBEMAP_SIZE); txtHelper.DrawFormattedTextLine( L"" ); //D3DXVECTOR3 ref = envmapRenderer->GetReferencePos(); //txtHelper.DrawFormattedTextLine( L"Reference_pos: %.2g %.2g %.2g", ref.x, ref.y, ref.z); txtHelper.SetForegroundColor( D3DXCOLOR( 0.7f, 0.7f, 1.0f, 1.0f ) ); if ( !pp.Get( bShowHelp ) ) { txtHelper.DrawTextLine( L"Press F1 for help" ); } else // show help { txtHelper.SetInsertionPos( backBufferDesc->Width - 260, backBufferDesc->Height-24*22 ); txtHelper.DrawTextLine( L"Controls (F1 to hide):\n" L"___________________________________\n" L" APPLICATION CONTROLS\n" L"\n" L"Left click+drag: Rotate mesh\n" L"Mouse wheel: Zoom\n" L"Arrow keys: Move object\n" L"F1: Help\n" L"Quit: ESC\n" L"F8: Switch to Wireframe mode\n" L"\n" L"L: [L]oad params\n" L"S: [S]ave params & take SCREENSHOT\n" L"R: [R]eset params\n" L"___________________________________\n" L" MESH OBJECT CONTROLS\n" L"\n" L"O: show 3 mesh [O]bjects\n" L"F: show [F]ireballs\n" L"Ins, Del: scale mesh object\n" L"Home, End, or 0-9: choose mesh object\n" L"gray +,-: adjust intensity\n" L"gray /,*: adjust specular shininess\n" L"___________________________________\n" L" ALGORITHM-SPECIFIC CONTROLS\n" L"\n" L"TAB,Q: choose shading method\n" L"N,M: choose cube map resolution\n" // L"A: refresh cube maps for every frame\n" // L"SPACE: refresh cube maps MANUALLY\n" L"C: choose visualized [C]ube map\n" L"___________________________________\n" L" Quit: ESC"); } txtHelper.End(); }