www.pudn.com > fluid.rar > demo.cpp, change:2006-10-29,size:31470b


#include "stableHeader.h" 
#include "resource.h" 
#include "Scene.h" 
#include "DTKStringConverter.h" 
#include "DTKUtil.h" 
#include "FluidAnimator2D.h" 
#include "DTKVectorTrigger.h" 
#include "DTKParamSettingDialog.h" 
#include "Substance2D.h" 
#include "DTKColorValue.h" 
//#define DEBUG_VS   // Uncomment this line to debug vertex shaders  
//#define DEBUG_PS   // Uncomment this line to debug pixel shaders  
 
 
//------------------------------------------------------------------------------ 
//external variables 
//------------------------------------------------------------------------------ 
extern DTK::FluidAnimator2D g_animator; 
extern DTK::Substance2D     g_substance; 
extern float g_fTimeScale; 
extern DTK::uint  g_uCurDisplayMode; 
extern bool g_bShowQuiverVelocityField; 
extern float                   g_forceRadius; 
extern float                   g_forceStrength; 
extern float                   g_sourceRadius; 
extern DTK::ColorValue         g_sourceStrength; 
 
//-------------------------------------------------------------------------------------- 
// Global variables 
//-------------------------------------------------------------------------------------- 
ID3DXFont*              g_pFont = NULL;         // Font for drawing text 
ID3DXSprite*            g_pTextSprite = NULL;   // Sprite for batching draw text calls 
 
CModelViewerCamera      g_Camera;               // A model viewing camera 
bool                    g_bShowHelp = true;     // If true, it renders the UI control text 
CDXUTDialogResourceManager g_DialogResourceManager; // manager for shared resources of dialogs 
CD3DSettingsDlg         g_SettingsDlg;          // Device settings dialog 
CDXUTDialog             g_HUD;                  // dialog for standard controls 
CDXUTDialog             g_SampleUI;             // dialog for sample specific controls 
 
DTK::VectorTrigger      g_vecTrigger; 
DTK::ParamSettingDialog g_paramDialog; 
 
const DTK::uint NUM_DISPLAY_MODE =5; 
const WCHAR* DISPLAY_MODE[]= 
{ 
	{L"source"}, 
	{L"velocity"}, 
	{L"pressure"}, 
	{L"vorticity"}, 
	{L"vorticity confinement force"}, 
	 
}; 
const DTK::uint NUM_FLUID_TYPE = 1; 
const WCHAR* FLUID_TYPE[]= 
{ 
	{L"Smoke"} 
}; 
DTK::uint g_uFluidType = Scene::FT_SMOKE; 
 
bool gs_bDiffuse=true; 
bool gs_bAdvection=true; 
bool gs_bProject=true; 
bool gs_bVelocityBoundary=true; 
bool gs_bPressureBoundary=true; 
bool gs_bVorticityConfinement = true; 
 
//-------------------------------------------------------------------------------------- 
// UI control IDs 
//-------------------------------------------------------------------------------------- 
#define IDC_TOGGLEFULLSCREEN    1 
#define IDC_TOGGLEREF           2 
#define IDC_CHANGEDEVICE        3 
 
