home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Common / DXUTmisc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  103.1 KB  |  2,885 lines

  1. //--------------------------------------------------------------------------------------
  2. // File: DXUTMisc.cpp
  3. //
  4. // Shortcut macros and functions for using DX objects
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved
  7. //--------------------------------------------------------------------------------------
  8. #include "dxstdafx.h"
  9.  
  10. //--------------------------------------------------------------------------------------
  11. // Global/Static Members
  12. //--------------------------------------------------------------------------------------
  13. CDXUTResourceCache& DXUTGetGlobalResourceCache()
  14. {
  15.     // Using an accessor function gives control of the construction order
  16.     static CDXUTResourceCache cache;
  17.     return cache;
  18. }
  19. CDXUTTimer* DXUTGetGlobalTimer()
  20. {
  21.     // Using an accessor function gives control of the construction order
  22.     static CDXUTTimer timer;
  23.     return &timer;
  24. }
  25.  
  26.  
  27. //--------------------------------------------------------------------------------------
  28. // Internal functions forward declarations
  29. //--------------------------------------------------------------------------------------
  30. bool DXUTFindMediaSearchTypicalDirs( WCHAR* strSearchPath, int cchSearch, LPCWSTR strLeaf, WCHAR* strExePath, WCHAR* strExeName, LPCWSTR strMediaDir );
  31. bool DXUTFindMediaSearchParentDirs( WCHAR* strSearchPath, int cchSearch, WCHAR* strStartAt, WCHAR* strLeafName );
  32.  
  33.  
  34. //--------------------------------------------------------------------------------------
  35. CDXUTTimer::CDXUTTimer()
  36. {
  37.     m_bUsingQPF         = false;
  38.     m_bTimerStopped     = true;
  39.     m_llQPFTicksPerSec  = 0;
  40.  
  41.     m_llStopTime        = 0;
  42.     m_llLastElapsedTime = 0;
  43.     m_llBaseTime        = 0;
  44.  
  45.     // Use QueryPerformanceFrequency() to get frequency of timer.  
  46.     LARGE_INTEGER qwTicksPerSec;
  47.     m_bUsingQPF = (bool) (QueryPerformanceFrequency( &qwTicksPerSec ) != 0);
  48.     m_llQPFTicksPerSec = qwTicksPerSec.QuadPart;
  49. }
  50.  
  51.  
  52. //--------------------------------------------------------------------------------------
  53. void CDXUTTimer::Reset()
  54. {
  55.     if( !m_bUsingQPF )
  56.         return;
  57.  
  58.     // Get either the current time or the stop time
  59.     LARGE_INTEGER qwTime;
  60.     if( m_llStopTime != 0 )
  61.         qwTime.QuadPart = m_llStopTime;
  62.     else
  63.         QueryPerformanceCounter( &qwTime );
  64.  
  65.     m_llBaseTime        = qwTime.QuadPart;
  66.     m_llLastElapsedTime = qwTime.QuadPart;
  67.     m_llStopTime        = 0;
  68.     m_bTimerStopped     = FALSE;
  69. }
  70.  
  71.  
  72. //--------------------------------------------------------------------------------------
  73. void CDXUTTimer::Start()
  74. {
  75.     if( !m_bUsingQPF )
  76.         return;
  77.  
  78.     // Get the current time
  79.     LARGE_INTEGER qwTime;
  80.     QueryPerformanceCounter( &qwTime );
  81.  
  82.     if( m_bTimerStopped )
  83.         m_llBaseTime += qwTime.QuadPart - m_llStopTime;
  84.     m_llStopTime = 0;
  85.     m_llLastElapsedTime = qwTime.QuadPart;
  86.     m_bTimerStopped = FALSE;
  87. }
  88.  
  89.  
  90. //--------------------------------------------------------------------------------------
  91. void CDXUTTimer::Stop()
  92. {
  93.     if( !m_bUsingQPF )
  94.         return;
  95.  
  96.     if( !m_bTimerStopped )
  97.     {
  98.         // Get either the current time or the stop time
  99.         LARGE_INTEGER qwTime;
  100.         if( m_llStopTime != 0 )
  101.             qwTime.QuadPart = m_llStopTime;
  102.         else
  103.             QueryPerformanceCounter( &qwTime );
  104.  
  105.         m_llStopTime = qwTime.QuadPart;
  106.         m_llLastElapsedTime = qwTime.QuadPart;
  107.         m_bTimerStopped = TRUE;
  108.     }
  109. }
  110.  
  111.  
  112. //--------------------------------------------------------------------------------------
  113. void CDXUTTimer::Advance()
  114. {
  115.     if( !m_bUsingQPF )
  116.         return;
  117.  
  118.     m_llStopTime += m_llQPFTicksPerSec/10;
  119. }
  120.  
  121.  
  122. //--------------------------------------------------------------------------------------
  123. double CDXUTTimer::GetAbsoluteTime()
  124. {
  125.     if( !m_bUsingQPF )
  126.         return -1.0;
  127.  
  128.     // Get either the current time or the stop time
  129.     LARGE_INTEGER qwTime;
  130.     if( m_llStopTime != 0 )
  131.         qwTime.QuadPart = m_llStopTime;
  132.     else
  133.         QueryPerformanceCounter( &qwTime );
  134.  
  135.     double fTime = qwTime.QuadPart / (double) m_llQPFTicksPerSec;
  136.  
  137.     return fTime;
  138. }
  139.  
  140.  
  141. //--------------------------------------------------------------------------------------
  142. double CDXUTTimer::GetTime()
  143. {
  144.     if( !m_bUsingQPF )
  145.         return -1.0;
  146.  
  147.     // Get either the current time or the stop time
  148.     LARGE_INTEGER qwTime;
  149.     if( m_llStopTime != 0 )
  150.         qwTime.QuadPart = m_llStopTime;
  151.     else
  152.         QueryPerformanceCounter( &qwTime );
  153.  
  154.     double fAppTime = (double) ( qwTime.QuadPart - m_llBaseTime ) / (double) m_llQPFTicksPerSec;
  155.  
  156.     return fAppTime;
  157. }
  158.  
  159.  
  160. //--------------------------------------------------------------------------------------
  161. double CDXUTTimer::GetElapsedTime()
  162. {
  163.     if( !m_bUsingQPF )
  164.         return -1.0;
  165.  
  166.     // Get either the current time or the stop time
  167.     LARGE_INTEGER qwTime;
  168.     if( m_llStopTime != 0 )
  169.         qwTime.QuadPart = m_llStopTime;
  170.     else
  171.         QueryPerformanceCounter( &qwTime );
  172.  
  173.     double fElapsedTime = (double) ( qwTime.QuadPart - m_llLastElapsedTime ) / (double) m_llQPFTicksPerSec;
  174.     m_llLastElapsedTime = qwTime.QuadPart;
  175.  
  176.     return fElapsedTime;
  177. }
  178.  
  179.  
  180. //--------------------------------------------------------------------------------------
  181. bool CDXUTTimer::IsStopped()
  182. {
  183.     return m_bTimerStopped;
  184. }
  185.  
  186.  
  187.  
  188. //--------------------------------------------------------------------------------------
  189. // Returns the DirectX SDK media path
  190. //       cchDest is the size in WCHARs of strDest.  Be careful not to 
  191. //       pass in sizeof(strDest) on UNICODE builds.
  192. //--------------------------------------------------------------------------------------
  193. HRESULT DXUTGetDXSDKMediaPathCch( WCHAR* strDest, int cchDest )
  194. {
  195.     if( strDest == NULL || cchDest < 1 )
  196.         return E_INVALIDARG;
  197.  
  198.     lstrcpy( strDest, TEXT("") );
  199.  
  200.     // Open the appropriate registry key
  201.     HKEY  hKey;
  202.     LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  203.                                 L"Software\\Microsoft\\DirectX SDK",
  204.                                 0, KEY_READ, &hKey );
  205.     if( ERROR_SUCCESS != lResult ) 
  206.         return E_FAIL;
  207.  
  208.     DWORD dwType;
  209.     DWORD dwSize = cchDest * sizeof(WCHAR);
  210.     lResult = RegQueryValueEx( hKey, L"DX9O4SDK Samples Path", NULL,
  211.                               &dwType, (BYTE*)strDest, &dwSize );
  212.     strDest[cchDest-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small
  213.     RegCloseKey( hKey );
  214.  
  215.     if( ERROR_SUCCESS != lResult )
  216.         return E_FAIL;
  217.  
  218.     const WCHAR* strMedia = L"\\Media\\";
  219.     if( lstrlen(strDest) + lstrlen(strMedia) < cchDest )
  220.         wcscat( strDest, strMedia );
  221.     else
  222.         return E_INVALIDARG;
  223.  
  224.     return S_OK;
  225. }
  226.  
  227.  
  228. //--------------------------------------------------------------------------------------
  229. // Tries to find the location of a SDK media file
  230. //       cchDest is the size in WCHARs of strDestPath.  Be careful not to 
  231. //       pass in sizeof(strDest) on UNICODE builds.
  232. //--------------------------------------------------------------------------------------
  233. HRESULT DXUTFindDXSDKMediaFileCch( WCHAR* strDestPath, int cchDest, LPCWSTR strFilename )
  234. {
  235.     bool bFound;
  236.     WCHAR strSearchFor[MAX_PATH];
  237.     
  238.     if( NULL==strFilename || strFilename[0] == 0 || NULL==strDestPath || cchDest < 10 )
  239.         return E_INVALIDARG;
  240.  
  241.     // Get the DirectX SDK's media dir if the SDK is installed
  242.     WCHAR strMediaDir[MAX_PATH] = {0};
  243.     DXUTGetDXSDKMediaPathCch( strMediaDir, MAX_PATH );
  244.  
  245.     // Get the exe name, and exe path
  246.     WCHAR strExePath[MAX_PATH] = {0};
  247.     WCHAR strExeName[MAX_PATH] = {0};
  248.     WCHAR* strLastSlash = NULL;
  249.     GetModuleFileName( NULL, strExePath, MAX_PATH );
  250.     strExePath[MAX_PATH-1]=0;
  251.     strLastSlash = wcsrchr( strExePath, TEXT('\\') );
  252.     if( strLastSlash )
  253.     {
  254.         lstrcpyn( strExeName, &strLastSlash[1], MAX_PATH );
  255.  
  256.         // Chop the exe name from the exe path
  257.         *strLastSlash = 0;
  258.  
  259.         // Chop the .exe from the exe name
  260.         strLastSlash = wcsrchr( strExeName, TEXT('.') );
  261.         if( strLastSlash )
  262.             *strLastSlash = 0;
  263.     }
  264.  
  265.     // Typical directories:
  266.     //      .\
  267.     //      ..\
  268.     //      ..\..\
  269.     //      %EXE_DIR%\
  270.     //      %EXE_DIR%\..\
  271.     //      %EXE_DIR%\..\..\
  272.     //      %EXE_DIR%\..\%EXE_NAME%
  273.     //      %EXE_DIR%\..\..\%EXE_NAME%
  274.     //      DXSDK media path
  275.  
  276.     // Typical directory search
  277.     bFound = DXUTFindMediaSearchTypicalDirs( strDestPath, cchDest, strFilename, strExePath, strExeName, strMediaDir );
  278.     if( bFound )
  279.         return S_OK;
  280.  
  281.     // Typical directory search again, but also look in a subdir called "\media\" 
  282.     _snwprintf( strSearchFor, MAX_PATH, L"media\\%s", strFilename ); strSearchFor[MAX_PATH-1] = 0;
  283.     bFound = DXUTFindMediaSearchTypicalDirs( strDestPath, cchDest, strSearchFor, strExePath, strExeName, strMediaDir );
  284.     if( bFound )
  285.         return S_OK;
  286.  
  287.     WCHAR strLeafName[MAX_PATH] = {0};
  288.  
  289.     // Search all parent directories starting at .\ and using strFilename as the leaf name
  290.     wcsncpy( strLeafName, strFilename, MAX_PATH ); strLeafName[MAX_PATH-1] = 0;
  291.     bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, L".", strLeafName );
  292.     if( bFound )
  293.         return S_OK;
  294.  
  295.     // Search all parent directories starting at the exe's dir and using strFilename as the leaf name
  296.     bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, strExePath, strLeafName );
  297.     if( bFound )
  298.         return S_OK;
  299.  
  300.     // Search all parent directories starting at .\ and using "media\strFilename" as the leaf name
  301.     _snwprintf( strLeafName, MAX_PATH, L"media\\%s", strFilename ); strLeafName[MAX_PATH-1] = 0;
  302.     bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, L".", strLeafName );
  303.     if( bFound )
  304.         return S_OK;
  305.  
  306.     // Search all parent directories starting at the exe's dir and using "media\strFilename" as the leaf name
  307.     bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, strExePath, strLeafName );
  308.     if( bFound )
  309.         return S_OK;
  310.  
  311.     // On failure, return the file as the path but also return an error code
  312.     wcsncpy( strDestPath, strFilename, cchDest );
  313.     strDestPath[cchDest-1] = 0;
  314.  
  315.     return DXUTERR_MEDIANOTFOUND;
  316. }
  317.  
  318.  
  319. //--------------------------------------------------------------------------------------
  320. // Search a set of typical directories
  321. //--------------------------------------------------------------------------------------
  322. bool DXUTFindMediaSearchTypicalDirs( WCHAR* strSearchPath, int cchSearch, LPCWSTR strLeaf, 
  323.                                      WCHAR* strExePath, WCHAR* strExeName, LPCWSTR strMediaDir )
  324. {
  325.     // Typical directories:
  326.     //      .\
  327.     //      ..\
  328.     //      ..\..\
  329.     //      %EXE_DIR%\
  330.     //      %EXE_DIR%\..\
  331.     //      %EXE_DIR%\..\..\
  332.     //      %EXE_DIR%\..\%EXE_NAME%
  333.     //      %EXE_DIR%\..\..\%EXE_NAME%
  334.     //      DXSDK media path
  335.  
  336.     // Search in .\  
  337.     wcsncpy( strSearchPath, strLeaf, cchSearch ); strSearchPath[cchSearch-1] = 0;
  338.     if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
  339.         return true;
  340.  
  341.     // Search in ..\  
  342.     _snwprintf( strSearchPath, cchSearch, L"..\\%s", strLeaf ); strSearchPath[cchSearch-1] = 0;
  343.     if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
  344.         return true;
  345.  
  346.     // Search in ..\..\ 
  347.     _snwprintf( strSearchPath, cchSearch, L"..\\..\\%s", strLeaf ); strSearchPath[cchSearch-1] = 0;
  348.     if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
  349.         return true;
  350.  
  351.     // Search in ..\..\ 
  352.     _snwprintf( strSearchPath, cchSearch, L"..\\..\\%s", strLeaf ); strSearchPath[cchSearch-1] = 0;
  353.     if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
  354.         return true;
  355.  
  356.     // Search in the %EXE_DIR%\ 
  357.     _snwprintf( strSearchPath, cchSearch, L"%s\\%s", strExePath, strLeaf ); strSearchPath[cchSearch-1] = 0;
  358.     if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
  359.         return true;
  360.  
  361.     // Search in the %EXE_DIR%\..\ 
  362.     _snwprintf( strSearchPath, cchSearch, L"%s\\..\\%s", strExePath, strLeaf ); strSearchPath[cchSearch-1] = 0;
  363.     if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
  364.         return true;
  365.  
  366.     // Search in the %EXE_DIR%\..\..\ 
  367.     _snwprintf( strSearchPath, cchSearch, L"%s\\..\\..\\%s", strExePath, strLeaf ); strSearchPath[cchSearch-1] = 0;
  368.     if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
  369.         return true;
  370.  
  371.     // Search in "%EXE_DIR%\..\%EXE_NAME%\".  This matches the DirectX SDK layout
  372.     _snwprintf( strSearchPath, cchSearch, L"%s\\..\\%s\\%s", strExePath, strExeName, strLeaf ); strSearchPath[cchSearch-1] = 0;
  373.     if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
  374.         return true;
  375.  
  376.     // Search in "%EXE_DIR%\..\..\%EXE_NAME%\".  This matches the DirectX SDK layout
  377.     _snwprintf( strSearchPath, cchSearch, L"%s\\..\\..\\%s\\%s", strExePath, strExeName, strLeaf ); strSearchPath[cchSearch-1] = 0;
  378.     if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
  379.         return true;
  380.  
  381.     // Search in DirectX SDK's media dir 
  382.     _snwprintf( strSearchPath, cchSearch, L"%s%s", strMediaDir, strLeaf ); strSearchPath[cchSearch-1] = 0;
  383.     if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF )
  384.         return true;
  385.  
  386.     return false;
  387. }
  388.  
  389.  
  390.  
  391. //--------------------------------------------------------------------------------------
  392. // Search parent directories starting at strStartAt, and appending strLeafName
  393. // at each parent directory.  It stops at the root directory.
  394. //--------------------------------------------------------------------------------------
  395. bool DXUTFindMediaSearchParentDirs( WCHAR* strSearchPath, int cchSearch, WCHAR* strStartAt, WCHAR* strLeafName )
  396. {
  397.     WCHAR strFullPath[MAX_PATH] = {0};
  398.     WCHAR strFullFileName[MAX_PATH] = {0};
  399.     WCHAR strSearch[MAX_PATH] = {0};
  400.     WCHAR* strFilePart = NULL;
  401.  
  402.     GetFullPathName( strStartAt, MAX_PATH, strFullPath, &strFilePart );
  403.     if( strFilePart == NULL )
  404.         return false;
  405.    
  406.     while( strFilePart != NULL && *strFilePart != '\0' )
  407.     {
  408.         _snwprintf( strFullFileName, MAX_PATH, L"%s\\%s", strFullPath, strLeafName ); strFullFileName[MAX_PATH-1] = 0;       
  409.         if( GetFileAttributes( strFullFileName ) != 0xFFFFFFFF )
  410.         {
  411.             wcsncpy( strSearchPath, strFullFileName, cchSearch ); strSearchPath[cchSearch-1] = 0; 
  412.             return true;
  413.         }
  414.  
  415.         _snwprintf( strSearch, MAX_PATH, L"%s\\..", strFullPath ); strSearch[MAX_PATH-1] = 0;
  416.         GetFullPathName( strSearch, MAX_PATH, strFullPath, &strFilePart );
  417.     }
  418.  
  419.     return false;
  420. }
  421.  
  422.  
  423. //--------------------------------------------------------------------------------------
  424. // CDXUTResourceCache
  425. //--------------------------------------------------------------------------------------
  426.  
  427.  
  428. CDXUTResourceCache::~CDXUTResourceCache()
  429. {
  430.     OnDestroyDevice();
  431.  
  432.     m_TextureCache.RemoveAll();
  433.     m_EffectCache.RemoveAll();
  434.     m_FontCache.RemoveAll();
  435. }
  436.  
  437.  
  438. HRESULT CDXUTResourceCache::CreateTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, LPDIRECT3DTEXTURE9 *ppTexture )
  439. {
  440.     return CreateTextureFromFileEx( pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
  441.                                     0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT,
  442.                                     0, NULL, NULL, ppTexture );
  443. }
  444.  
  445.  
  446. //--------------------------------------------------------------------------------------
  447. HRESULT CDXUTResourceCache::CreateTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Width, UINT Height, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DTEXTURE9 *ppTexture )
  448. {
  449.     // Search the cache for a matching entry.
  450.     for( int i = 0; i < m_TextureCache.GetSize(); ++i )
  451.     {
  452.         DXUTCache_Texture &Entry = m_TextureCache[i];
  453.         if( Entry.Location == DXUTCACHE_LOCATION_FILE &&
  454.             !lstrcmpW( Entry.wszSource, pSrcFile ) &&
  455.             Entry.Width == Width &&
  456.             Entry.Height == Height &&
  457.             Entry.MipLevels == MipLevels &&
  458.             Entry.Usage == Usage &&
  459.             Entry.Format == Format &&
  460.             Entry.Pool == Pool &&
  461.             Entry.Type == D3DRTYPE_TEXTURE )
  462.         {
  463.             // A match is found. Obtain the IDirect3DTexture9 interface and return that.
  464.             return Entry.pTexture->QueryInterface( IID_IDirect3DTexture9, (LPVOID*)ppTexture );
  465.         }
  466.     }
  467.  
  468.     HRESULT hr;
  469.  
  470.     // No matching entry.  Load the resource and create a new entry.
  471.     hr = D3DXCreateTextureFromFileEx( pDevice, pSrcFile, Width, Height, MipLevels, Usage, Format,
  472.                                       Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppTexture );
  473.     if( FAILED( hr ) )
  474.         return hr;
  475.  
  476.     DXUTCache_Texture NewEntry;
  477.     NewEntry.Location = DXUTCACHE_LOCATION_FILE;
  478.     lstrcpyW( NewEntry.wszSource, pSrcFile );
  479.     NewEntry.Width = Width;
  480.     NewEntry.Height = Height;
  481.     NewEntry.MipLevels = MipLevels;
  482.     NewEntry.Usage = Usage;
  483.     NewEntry.Format = Format;
  484.     NewEntry.Pool = Pool;
  485.     NewEntry.Type = D3DRTYPE_TEXTURE;
  486.     (*ppTexture)->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&NewEntry.pTexture );
  487.  
  488.     m_TextureCache.Add( NewEntry );
  489.     return S_OK;
  490. }
  491.  
  492.  
  493. //--------------------------------------------------------------------------------------
  494. HRESULT CDXUTResourceCache::CreateTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, LPDIRECT3DTEXTURE9 *ppTexture )
  495. {
  496.     return CreateTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, D3DX_DEFAULT, D3DX_DEFAULT,
  497.                                         D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT,
  498.                                         D3DX_DEFAULT, 0, NULL, NULL, ppTexture );
  499. }
  500.  
  501.  
  502. //--------------------------------------------------------------------------------------
  503. HRESULT CDXUTResourceCache::CreateTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, UINT Width, UINT Height, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DTEXTURE9 *ppTexture )
  504. {
  505.     // Search the cache for a matching entry.
  506.     for( int i = 0; i < m_TextureCache.GetSize(); ++i )
  507.     {
  508.         DXUTCache_Texture &Entry = m_TextureCache[i];
  509.         if( Entry.Location == DXUTCACHE_LOCATION_RESOURCE &&
  510.             Entry.hSrcModule == hSrcModule &&
  511.             !lstrcmpW( Entry.wszSource, pSrcResource ) &&
  512.             Entry.Width == Width &&
  513.             Entry.Height == Height &&
  514.             Entry.MipLevels == MipLevels &&
  515.             Entry.Usage == Usage &&
  516.             Entry.Format == Format &&
  517.             Entry.Pool == Pool &&
  518.             Entry.Type == D3DRTYPE_TEXTURE )
  519.         {
  520.             // A match is found. Obtain the IDirect3DTexture9 interface and return that.
  521.             return Entry.pTexture->QueryInterface( IID_IDirect3DTexture9, (LPVOID*)ppTexture );
  522.         }
  523.     }
  524.  
  525.     HRESULT hr;
  526.  
  527.     // No matching entry.  Load the resource and create a new entry.
  528.     hr = D3DXCreateTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, Width, Height, MipLevels, Usage,
  529.                                           Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppTexture );
  530.     if( FAILED( hr ) )
  531.         return hr;
  532.  
  533.     DXUTCache_Texture NewEntry;
  534.     NewEntry.Location = DXUTCACHE_LOCATION_RESOURCE;
  535.     NewEntry.hSrcModule = hSrcModule;
  536.     lstrcpyW( NewEntry.wszSource, pSrcResource );
  537.     NewEntry.Width = Width;
  538.     NewEntry.Height = Height;
  539.     NewEntry.MipLevels = MipLevels;
  540.     NewEntry.Usage = Usage;
  541.     NewEntry.Format = Format;
  542.     NewEntry.Pool = Pool;
  543.     NewEntry.Type = D3DRTYPE_TEXTURE;
  544.     (*ppTexture)->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&NewEntry.pTexture );
  545.  
  546.     m_TextureCache.Add( NewEntry );
  547.     return S_OK;
  548. }
  549.  
  550.  
  551. //--------------------------------------------------------------------------------------
  552. HRESULT CDXUTResourceCache::CreateCubeTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture )
  553. {
  554.     return CreateCubeTextureFromFileEx( pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT, 0,
  555.                                         D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT,
  556.                                         0, NULL, NULL, ppCubeTexture );
  557. }
  558.  
  559.  
  560. //--------------------------------------------------------------------------------------
  561. HRESULT CDXUTResourceCache::CreateCubeTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Size, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture )
  562. {
  563.     // Search the cache for a matching entry.
  564.     for( int i = 0; i < m_TextureCache.GetSize(); ++i )
  565.     {
  566.         DXUTCache_Texture &Entry = m_TextureCache[i];
  567.         if( Entry.Location == DXUTCACHE_LOCATION_FILE &&
  568.             !lstrcmpW( Entry.wszSource, pSrcFile ) &&
  569.             Entry.Width == Size &&
  570.             Entry.MipLevels == MipLevels &&
  571.             Entry.Usage == Usage &&
  572.             Entry.Format == Format &&
  573.             Entry.Pool == Pool &&
  574.             Entry.Type == D3DRTYPE_CUBETEXTURE )
  575.         {
  576.             // A match is found. Obtain the IDirect3DCubeTexture9 interface and return that.
  577.             return Entry.pTexture->QueryInterface( IID_IDirect3DCubeTexture9, (LPVOID*)ppCubeTexture );
  578.         }
  579.     }
  580.  
  581.     HRESULT hr;
  582.  
  583.     // No matching entry.  Load the resource and create a new entry.
  584.     hr = D3DXCreateCubeTextureFromFileEx( pDevice, pSrcFile, Size, MipLevels, Usage, Format, Pool, Filter,
  585.                                           MipFilter, ColorKey, pSrcInfo, pPalette, ppCubeTexture );
  586.     if( FAILED( hr ) )
  587.         return hr;
  588.  
  589.     DXUTCache_Texture NewEntry;
  590.     NewEntry.Location = DXUTCACHE_LOCATION_FILE;
  591.     lstrcpyW( NewEntry.wszSource, pSrcFile );
  592.     NewEntry.Width = Size;
  593.     NewEntry.MipLevels = MipLevels;
  594.     NewEntry.Usage = Usage;
  595.     NewEntry.Format = Format;
  596.     NewEntry.Pool = Pool;
  597.     NewEntry.Type = D3DRTYPE_CUBETEXTURE;
  598.     (*ppCubeTexture)->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&NewEntry.pTexture );
  599.  
  600.     m_TextureCache.Add( NewEntry );
  601.     return S_OK;
  602. }
  603.  
  604.  
  605. //--------------------------------------------------------------------------------------
  606. HRESULT CDXUTResourceCache::CreateCubeTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture )
  607. {
  608.     return CreateCubeTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, D3DX_DEFAULT, D3DX_DEFAULT,
  609.                                             0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT,
  610.                                             0, NULL, NULL, ppCubeTexture );
  611. }
  612.  
  613.  
  614. //--------------------------------------------------------------------------------------
  615. HRESULT CDXUTResourceCache::CreateCubeTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, UINT Size, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture )
  616. {
  617.     // Search the cache for a matching entry.
  618.     for( int i = 0; i < m_TextureCache.GetSize(); ++i )
  619.     {
  620.         DXUTCache_Texture &Entry = m_TextureCache[i];
  621.         if( Entry.Location == DXUTCACHE_LOCATION_RESOURCE &&
  622.             Entry.hSrcModule == hSrcModule &&
  623.             !lstrcmpW( Entry.wszSource, pSrcResource ) &&
  624.             Entry.Width == Size &&
  625.             Entry.MipLevels == MipLevels &&
  626.             Entry.Usage == Usage &&
  627.             Entry.Format == Format &&
  628.             Entry.Pool == Pool &&
  629.             Entry.Type == D3DRTYPE_CUBETEXTURE )
  630.         {
  631.             // A match is found. Obtain the IDirect3DCubeTexture9 interface and return that.
  632.             return Entry.pTexture->QueryInterface( IID_IDirect3DCubeTexture9, (LPVOID*)ppCubeTexture );
  633.         }
  634.     }
  635.  
  636.     HRESULT hr;
  637.  
  638.     // No matching entry.  Load the resource and create a new entry.
  639.     hr = D3DXCreateCubeTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, Size, MipLevels, Usage, Format,
  640.                                               Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppCubeTexture );
  641.     if( FAILED( hr ) )
  642.         return hr;
  643.  
  644.     DXUTCache_Texture NewEntry;
  645.     NewEntry.Location = DXUTCACHE_LOCATION_RESOURCE;
  646.     NewEntry.hSrcModule = hSrcModule;
  647.     lstrcpyW( NewEntry.wszSource, pSrcResource );
  648.     NewEntry.Width = Size;
  649.     NewEntry.MipLevels = MipLevels;
  650.     NewEntry.Usage = Usage;
  651.     NewEntry.Format = Format;
  652.     NewEntry.Pool = Pool;
  653.     NewEntry.Type = D3DRTYPE_CUBETEXTURE;
  654.     (*ppCubeTexture)->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&NewEntry.pTexture );
  655.  
  656.     m_TextureCache.Add( NewEntry );
  657.     return S_OK;
  658. }
  659.  
  660.  
  661. //--------------------------------------------------------------------------------------
  662. HRESULT CDXUTResourceCache::CreateVolumeTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, LPDIRECT3DVOLUMETEXTURE9 *ppVolumeTexture )
  663. {
  664.     return CreateVolumeTextureFromFileEx( pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
  665.                                           0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT,
  666.                                           0, NULL, NULL, ppVolumeTexture );
  667. }
  668.  
  669.  
  670. //--------------------------------------------------------------------------------------
  671. HRESULT CDXUTResourceCache::CreateVolumeTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Width, UINT Height, UINT Depth, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DVOLUMETEXTURE9 *ppTexture )
  672. {
  673.     // Search the cache for a matching entry.
  674.     for( int i = 0; i < m_TextureCache.GetSize(); ++i )
  675.     {
  676.         DXUTCache_Texture &Entry = m_TextureCache[i];
  677.         if( Entry.Location == DXUTCACHE_LOCATION_FILE &&
  678.             !lstrcmpW( Entry.wszSource, pSrcFile ) &&
  679.             Entry.Width == Width &&
  680.             Entry.Height == Height &&
  681.             Entry.Depth == Depth &&
  682.             Entry.MipLevels == MipLevels &&
  683.             Entry.Usage == Usage &&
  684.             Entry.Format == Format &&
  685.             Entry.Pool == Pool &&
  686.             Entry.Type == D3DRTYPE_VOLUMETEXTURE )
  687.         {
  688.             // A match is found. Obtain the IDirect3DVolumeTexture9 interface and return that.
  689.             return Entry.pTexture->QueryInterface( IID_IDirect3DVolumeTexture9, (LPVOID*)ppTexture );
  690.         }
  691.     }
  692.  
  693.     HRESULT hr;
  694.  
  695.     // No matching entry.  Load the resource and create a new entry.
  696.     hr = D3DXCreateVolumeTextureFromFileEx( pDevice, pSrcFile, Width, Height, Depth, MipLevels, Usage, Format,
  697.                                             Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppTexture );
  698.     if( FAILED( hr ) )
  699.         return hr;
  700.  
  701.     DXUTCache_Texture NewEntry;
  702.     NewEntry.Location = DXUTCACHE_LOCATION_FILE;
  703.     lstrcpyW( NewEntry.wszSource, pSrcFile );
  704.     NewEntry.Width = Width;
  705.     NewEntry.Height = Height;
  706.     NewEntry.Depth = Depth;
  707.     NewEntry.MipLevels = MipLevels;
  708.     NewEntry.Usage = Usage;
  709.     NewEntry.Format = Format;
  710.     NewEntry.Pool = Pool;
  711.     NewEntry.Type = D3DRTYPE_VOLUMETEXTURE;
  712.     (*ppTexture)->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&NewEntry.pTexture );
  713.  
  714.     m_TextureCache.Add( NewEntry );
  715.     return S_OK;
  716. }
  717.  
  718.  
  719. //--------------------------------------------------------------------------------------
  720. HRESULT CDXUTResourceCache::CreateVolumeTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, LPDIRECT3DVOLUMETEXTURE9 *ppVolumeTexture )
  721. {
  722.     return CreateVolumeTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, D3DX_DEFAULT, D3DX_DEFAULT,
  723.                                               D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
  724.                                               D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, ppVolumeTexture );
  725. }
  726.  
  727.  
  728. //--------------------------------------------------------------------------------------
  729. HRESULT CDXUTResourceCache::CreateVolumeTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, UINT Width, UINT Height, UINT Depth, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DVOLUMETEXTURE9 *ppVolumeTexture )
  730. {
  731.     // Search the cache for a matching entry.
  732.     for( int i = 0; i < m_TextureCache.GetSize(); ++i )
  733.     {
  734.         DXUTCache_Texture &Entry = m_TextureCache[i];
  735.         if( Entry.Location == DXUTCACHE_LOCATION_RESOURCE &&
  736.             Entry.hSrcModule == hSrcModule &&
  737.             !lstrcmpW( Entry.wszSource, pSrcResource ) &&
  738.             Entry.Width == Width &&
  739.             Entry.Height == Height &&
  740.             Entry.Depth == Depth &&
  741.             Entry.MipLevels == MipLevels &&
  742.             Entry.Usage == Usage &&
  743.             Entry.Format == Format &&
  744.             Entry.Pool == Pool &&
  745.             Entry.Type == D3DRTYPE_VOLUMETEXTURE )
  746.         {
  747.             // A match is found. Obtain the IDirect3DVolumeTexture9 interface and return that.
  748.             return Entry.pTexture->QueryInterface( IID_IDirect3DVolumeTexture9, (LPVOID*)ppVolumeTexture );
  749.         }
  750.     }
  751.  
  752.     HRESULT hr;
  753.  
  754.     // No matching entry.  Load the resource and create a new entry.
  755.     hr = D3DXCreateVolumeTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, Width, Height, Depth, MipLevels, Usage,
  756.                                                 Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppVolumeTexture );
  757.     if( FAILED( hr ) )
  758.         return hr;
  759.  
  760.     DXUTCache_Texture NewEntry;
  761.     NewEntry.Location = DXUTCACHE_LOCATION_RESOURCE;
  762.     NewEntry.hSrcModule = hSrcModule;
  763.     lstrcpyW( NewEntry.wszSource, pSrcResource );
  764.     NewEntry.Width = Width;
  765.     NewEntry.Height = Height;
  766.     NewEntry.Depth = Depth;
  767.     NewEntry.MipLevels = MipLevels;
  768.     NewEntry.Usage = Usage;
  769.     NewEntry.Format = Format;
  770.     NewEntry.Pool = Pool;
  771.     NewEntry.Type = D3DRTYPE_VOLUMETEXTURE;
  772.     (*ppVolumeTexture)->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&NewEntry.pTexture );
  773.  
  774.     m_TextureCache.Add( NewEntry );
  775.     return S_OK;
  776. }
  777.  
  778.  
  779. //--------------------------------------------------------------------------------------
  780. HRESULT CDXUTResourceCache::CreateFont( LPDIRECT3DDEVICE9 pDevice, UINT Height, UINT Width, UINT Weight, UINT MipLevels, BOOL Italic, DWORD CharSet, DWORD OutputPrecision, DWORD Quality, DWORD PitchAndFamily, LPCTSTR pFacename, LPD3DXFONT *ppFont )
  781. {
  782.     D3DXFONT_DESCW Desc;
  783.     
  784.     Desc.Height = Height;
  785.     Desc.Width = Width;
  786.     Desc.Weight = Weight;
  787.     Desc.MipLevels = MipLevels;
  788.     Desc.Italic = Italic;
  789.     Desc.CharSet = (BYTE)CharSet;
  790.     Desc.OutputPrecision = (BYTE)OutputPrecision;
  791.     Desc.Quality = (BYTE)Quality;
  792.     Desc.PitchAndFamily = (BYTE)PitchAndFamily;
  793.     wcsncpy( Desc.FaceName, pFacename, LF_FACESIZE );
  794.     Desc.FaceName[LF_FACESIZE - 1] = L'\0';
  795.  
  796.     return CreateFontIndirect( pDevice, &Desc, ppFont );
  797. }
  798.  
  799.  
  800. //--------------------------------------------------------------------------------------
  801. HRESULT CDXUTResourceCache::CreateFontIndirect( LPDIRECT3DDEVICE9 pDevice, CONST D3DXFONT_DESC *pDesc, LPD3DXFONT *ppFont )
  802. {
  803.     // Search the cache for a matching entry.
  804.     for( int i = 0; i < m_FontCache.GetSize(); ++i )
  805.     {
  806.         DXUTCache_Font &Entry = m_FontCache[i];
  807.  
  808.         if( Entry.Width == pDesc->Width &&
  809.             Entry.Height == pDesc->Height &&
  810.             Entry.Weight == pDesc->Weight &&
  811.             Entry.MipLevels == pDesc->MipLevels &&
  812.             Entry.Italic == pDesc->Italic &&
  813.             Entry.CharSet == pDesc->CharSet &&
  814.             Entry.OutputPrecision == pDesc->OutputPrecision &&
  815.             Entry.Quality == pDesc->Quality &&
  816.             Entry.PitchAndFamily == pDesc->PitchAndFamily &&
  817.             CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  818.                            Entry.FaceName, -1,
  819.                            pDesc->FaceName, -1 ) == CSTR_EQUAL )
  820.         {
  821.             // A match is found.  Increment the reference and return the ID3DXFont object.
  822.             Entry.pFont->AddRef();
  823.             *ppFont = Entry.pFont;
  824.             return S_OK;
  825.         }
  826.     }
  827.  
  828.     HRESULT hr;
  829.  
  830.     // No matching entry.  Load the resource and create a new entry.
  831.     hr = D3DXCreateFontIndirect( pDevice, pDesc, ppFont );
  832.     if( FAILED( hr ) )
  833.         return hr;
  834.  
  835.     DXUTCache_Font NewEntry;
  836.     (D3DXFONT_DESC &)NewEntry = *pDesc;
  837.     NewEntry.pFont = *ppFont;
  838.     NewEntry.pFont->AddRef();
  839.  
  840.     m_FontCache.Add( NewEntry );
  841.     return S_OK;
  842. }
  843.  
  844.  
  845. //--------------------------------------------------------------------------------------
  846. HRESULT CDXUTResourceCache::CreateEffectFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, const D3DXMACRO *pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXEFFECTPOOL pPool, LPD3DXEFFECT *ppEffect, LPD3DXBUFFER *ppCompilationErrors )
  847. {
  848.     // Search the cache for a matching entry.
  849.     for( int i = 0; i < m_EffectCache.GetSize(); ++i )
  850.     {
  851.         DXUTCache_Effect &Entry = m_EffectCache[i];
  852.  
  853.         if( Entry.Location == DXUTCACHE_LOCATION_FILE &&
  854.             !lstrcmpW( Entry.wszSource, pSrcFile ) &&
  855.             Entry.dwFlags == Flags )
  856.         {
  857.             // A match is found.  Increment the ref coutn and return the ID3DXEffect object.
  858.             *ppEffect = Entry.pEffect;
  859.             (*ppEffect)->AddRef();
  860.             return S_OK;
  861.         }
  862.     }
  863.  
  864.     HRESULT hr;
  865.  
  866.     // No matching entry.  Load the resource and create a new entry.
  867.     hr = D3DXCreateEffectFromFile( pDevice, pSrcFile, pDefines, pInclude, Flags, pPool, ppEffect, ppCompilationErrors );
  868.     if( FAILED( hr ) )
  869.         return hr;
  870.  
  871.     DXUTCache_Effect NewEntry;
  872.     NewEntry.Location = DXUTCACHE_LOCATION_FILE;
  873.     lstrcpyW( NewEntry.wszSource, pSrcFile );
  874.     NewEntry.dwFlags = Flags;
  875.     NewEntry.pEffect = *ppEffect;
  876.     NewEntry.pEffect->AddRef();
  877.  
  878.     m_EffectCache.Add( NewEntry );
  879.     return S_OK;
  880. }
  881.  
  882.  
  883. //--------------------------------------------------------------------------------------
  884. HRESULT CDXUTResourceCache::CreateEffectFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, const D3DXMACRO *pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXEFFECTPOOL pPool, LPD3DXEFFECT *ppEffect, LPD3DXBUFFER *ppCompilationErrors )
  885. {
  886.     // Search the cache for a matching entry.
  887.     for( int i = 0; i < m_EffectCache.GetSize(); ++i )
  888.     {
  889.         DXUTCache_Effect &Entry = m_EffectCache[i];
  890.  
  891.         if( Entry.Location == DXUTCACHE_LOCATION_RESOURCE &&
  892.             Entry.hSrcModule == hSrcModule &&
  893.             !lstrcmpW( Entry.wszSource, pSrcResource ) &&
  894.             Entry.dwFlags == Flags )
  895.         {
  896.             // A match is found.  Increment the ref coutn and return the ID3DXEffect object.
  897.             *ppEffect = Entry.pEffect;
  898.             (*ppEffect)->AddRef();
  899.             return S_OK;
  900.         }
  901.     }
  902.  
  903.     HRESULT hr;
  904.  
  905.     // No matching entry.  Load the resource and create a new entry.
  906.     hr = D3DXCreateEffectFromResource( pDevice, hSrcModule, pSrcResource, pDefines, pInclude, Flags,
  907.                                        pPool, ppEffect, ppCompilationErrors );
  908.     if( FAILED( hr ) )
  909.         return hr;
  910.  
  911.     DXUTCache_Effect NewEntry;
  912.     NewEntry.Location = DXUTCACHE_LOCATION_RESOURCE;
  913.     NewEntry.hSrcModule = hSrcModule;
  914.     lstrcpyW( NewEntry.wszSource, pSrcResource );
  915.     NewEntry.dwFlags = Flags;
  916.     NewEntry.pEffect = *ppEffect;
  917.     NewEntry.pEffect->AddRef();
  918.  
  919.     m_EffectCache.Add( NewEntry );
  920.     return S_OK;
  921. }
  922.  
  923.  
  924. //--------------------------------------------------------------------------------------
  925. // Device event callbacks
  926. //--------------------------------------------------------------------------------------
  927.  
  928.  
  929. //--------------------------------------------------------------------------------------
  930. HRESULT CDXUTResourceCache::OnCreateDevice( IDirect3DDevice9 *pd3dDevice )
  931. {
  932.     return S_OK;
  933. }
  934.  
  935.  
  936. //--------------------------------------------------------------------------------------
  937. HRESULT CDXUTResourceCache::OnResetDevice( IDirect3DDevice9 *pd3dDevice )
  938. {
  939.     // Call OnResetDevice on all effect and font objects
  940.     for( int i = 0; i < m_EffectCache.GetSize(); ++i )
  941.         m_EffectCache[i].pEffect->OnResetDevice();
  942.     for( int i = 0; i < m_FontCache.GetSize(); ++i )
  943.         m_FontCache[i].pFont->OnResetDevice();
  944.  
  945.  
  946.     return S_OK;
  947. }
  948.  
  949.  
  950. //--------------------------------------------------------------------------------------
  951. HRESULT CDXUTResourceCache::OnLostDevice()
  952. {
  953.     // Call OnLostDevice on all effect and font objects
  954.     for( int i = 0; i < m_EffectCache.GetSize(); ++i )
  955.         m_EffectCache[i].pEffect->OnLostDevice();
  956.     for( int i = 0; i < m_FontCache.GetSize(); ++i )
  957.         m_FontCache[i].pFont->OnLostDevice();
  958.  
  959.     // Release all the default pool textures
  960.     for( int i = m_TextureCache.GetSize() - 1; i >= 0; --i )
  961.         if( m_TextureCache[i].Pool == D3DPOOL_DEFAULT )
  962.         {
  963.             SAFE_RELEASE( m_TextureCache[i].pTexture );
  964.             m_TextureCache.Remove( i );  // Remove the entry
  965.         }
  966.  
  967.     return S_OK;
  968. }
  969.  
  970.  
  971. //--------------------------------------------------------------------------------------
  972. HRESULT CDXUTResourceCache::OnDestroyDevice()
  973. {
  974.     // Release all resources
  975.     for( int i = m_EffectCache.GetSize() - 1; i >= 0; --i )
  976.     {
  977.         SAFE_RELEASE( m_EffectCache[i].pEffect );
  978.         m_EffectCache.Remove( i );
  979.     }
  980.     for( int i = m_FontCache.GetSize() - 1; i >= 0; --i )
  981.     {
  982.         SAFE_RELEASE( m_FontCache[i].pFont );
  983.         m_FontCache.Remove( i );
  984.     }
  985.     for( int i = m_TextureCache.GetSize() - 1; i >= 0; --i )
  986.     {
  987.         SAFE_RELEASE( m_TextureCache[i].pTexture );
  988.         m_TextureCache.Remove( i );
  989.     }
  990.  
  991.     return S_OK;
  992. }
  993.  
  994.  
  995. //--------------------------------------------------------------------------------------
  996. CD3DArcBall::CD3DArcBall()
  997. {
  998.     Reset();
  999.     m_vDownPt = D3DXVECTOR3(0,0,0);
  1000.     m_vCurrentPt = D3DXVECTOR3(0,0,0);
  1001.     m_Offset.x = m_Offset.y = 0;
  1002.  
  1003.     RECT rc;
  1004.     GetClientRect( GetForegroundWindow(), &rc );
  1005.     SetWindow( rc.right, rc.bottom );
  1006. }
  1007.  
  1008.  
  1009.  
  1010.  
  1011.  
  1012. //--------------------------------------------------------------------------------------
  1013. void CD3DArcBall::Reset()
  1014. {
  1015.     D3DXQuaternionIdentity( &m_qDown );
  1016.     D3DXQuaternionIdentity( &m_qNow );
  1017.     D3DXMatrixIdentity( &m_mRotation );
  1018.     D3DXMatrixIdentity( &m_mTranslation );
  1019.     D3DXMatrixIdentity( &m_mTranslationDelta );
  1020.     m_bDrag = FALSE;
  1021.     m_fRadiusTranslation = 1.0f;
  1022.     m_fRadius = 1.0f;
  1023. }
  1024.  
  1025.  
  1026.  
  1027.  
  1028. //--------------------------------------------------------------------------------------
  1029. D3DXVECTOR3 CD3DArcBall::ScreenToVector( float fScreenPtX, float fScreenPtY )
  1030. {
  1031.     // Scale to screen
  1032.     FLOAT x   = -(fScreenPtX - m_Offset.x - m_nWidth/2)  / (m_fRadius*m_nWidth/2);
  1033.     FLOAT y   =  (fScreenPtY - m_Offset.y - m_nHeight/2) / (m_fRadius*m_nHeight/2);
  1034.  
  1035.     FLOAT z   = 0.0f;
  1036.     FLOAT mag = x*x + y*y;
  1037.  
  1038.     if( mag > 1.0f )
  1039.     {
  1040.         FLOAT scale = 1.0f/sqrtf(mag);
  1041.         x *= scale;
  1042.         y *= scale;
  1043.     }
  1044.     else
  1045.         z = sqrtf( 1.0f - mag );
  1046.  
  1047.     // Return vector
  1048.     return D3DXVECTOR3( x, y, z );
  1049. }
  1050.  
  1051.  
  1052.  
  1053.  
  1054. //--------------------------------------------------------------------------------------
  1055. D3DXQUATERNION CD3DArcBall::QuatFromBallPoints(const D3DXVECTOR3 &vFrom, const D3DXVECTOR3 &vTo)
  1056. {
  1057.     D3DXVECTOR3 vPart;
  1058.     float fDot = D3DXVec3Dot(&vFrom, &vTo);
  1059.     D3DXVec3Cross(&vPart, &vFrom, &vTo);
  1060.  
  1061.     return D3DXQUATERNION(vPart.x, vPart.y, vPart.z, fDot);
  1062. }
  1063.  
  1064.  
  1065.  
  1066.  
  1067. //--------------------------------------------------------------------------------------
  1068. void CD3DArcBall::OnBegin( int nX, int nY )
  1069. {
  1070.     // Only enter the drag state if the click falls
  1071.     // inside the click rectangle.
  1072.     if( nX >= m_Offset.x &&
  1073.         nX < m_Offset.x + m_nWidth &&
  1074.         nY >= m_Offset.y &&
  1075.         nY < m_Offset.y + m_nHeight )
  1076.     {
  1077.         m_bDrag = true;
  1078.         m_qDown = m_qNow;
  1079.         m_vDownPt = ScreenToVector( (float)nX, (float)nY );
  1080.     }
  1081. }
  1082.  
  1083.  
  1084.  
  1085.  
  1086. //--------------------------------------------------------------------------------------
  1087. void CD3DArcBall::OnMove( int nX, int nY )
  1088. {
  1089.     if (m_bDrag) 
  1090.     { 
  1091.         m_vCurrentPt = ScreenToVector( (float)nX, (float)nY );
  1092.         m_qNow = m_qDown * QuatFromBallPoints( m_vDownPt, m_vCurrentPt );
  1093.     }
  1094. }
  1095.  
  1096.  
  1097.  
  1098.  
  1099. //--------------------------------------------------------------------------------------
  1100. void CD3DArcBall::OnEnd()
  1101. {
  1102.     m_bDrag = false;
  1103. }
  1104.  
  1105.  
  1106.  
  1107.  
  1108. //--------------------------------------------------------------------------------------
  1109. // Desc:
  1110. //--------------------------------------------------------------------------------------
  1111. LRESULT CD3DArcBall::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1112. {
  1113.     // Current mouse position
  1114.     int iMouseX = (short)LOWORD(lParam);
  1115.     int iMouseY = (short)HIWORD(lParam);
  1116.  
  1117.     switch( uMsg )
  1118.     {
  1119.         case WM_LBUTTONDOWN:
  1120.         case WM_LBUTTONDBLCLK:
  1121.             SetCapture( hWnd );
  1122.             OnBegin( iMouseX, iMouseY );
  1123.             return TRUE;
  1124.  
  1125.         case WM_LBUTTONUP:
  1126.             ReleaseCapture();
  1127.             OnEnd();
  1128.             return TRUE;
  1129.  
  1130.         case WM_RBUTTONDOWN:
  1131.         case WM_RBUTTONDBLCLK:
  1132.         case WM_MBUTTONDOWN:
  1133.         case WM_MBUTTONDBLCLK:
  1134.             SetCapture( hWnd );
  1135.             // Store off the position of the cursor when the button is pressed
  1136.             m_ptLastMouse.x = iMouseX;
  1137.             m_ptLastMouse.y = iMouseY;
  1138.             return TRUE;
  1139.  
  1140.         case WM_RBUTTONUP:
  1141.         case WM_MBUTTONUP:
  1142.             ReleaseCapture();
  1143.             return TRUE;
  1144.  
  1145.         case WM_MOUSEMOVE:
  1146.             if( MK_LBUTTON&wParam )
  1147.             {
  1148.                 OnMove( iMouseX, iMouseY );
  1149.             }
  1150.             else if( (MK_RBUTTON&wParam) || (MK_MBUTTON&wParam) )
  1151.             {
  1152.                 // Normalize based on size of window and bounding sphere radius
  1153.                 FLOAT fDeltaX = ( m_ptLastMouse.x-iMouseX ) * m_fRadiusTranslation / m_nWidth;
  1154.                 FLOAT fDeltaY = ( m_ptLastMouse.y-iMouseY ) * m_fRadiusTranslation / m_nHeight;
  1155.  
  1156.                 if( wParam & MK_RBUTTON )
  1157.                 {
  1158.                     D3DXMatrixTranslation( &m_mTranslationDelta, -2*fDeltaX, 2*fDeltaY, 0.0f );
  1159.                     D3DXMatrixMultiply( &m_mTranslation, &m_mTranslation, &m_mTranslationDelta );
  1160.                 }
  1161.                 else  // wParam & MK_MBUTTON
  1162.                 {
  1163.                     D3DXMatrixTranslation( &m_mTranslationDelta, 0.0f, 0.0f, 5*fDeltaY );
  1164.                     D3DXMatrixMultiply( &m_mTranslation, &m_mTranslation, &m_mTranslationDelta );
  1165.                 }
  1166.  
  1167.                 // Store mouse coordinate
  1168.                 m_ptLastMouse.x = iMouseX;
  1169.                 m_ptLastMouse.y = iMouseY;
  1170.             }
  1171.             return TRUE;
  1172.     }
  1173.  
  1174.     return FALSE;
  1175. }
  1176.  
  1177.  
  1178.  
  1179.  
  1180. //--------------------------------------------------------------------------------------
  1181. // Constructor
  1182. //--------------------------------------------------------------------------------------
  1183. CBaseCamera::CBaseCamera()
  1184. {
  1185.     ZeroMemory( m_aKeys, sizeof(BYTE)*CAM_MAX_KEYS );
  1186.  
  1187.     // Set attributes for the view matrix
  1188.     D3DXVECTOR3 vEyePt    = D3DXVECTOR3(0.0f,0.0f,0.0f);
  1189.     D3DXVECTOR3 vLookatPt = D3DXVECTOR3(0.0f,0.0f,1.0f);
  1190.  
  1191.     // Setup the view matrix
  1192.     SetViewParams( &vEyePt, &vLookatPt );
  1193.  
  1194.     // Setup the projection matrix
  1195.     SetProjParams( D3DX_PI/4, 1.0f, 1.0f, 1000.0f );
  1196.  
  1197.     GetCursorPos( &m_ptLastMousePosition );
  1198.     m_bMouseLButtonDown = false;
  1199.     m_bMouseMButtonDown = false;
  1200.     m_bMouseRButtonDown = false;
  1201.     m_nCurrentButtonMask = 0;
  1202.     m_nMouseWheelDelta = 0;
  1203.  
  1204.     m_fCameraYawAngle = 0.0f;
  1205.     m_fCameraPitchAngle = 0.0f;
  1206.  
  1207.     SetRect( &m_rcDrag, LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX );
  1208.     m_vVelocity     = D3DXVECTOR3(0,0,0);
  1209.     m_bMovementDrag = false;
  1210.     m_vVelocityDrag = D3DXVECTOR3(0,0,0);
  1211.     m_fDragTimer    = 0.0f;
  1212.     m_fTotalDragTimeToZero = 0.25;
  1213.     m_vRotVelocity = D3DXVECTOR2(0,0);
  1214.  
  1215.     m_fRotationScaler = 0.01f;           
  1216.     m_fMoveScaler = 5.0f;           
  1217.  
  1218.     m_bInvertPitch = false;
  1219.     m_bEnableYAxisMovement = true;
  1220.     m_bEnablePositionMovement = true;
  1221.  
  1222.     m_vMouseDelta   = D3DXVECTOR2(0,0);
  1223.     m_fFramesToSmoothMouseData = 2.0f;
  1224.  
  1225.     m_bClipToBoundary = false;
  1226.     m_vMinBoundary = D3DXVECTOR3(-1,-1,-1);
  1227.     m_vMaxBoundary = D3DXVECTOR3(1,1,1);
  1228.  
  1229.     m_bResetCursorAfterMove = false;
  1230. }
  1231.  
  1232.  
  1233. //--------------------------------------------------------------------------------------
  1234. // Client can call this to change the position and direction of camera
  1235. //--------------------------------------------------------------------------------------
  1236. VOID CBaseCamera::SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt )
  1237. {
  1238.     if( NULL == pvEyePt || NULL == pvLookatPt )
  1239.         return;
  1240.  
  1241.     m_vDefaultEye = m_vEye = *pvEyePt;
  1242.     m_vDefaultLookAt = m_vLookAt = *pvLookatPt;
  1243.  
  1244.     // Calc the view matrix
  1245.     D3DXVECTOR3 vUp(0,1,0);
  1246.     D3DXMatrixLookAtLH( &m_mView, pvEyePt, pvLookatPt, &vUp );
  1247.  
  1248.     D3DXMATRIX mInvView;
  1249.     D3DXMatrixInverse( &mInvView, NULL, &m_mView );
  1250.  
  1251.     // The axis basis vectors and camera position are stored inside the 
  1252.     // position matrix in the 4 rows of the camera's world matrix.
  1253.     // To figure out the yaw/pitch of the camera, we just need the Z basis vector
  1254.     D3DXVECTOR3* pZBasis = (D3DXVECTOR3*) &mInvView._31;
  1255.  
  1256.     m_fCameraYawAngle   = atan2f( pZBasis->x, pZBasis->z );
  1257.     float fLen = sqrtf(pZBasis->z*pZBasis->z + pZBasis->x*pZBasis->x);
  1258.     m_fCameraPitchAngle = -atan2f( pZBasis->y, fLen );
  1259. }
  1260.  
  1261.  
  1262.  
  1263.  
  1264. //--------------------------------------------------------------------------------------
  1265. // Calculates the projection matrix based on input params
  1266. //--------------------------------------------------------------------------------------
  1267. VOID CBaseCamera::SetProjParams( FLOAT fFOV, FLOAT fAspect, FLOAT fNearPlane,
  1268.                                    FLOAT fFarPlane )
  1269. {
  1270.     // Set attributes for the projection matrix
  1271.     m_fFOV        = fFOV;
  1272.     m_fAspect     = fAspect;
  1273.     m_fNearPlane  = fNearPlane;
  1274.     m_fFarPlane   = fFarPlane;
  1275.  
  1276.     D3DXMatrixPerspectiveFovLH( &m_mProj, fFOV, fAspect, fNearPlane, fFarPlane );
  1277. }
  1278.  
  1279.  
  1280.  
  1281.  
  1282. //--------------------------------------------------------------------------------------
  1283. // Call this from your message proc so this class can handle window messages
  1284. //--------------------------------------------------------------------------------------
  1285. LRESULT CBaseCamera::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1286. {
  1287.     UNREFERENCED_PARAMETER( hWnd );
  1288.     UNREFERENCED_PARAMETER( lParam );
  1289.  
  1290.     switch( uMsg )
  1291.     {
  1292.         case WM_KEYDOWN:
  1293.         {
  1294.             // Map this key to a D3DUtil_CameraKeys enum and update the
  1295.             // state of m_aKeys[] by adding the KEY_WAS_DOWN_MASK|KEY_IS_DOWN_MASK mask
  1296.             // only if the key is not down
  1297.             D3DUtil_CameraKeys mappedKey = MapKey( (UINT)wParam );
  1298.             if( mappedKey != CAM_UNKNOWN )
  1299.             {
  1300.                 if( FALSE == IsKeyDown(m_aKeys[mappedKey]) )
  1301.                     m_aKeys[ mappedKey ] = KEY_WAS_DOWN_MASK | KEY_IS_DOWN_MASK;
  1302.             }
  1303.             break;
  1304.         }
  1305.  
  1306.         case WM_KEYUP:
  1307.         {
  1308.             // Map this key to a D3DUtil_CameraKeys enum and update the
  1309.             // state of m_aKeys[] by removing the KEY_IS_DOWN_MASK mask.
  1310.             D3DUtil_CameraKeys mappedKey = MapKey( (UINT)wParam );
  1311.             if( mappedKey != CAM_UNKNOWN )
  1312.                 m_aKeys[ mappedKey ] &= ~KEY_IS_DOWN_MASK;
  1313.             break;
  1314.         }
  1315.  
  1316.         case WM_RBUTTONDOWN:
  1317.         case WM_MBUTTONDOWN:
  1318.         case WM_LBUTTONDOWN:
  1319.         case WM_RBUTTONDBLCLK:
  1320.         case WM_MBUTTONDBLCLK:
  1321.         case WM_LBUTTONDBLCLK:
  1322.         {
  1323.             // Compute the drag rectangle in screen coord.
  1324.             POINT ptCursor = { (short)LOWORD(lParam), (short)HIWORD(lParam) };
  1325.  
  1326.             // Update member var state
  1327.             if( ( uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && PtInRect( &m_rcDrag, ptCursor ) )
  1328.                 { m_bMouseLButtonDown = true; m_nCurrentButtonMask |= MOUSE_LEFT_BUTTON; }
  1329.             if( ( uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && PtInRect( &m_rcDrag, ptCursor ) )
  1330.                 { m_bMouseMButtonDown = true; m_nCurrentButtonMask |= MOUSE_MIDDLE_BUTTON; }
  1331.             if( ( uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && PtInRect( &m_rcDrag, ptCursor ) )
  1332.                 { m_bMouseRButtonDown = true; m_nCurrentButtonMask |= MOUSE_RIGHT_BUTTON; }
  1333.  
  1334.             // Capture the mouse, so if the mouse button is 
  1335.             // released outside the window, we'll get the WM_LBUTTONUP message
  1336.             SetCapture(hWnd);
  1337.             GetCursorPos( &m_ptLastMousePosition );
  1338.             return TRUE;
  1339.         }
  1340.  
  1341.         case WM_RBUTTONUP: 
  1342.         case WM_MBUTTONUP: 
  1343.         case WM_LBUTTONUP:   
  1344.         {
  1345.             // Update member var state
  1346.             if( uMsg == WM_LBUTTONUP ) { m_bMouseLButtonDown = false; m_nCurrentButtonMask &= ~MOUSE_LEFT_BUTTON; }
  1347.             if( uMsg == WM_MBUTTONUP ) { m_bMouseMButtonDown = false; m_nCurrentButtonMask &= ~MOUSE_MIDDLE_BUTTON; }
  1348.             if( uMsg == WM_RBUTTONUP ) { m_bMouseRButtonDown = false; m_nCurrentButtonMask &= ~MOUSE_RIGHT_BUTTON; }
  1349.  
  1350.             // Release the capture if no mouse buttons down
  1351.             if( !m_bMouseLButtonDown  && 
  1352.                 !m_bMouseRButtonDown &&
  1353.                 !m_bMouseMButtonDown )
  1354.             {
  1355.                 ReleaseCapture();
  1356.             }
  1357.             break;
  1358.         }
  1359.  
  1360.         case WM_MOUSEWHEEL: 
  1361.             // Update member var state
  1362.             m_nMouseWheelDelta = (short)HIWORD(wParam) / 120;
  1363.             break;
  1364.     }
  1365.  
  1366.     return FALSE;
  1367. }
  1368.  
  1369.  
  1370.  
  1371.  
  1372. //--------------------------------------------------------------------------------------
  1373. // Figure out the mouse delta based on mouse movement
  1374. //--------------------------------------------------------------------------------------
  1375. void CBaseCamera::UpdateMouseDelta( float fElapsedTime )
  1376. {
  1377.     UNREFERENCED_PARAMETER( fElapsedTime );
  1378.  
  1379.     POINT ptCurMouseDelta;
  1380.     POINT ptCurMousePos;
  1381.     
  1382.     // Get current position of mouse
  1383.     GetCursorPos( &ptCurMousePos );
  1384.  
  1385.     // Calc how far it's moved since last frame
  1386.     ptCurMouseDelta.x = ptCurMousePos.x - m_ptLastMousePosition.x;
  1387.     ptCurMouseDelta.y = ptCurMousePos.y - m_ptLastMousePosition.y;
  1388.  
  1389.     // Record current position for next time
  1390.     m_ptLastMousePosition = ptCurMousePos;
  1391.  
  1392.     if( m_bResetCursorAfterMove )
  1393.     {
  1394.         // Set position of camera to center of desktop, 
  1395.         // so it always has room to move.  This is very useful
  1396.         // if the cursor is hidden.  If this isn't done and cursor is hidden, 
  1397.         // then invisible cursor will hit the edge of the screen 
  1398.         // and the user can't tell what happened
  1399.         POINT ptCenter;
  1400.         RECT rcDesktop;
  1401.         GetWindowRect( GetDesktopWindow(), &rcDesktop );
  1402.         ptCenter.x = (rcDesktop.right - rcDesktop.left) / 2;
  1403.         ptCenter.y = (rcDesktop.bottom - rcDesktop.top) / 2;   
  1404.         SetCursorPos( ptCenter.x, ptCenter.y );
  1405.         m_ptLastMousePosition = ptCenter;
  1406.     }
  1407.  
  1408.     // Smooth the relative mouse data over a few frames so it isn't 
  1409.     // jerky when moving slowly at low frame rates.
  1410.     float fPercentOfNew =  1.0f / m_fFramesToSmoothMouseData;
  1411.     float fPercentOfOld =  1.0f - fPercentOfNew;
  1412.     m_vMouseDelta.x = m_vMouseDelta.x*fPercentOfOld + ptCurMouseDelta.x*fPercentOfNew;
  1413.     m_vMouseDelta.y = m_vMouseDelta.y*fPercentOfOld + ptCurMouseDelta.y*fPercentOfNew;
  1414.  
  1415.     m_vRotVelocity = m_vMouseDelta * m_fRotationScaler;
  1416. }
  1417.  
  1418.  
  1419.  
  1420.  
  1421. //--------------------------------------------------------------------------------------
  1422. // Figure out the velocity based on keyboard input & drag if any
  1423. //--------------------------------------------------------------------------------------
  1424. void CBaseCamera::UpdateVelocity( float fElapsedTime )
  1425. {
  1426.     D3DXMATRIX mRotDelta;
  1427.     D3DXVECTOR3 vAccel = D3DXVECTOR3(0,0,0);
  1428.  
  1429.     if( m_bEnablePositionMovement )
  1430.     {
  1431.         // Update acceleration vector based on keyboard state
  1432.         if( IsKeyDown(m_aKeys[CAM_MOVE_FORWARD]) )
  1433.             vAccel.z += 1.0f;
  1434.         if( IsKeyDown(m_aKeys[CAM_MOVE_BACKWARD]) )
  1435.             vAccel.z -= 1.0f;
  1436.         if( m_bEnableYAxisMovement )
  1437.         {
  1438.             if( IsKeyDown(m_aKeys[CAM_MOVE_UP]) )
  1439.                 vAccel.y += 1.0f;
  1440.             if( IsKeyDown(m_aKeys[CAM_MOVE_DOWN]) )
  1441.                 vAccel.y -= 1.0f;
  1442.         }
  1443.         if( IsKeyDown(m_aKeys[CAM_STRAFE_RIGHT]) )
  1444.             vAccel.x += 1.0f;
  1445.         if( IsKeyDown(m_aKeys[CAM_STRAFE_LEFT]) )
  1446.             vAccel.x -= 1.0f;
  1447.     }
  1448.  
  1449.     // Normalize vector so if moving 2 dirs (left & forward), 
  1450.     // the camera doesn't move faster than if moving in 1 dir
  1451.     D3DXVec3Normalize( &vAccel, &vAccel );
  1452.  
  1453.     // Scale the acceleration vector
  1454.     vAccel *= m_fMoveScaler;
  1455.  
  1456.     if( m_bMovementDrag )
  1457.     {
  1458.         // Is there any acceleration this frame?
  1459.         if( D3DXVec3LengthSq( &vAccel ) > 0 )
  1460.         {
  1461.             // If so, then this means the user has pressed a movement key\
  1462.             // so change the velocity immediately to acceleration 
  1463.             // upon keyboard input.  This isn't normal physics
  1464.             // but it will give a quick response to keyboard input
  1465.             m_vVelocity = vAccel;
  1466.             m_fDragTimer = m_fTotalDragTimeToZero;
  1467.             m_vVelocityDrag = vAccel / m_fDragTimer;
  1468.         }
  1469.         else 
  1470.         {
  1471.             // If no key being pressed, then slowly decrease velocity to 0
  1472.             if( m_fDragTimer > 0 )
  1473.             {
  1474.                 // Drag until timer is <= 0
  1475.                 m_vVelocity -= m_vVelocityDrag * fElapsedTime;
  1476.                 m_fDragTimer -= fElapsedTime;
  1477.             }
  1478.             else
  1479.             {
  1480.                 // Zero velocity
  1481.                 m_vVelocity = D3DXVECTOR3(0,0,0);
  1482.             }
  1483.         }
  1484.     }
  1485.     else
  1486.     {
  1487.         // No drag, so immediately change the velocity
  1488.         m_vVelocity = vAccel;
  1489.     }
  1490. }
  1491.  
  1492.  
  1493.  
  1494.  
  1495. //--------------------------------------------------------------------------------------
  1496. // Clamps pV to lie inside m_vMinBoundary & m_vMaxBoundary
  1497. //--------------------------------------------------------------------------------------
  1498. void CBaseCamera::ConstrainToBoundary( D3DXVECTOR3* pV )
  1499. {
  1500.     // Constrain vector to a bounding box 
  1501.     pV->x = max(pV->x, m_vMinBoundary.x);
  1502.     pV->y = max(pV->y, m_vMinBoundary.y);
  1503.     pV->z = max(pV->z, m_vMinBoundary.z);
  1504.  
  1505.     pV->x = min(pV->x, m_vMaxBoundary.x);
  1506.     pV->y = min(pV->y, m_vMaxBoundary.y);
  1507.     pV->z = min(pV->z, m_vMaxBoundary.z);
  1508. }
  1509.  
  1510.  
  1511.  
  1512.  
  1513. //--------------------------------------------------------------------------------------
  1514. // Maps a windows virtual key to an enum
  1515. //--------------------------------------------------------------------------------------
  1516. D3DUtil_CameraKeys CBaseCamera::MapKey( UINT nKey )
  1517. {
  1518.     // This could be upgraded to a method that's user-definable but for 
  1519.     // simplicity, we'll use a hardcoded mapping.
  1520.     switch( nKey )
  1521.     {
  1522.         case VK_CONTROL:  return CAM_CONTROLDOWN;
  1523.         case VK_LEFT:  return CAM_STRAFE_LEFT;
  1524.         case VK_RIGHT: return CAM_STRAFE_RIGHT;
  1525.         case VK_UP:    return CAM_MOVE_FORWARD;
  1526.         case VK_DOWN:  return CAM_MOVE_BACKWARD;
  1527.         case VK_PRIOR: return CAM_MOVE_UP;        // pgup
  1528.         case VK_NEXT:  return CAM_MOVE_DOWN;      // pgdn
  1529.  
  1530.         case 'A':      return CAM_STRAFE_LEFT;
  1531.         case 'D':      return CAM_STRAFE_RIGHT;
  1532.         case 'W':      return CAM_MOVE_FORWARD;
  1533.         case 'S':      return CAM_MOVE_BACKWARD;
  1534.         case 'Q':      return CAM_MOVE_DOWN;
  1535.         case 'E':      return CAM_MOVE_UP;
  1536.  
  1537.         case VK_NUMPAD4: return CAM_STRAFE_LEFT;
  1538.         case VK_NUMPAD6: return CAM_STRAFE_RIGHT;
  1539.         case VK_NUMPAD8: return CAM_MOVE_FORWARD;
  1540.         case VK_NUMPAD2: return CAM_MOVE_BACKWARD;
  1541.         case VK_NUMPAD9: return CAM_MOVE_UP;        
  1542.         case VK_NUMPAD3: return CAM_MOVE_DOWN;      
  1543.  
  1544.         case VK_HOME:   return CAM_RESET;
  1545.     }
  1546.  
  1547.     return CAM_UNKNOWN;
  1548. }
  1549.  
  1550.  
  1551.  
  1552.  
  1553. //--------------------------------------------------------------------------------------
  1554. // Reset the camera's position back to the default
  1555. //--------------------------------------------------------------------------------------
  1556. VOID CBaseCamera::Reset()
  1557. {
  1558.     SetViewParams( &m_vDefaultEye, &m_vDefaultLookAt );
  1559. }
  1560.  
  1561.  
  1562.  
  1563.  
  1564. //--------------------------------------------------------------------------------------
  1565. // Constructor
  1566. //--------------------------------------------------------------------------------------
  1567. CFirstPersonCamera::CFirstPersonCamera() :
  1568.     m_nActiveButtonMask( 0x07 )
  1569. {
  1570. }
  1571.  
  1572.  
  1573.  
  1574.  
  1575. //--------------------------------------------------------------------------------------
  1576. // Update the view matrix based on user input & elapsed time
  1577. //--------------------------------------------------------------------------------------
  1578. VOID CFirstPersonCamera::FrameMove( FLOAT fElapsedTime )
  1579. {
  1580.     if( DXUTGetGlobalTimer()->IsStopped() )
  1581.         fElapsedTime = 1.0f / DXUTGetFPS();
  1582.  
  1583.     if( IsKeyDown(m_aKeys[CAM_RESET]) )
  1584.         Reset();
  1585.  
  1586.     // Get the mouse movement (if any) if the mouse button are down
  1587.     if( m_nActiveButtonMask & m_nCurrentButtonMask )
  1588.         UpdateMouseDelta( fElapsedTime );
  1589.  
  1590.     // Get amount of velocity based on the keyboard input and drag (if any)
  1591.     UpdateVelocity( fElapsedTime );
  1592.  
  1593.     // Simple euler method to calculate position delta
  1594.     D3DXVECTOR3 vPosDelta = m_vVelocity * fElapsedTime;
  1595.  
  1596.     // If rotating the camera 
  1597.     if( m_nActiveButtonMask & m_nCurrentButtonMask )
  1598.     {
  1599.         // Update the pitch & yaw angle based on mouse movement
  1600.         float fYawDelta   = m_vRotVelocity.x;
  1601.         float fPitchDelta = m_vRotVelocity.y;
  1602.  
  1603.         // Invert pitch if requested
  1604.         if( m_bInvertPitch )
  1605.             fPitchDelta = -fPitchDelta;
  1606.  
  1607.         m_fCameraPitchAngle += fPitchDelta;
  1608.         m_fCameraYawAngle   += fYawDelta;
  1609.  
  1610.         // Limit pitch to straight up or straight down
  1611.         m_fCameraPitchAngle = max( -D3DX_PI/2.0f,  m_fCameraPitchAngle );
  1612.         m_fCameraPitchAngle = min( +D3DX_PI/2.0f,  m_fCameraPitchAngle );
  1613.     }
  1614.  
  1615.     // Make a rotation matrix based on the camera's yaw & pitch
  1616.     D3DXMATRIX mCameraRot;
  1617.     D3DXMatrixRotationYawPitchRoll( &mCameraRot, m_fCameraYawAngle, m_fCameraPitchAngle, 0 );
  1618.  
  1619.     // Transform vectors based on camera's rotation matrix
  1620.     D3DXVECTOR3 vWorldUp, vWorldAhead;
  1621.     D3DXVECTOR3 vLocalUp    = D3DXVECTOR3(0,1,0);
  1622.     D3DXVECTOR3 vLocalAhead = D3DXVECTOR3(0,0,1);
  1623.     D3DXVec3TransformCoord( &vWorldUp, &vLocalUp, &mCameraRot );
  1624.     D3DXVec3TransformCoord( &vWorldAhead, &vLocalAhead, &mCameraRot );
  1625.  
  1626.     // Transform the position delta by the camera's rotation 
  1627.     D3DXVECTOR3 vPosDeltaWorld;
  1628.     if( !m_bEnableYAxisMovement )
  1629.     {
  1630.         // If restricting Y movement, do not include pitch
  1631.         // when transforming position delta vector.
  1632.         D3DXMatrixRotationYawPitchRoll( &mCameraRot, m_fCameraYawAngle, 0.0f, 0.0f );
  1633.     }
  1634.     D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot );
  1635.  
  1636.     // Move the eye position 
  1637.     m_vEye += vPosDeltaWorld;
  1638.     if( m_bClipToBoundary )
  1639.         ConstrainToBoundary( &m_vEye );
  1640.  
  1641.     // Update the lookAt position based on the eye position 
  1642.     m_vLookAt = m_vEye + vWorldAhead;
  1643.  
  1644.     // Update the view matrix
  1645.     D3DXMatrixLookAtLH( &m_mView, &m_vEye, &m_vLookAt, &vWorldUp );
  1646.  
  1647.     D3DXMatrixInverse( &m_mCameraWorld, NULL, &m_mView );
  1648. }
  1649.  
  1650.  
  1651. //--------------------------------------------------------------------------------------
  1652. // Enable or disable each of the mouse buttons for rotation drag.
  1653. //--------------------------------------------------------------------------------------
  1654. void CFirstPersonCamera::SetRotateButtons( bool bLeft, bool bMiddle, bool bRight )
  1655. {
  1656.     m_nActiveButtonMask = ( bLeft ? MOUSE_LEFT_BUTTON : 0 ) |
  1657.                           ( bMiddle ? MOUSE_MIDDLE_BUTTON : 0 ) |
  1658.                           ( bRight ? MOUSE_RIGHT_BUTTON : 0 );
  1659. }
  1660.  
  1661.  
  1662. //--------------------------------------------------------------------------------------
  1663. // Constructor 
  1664. //--------------------------------------------------------------------------------------
  1665. CModelViewerCamera::CModelViewerCamera()
  1666. {
  1667.     D3DXMatrixIdentity( &m_mWorld );
  1668.     D3DXMatrixIdentity( &m_mModelRot );
  1669.     D3DXMatrixIdentity( &m_mModelLastRot );    
  1670.     D3DXMatrixIdentity( &m_mCameraRotLast );    
  1671.     m_vModelCenter = D3DXVECTOR3(0,0,0);
  1672.     m_fRadius    = 5.0f;
  1673.     m_fDefaultRadius = 5.0f;
  1674.     m_fMinRadius = 1.0f;
  1675.     m_fMaxRadius = FLT_MAX;
  1676.     m_bLimitPitch = false;
  1677.     m_bEnablePositionMovement = false;
  1678.     m_bAttachCameraToModel = false;
  1679.  
  1680.     m_nRotateModelButtonMask  = MOUSE_LEFT_BUTTON;
  1681.     m_nZoomButtonMask         = MOUSE_WHEEL;
  1682.     m_nRotateCameraButtonMask = MOUSE_RIGHT_BUTTON;
  1683. }
  1684.  
  1685.  
  1686.  
  1687.  
  1688. //--------------------------------------------------------------------------------------
  1689. // Update the view matrix & the model's world matrix based 
  1690. //       on user input & elapsed time
  1691. //--------------------------------------------------------------------------------------
  1692. VOID CModelViewerCamera::FrameMove( FLOAT fElapsedTime )
  1693. {
  1694.     if( IsKeyDown(m_aKeys[CAM_RESET]) )
  1695.         Reset();
  1696.  
  1697.     // Get the mouse movement (if any) if the mouse button are down
  1698.     if( m_nCurrentButtonMask != 0 ) 
  1699.         UpdateMouseDelta( fElapsedTime );
  1700.  
  1701.     // Get amount of velocity based on the keyboard input and drag (if any)
  1702.     UpdateVelocity( fElapsedTime );
  1703.  
  1704.     // Simple euler method to calculate position delta
  1705.     D3DXVECTOR3 vPosDelta = m_vVelocity * fElapsedTime;
  1706.  
  1707.     // Change the radius from the camera to the model based on wheel scrolling
  1708.     if( m_nMouseWheelDelta && m_nZoomButtonMask == MOUSE_WHEEL )
  1709.         m_fRadius -= m_nMouseWheelDelta * m_fRadius * 0.1f;
  1710.     m_fRadius = min( m_fMaxRadius, m_fRadius );
  1711.     m_fRadius = max( m_fMinRadius, m_fRadius );
  1712.     m_nMouseWheelDelta = 0;
  1713.  
  1714.     // Get the inverse of the arcball's rotation matrix
  1715.     D3DXMATRIX mCameraRot;
  1716.     D3DXMatrixInverse( &mCameraRot, NULL, m_ViewArcBall.GetRotationMatrix() );
  1717.  
  1718.     // Transform vectors based on camera's rotation matrix
  1719.     D3DXVECTOR3 vWorldUp, vWorldAhead;
  1720.     D3DXVECTOR3 vLocalUp    = D3DXVECTOR3(0,1,0);
  1721.     D3DXVECTOR3 vLocalAhead = D3DXVECTOR3(0,0,1);
  1722.     D3DXVec3TransformCoord( &vWorldUp, &vLocalUp, &mCameraRot );
  1723.     D3DXVec3TransformCoord( &vWorldAhead, &vLocalAhead, &mCameraRot );
  1724.  
  1725.     // Transform the position delta by the camera's rotation 
  1726.     D3DXVECTOR3 vPosDeltaWorld;
  1727.     D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot );
  1728.  
  1729.     // Move the lookAt position 
  1730.     m_vLookAt += vPosDeltaWorld;
  1731.     if( m_bClipToBoundary )
  1732.         ConstrainToBoundary( &m_vLookAt );
  1733.  
  1734.     // Update the eye point based on a radius away from the lookAt position
  1735.     m_vEye = m_vLookAt - vWorldAhead * m_fRadius;
  1736.  
  1737.     // Update the view matrix
  1738.     D3DXMatrixLookAtLH( &m_mView, &m_vEye, &m_vLookAt, &vWorldUp );
  1739.  
  1740.     D3DXMATRIX mInvView;
  1741.     D3DXMatrixInverse( &mInvView, NULL, &m_mView );
  1742.     mInvView._41 = mInvView._42 = mInvView._43 = 0;
  1743.  
  1744.     D3DXMATRIX mModelLastRotInv;
  1745.     D3DXMatrixInverse(&mModelLastRotInv, NULL, &m_mModelLastRot);
  1746.  
  1747.     // Accumulate the delta of the arcball's rotation in view space.
  1748.     // Note that per-frame delta rotations could be problematic over long periods of time.
  1749.     D3DXMATRIX mModelRot;
  1750.     mModelRot = *m_WorldArcBall.GetRotationMatrix();
  1751.     m_mModelRot *= m_mView * mModelLastRotInv * mModelRot * mInvView;
  1752.  
  1753.     if( m_ViewArcBall.IsBeingDragged() && m_bAttachCameraToModel && !IsKeyDown(m_aKeys[CAM_CONTROLDOWN]) )
  1754.     {
  1755.         // Attach camera to model by inverse of the model rotation
  1756.         D3DXMATRIX mCameraLastRotInv;
  1757.         D3DXMatrixInverse(&mCameraLastRotInv, NULL, &m_mCameraRotLast);
  1758.         D3DXMATRIX mCameraRotDelta = mCameraLastRotInv * mCameraRot; // local to world matrix
  1759.         m_mModelRot *= mCameraRotDelta;
  1760.     }
  1761.     m_mCameraRotLast = mCameraRot; 
  1762.  
  1763.     m_mModelLastRot = mModelRot;
  1764.  
  1765.     // Since we're accumulating delta rotations, we need to orthonormalize 
  1766.     // the matrix to prevent eventual matrix skew
  1767.     D3DXVECTOR3* pXBasis = (D3DXVECTOR3*) &m_mModelRot._11;
  1768.     D3DXVECTOR3* pYBasis = (D3DXVECTOR3*) &m_mModelRot._21;
  1769.     D3DXVECTOR3* pZBasis = (D3DXVECTOR3*) &m_mModelRot._31;
  1770.     D3DXVec3Normalize( pXBasis, pXBasis );
  1771.     D3DXVec3Cross( pYBasis, pZBasis, pXBasis );
  1772.     D3DXVec3Normalize( pYBasis, pYBasis );
  1773.     D3DXVec3Cross( pZBasis, pXBasis, pYBasis );
  1774.  
  1775.     // Translate the rotation matrix to the same position as the lookAt position
  1776.     m_mModelRot._41 = m_vLookAt.x;
  1777.     m_mModelRot._42 = m_vLookAt.y;
  1778.     m_mModelRot._43 = m_vLookAt.z;
  1779.  
  1780.     // Translate world matrix so its at the center of the model
  1781.     D3DXMATRIX mTrans;
  1782.     D3DXMatrixTranslation( &mTrans, -m_vModelCenter.x, -m_vModelCenter.y, -m_vModelCenter.z );
  1783.     m_mWorld = mTrans * m_mModelRot;
  1784. }
  1785.  
  1786.  
  1787. void CModelViewerCamera::SetDragRect( RECT &rc )
  1788. {
  1789.     CBaseCamera::SetDragRect( rc );
  1790.  
  1791.     m_WorldArcBall.SetOffset( rc.left, rc.top );
  1792.     m_ViewArcBall.SetOffset( rc.left, rc.top );
  1793.     SetWindow( rc.right - rc.left, rc.bottom - rc.top );
  1794. }
  1795.  
  1796.  
  1797. //--------------------------------------------------------------------------------------
  1798. // Reset the camera's position back to the default
  1799. //--------------------------------------------------------------------------------------
  1800. VOID CModelViewerCamera::Reset()
  1801. {
  1802.     CBaseCamera::Reset();
  1803.  
  1804.     D3DXMatrixIdentity( &m_mWorld );
  1805.     D3DXMatrixIdentity( &m_mModelRot );
  1806.     D3DXMatrixIdentity( &m_mModelLastRot );    
  1807.     D3DXMatrixIdentity( &m_mCameraRotLast );    
  1808.  
  1809.     m_fRadius = m_fDefaultRadius;
  1810.     m_WorldArcBall.Reset();
  1811.     m_ViewArcBall.Reset();
  1812. }
  1813.  
  1814.  
  1815. //--------------------------------------------------------------------------------------
  1816. // Override for setting the view parameters
  1817. //--------------------------------------------------------------------------------------
  1818. void CModelViewerCamera::SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt )
  1819. {
  1820.     CBaseCamera::SetViewParams( pvEyePt, pvLookatPt );
  1821.  
  1822.     // Propogate changes to the member arcball
  1823.     D3DXQUATERNION quat;
  1824.     D3DXMATRIXA16 mRotation;
  1825.     D3DXVECTOR3 vUp(0,1,0);
  1826.     D3DXMatrixLookAtLH( &mRotation, pvEyePt, pvLookatPt, &vUp );
  1827.     D3DXQuaternionRotationMatrix( &quat, &mRotation );
  1828.     m_ViewArcBall.SetQuatNow( quat );
  1829.  
  1830.     // Set the radius according to the distance
  1831.     D3DXVECTOR3 vEyeToPoint;
  1832.     D3DXVec3Subtract( &vEyeToPoint, pvLookatPt, pvEyePt );
  1833.     SetRadius( D3DXVec3Length( &vEyeToPoint ) );
  1834. }
  1835.  
  1836.  
  1837.  
  1838. //--------------------------------------------------------------------------------------
  1839. // Call this from your message proc so this class can handle window messages
  1840. //--------------------------------------------------------------------------------------
  1841. LRESULT CModelViewerCamera::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1842. {
  1843.     CBaseCamera::HandleMessages( hWnd, uMsg, wParam, lParam );
  1844.  
  1845.     if( ( (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON) ||
  1846.         ( (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON) ||
  1847.         ( (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON) )
  1848.     {
  1849.         int iMouseX = (short)LOWORD(lParam);
  1850.         int iMouseY = (short)HIWORD(lParam);
  1851.         m_WorldArcBall.OnBegin( iMouseX, iMouseY );
  1852.     }
  1853.  
  1854.     if( ( (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON) ||
  1855.         ( (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON) ||
  1856.         ( (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON) )
  1857.     {
  1858.         int iMouseX = (short)LOWORD(lParam);
  1859.         int iMouseY = (short)HIWORD(lParam);
  1860.         m_ViewArcBall.OnBegin( iMouseX, iMouseY );
  1861.     }
  1862.  
  1863.     if( uMsg == WM_MOUSEMOVE )
  1864.     {
  1865.         int iMouseX = (short)LOWORD(lParam);
  1866.         int iMouseY = (short)HIWORD(lParam);
  1867.         m_WorldArcBall.OnMove( iMouseX, iMouseY );
  1868.         m_ViewArcBall.OnMove( iMouseX, iMouseY );
  1869.     }
  1870.  
  1871.     if( (uMsg == WM_LBUTTONUP && m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON) ||
  1872.         (uMsg == WM_MBUTTONUP && m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON) ||
  1873.         (uMsg == WM_RBUTTONUP && m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON) )
  1874.     {
  1875.         m_WorldArcBall.OnEnd();
  1876.     }
  1877.  
  1878.     if( (uMsg == WM_LBUTTONUP && m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON) ||
  1879.         (uMsg == WM_MBUTTONUP && m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON) ||
  1880.         (uMsg == WM_RBUTTONUP && m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON) )
  1881.     {
  1882.         m_ViewArcBall.OnEnd();
  1883.     }
  1884.  
  1885.     return FALSE;
  1886. }
  1887.  
  1888.  
  1889.  
  1890.  
  1891. //--------------------------------------------------------------------------------------
  1892. // Gives the D3D device a cursor with image and hotspot from hCursor.
  1893. //--------------------------------------------------------------------------------------
  1894. HRESULT DXUTSetDeviceCursor( IDirect3DDevice9* pd3dDevice, HCURSOR hCursor, bool bAddWatermark )
  1895. {
  1896.     HRESULT hr = E_FAIL;
  1897.     ICONINFO iconinfo;
  1898.     bool bBWCursor;
  1899.     LPDIRECT3DSURFACE9 pCursorSurface = NULL;
  1900.     HDC hdcColor = NULL;
  1901.     HDC hdcMask = NULL;
  1902.     HDC hdcScreen = NULL;
  1903.     BITMAP bm;
  1904.     DWORD dwWidth;
  1905.     DWORD dwHeightSrc;
  1906.     DWORD dwHeightDest;
  1907.     COLORREF crColor;
  1908.     COLORREF crMask;
  1909.     UINT x;
  1910.     UINT y;
  1911.     BITMAPINFO bmi;
  1912.     COLORREF* pcrArrayColor = NULL;
  1913.     COLORREF* pcrArrayMask = NULL;
  1914.     DWORD* pBitmap;
  1915.     HGDIOBJ hgdiobjOld;
  1916.  
  1917.     ZeroMemory( &iconinfo, sizeof(iconinfo) );
  1918.     if( !GetIconInfo( hCursor, &iconinfo ) )
  1919.         goto End;
  1920.  
  1921.     if (0 == GetObject((HGDIOBJ)iconinfo.hbmMask, sizeof(BITMAP), (LPVOID)&bm))
  1922.         goto End;
  1923.     dwWidth = bm.bmWidth;
  1924.     dwHeightSrc = bm.bmHeight;
  1925.  
  1926.     if( iconinfo.hbmColor == NULL )
  1927.     {
  1928.         bBWCursor = TRUE;
  1929.         dwHeightDest = dwHeightSrc / 2;
  1930.     }
  1931.     else 
  1932.     {
  1933.         bBWCursor = FALSE;
  1934.         dwHeightDest = dwHeightSrc;
  1935.     }
  1936.  
  1937.     // Create a surface for the fullscreen cursor
  1938.     if( FAILED( hr = pd3dDevice->CreateOffscreenPlainSurface( dwWidth, dwHeightDest, 
  1939.         D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pCursorSurface, NULL ) ) )
  1940.     {
  1941.         goto End;
  1942.     }
  1943.  
  1944.     pcrArrayMask = new DWORD[dwWidth * dwHeightSrc];
  1945.  
  1946.     ZeroMemory(&bmi, sizeof(bmi));
  1947.     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
  1948.     bmi.bmiHeader.biWidth = dwWidth;
  1949.     bmi.bmiHeader.biHeight = dwHeightSrc;
  1950.     bmi.bmiHeader.biPlanes = 1;
  1951.     bmi.bmiHeader.biBitCount = 32;
  1952.     bmi.bmiHeader.biCompression = BI_RGB;
  1953.  
  1954.     hdcScreen = GetDC( NULL );
  1955.     hdcMask = CreateCompatibleDC( hdcScreen );
  1956.     if( hdcMask == NULL )
  1957.     {
  1958.         hr = E_FAIL;
  1959.         goto End;
  1960.     }
  1961.     hgdiobjOld = SelectObject(hdcMask, iconinfo.hbmMask);
  1962.     GetDIBits(hdcMask, iconinfo.hbmMask, 0, dwHeightSrc, 
  1963.         pcrArrayMask, &bmi, DIB_RGB_COLORS);
  1964.     SelectObject(hdcMask, hgdiobjOld);
  1965.  
  1966.     if (!bBWCursor)
  1967.     {
  1968.         pcrArrayColor = new DWORD[dwWidth * dwHeightDest];
  1969.         hdcColor = CreateCompatibleDC( hdcScreen );
  1970.         if( hdcColor == NULL )
  1971.         {
  1972.             hr = E_FAIL;
  1973.             goto End;
  1974.         }
  1975.         SelectObject(hdcColor, iconinfo.hbmColor);
  1976.         GetDIBits(hdcColor, iconinfo.hbmColor, 0, dwHeightDest, 
  1977.             pcrArrayColor, &bmi, DIB_RGB_COLORS);
  1978.     }
  1979.  
  1980.     // Transfer cursor image into the surface
  1981.     D3DLOCKED_RECT lr;
  1982.     pCursorSurface->LockRect( &lr, NULL, 0 );
  1983.     pBitmap = (DWORD*)lr.pBits;
  1984.     for( y = 0; y < dwHeightDest; y++ )
  1985.     {
  1986.         for( x = 0; x < dwWidth; x++ )
  1987.         {
  1988.             if (bBWCursor)
  1989.             {
  1990.                 crColor = pcrArrayMask[dwWidth*(dwHeightDest-1-y) + x];
  1991.                 crMask = pcrArrayMask[dwWidth*(dwHeightSrc-1-y) + x];
  1992.             }
  1993.             else
  1994.             {
  1995.                 crColor = pcrArrayColor[dwWidth*(dwHeightDest-1-y) + x];
  1996.                 crMask = pcrArrayMask[dwWidth*(dwHeightDest-1-y) + x];
  1997.             }
  1998.             if (crMask == 0)
  1999.                 pBitmap[dwWidth*y + x] = 0xff000000 | crColor;
  2000.             else
  2001.                 pBitmap[dwWidth*y + x] = 0x00000000;
  2002.  
  2003.             // It may be helpful to make the D3D cursor look slightly 
  2004.             // different from the Windows cursor so you can distinguish 
  2005.             // between the two when developing/testing code.  When
  2006.             // bAddWatermark is TRUE, the following code adds some
  2007.             // small grey "D3D" characters to the upper-left corner of
  2008.             // the D3D cursor image.
  2009.             if( bAddWatermark && x < 12 && y < 5 )
  2010.             {
  2011.                 // 11.. 11.. 11.. .... CCC0
  2012.                 // 1.1. ..1. 1.1. .... A2A0
  2013.                 // 1.1. .1.. 1.1. .... A4A0
  2014.                 // 1.1. ..1. 1.1. .... A2A0
  2015.                 // 11.. 11.. 11.. .... CCC0
  2016.  
  2017.                 const WORD wMask[5] = { 0xccc0, 0xa2a0, 0xa4a0, 0xa2a0, 0xccc0 };
  2018.                 if( wMask[y] & (1 << (15 - x)) )
  2019.                 {
  2020.                     pBitmap[dwWidth*y + x] |= 0xff808080;
  2021.                 }
  2022.             }
  2023.         }
  2024.     }
  2025.     pCursorSurface->UnlockRect();
  2026.  
  2027.     // Set the device cursor
  2028.     if( FAILED( hr = pd3dDevice->SetCursorProperties( iconinfo.xHotspot, 
  2029.         iconinfo.yHotspot, pCursorSurface ) ) )
  2030.     {
  2031.         goto End;
  2032.     }
  2033.  
  2034.     hr = S_OK;
  2035.  
  2036. End:
  2037.     if( iconinfo.hbmMask != NULL )
  2038.         DeleteObject( iconinfo.hbmMask );
  2039.     if( iconinfo.hbmColor != NULL )
  2040.         DeleteObject( iconinfo.hbmColor );
  2041.     if( hdcScreen != NULL )
  2042.         ReleaseDC( NULL, hdcScreen );
  2043.     if( hdcColor != NULL )
  2044.         DeleteDC( hdcColor );
  2045.     if( hdcMask != NULL )
  2046.         DeleteDC( hdcMask );
  2047.     SAFE_DELETE_ARRAY( pcrArrayColor );
  2048.     SAFE_DELETE_ARRAY( pcrArrayMask );
  2049.     SAFE_RELEASE( pCursorSurface );
  2050.     return hr;
  2051. }
  2052.  
  2053.  
  2054. //--------------------------------------------------------------------------------------
  2055. // Desc: Returns a view matrix for rendering to a face of a cubemap.
  2056. //--------------------------------------------------------------------------------------
  2057. D3DXMATRIX DXUTGetCubeMapViewMatrix( DWORD dwFace )
  2058. {
  2059.     D3DXVECTOR3 vEyePt   = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  2060.     D3DXVECTOR3 vLookDir;
  2061.     D3DXVECTOR3 vUpDir;
  2062.  
  2063.     switch( dwFace )
  2064.     {
  2065.         case D3DCUBEMAP_FACE_POSITIVE_X:
  2066.             vLookDir = D3DXVECTOR3( 1.0f, 0.0f, 0.0f );
  2067.             vUpDir   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  2068.             break;
  2069.         case D3DCUBEMAP_FACE_NEGATIVE_X:
  2070.             vLookDir = D3DXVECTOR3(-1.0f, 0.0f, 0.0f );
  2071.             vUpDir   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  2072.             break;
  2073.         case D3DCUBEMAP_FACE_POSITIVE_Y:
  2074.             vLookDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  2075.             vUpDir   = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
  2076.             break;
  2077.         case D3DCUBEMAP_FACE_NEGATIVE_Y:
  2078.             vLookDir = D3DXVECTOR3( 0.0f,-1.0f, 0.0f );
  2079.             vUpDir   = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
  2080.             break;
  2081.         case D3DCUBEMAP_FACE_POSITIVE_Z:
  2082.             vLookDir = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
  2083.             vUpDir   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  2084.             break;
  2085.         case D3DCUBEMAP_FACE_NEGATIVE_Z:
  2086.             vLookDir = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
  2087.             vUpDir   = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
  2088.             break;
  2089.     }
  2090.  
  2091.     // Set the view transform for this cubemap surface
  2092.     D3DXMATRIXA16 mView;
  2093.     D3DXMatrixLookAtLH( &mView, &vEyePt, &vLookDir, &vUpDir );
  2094.     return mView;
  2095. }
  2096.  
  2097.  
  2098. //--------------------------------------------------------------------------------------
  2099. // Returns the string for the given D3DFORMAT.
  2100. //--------------------------------------------------------------------------------------
  2101. LPCWSTR DXUTD3DFormatToString( D3DFORMAT format, bool bWithPrefix )
  2102. {
  2103.     WCHAR* pstr = NULL;
  2104.     switch( format )
  2105.     {
  2106.     case D3DFMT_UNKNOWN:         pstr = L"D3DFMT_UNKNOWN"; break;
  2107.     case D3DFMT_R8G8B8:          pstr = L"D3DFMT_R8G8B8"; break;
  2108.     case D3DFMT_A8R8G8B8:        pstr = L"D3DFMT_A8R8G8B8"; break;
  2109.     case D3DFMT_X8R8G8B8:        pstr = L"D3DFMT_X8R8G8B8"; break;
  2110.     case D3DFMT_R5G6B5:          pstr = L"D3DFMT_R5G6B5"; break;
  2111.     case D3DFMT_X1R5G5B5:        pstr = L"D3DFMT_X1R5G5B5"; break;
  2112.     case D3DFMT_A1R5G5B5:        pstr = L"D3DFMT_A1R5G5B5"; break;
  2113.     case D3DFMT_A4R4G4B4:        pstr = L"D3DFMT_A4R4G4B4"; break;
  2114.     case D3DFMT_R3G3B2:          pstr = L"D3DFMT_R3G3B2"; break;
  2115.     case D3DFMT_A8:              pstr = L"D3DFMT_A8"; break;
  2116.     case D3DFMT_A8R3G3B2:        pstr = L"D3DFMT_A8R3G3B2"; break;
  2117.     case D3DFMT_X4R4G4B4:        pstr = L"D3DFMT_X4R4G4B4"; break;
  2118.     case D3DFMT_A2B10G10R10:     pstr = L"D3DFMT_A2B10G10R10"; break;
  2119.     case D3DFMT_A8B8G8R8:        pstr = L"D3DFMT_A8B8G8R8"; break;
  2120.     case D3DFMT_X8B8G8R8:        pstr = L"D3DFMT_X8B8G8R8"; break;
  2121.     case D3DFMT_G16R16:          pstr = L"D3DFMT_G16R16"; break;
  2122.     case D3DFMT_A2R10G10B10:     pstr = L"D3DFMT_A2R10G10B10"; break;
  2123.     case D3DFMT_A16B16G16R16:    pstr = L"D3DFMT_A16B16G16R16"; break;
  2124.     case D3DFMT_A8P8:            pstr = L"D3DFMT_A8P8"; break;
  2125.     case D3DFMT_P8:              pstr = L"D3DFMT_P8"; break;
  2126.     case D3DFMT_L8:              pstr = L"D3DFMT_L8"; break;
  2127.     case D3DFMT_A8L8:            pstr = L"D3DFMT_A8L8"; break;
  2128.     case D3DFMT_A4L4:            pstr = L"D3DFMT_A4L4"; break;
  2129.     case D3DFMT_V8U8:            pstr = L"D3DFMT_V8U8"; break;
  2130.     case D3DFMT_L6V5U5:          pstr = L"D3DFMT_L6V5U5"; break;
  2131.     case D3DFMT_X8L8V8U8:        pstr = L"D3DFMT_X8L8V8U8"; break;
  2132.     case D3DFMT_Q8W8V8U8:        pstr = L"D3DFMT_Q8W8V8U8"; break;
  2133.     case D3DFMT_V16U16:          pstr = L"D3DFMT_V16U16"; break;
  2134.     case D3DFMT_A2W10V10U10:     pstr = L"D3DFMT_A2W10V10U10"; break;
  2135.     case D3DFMT_UYVY:            pstr = L"D3DFMT_UYVY"; break;
  2136.     case D3DFMT_YUY2:            pstr = L"D3DFMT_YUY2"; break;
  2137.     case D3DFMT_DXT1:            pstr = L"D3DFMT_DXT1"; break;
  2138.     case D3DFMT_DXT2:            pstr = L"D3DFMT_DXT2"; break;
  2139.     case D3DFMT_DXT3:            pstr = L"D3DFMT_DXT3"; break;
  2140.     case D3DFMT_DXT4:            pstr = L"D3DFMT_DXT4"; break;
  2141.     case D3DFMT_DXT5:            pstr = L"D3DFMT_DXT5"; break;
  2142.     case D3DFMT_D16_LOCKABLE:    pstr = L"D3DFMT_D16_LOCKABLE"; break;
  2143.     case D3DFMT_D32:             pstr = L"D3DFMT_D32"; break;
  2144.     case D3DFMT_D15S1:           pstr = L"D3DFMT_D15S1"; break;
  2145.     case D3DFMT_D24S8:           pstr = L"D3DFMT_D24S8"; break;
  2146.     case D3DFMT_D24X8:           pstr = L"D3DFMT_D24X8"; break;
  2147.     case D3DFMT_D24X4S4:         pstr = L"D3DFMT_D24X4S4"; break;
  2148.     case D3DFMT_D16:             pstr = L"D3DFMT_D16"; break;
  2149.     case D3DFMT_L16:             pstr = L"D3DFMT_L16"; break;
  2150.     case D3DFMT_VERTEXDATA:      pstr = L"D3DFMT_VERTEXDATA"; break;
  2151.     case D3DFMT_INDEX16:         pstr = L"D3DFMT_INDEX16"; break;
  2152.     case D3DFMT_INDEX32:         pstr = L"D3DFMT_INDEX32"; break;
  2153.     case D3DFMT_Q16W16V16U16:    pstr = L"D3DFMT_Q16W16V16U16"; break;
  2154.     case D3DFMT_MULTI2_ARGB8:    pstr = L"D3DFMT_MULTI2_ARGB8"; break;
  2155.     case D3DFMT_R16F:            pstr = L"D3DFMT_R16F"; break;
  2156.     case D3DFMT_G16R16F:         pstr = L"D3DFMT_G16R16F"; break;
  2157.     case D3DFMT_A16B16G16R16F:   pstr = L"D3DFMT_A16B16G16R16F"; break;
  2158.     case D3DFMT_R32F:            pstr = L"D3DFMT_R32F"; break;
  2159.     case D3DFMT_G32R32F:         pstr = L"D3DFMT_G32R32F"; break;
  2160.     case D3DFMT_A32B32G32R32F:   pstr = L"D3DFMT_A32B32G32R32F"; break;
  2161.     case D3DFMT_CxV8U8:          pstr = L"D3DFMT_CxV8U8"; break;
  2162.     default:                     pstr = L"Unknown format"; break;
  2163.     }
  2164.     if( bWithPrefix || wcsstr( pstr, L"D3DFMT_" )== NULL )
  2165.         return pstr;
  2166.     else
  2167.         return pstr + lstrlen( L"D3DFMT_" );
  2168. }
  2169.  
  2170.  
  2171.  
  2172. //--------------------------------------------------------------------------------------
  2173. // Outputs to the debug stream a formatted Unicode string with a variable-argument list.
  2174. //--------------------------------------------------------------------------------------
  2175. VOID DXUTOutputDebugStringW( LPCWSTR strMsg, ... )
  2176. {
  2177. #if defined(DEBUG) | defined(_DEBUG)
  2178.     WCHAR strBuffer[512];
  2179.     
  2180.     va_list args;
  2181.     va_start(args, strMsg);
  2182.     _vsnwprintf( strBuffer, 512, strMsg, args );
  2183.     strBuffer[511] = L'\0';
  2184.     va_end(args);
  2185.  
  2186.     OutputDebugString( strBuffer );
  2187. #else
  2188.     UNREFERENCED_PARAMETER(strMsg);
  2189. #endif
  2190. }
  2191.  
  2192.  
  2193. //--------------------------------------------------------------------------------------
  2194. // Outputs to the debug stream a formatted MBCS string with a variable-argument list.
  2195. //--------------------------------------------------------------------------------------
  2196. VOID DXUTOutputDebugStringA( LPCSTR strMsg, ... )
  2197. {
  2198. #if defined(DEBUG) | defined(_DEBUG)
  2199.     CHAR strBuffer[512];
  2200.     
  2201.     va_list args;
  2202.     va_start(args, strMsg);
  2203.     _vsnprintf( strBuffer, 512, strMsg, args );
  2204.     strBuffer[511] = '\0';
  2205.     va_end(args);
  2206.  
  2207.     OutputDebugStringA( strBuffer );
  2208. #else
  2209.     UNREFERENCED_PARAMETER(strMsg);
  2210. #endif
  2211. }
  2212.  
  2213.  
  2214. //--------------------------------------------------------------------------------------
  2215. CDXUTLineManager::CDXUTLineManager()
  2216. {
  2217.     m_pd3dDevice = NULL;
  2218.     m_pD3DXLine = NULL;
  2219. }
  2220.  
  2221.  
  2222. //--------------------------------------------------------------------------------------
  2223. CDXUTLineManager::~CDXUTLineManager()
  2224. {
  2225.     OnDeletedDevice();
  2226. }
  2227.  
  2228.  
  2229. //--------------------------------------------------------------------------------------
  2230. HRESULT CDXUTLineManager::OnCreatedDevice( IDirect3DDevice9* pd3dDevice )
  2231. {
  2232.     m_pd3dDevice = pd3dDevice;
  2233.  
  2234.     HRESULT hr;
  2235.     hr = D3DXCreateLine( m_pd3dDevice, &m_pD3DXLine );
  2236.     if( FAILED(hr) )
  2237.         return hr;
  2238.  
  2239.     return S_OK;
  2240. }
  2241.  
  2242.  
  2243. //--------------------------------------------------------------------------------------
  2244. HRESULT CDXUTLineManager::OnResetDevice()
  2245. {
  2246.     if( m_pD3DXLine )
  2247.         m_pD3DXLine->OnResetDevice();
  2248.  
  2249.     return S_OK;
  2250. }
  2251.  
  2252.  
  2253. //--------------------------------------------------------------------------------------
  2254. HRESULT CDXUTLineManager::OnRender()
  2255. {
  2256.     HRESULT hr;
  2257.     if( NULL == m_pD3DXLine )
  2258.         return E_INVALIDARG;
  2259.  
  2260.     bool bDrawingHasBegun = false;
  2261.     float fLastWidth = 0.0f;
  2262.     bool bLastAntiAlias = false;
  2263.     
  2264.     for( int i=0; i<m_LinesList.GetSize(); i++ )
  2265.     {
  2266.         LINE_NODE* pLineNode = m_LinesList.GetAt(i);
  2267.         if( pLineNode )
  2268.         {
  2269.             if( !bDrawingHasBegun || 
  2270.                 fLastWidth != pLineNode->fWidth || 
  2271.                 bLastAntiAlias != pLineNode->bAntiAlias )
  2272.             {
  2273.                 if( bDrawingHasBegun )
  2274.                 {
  2275.                     hr = m_pD3DXLine->End();
  2276.                     if( FAILED(hr) )
  2277.                         return hr;
  2278.                 }
  2279.  
  2280.                 m_pD3DXLine->SetWidth( pLineNode->fWidth );
  2281.                 m_pD3DXLine->SetAntialias( pLineNode->bAntiAlias );
  2282.  
  2283.                 fLastWidth = pLineNode->fWidth;
  2284.                 bLastAntiAlias = pLineNode->bAntiAlias;
  2285.  
  2286.                 hr = m_pD3DXLine->Begin();
  2287.                 if( FAILED(hr) )
  2288.                     return hr;
  2289.                 bDrawingHasBegun = true;
  2290.             }
  2291.  
  2292.             hr = m_pD3DXLine->Draw( pLineNode->pVertexList, pLineNode->dwVertexListCount, pLineNode->Color );
  2293.             if( FAILED(hr) )
  2294.                 return hr;
  2295.         }
  2296.     }
  2297.  
  2298.     if( bDrawingHasBegun )
  2299.     {
  2300.         hr = m_pD3DXLine->End();
  2301.         if( FAILED(hr) )
  2302.             return hr;
  2303.     }
  2304.  
  2305.     return S_OK;
  2306. }
  2307.  
  2308.  
  2309. //--------------------------------------------------------------------------------------
  2310. HRESULT CDXUTLineManager::OnLostDevice()
  2311. {
  2312.     if( m_pD3DXLine )
  2313.         m_pD3DXLine->OnLostDevice();
  2314.  
  2315.     return S_OK;
  2316. }
  2317.  
  2318.  
  2319. //--------------------------------------------------------------------------------------
  2320. HRESULT CDXUTLineManager::OnDeletedDevice()
  2321. {
  2322.     RemoveAllLines();
  2323.     SAFE_RELEASE( m_pD3DXLine );
  2324.  
  2325.     return S_OK;
  2326. }
  2327.  
  2328.  
  2329. //--------------------------------------------------------------------------------------
  2330. HRESULT CDXUTLineManager::AddLine( int* pnLineID, D3DXVECTOR2* pVertexList, DWORD dwVertexListCount, D3DCOLOR Color, float fWidth, float fScaleRatio, bool bAntiAlias )
  2331. {
  2332.     if( pVertexList == NULL || dwVertexListCount == 0 )
  2333.         return E_INVALIDARG;
  2334.  
  2335.     LINE_NODE* pLineNode = new LINE_NODE;
  2336.     if( pLineNode == NULL )
  2337.         return E_OUTOFMEMORY;
  2338.     ZeroMemory( pLineNode, sizeof(LINE_NODE) );
  2339.  
  2340.     pLineNode->nLineID = m_LinesList.GetSize();
  2341.     pLineNode->Color = Color;
  2342.     pLineNode->fWidth = fWidth;
  2343.     pLineNode->bAntiAlias = bAntiAlias;
  2344.     pLineNode->dwVertexListCount = dwVertexListCount;
  2345.  
  2346.     if( pnLineID )
  2347.         *pnLineID = pLineNode->nLineID;
  2348.  
  2349.     pLineNode->pVertexList = new D3DXVECTOR2[dwVertexListCount];
  2350.     if( pLineNode->pVertexList == NULL )
  2351.     {
  2352.         delete pLineNode;
  2353.         return E_OUTOFMEMORY;
  2354.     }
  2355.     for( DWORD i=0; i<dwVertexListCount; i++ )
  2356.     {
  2357.         pLineNode->pVertexList[i] = pVertexList[i] * fScaleRatio;
  2358.     }
  2359.  
  2360.     m_LinesList.Add( pLineNode );
  2361.  
  2362.     return S_OK;
  2363. }
  2364.  
  2365.  
  2366. //--------------------------------------------------------------------------------------
  2367. HRESULT CDXUTLineManager::AddRect( int* pnLineID, RECT rc, D3DCOLOR Color, float fWidth, float fScaleRatio, bool bAntiAlias )
  2368. {
  2369.     if( fWidth > 2.0f )
  2370.     {
  2371.         D3DXVECTOR2 vertexList[8];
  2372.  
  2373.         vertexList[0].x = (float)rc.left;
  2374.         vertexList[0].y = (float)rc.top - (fWidth/2.0f);
  2375.  
  2376.         vertexList[1].x = (float)rc.left;
  2377.         vertexList[1].y = (float)rc.bottom + (fWidth/2.0f);
  2378.  
  2379.         vertexList[2].x = (float)rc.left;
  2380.         vertexList[2].y = (float)rc.bottom - 0.5f;
  2381.  
  2382.         vertexList[3].x = (float)rc.right;
  2383.         vertexList[3].y = (float)rc.bottom - 0.5f;
  2384.  
  2385.         vertexList[4].x = (float)rc.right;
  2386.         vertexList[4].y = (float)rc.bottom + (fWidth/2.0f);
  2387.  
  2388.         vertexList[5].x = (float)rc.right;
  2389.         vertexList[5].y = (float)rc.top - (fWidth/2.0f);
  2390.  
  2391.         vertexList[6].x = (float)rc.right;
  2392.         vertexList[6].y = (float)rc.top;
  2393.  
  2394.         vertexList[7].x = (float)rc.left;
  2395.         vertexList[7].y = (float)rc.top;
  2396.         
  2397.         return AddLine( pnLineID, vertexList, 8, Color, fWidth, fScaleRatio, bAntiAlias );
  2398.     }
  2399.     else
  2400.     {
  2401.         D3DXVECTOR2 vertexList[5];
  2402.         vertexList[0].x = (float)rc.left;
  2403.         vertexList[0].y = (float)rc.top;
  2404.  
  2405.         vertexList[1].x = (float)rc.left;
  2406.         vertexList[1].y = (float)rc.bottom;
  2407.  
  2408.         vertexList[2].x = (float)rc.right;
  2409.         vertexList[2].y = (float)rc.bottom;
  2410.  
  2411.         vertexList[3].x = (float)rc.right;
  2412.         vertexList[3].y = (float)rc.top;
  2413.  
  2414.         vertexList[4].x = (float)rc.left;
  2415.         vertexList[4].y = (float)rc.top;
  2416.         
  2417.         return AddLine( pnLineID, vertexList, 5, Color, fWidth, fScaleRatio, bAntiAlias );
  2418.     }
  2419. }
  2420.  
  2421.  
  2422.  
  2423. //--------------------------------------------------------------------------------------
  2424. HRESULT CDXUTLineManager::RemoveLine( int nLineID )
  2425. {
  2426.     for( int i=0; i<m_LinesList.GetSize(); i++ )
  2427.     {
  2428.         LINE_NODE* pLineNode = m_LinesList.GetAt(i);
  2429.         if( pLineNode && pLineNode->nLineID == nLineID )
  2430.         {
  2431.             SAFE_DELETE_ARRAY( pLineNode->pVertexList );
  2432.             delete pLineNode;
  2433.             m_LinesList.SetAt(i, NULL);
  2434.         }
  2435.     }
  2436.  
  2437.     return S_OK;
  2438. }
  2439.  
  2440.  
  2441. //--------------------------------------------------------------------------------------
  2442. HRESULT CDXUTLineManager::RemoveAllLines()
  2443. {
  2444.     for( int i=0; i<m_LinesList.GetSize(); i++ )
  2445.     {
  2446.         LINE_NODE* pLineNode = m_LinesList.GetAt(i);
  2447.         if( pLineNode )
  2448.         {
  2449.             SAFE_DELETE_ARRAY( pLineNode->pVertexList );
  2450.             delete pLineNode;
  2451.         }
  2452.     }
  2453.     m_LinesList.RemoveAll();
  2454.  
  2455.     return S_OK;
  2456. }
  2457.  
  2458.  
  2459. //--------------------------------------------------------------------------------------
  2460. CDXUTTextHelper::CDXUTTextHelper( ID3DXFont* pFont, ID3DXSprite* pSprite, int nLineHeight )
  2461. {
  2462.     m_pFont = pFont;
  2463.     m_pSprite = pSprite;
  2464.     m_clr = D3DXCOLOR(1,1,1,1);
  2465.     m_pt.x = 0; 
  2466.     m_pt.y = 0; 
  2467.     m_nLineHeight = nLineHeight;
  2468. }
  2469.  
  2470.  
  2471. //--------------------------------------------------------------------------------------
  2472. HRESULT CDXUTTextHelper::DrawFormattedTextLine( const WCHAR* strMsg, ... )
  2473. {
  2474.     WCHAR strBuffer[512];
  2475.     
  2476.     va_list args;
  2477.     va_start(args, strMsg);
  2478.     _vsnwprintf( strBuffer, 512, strMsg, args );
  2479.     strBuffer[511] = L'\0';
  2480.     va_end(args);
  2481.  
  2482.     return DrawTextLine( strBuffer );
  2483. }
  2484.  
  2485.  
  2486. //--------------------------------------------------------------------------------------
  2487. HRESULT CDXUTTextHelper::DrawTextLine( const WCHAR* strMsg )
  2488. {
  2489.     if( NULL == m_pFont ) 
  2490.         return DXUT_ERR_MSGBOX( L"DrawTextLine", E_INVALIDARG );
  2491.  
  2492.     HRESULT hr;
  2493.     RECT rc;
  2494.     SetRect( &rc, m_pt.x, m_pt.y, 0, 0 ); 
  2495.     hr = m_pFont->DrawText( m_pSprite, strMsg, -1, &rc, DT_NOCLIP, m_clr );
  2496.     if( FAILED(hr) )
  2497.         return DXTRACE_ERR_MSGBOX( L"DrawText", hr );
  2498.  
  2499.     m_pt.y += m_nLineHeight;
  2500.  
  2501.     return S_OK;
  2502. }
  2503.  
  2504.  
  2505. HRESULT CDXUTTextHelper::DrawFormattedTextLine( RECT &rc, DWORD dwFlags, const WCHAR* strMsg, ... )
  2506. {
  2507.     WCHAR strBuffer[512];
  2508.     
  2509.     va_list args;
  2510.     va_start(args, strMsg);
  2511.     _vsnwprintf( strBuffer, 512, strMsg, args );
  2512.     strBuffer[511] = L'\0';
  2513.     va_end(args);
  2514.  
  2515.     return DrawTextLine( rc, dwFlags, strBuffer );
  2516. }
  2517.  
  2518.  
  2519. HRESULT CDXUTTextHelper::DrawTextLine( RECT &rc, DWORD dwFlags, const WCHAR* strMsg )
  2520. {
  2521.     if( NULL == m_pFont ) 
  2522.         return DXUT_ERR_MSGBOX( L"DrawTextLine", E_INVALIDARG );
  2523.  
  2524.     HRESULT hr;
  2525.     hr = m_pFont->DrawText( m_pSprite, strMsg, -1, &rc, dwFlags, m_clr );
  2526.     if( FAILED(hr) )
  2527.         return DXTRACE_ERR_MSGBOX( L"DrawText", hr );
  2528.  
  2529.     m_pt.y += m_nLineHeight;
  2530.  
  2531.     return S_OK;
  2532. }
  2533.  
  2534.  
  2535. //--------------------------------------------------------------------------------------
  2536. void CDXUTTextHelper::Begin()
  2537. {
  2538.     if( m_pSprite )
  2539.         m_pSprite->Begin( D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE );
  2540. }
  2541. void CDXUTTextHelper::End()
  2542. {
  2543.     if( m_pSprite )
  2544.         m_pSprite->End();
  2545. }
  2546.  
  2547.  
  2548. //--------------------------------------------------------------------------------------
  2549. IDirect3DDevice9* CDXUTDirectionWidget::s_pd3dDevice = NULL;
  2550. ID3DXEffect*      CDXUTDirectionWidget::s_pEffect = NULL;       
  2551. ID3DXMesh*        CDXUTDirectionWidget::s_pMesh = NULL;    
  2552.  
  2553.  
  2554. //--------------------------------------------------------------------------------------
  2555. CDXUTDirectionWidget::CDXUTDirectionWidget()
  2556. {
  2557.     m_fRadius = 1.0f;
  2558.     m_vDefaultDir = D3DXVECTOR3(0,1,0);
  2559.     m_vCurrentDir = m_vDefaultDir;
  2560.     m_nRotateMask = MOUSE_RIGHT_BUTTON;
  2561.  
  2562.     D3DXMatrixIdentity( &m_mView );
  2563.     D3DXMatrixIdentity( &m_mRot );
  2564.     D3DXMatrixIdentity( &m_mRotSnapshot );
  2565. }
  2566.  
  2567.  
  2568. //--------------------------------------------------------------------------------------
  2569. HRESULT CDXUTDirectionWidget::StaticOnCreateDevice( IDirect3DDevice9* pd3dDevice )
  2570. {
  2571.     WCHAR str[MAX_PATH];
  2572.     HRESULT hr;
  2573.  
  2574.     s_pd3dDevice = pd3dDevice;
  2575.    
  2576.     // Read the D3DX effect file
  2577.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"UI\\DXUTShared.fx" ) );
  2578.  
  2579.     // If this fails, there should be debug output as to 
  2580.     // why the .fx file failed to compile
  2581.     V_RETURN( D3DXCreateEffectFromFile( s_pd3dDevice, str, NULL, NULL, 0, NULL, &s_pEffect, NULL ) );
  2582.  
  2583.     // Load the mesh with D3DX and get back a ID3DXMesh*.  For this
  2584.     // sample we'll ignore the X file's embedded materials since we know 
  2585.     // exactly the model we're loading.  See the mesh samples such as
  2586.     // "OptimizedMesh" for a more generic mesh loading example.
  2587.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"UI\\arrow.x" ) );
  2588.  
  2589.     V_RETURN( D3DXLoadMeshFromX( str, D3DXMESH_MANAGED, s_pd3dDevice, NULL, 
  2590.                                  NULL, NULL, NULL, &s_pMesh) );
  2591.  
  2592.     // Optimize the mesh for this graphics card's vertex cache 
  2593.     // so when rendering the mesh's triangle list the vertices will 
  2594.     // cache hit more often so it won't have to re-execute the vertex shader 
  2595.     // on those vertices so it will improve perf.     
  2596.     DWORD* rgdwAdjacency = new DWORD[s_pMesh->GetNumFaces() * 3];
  2597.     if( rgdwAdjacency == NULL )
  2598.         return E_OUTOFMEMORY;
  2599.     V( s_pMesh->ConvertPointRepsToAdjacency(NULL, rgdwAdjacency) );
  2600.     V( s_pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL) );
  2601.     delete []rgdwAdjacency;
  2602.  
  2603.     return S_OK;
  2604. }
  2605.  
  2606.  
  2607. //--------------------------------------------------------------------------------------
  2608. HRESULT CDXUTDirectionWidget::OnResetDevice( const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  2609. {
  2610.     m_ArcBall.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
  2611.     return S_OK;
  2612. }
  2613.  
  2614.  
  2615. //--------------------------------------------------------------------------------------
  2616. void CDXUTDirectionWidget::StaticOnLostDevice()
  2617. {
  2618.     if( s_pEffect )
  2619.         s_pEffect->OnLostDevice();
  2620. }
  2621.  
  2622.  
  2623. //--------------------------------------------------------------------------------------
  2624. void CDXUTDirectionWidget::StaticOnDestroyDevice()
  2625. {
  2626.     SAFE_RELEASE(s_pEffect);
  2627.     SAFE_RELEASE(s_pMesh);
  2628. }    
  2629.  
  2630.  
  2631. //--------------------------------------------------------------------------------------
  2632. LRESULT CDXUTDirectionWidget::HandleMessages( HWND hWnd, UINT uMsg, 
  2633.                                               WPARAM wParam, LPARAM lParam )
  2634. {
  2635.     switch( uMsg )
  2636.     {
  2637.         case WM_LBUTTONDOWN:
  2638.         case WM_MBUTTONDOWN:
  2639.         case WM_RBUTTONDOWN:
  2640.         {
  2641.             if( ((m_nRotateMask & MOUSE_LEFT_BUTTON) != 0 && uMsg == WM_LBUTTONDOWN) ||
  2642.                 ((m_nRotateMask & MOUSE_MIDDLE_BUTTON) != 0 && uMsg == WM_MBUTTONDOWN) ||
  2643.                 ((m_nRotateMask & MOUSE_RIGHT_BUTTON) != 0 && uMsg == WM_RBUTTONDOWN) )
  2644.             {
  2645.                 int iMouseX = (int)(short)LOWORD(lParam);
  2646.                 int iMouseY = (int)(short)HIWORD(lParam);
  2647.                 m_ArcBall.OnBegin( iMouseX, iMouseY );
  2648.                 SetCapture(hWnd);
  2649.             }
  2650.             return TRUE;
  2651.         }
  2652.  
  2653.         case WM_MOUSEMOVE:
  2654.         {
  2655.             if( m_ArcBall.IsBeingDragged() )
  2656.             {
  2657.                 int iMouseX = (int)(short)LOWORD(lParam);
  2658.                 int iMouseY = (int)(short)HIWORD(lParam);
  2659.                 m_ArcBall.OnMove( iMouseX, iMouseY );
  2660.                 UpdateLightDir();
  2661.             }
  2662.             return TRUE;
  2663.         }
  2664.  
  2665.         case WM_LBUTTONUP:
  2666.         case WM_MBUTTONUP:
  2667.         case WM_RBUTTONUP:
  2668.         {
  2669.             if( ((m_nRotateMask & MOUSE_LEFT_BUTTON) != 0 && uMsg == WM_LBUTTONUP) ||
  2670.                 ((m_nRotateMask & MOUSE_MIDDLE_BUTTON) != 0 && uMsg == WM_MBUTTONUP) ||
  2671.                 ((m_nRotateMask & MOUSE_RIGHT_BUTTON) != 0 && uMsg == WM_RBUTTONUP) )
  2672.             {
  2673.                 m_ArcBall.OnEnd();
  2674.                 ReleaseCapture();
  2675.             }
  2676.  
  2677.             UpdateLightDir();
  2678.             return TRUE;
  2679.         }
  2680.     }
  2681.  
  2682.     return 0;
  2683. }
  2684.  
  2685.  
  2686. //--------------------------------------------------------------------------------------
  2687. HRESULT CDXUTDirectionWidget::OnRender( D3DXCOLOR color, D3DXMATRIX* pmView, 
  2688.                                         D3DXMATRIX* pmProj, const D3DXVECTOR3* pEyePt )
  2689. {
  2690.     m_mView = *pmView;
  2691.  
  2692.     // Render the light spheres so the user can visually see the light dir
  2693.     UINT iPass, cPasses;
  2694.     D3DXMATRIX mRotate;
  2695.     D3DXMATRIX mScale;
  2696.     D3DXMATRIX mTrans;
  2697.     D3DXMATRIXA16 mWorldViewProj;
  2698.     HRESULT hr;
  2699.  
  2700.     V( s_pEffect->SetTechnique( "RenderWith1LightNoTexture" ) );
  2701.     V( s_pEffect->SetVector( "g_MaterialDiffuseColor", (D3DXVECTOR4*)&color ) );
  2702.  
  2703.     D3DXVECTOR3 vEyePt;
  2704.     D3DXVec3Normalize( &vEyePt, pEyePt );
  2705.     V( s_pEffect->SetValue( "g_LightDir", &vEyePt, sizeof(D3DXVECTOR3) ) );
  2706.  
  2707.     // Rotate arrow model to point towards origin
  2708.     D3DXMATRIX mRotateA, mRotateB;
  2709.     D3DXVECTOR3 vAt = D3DXVECTOR3(0,0,0);
  2710.     D3DXVECTOR3 vUp = D3DXVECTOR3(0,1,0);
  2711.     D3DXMatrixRotationX( &mRotateB, D3DX_PI );
  2712.     D3DXMatrixLookAtLH( &mRotateA, &m_vCurrentDir, &vAt, &vUp );
  2713.     D3DXMatrixInverse( &mRotateA, NULL, &mRotateA );
  2714.     mRotate = mRotateB * mRotateA;
  2715.  
  2716.     D3DXVECTOR3 vL = m_vCurrentDir * m_fRadius * 1.0f;
  2717.     D3DXMatrixTranslation( &mTrans, vL.x, vL.y, vL.z );
  2718.     D3DXMatrixScaling( &mScale, m_fRadius*0.2f, m_fRadius*0.2f, m_fRadius*0.2f );
  2719.  
  2720.     D3DXMATRIX mWorld = mRotate * mScale * mTrans;
  2721.     mWorldViewProj = mWorld * (m_mView) * (*pmProj);
  2722.  
  2723.     V( s_pEffect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProj ) );
  2724.     V( s_pEffect->SetMatrix( "g_mWorld", &mWorld ) );
  2725.  
  2726.     for( int iSubset=0; iSubset<2; iSubset++ )
  2727.     {
  2728.         V( s_pEffect->Begin(&cPasses, 0) );
  2729.         for (iPass = 0; iPass < cPasses; iPass++)
  2730.         {
  2731.             V( s_pEffect->BeginPass(iPass) );
  2732.             V( s_pMesh->DrawSubset(iSubset) );
  2733.             V( s_pEffect->EndPass() );
  2734.         }
  2735.         V( s_pEffect->End() );
  2736.     }
  2737.  
  2738.     return S_OK;
  2739. }
  2740.  
  2741.  
  2742. //--------------------------------------------------------------------------------------
  2743. HRESULT CDXUTDirectionWidget::UpdateLightDir()
  2744. {
  2745.     D3DXMATRIX mInvView;
  2746.     D3DXMatrixInverse(&mInvView, NULL, &m_mView);
  2747.     mInvView._41 = mInvView._42 = mInvView._43 = 0;
  2748.  
  2749.     D3DXMATRIX mLastRotInv;
  2750.     D3DXMatrixInverse(&mLastRotInv, NULL, &m_mRotSnapshot);
  2751.  
  2752.     D3DXMATRIX mRot = *m_ArcBall.GetRotationMatrix();
  2753.     m_mRotSnapshot = mRot;
  2754.  
  2755.     // Accumulate the delta of the arcball's rotation in view space.
  2756.     // Note that per-frame delta rotations could be problematic over long periods of time.
  2757.     m_mRot *= m_mView * mLastRotInv * mRot * mInvView;
  2758.  
  2759.     // Since we're accumulating delta rotations, we need to orthonormalize 
  2760.     // the matrix to prevent eventual matrix skew
  2761.     D3DXVECTOR3* pXBasis = (D3DXVECTOR3*) &m_mRot._11;
  2762.     D3DXVECTOR3* pYBasis = (D3DXVECTOR3*) &m_mRot._21;
  2763.     D3DXVECTOR3* pZBasis = (D3DXVECTOR3*) &m_mRot._31;
  2764.     D3DXVec3Normalize( pXBasis, pXBasis );
  2765.     D3DXVec3Cross( pYBasis, pZBasis, pXBasis );
  2766.     D3DXVec3Normalize( pYBasis, pYBasis );
  2767.     D3DXVec3Cross( pZBasis, pXBasis, pYBasis );
  2768.  
  2769.     // Transform the default direction vector by the light's rotation matrix
  2770.     D3DXVec3TransformNormal( &m_vCurrentDir, &m_vDefaultDir, &m_mRot );
  2771.  
  2772.     return S_OK;
  2773. }
  2774.  
  2775. //--------------------------------------------------------------------------------------
  2776. // Direct3D9 dynamic linking support -- calls top-level D3D9 APIs with graceful
  2777. // failure if APIs are not present.
  2778. //--------------------------------------------------------------------------------------
  2779.  
  2780. // Function prototypes
  2781. typedef IDirect3D9* (WINAPI * LPDIRECT3DCREATE9) (UINT);
  2782. typedef INT         (WINAPI * LPD3DPERF_BEGINEVENT)(D3DCOLOR, LPCWSTR);
  2783. typedef INT         (WINAPI * LPD3DPERF_ENDEVENT)(void);
  2784. typedef VOID        (WINAPI * LPD3DPERF_SETMARKER)(D3DCOLOR, LPCWSTR);
  2785. typedef VOID        (WINAPI * LPD3DPERF_SETREGION)(D3DCOLOR, LPCWSTR);
  2786. typedef BOOL        (WINAPI * LPD3DPERF_QUERYREPEATFRAME)(void);
  2787. typedef VOID        (WINAPI * LPD3DPERF_SETOPTIONS)( DWORD dwOptions );
  2788. typedef DWORD       (WINAPI * LPD3DPERF_GETSTATUS)( void );
  2789.  
  2790. // Module and function pointers
  2791. static HMODULE s_hModD3D9 = NULL;
  2792. static LPDIRECT3DCREATE9 s_DynamicDirect3DCreate9 = NULL;
  2793. static LPD3DPERF_BEGINEVENT s_DynamicD3DPERF_BeginEvent = NULL;
  2794. static LPD3DPERF_ENDEVENT s_DynamicD3DPERF_EndEvent = NULL;
  2795. static LPD3DPERF_SETMARKER s_DynamicD3DPERF_SetMarker = NULL;
  2796. static LPD3DPERF_SETREGION s_DynamicD3DPERF_SetRegion = NULL;
  2797. static LPD3DPERF_QUERYREPEATFRAME s_DynamicD3DPERF_QueryRepeatFrame = NULL;
  2798. static LPD3DPERF_SETOPTIONS s_DynamicD3DPERF_SetOptions = NULL;
  2799. static LPD3DPERF_GETSTATUS s_DynamicD3DPERF_GetStatus = NULL;
  2800.  
  2801. // Ensure function pointers are initialized
  2802. static bool DXUT_EnsureD3DAPIs( void )
  2803. {
  2804.     // If module is non-NULL, this function has already been called.  Note
  2805.     // that this doesn't guarantee that all D3D9 procaddresses were found.
  2806.     if( s_hModD3D9 != NULL )
  2807.         return true;
  2808.  
  2809.     // This may fail if DirectX 9 isn't installed
  2810.     WCHAR wszPath[MAX_PATH+1];
  2811.     if( !::GetSystemDirectory( wszPath, MAX_PATH+1 ) )
  2812.         return false;
  2813.     lstrcatW( wszPath, L"\\d3d9.dll" );
  2814.     s_hModD3D9 = LoadLibrary( wszPath );
  2815.     if( s_hModD3D9 == NULL ) 
  2816.         return false;
  2817.     s_DynamicDirect3DCreate9 = (LPDIRECT3DCREATE9)GetProcAddress( s_hModD3D9, "Direct3DCreate9" );
  2818.     s_DynamicD3DPERF_BeginEvent = (LPD3DPERF_BEGINEVENT)GetProcAddress( s_hModD3D9, "D3DPERF_BeginEvent" );
  2819.     s_DynamicD3DPERF_EndEvent = (LPD3DPERF_ENDEVENT)GetProcAddress( s_hModD3D9, "D3DPERF_EndEvent" );
  2820.     s_DynamicD3DPERF_SetMarker = (LPD3DPERF_SETMARKER)GetProcAddress( s_hModD3D9, "D3DPERF_SetMarker" );
  2821.     s_DynamicD3DPERF_SetRegion = (LPD3DPERF_SETREGION)GetProcAddress( s_hModD3D9, "D3DPERF_SetRegion" );
  2822.     s_DynamicD3DPERF_QueryRepeatFrame = (LPD3DPERF_QUERYREPEATFRAME)GetProcAddress( s_hModD3D9, "D3DPERF_QueryRepeatFrame" );
  2823.     s_DynamicD3DPERF_SetOptions = (LPD3DPERF_SETOPTIONS)GetProcAddress( s_hModD3D9, "D3DPERF_SetOptions" );
  2824.     s_DynamicD3DPERF_GetStatus = (LPD3DPERF_GETSTATUS)GetProcAddress( s_hModD3D9, "D3DPERF_GetStatus" );
  2825.     return true;
  2826. }
  2827.  
  2828. IDirect3D9 * WINAPI DXUT_Dynamic_Direct3DCreate9(UINT SDKVersion) 
  2829. {
  2830.     if( DXUT_EnsureD3DAPIs() && s_DynamicDirect3DCreate9 != NULL )
  2831.         return s_DynamicDirect3DCreate9( SDKVersion );
  2832.     else
  2833.         return NULL;
  2834. }
  2835.  
  2836. int WINAPI DXUT_Dynamic_D3DPERF_BeginEvent( D3DCOLOR col, LPCWSTR wszName )
  2837. {
  2838.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_BeginEvent != NULL )
  2839.         return s_DynamicD3DPERF_BeginEvent( col, wszName );
  2840.     else
  2841.         return -1;
  2842. }
  2843.  
  2844. int WINAPI DXUT_Dynamic_D3DPERF_EndEvent( void )
  2845. {
  2846.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_EndEvent != NULL )
  2847.         return s_DynamicD3DPERF_EndEvent();
  2848.     else
  2849.         return -1;
  2850. }
  2851.  
  2852. void WINAPI DXUT_Dynamic_D3DPERF_SetMarker( D3DCOLOR col, LPCWSTR wszName )
  2853. {
  2854.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_SetMarker != NULL )
  2855.         s_DynamicD3DPERF_SetMarker( col, wszName );
  2856. }
  2857.  
  2858. void WINAPI DXUT_Dynamic_D3DPERF_SetRegion( D3DCOLOR col, LPCWSTR wszName )
  2859. {
  2860.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_SetRegion != NULL )
  2861.         s_DynamicD3DPERF_SetRegion( col, wszName );
  2862. }
  2863.  
  2864. BOOL WINAPI DXUT_Dynamic_D3DPERF_QueryRepeatFrame( void )
  2865. {
  2866.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_QueryRepeatFrame != NULL )
  2867.         return s_DynamicD3DPERF_QueryRepeatFrame();
  2868.     else
  2869.         return FALSE;
  2870. }
  2871.  
  2872. void WINAPI DXUT_Dynamic_D3DPERF_SetOptions( DWORD dwOptions )
  2873. {
  2874.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_SetOptions != NULL )
  2875.         s_DynamicD3DPERF_SetOptions( dwOptions );
  2876. }
  2877.  
  2878. DWORD WINAPI DXUT_Dynamic_D3DPERF_GetStatus( void )
  2879. {
  2880.     if( DXUT_EnsureD3DAPIs() && s_DynamicD3DPERF_GetStatus != NULL )
  2881.         return s_DynamicD3DPERF_GetStatus();
  2882.     else
  2883.         return 0;
  2884. }
  2885.