const int IDP_D              = 0; 
const int IDP_TIME_SCALE     = 1; 
const int IDP_FORCE_RADIUS   = 2; 
const int IDP_FORCE_STRENGTH = 3; 
const int IDP_VISCOUS        = 4; 
const int IDP_VORTICITY_CONFINEMENT_COEFFICIENT = 5; 
const int IDP_JACOBI_ITERATE_NUM = 6; 
const int IDP_DISSIPATION    = 7; 
const int IDP_UNIT           = 8;  
const int IDP_SUBSTANCE_DISSIPATION = 9; 
const int IDP_SOURCE_RADIUS  = 10; 
const int IDP_SOURCE_STRENGTH = 11; 
//-------------------------------------------------------------------------------------- 
// Forward declarations  
//-------------------------------------------------------------------------------------- 
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* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ); 
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ); 
void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ); 
void    CALLBACK OnFrameRender( IDirect3DDevice9* 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    InitApp(); 
void    RenderText(); 
 
 
void impulse(DTK::Vector2 pos,DTK::Vector2 vec); 
void toggleQuiverVelocityField(); 
void toggleDisplayMode(); 
void toggleDiffuse(); 
void toggleAdvection(); 
void toggleProject(); 
void toggleVelocityBoundary(); 
void togglePressureBoundary(); 
void toggleVorticityConfinement(); 
void toggleDefaultParam(); 
void updateParam(int iID,const float value[4]); 
 
//-------------------------------------------------------------------------------------- 
// 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 
 
    // Set the callback functions. These functions allow DXUT to notify 
    // the application about device changes, user input, and windows messages.  The  
    // callbacks are optional so you need only set callbacks for events you're interested  
    // in. However, if you don't handle the device reset/lost callbacks then the sample  
    // framework won't be able to reset your device since the application must first  
    // release all device resources before resetting.  Likewise, if you don't handle the  
    // device created/destroyed callbacks then DXUT won't be able to  
    // recreate your device resources. 
    DXUTSetCallbackDeviceCreated( OnCreateDevice ); 
    DXUTSetCallbackDeviceReset( OnResetDevice ); 
    DXUTSetCallbackDeviceLost( OnLostDevice ); 
    DXUTSetCallbackDeviceDestroyed( OnDestroyDevice ); 
    DXUTSetCallbackMsgProc( MsgProc ); 
    DXUTSetCallbackKeyboard( KeyboardProc ); 
    DXUTSetCallbackFrameRender( OnFrameRender ); 
    DXUTSetCallbackFrameMove( OnFrameMove ); 
 
    // Show the cursor and clip it when in full screen 
    DXUTSetCursorSettings( true, true ); 
 
	DTK::init(); 
    InitApp();	 
	Scene::init(); 
 
    // Initialize DXUT and create the desired Win32 window and Direct3D  
    // device for the application. Calling each of these functions is optional, but they 
    // allow you to set several options which control the behavior of the framework. 
    DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes 
	DXUTCreateWindow( L"GPU Fluid Simulation:by Kaijie Xu. 2006.10.28" ); 
    DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 500, 500, IsDeviceAcceptable, ModifyDeviceSettings ); 
 
    // Pass control to DXUT for handling the message pump and  
    // dispatching render calls. DXUT will call your FrameMove  
    // and FrameRender callback when there is idle time between handling window messages. 
    DXUTMainLoop(); 
 
    // Perform any application-level cleanup here. Direct3D device resources are released within the 
    // appropriate callback functions and therefore don't require any cleanup code here. 
 
	DTK::shutdown(); 
 
    return DXUTGetExitCode(); 
} 
 
 
//-------------------------------------------------------------------------------------- 
// Initialize the app  
//-------------------------------------------------------------------------------------- 
void InitApp() 
{ 
	g_vecTrigger.setImpulseCallback(impulse); 
	g_vecTrigger.setImpulseUnit(1.0f/64.0f); 
	g_vecTrigger.setWindowSize(640.0f,480.0f); 
 
 
    // Initialize dialogs 
    g_SettingsDlg.Init( &g_DialogResourceManager ); 
    g_HUD.Init( &g_DialogResourceManager ); 
    g_SampleUI.Init( &g_DialogResourceManager ); 
 
    g_HUD.SetCallback( OnGUIEvent ); int iY = 10;  
    g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, 125, 22 ); 
    g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22 ); 
    g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22, VK_F2 ); 
 
    g_SampleUI.SetCallback( OnGUIEvent ); iY = 10;  
 
	g_paramDialog.init(g_DialogResourceManager); 
	g_paramDialog.setUpdateParamCallback(updateParam); 
 
 
 
	g_paramDialog.addFloatParam(IDP_FORCE_RADIUS,L"Force Radius",1,0.0f,0.1f); 
	g_paramDialog.addFloatParam(IDP_FORCE_STRENGTH,L"Force Strength",1,0.0f,10000.0f); 
 
	g_paramDialog.addFloatParam(IDP_DISSIPATION,L"dissipation",1,0.98f,1.0f); 
	g_paramDialog.addFloatParam(IDP_D,L"Particle Distance",1,0.0f,1.0f); 
	g_paramDialog.addFloatParam(IDP_JACOBI_ITERATE_NUM,L"Jacobi Iterate Number",1,1.0f,64.0f); 
	g_paramDialog.addFloatParam(IDP_VISCOUS,L"Kinematic Viscosity",1.0f,0.0f,10.0f); 
	g_paramDialog.addFloatParam(IDP_VORTICITY_CONFINEMENT_COEFFICIENT, 
		L"Vorticity Confinement Coefficient",1.0f,0.0f,20.0f); 
 
    g_paramDialog.addFloatParam(IDP_UNIT,L"Substance Advect Speed",1,0.0f,0.5f); 
	g_paramDialog.addFloatParam(IDP_SOURCE_RADIUS,L"Source Radius",1,0.0f,0.5f); 
	g_paramDialog.addColorParam(IDP_SOURCE_STRENGTH,L"Source Color"); 
	g_paramDialog.addFloatParam(IDP_SUBSTANCE_DISSIPATION,L"Substance Dissipationt",1,0.98f,1.0f); 
 
	g_paramDialog.addFloatParam(IDP_TIME_SCALE,L"Time Scale",1,0.0f,2.0f); 
 
	 
	 
	 
	 
	 
	DTK::registerDeviceListener(&g_paramDialog); 
 
/* 
    TODO: add UI controls as needed 
    g_SampleUI.AddComboBox( 19, 35, iY += 24, 125, 22 ); 
    g_SampleUI.GetComboBox( 19 )->AddItem( L"Text1", NULL ); 
    g_SampleUI.GetComboBox( 19 )->AddItem( L"Text2", NULL ); 
    g_SampleUI.GetComboBox( 19 )->AddItem( L"Text3", NULL ); 
    g_SampleUI.GetComboBox( 19 )->AddItem( L"Text4", NULL ); 
    g_SampleUI.AddCheckBox( 21, L"Checkbox1", 35, iY += 24, 125, 22 ); 
    g_SampleUI.AddCheckBox( 11, L"Checkbox2", 35, iY += 24, 125, 22 ); 
    g_SampleUI.AddRadioButton( 12, 1, L"Radio1G1", 35, iY += 24, 125, 22 ); 
    g_SampleUI.AddRadioButton( 13, 1, L"Radio2G1", 35, iY += 24, 125, 22 ); 
    g_SampleUI.AddRadioButton( 14, 1, L"Radio3G1", 35, iY += 24, 125, 22 ); 
    g_SampleUI.GetRadioButton( 14 )->SetChecked( true );  
    g_SampleUI.AddButton( 17, L"Button1", 35, iY += 24, 125, 22 ); 
    g_SampleUI.AddButton( 18, L"Button2", 35, iY += 24, 125, 22 ); 
    g_SampleUI.AddRadioButton( 15, 2, L"Radio1G2", 35, iY += 24, 125, 22 ); 
    g_SampleUI.AddRadioButton( 16, 2, L"Radio2G3", 35, iY += 24, 125, 22 ); 
    g_SampleUI.GetRadioButton( 16 )->SetChecked( true ); 
    g_SampleUI.AddSlider( 20, 50, iY += 24, 100, 22 ); 
    g_SampleUI.GetSlider( 20 )->SetRange( 0, 100 ); 
    g_SampleUI.GetSlider( 20 )->SetValue( 50 ); 
    g_SampleUI.AddEditBox( 20, L"Test", 35, iY += 24, 125, 32 ); 
*/ 
} 
 
 
//-------------------------------------------------------------------------------------- 
// Called during device initialization, this code checks the device for some  
// minimum set of capabilities, and rejects those that don't pass 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; 
} 
 
 
//-------------------------------------------------------------------------------------- 
// This callback function is called immediately before a device is created to allow the  
// application to modify the device settings. The supplied pDeviceSettings parameter  
// contains the settings that the framework has selected for the new device, and the  
// application can make any desired changes directly to this structure.  Note however that  
// DXUT will not correct invalid device settings so care must be taken  
// to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.   
//-------------------------------------------------------------------------------------- 
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext ) 
{ 
	//check if device support vertex shader 3.0 
	if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 || 
		pCaps->VertexShaderVersion  D3DVS_VERSION(3,0) || 
		pCaps->PixelShaderVersion  D3DPS_VERSION(3,0)) 
	{ 
		MessageBox(NULL, 
			L"Sorry this demo require SM3 which is not supported by your GPU, we suggest Geforce6 Serial GPU or above.", 
			L"Your video card is not capable with this demo",MB_OK); 
		exit(0); 
	} 
 
	pDeviceSettings->pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ; 
    // 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; 
} 
 
 
//-------------------------------------------------------------------------------------- 
// 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; 
 
    V_RETURN( g_DialogResourceManager.OnCreateDevice( pd3dDevice ) ); 
    V_RETURN( g_SettingsDlg.OnCreateDevice( 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 ) ); 
 
    
 
    // Setup the camera's view parameters 
    D3DXVECTOR3 vecEye(0.0f, 0.0f, -5.0f); 
    D3DXVECTOR3 vecAt (0.0f, 0.0f, -0.0f); 
    g_Camera.SetViewParams( &vecEye, &vecAt ); 
 
	DTK::onCreateDevice(pd3dDevice,pBackBufferSurfaceDesc,pUserContext); 
	Scene::onCreateDevice(pd3dDevice,pBackBufferSurfaceDesc,pUserContext); 
 
    return S_OK; 
} 
 
 
//-------------------------------------------------------------------------------------- 
// 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.OnResetDevice() ); 
    V_RETURN( g_SettingsDlg.OnResetDevice() ); 
 
    if( g_pFont ) 
        V_RETURN( g_pFont->OnResetDevice() ); 
 
 
    // 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_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width-170, pBackBufferSurfaceDesc->Height-350 ); 
    g_SampleUI.SetSize( 170, 300 ); 
 
	DTK::onResetDevice(pd3dDevice,pBackBufferSurfaceDesc,pUserContext); 
	Scene::onResetDevice(pd3dDevice,pBackBufferSurfaceDesc,pUserContext); 
	 
 
    return S_OK; 
} 
 
 
//-------------------------------------------------------------------------------------- 
// This callback function will be called once at the beginning of every frame. This is the 
// best location for your application to handle updates to the scene, but is not  
// intended to contain actual rendering calls, which should instead be placed in the  
// OnFrameRender callback.   
//-------------------------------------------------------------------------------------- 
void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ) 
{ 
    // Update the camera's position based on user input  
    g_Camera.FrameMove( fElapsedTime ); 
	g_vecTrigger.timeStep(fElapsedTime); 
} 
 
 
//-------------------------------------------------------------------------------------- 
// This callback function will be called at the end of every frame to perform all the  
// rendering calls for the scene, and it will also be called if the window needs to be  
// repainted. After this function has returned, DXUT will call  
// IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain 
//-------------------------------------------------------------------------------------- 
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ) 
{ 
    HRESULT hr; 
    D3DXMATRIXA16 mWorld; 
    D3DXMATRIXA16 mView; 
    D3DXMATRIXA16 mProj; 
    D3DXMATRIXA16 mWorldViewProjection; 
     
    // 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; 
    } 
 
    // Clear the render target and the zbuffer  
    V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(255, 0, 0, 0), 1.0f, 0) ); 
 
    // Render the scene 
    if( SUCCEEDED( pd3dDevice->BeginScene() ) ) 
    { 
        // Get the projection & view matrix from the camera class 
        mWorld = *g_Camera.GetWorldMatrix(); 
        mProj = *g_Camera.GetProjMatrix(); 
        mView = *g_Camera.GetViewMatrix(); 
 
        mWorldViewProjection = mWorld * mView * mProj; 
 
 
		Scene::render(fTime,fElapsedTime); 
 
		if (g_bShowHelp) 
		{ 
			DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"HUD / Stats" ); // These events are to help PIX identify what the code is doing 
			RenderText(); 
			V( g_HUD.OnRender( fElapsedTime ) ); 
			V( g_SampleUI.OnRender( fElapsedTime ) ); 
			V( g_paramDialog.onRender(fElapsedTime)); 
 
			DXUT_EndPerfEvent(); 
		} 
 
 
 
        V( pd3dDevice->EndScene() ); 
    } 
} 
 
 
//-------------------------------------------------------------------------------------- 
// Render the help and statistics text. This function uses the ID3DXFont interface for  
// efficient text rendering. 
//-------------------------------------------------------------------------------------- 
void RenderText() 
{ 
    // The helper object simply helps keep track of text position, and color 
    // and then it calls pFont->DrawText( m_pSprite, strMsg, -1, &rc, DT_NOCLIP, m_clr ); 
    // If NULL is passed in as the sprite object, then it will work however the  
    // pFont->DrawText() will not be batched together.  Batching calls will improves performance. 
    CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 ); 
 
    // Output statistics 
    txtHelper.Begin(); 
    txtHelper.SetInsertionPos( 5, 5 ); 
    txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) ); 
    txtHelper.DrawTextLine( DXUTGetFrameStats() ); 
    txtHelper.DrawTextLine( DXUTGetDeviceStats() ); 
 
	DTK::String buf; 
	buf = DTK::String(L"FPS :")+DTK::StringConverter::toString(DXUTGetFPS()); 
	txtHelper.DrawTextLine(buf.c_str()); 
 
	buf = DTK::String(L"[R] : clear scene"); 
	txtHelper.DrawTextLine(buf.c_str()); 
 
	buf = DTK::String(L"[1] : toggle display mode : ")+DISPLAY_MODE[g_uCurDisplayMode]; 
	txtHelper.DrawTextLine(buf.c_str()); 
	buf = DTK::String(L"[2] : toggle quiver velocity field : ")+ 
		DTK::StringConverter::toString(g_bShowQuiverVelocityField); 
	txtHelper.DrawTextLine(buf.c_str()); 
	buf = DTK::String(L"[0] : toggle default fluid param : ")+FLUID_TYPE[g_uFluidType]; 
	txtHelper.DrawTextLine(buf.c_str()); 
 
	buf = DTK::String(L"[Z] : toggle diffuse   : ")+DTK::StringConverter::toString(gs_bDiffuse); 
	txtHelper.DrawTextLine(buf.c_str()); 
	buf = DTK::String(L"[X] : toggle advection : ")+DTK::StringConverter::toString(gs_bAdvection); 
	txtHelper.DrawTextLine(buf.c_str()); 
	buf = DTK::String(L"[C] : toggle project   : ")+DTK::StringConverter::toString(gs_bProject); 
	txtHelper.DrawTextLine(buf.c_str()); 
	buf = DTK::String(L"[V] : toggle velocity boundary : ")+DTK::StringConverter::toString(gs_bVelocityBoundary); 
	txtHelper.DrawTextLine(buf.c_str()); 
	buf = DTK::String(L"[B] : toggle pressure boundary : ")+DTK::StringConverter::toString(gs_bPressureBoundary); 
	txtHelper.DrawTextLine(buf.c_str()); 
	buf = DTK::String(L"[N] : toggle vorticity confinement  : ")+ 
		DTK::StringConverter::toString(gs_bVorticityConfinement); 
	txtHelper.DrawTextLine(buf.c_str()); 
	buf = DTK::String(L"[F1]: toggle UI"); 
	txtHelper.DrawTextLine(buf.c_str()); 
	 
	/* 
    TODO: add UI text as needed 
    txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) ); 
    txtHelper.DrawTextLine( L"Put whatever misc status here" ); 
     
    // Draw help 
    const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc(); 
    if( g_bShowHelp ) 
    { 
        txtHelper.SetInsertionPos( 10, pd3dsdBackBuffer->Height-15*6 ); 
        txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) ); 
        txtHelper.DrawTextLine( L"Controls (F1 to hide):" ); 
 
        txtHelper.SetInsertionPos( 40, pd3dsdBackBuffer->Height-15*5 ); 
        txtHelper.DrawTextLine( L"Quit: ESC" ); 
    } 
    else 
    { 
        txtHelper.SetInsertionPos( 10, pd3dsdBackBuffer->Height-15*2 ); 
        txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) ); 
        txtHelper.DrawTextLine( L"Press F1 for help" ); 
    } 
*/ 
    txtHelper.End(); 
} 
 
 
//-------------------------------------------------------------------------------------- 
// Before handling window messages, DXUT passes incoming windows  
// messages to the application through this callback function. If the application sets  
// *pbNoFurtherProcessing to TRUE, then DXUT will not process this message. 
//-------------------------------------------------------------------------------------- 
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; 
    *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam ); 
    if( *pbNoFurtherProcessing ) 
        return 0; 
	g_paramDialog.onMessage(hWnd,uMsg,wParam,lParam,pbNoFurtherProcessing); 
	if( *pbNoFurtherProcessing ) 
		return 0; 
    // Pass all remaining windows messages to camera so it can respond to user input 
    g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam ); 
 
 
 
	g_vecTrigger.onMessage(hWnd,uMsg,wParam,lParam); 
 
	if (hWnd = DXUTGetHWND()) 
	{ 
		//switch(uMsg) 
		//{ 
		//default: 
		//	break;			 
		//} 
 
	} 
 
 
    return 0; 
} 
 
 
//-------------------------------------------------------------------------------------- 
// As a convenience, DXUT inspects the incoming windows messages for 
// keystroke messages and decodes the message parameters to pass relevant keyboard 
// messages to the application.  The framework does not remove the underlying keystroke  
// messages, which are still passed to the application's MsgProc callback. 
//-------------------------------------------------------------------------------------- 
void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext ) 
{ 
    if( bKeyDown ) 
    { 
        switch( nChar ) 
        { 
            case VK_F1: g_bShowHelp = !g_bShowHelp; break; 
			case 'R':Scene::clearScene(); break; 
			case '1':toggleDisplayMode(); break; 
			case '2':toggleQuiverVelocityField(); break; 
			case '0':toggleDefaultParam();break; 
 
			case 'Z':toggleDiffuse(); break; 
			case 'X':toggleAdvection();break; 
			case 'C':toggleProject();break; 
			case 'V':toggleVelocityBoundary();break; 
			case 'B':togglePressureBoundary();break; 
			case 'N':toggleVorticityConfinement();break; 
 
 
			default: 
				break; 
        } 
    } 
} 
 
 
//-------------------------------------------------------------------------------------- 
// Handles the GUI events 
//-------------------------------------------------------------------------------------- 
void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ) 
{ 
    switch( nControlID ) 
    { 
        case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break; 
        case IDC_TOGGLEREF:        DXUTToggleREF(); break; 
        case IDC_CHANGEDEVICE:     g_SettingsDlg.SetActive( !g_SettingsDlg.IsActive() ); break; 
    } 
} 
 
 
//-------------------------------------------------------------------------------------- 
// This callback function will be called immediately after the Direct3D device has  
// entered a lost state and before IDirect3DDevice9::Reset is called. Resources created 
// in the OnResetDevice callback should be released here, which generally includes all  
// D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for  
// information about lost devices. 
//-------------------------------------------------------------------------------------- 
void CALLBACK OnLostDevice( void* pUserContext ) 
{ 
    g_DialogResourceManager.OnLostDevice(); 
    g_SettingsDlg.OnLostDevice(); 
    if( g_pFont ) 
        g_pFont->OnLostDevice(); 
 
    SAFE_RELEASE( g_pTextSprite ); 
  
	Scene::onLostDevice(pUserContext); 
	DTK::onLostDevice(pUserContext); 
	 
} 
 
 
//-------------------------------------------------------------------------------------- 
// This callback function will be called immediately after the Direct3D device has  
// been destroyed, which generally happens as a result of application termination or  
// windowed/full screen toggles. Resources created in the OnCreateDevice callback  
// should be released here, which generally includes all D3DPOOL_MANAGED resources.  
//-------------------------------------------------------------------------------------- 
void CALLBACK OnDestroyDevice( void* pUserContext ) 
{ 
    g_DialogResourceManager.OnDestroyDevice(); 
    g_SettingsDlg.OnDestroyDevice(); 
 
    SAFE_RELEASE( g_pFont ); 
 
	Scene::onDestroyDevice(pUserContext); 
	DTK::onDestroyDevice(pUserContext); 
	 
} 
 
void toggleQuiverVelocityField() 
{ 
	g_bShowQuiverVelocityField =!g_bShowQuiverVelocityField; 
} 
void toggleDisplayMode() 
{ 
	++g_uCurDisplayMode; 
	g_uCurDisplayMode %= NUM_DISPLAY_MODE; 
} 
 
void toggleDiffuse() 
{ 
	gs_bDiffuse = !gs_bDiffuse; 
	g_animator.enableDiffuse(gs_bDiffuse); 
} 
void toggleAdvection() 
{ 
	gs_bAdvection = !gs_bAdvection; 
	g_animator.enableAdvection(gs_bAdvection); 
} 
void toggleProject() 
{ 
	gs_bProject = !gs_bProject; 
	g_animator.enableProject(gs_bProject); 
} 
void toggleVelocityBoundary() 
{ 
	gs_bVelocityBoundary = ! gs_bVelocityBoundary; 
	g_animator.enableVelocityBoundary(gs_bVelocityBoundary); 
} 
void togglePressureBoundary() 
{ 
	gs_bPressureBoundary = ! gs_bPressureBoundary; 
	g_animator.enablePressureBoundary(gs_bPressureBoundary); 
} 
 
void toggleVorticityConfinement() 
{ 
	gs_bVorticityConfinement = !gs_bVorticityConfinement; 
	g_animator.enableVorticityConfinement(gs_bVorticityConfinement); 
} 
 
void toggleDefaultParam() 
{ 
 
	++g_uFluidType; 
	g_uFluidType %= NUM_FLUID_TYPE; 
 
	Scene::setFluidType(g_uFluidType); 
} 
 
void impulse(DTK::Vector2 pos,DTK::Vector2 vec) 
{ 
	DTK::FluidAnimator2D::ExternalForce force(g_forceRadius,pos,vec*g_forceStrength); 
	g_animator.addExternalForce(force); 
	DTK::Substance2D::PointSource src(g_sourceRadius,pos,g_sourceStrength); 
	g_substance.injectSource(src); 
	 
} 
 
void updateParam(int iID,const float value[4]) 
{ 
	switch(iID) 
	{ 
	case IDP_SOURCE_STRENGTH: 
		g_sourceStrength = DTK::ColorValue(value[0],value[1],value[2],value[4]); 
		break; 
	case IDP_SUBSTANCE_DISSIPATION: 
		g_substance.setDissipation(value[0]); 
		break; 
	case IDP_UNIT: 
		{ 
			DTK::Vector2 unit(value[0],value[0]); 
			g_substance.setUint(unit); 
		} 
		break; 
	case IDP_SOURCE_RADIUS: 
		g_sourceRadius = value[0]; 
		break; 
 
	case IDP_D: 
		g_animator.setParticleDistance(value[0]); 
		break; 
	case IDP_DISSIPATION: 
		g_animator.setDissipation(value[0]); 
		 
		break; 
	case IDP_TIME_SCALE: 
		g_fTimeScale = value[0]; 
		break; 
	case IDP_FORCE_RADIUS: 
		g_forceRadius = value[0]; 
		break; 
	case IDP_FORCE_STRENGTH: 
		g_forceStrength = value[0]; 
		break; 
	case IDP_JACOBI_ITERATE_NUM: 
		g_animator.setIterateNumber(static_cast<DTK::uint>(value[0])); 
		break; 
	case IDP_VISCOUS: 
		g_animator.setViscous(value[0]); 
		break; 
	case IDP_VORTICITY_CONFINEMENT_COEFFICIENT: 
		g_animator.setVorticityConfinementCoefficient(value[0]); 
		break; 
	default: 
		break; 
	} 
 
}