Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

898 lines
28 KiB

  1. /*****************************************************************************\
  2. FILE: util.cpp
  3. DESCRIPTION:
  4. BryanSt 12/22/2000
  5. Copyright (C) Microsoft Corp 2000-2001. All rights reserved.
  6. \*****************************************************************************/
  7. #include "stdafx.h"
  8. #include "..\\d3dsaver\\dxutil.h"
  9. #define SECURITY_WIN32
  10. #include <sspi.h>
  11. extern "C" {
  12. #include <Secext.h> // for GetUserNameEx()
  13. }
  14. // Define some things for debug.h
  15. //
  16. #define SZ_DEBUGINI "ccshell.ini"
  17. #define SZ_DEBUGSECTION "MSMUSEUM"
  18. #define SZ_MODULE "MSMUSEUM"
  19. #define DECLARE_DEBUG
  20. #undef __IShellFolder2_FWD_DEFINED__
  21. #include <ccstock.h>
  22. #include <debug.h>
  23. #include "util.h"
  24. BOOL g_fOverheadViewTest = FALSE;
  25. #ifdef DEBUG
  26. DWORD g_TLSliStopWatchStartHi = 0xFFFFFFFF;
  27. DWORD g_TLSliStopWatchStartLo = 0xFFFFFFFF;
  28. LARGE_INTEGER g_liStopWatchFreq = {0};
  29. #endif // DEBUG
  30. /////////////////////////////////////////////////////////////////////
  31. // Debug Timing Helpers
  32. /////////////////////////////////////////////////////////////////////
  33. #ifdef DEBUG
  34. void DebugStartWatch(void)
  35. {
  36. LARGE_INTEGER liStopWatchStart;
  37. if (-1 == g_TLSliStopWatchStartHi)
  38. {
  39. g_TLSliStopWatchStartHi = TlsAlloc();
  40. g_TLSliStopWatchStartLo = TlsAlloc();
  41. liStopWatchStart.QuadPart = 0;
  42. QueryPerformanceFrequency(&g_liStopWatchFreq); // Only a one time call since it's value can't change while the system is running.
  43. }
  44. else
  45. {
  46. liStopWatchStart.HighPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartHi));
  47. liStopWatchStart.LowPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartLo));
  48. }
  49. QueryPerformanceCounter(&liStopWatchStart);
  50. TlsSetValue(g_TLSliStopWatchStartHi, IntToPtr(liStopWatchStart.HighPart));
  51. TlsSetValue(g_TLSliStopWatchStartLo, IntToPtr(liStopWatchStart.LowPart));
  52. }
  53. DWORD DebugStopWatch(void)
  54. {
  55. LARGE_INTEGER liDiff;
  56. LARGE_INTEGER liStopWatchStart;
  57. QueryPerformanceCounter(&liDiff);
  58. liStopWatchStart.HighPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartHi));
  59. liStopWatchStart.LowPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartLo));
  60. liDiff.QuadPart -= liStopWatchStart.QuadPart;
  61. DWORD dwTime = (DWORD)((liDiff.QuadPart * 1000) / g_liStopWatchFreq.QuadPart);
  62. TlsSetValue(g_TLSliStopWatchStartHi, (LPVOID) 0);
  63. TlsSetValue(g_TLSliStopWatchStartLo, (LPVOID) 0);
  64. return dwTime;
  65. }
  66. #else // DEBUG
  67. void DebugStartWatch(void)
  68. {
  69. }
  70. DWORD DebugStopWatch(void)
  71. {
  72. return 0;
  73. }
  74. #endif // DEBUG
  75. float rnd(void)
  76. {
  77. return (((FLOAT)rand() ) / RAND_MAX);
  78. }
  79. int GetRandomInt(int nMin, int nMax)
  80. {
  81. int nDelta = (nMax - nMin + 1);
  82. float fRandom = (((float) rand()) / ((float) RAND_MAX));
  83. float fDelta = (fRandom * nDelta);
  84. int nAmount = (int)(fDelta);
  85. nAmount = min(nAmount, nDelta - 1);
  86. return (nMin + nAmount);
  87. }
  88. HRESULT SetBoxStripVertexes(MYVERTEX * ppvVertexs, D3DXVECTOR3 vLocation, D3DXVECTOR3 vSize, D3DXVECTOR3 vNormal)
  89. {
  90. HRESULT hr = S_OK;
  91. float fTextureScale = 1.0f; // How many repeats per 1 unit.
  92. // Draw Object
  93. if (vNormal.x) // The object is in the y-z plane
  94. {
  95. ppvVertexs[0] = MYVERTEX(D3DXVECTOR3(vLocation.x, vLocation.y, vLocation.z), vNormal, 0, fTextureScale);
  96. ppvVertexs[1] = MYVERTEX(D3DXVECTOR3(vLocation.x, vLocation.y + vSize.y, vLocation.z), vNormal, 0, 0);
  97. ppvVertexs[2] = MYVERTEX(D3DXVECTOR3(vLocation.x, vLocation.y, vLocation.z + vSize.z), vNormal, fTextureScale, fTextureScale);
  98. ppvVertexs[3] = MYVERTEX(D3DXVECTOR3(vLocation.x, vLocation.y + vSize.y, vLocation.z + vSize.z), vNormal, fTextureScale, 0);
  99. }
  100. else if (vNormal.y) // The object is in the x-z plane
  101. {
  102. ppvVertexs[0] = MYVERTEX(D3DXVECTOR3(vLocation.x, vLocation.y, vLocation.z), vNormal, 0, fTextureScale);
  103. ppvVertexs[1] = MYVERTEX(D3DXVECTOR3(vLocation.x, vLocation.y, vLocation.z + vSize.z), vNormal, 0, 0);
  104. ppvVertexs[2] = MYVERTEX(D3DXVECTOR3(vLocation.x + vSize.x, vLocation.y, vLocation.z), vNormal, fTextureScale, fTextureScale);
  105. ppvVertexs[3] = MYVERTEX(D3DXVECTOR3(vLocation.x + vSize.x, vLocation.y, vLocation.z + vSize.z), vNormal, fTextureScale, 0);
  106. }
  107. else
  108. { // The object is in the x-y plane
  109. ppvVertexs[0] = MYVERTEX(D3DXVECTOR3(vLocation.x, vLocation.y, vLocation.z), vNormal, 0, fTextureScale);
  110. ppvVertexs[1] = MYVERTEX(D3DXVECTOR3(vLocation.x, vLocation.y + vSize.y, vLocation.z), vNormal, 0, 0);
  111. ppvVertexs[2] = MYVERTEX(D3DXVECTOR3(vLocation.x + vSize.x, vLocation.y, vLocation.z), vNormal, fTextureScale, fTextureScale);
  112. ppvVertexs[3] = MYVERTEX(D3DXVECTOR3(vLocation.x + vSize.x, vLocation.y + vSize.y, vLocation.z), vNormal, fTextureScale, 0);
  113. }
  114. return hr;
  115. }
  116. float AddVectorComponents(D3DXVECTOR3 vDir)
  117. {
  118. return (vDir.x + vDir.y + vDir.z);
  119. }
  120. int CALLBACK DPALocalFree_Callback(LPVOID p, LPVOID pData)
  121. {
  122. LocalFree(p); // NULLs will be ignored.
  123. return 1;
  124. }
  125. int CALLBACK DPAStrCompare(void * pv1, void * pv2, LPARAM lParam)
  126. {
  127. LPCTSTR pszSearch = (LPCTSTR) pv1;
  128. LPCTSTR pszCurrent = (LPCTSTR) pv2;
  129. if (pszSearch && pszCurrent &&
  130. !StrCmpI(pszSearch, pszCurrent))
  131. {
  132. return 0; // They match
  133. }
  134. return 1;
  135. }
  136. float GetSurfaceRatio(IDirect3DTexture8 * pTexture)
  137. {
  138. float fX = 1.0f;
  139. float fY = 1.0f;
  140. if (pTexture)
  141. {
  142. D3DSURFACE_DESC desc;
  143. if (SUCCEEDED(pTexture->GetLevelDesc(0, &desc)))
  144. {
  145. fX = (float) desc.Width;
  146. fY = (float) desc.Height;
  147. }
  148. }
  149. if (0.0f == fX)
  150. {
  151. fX = 1.0f; // Protect from zero divides
  152. }
  153. return (fY / fX);
  154. }
  155. int GetTextureHeight(IDirect3DTexture8 * pTexture)
  156. {
  157. int nHeight = 0;
  158. if (pTexture)
  159. {
  160. D3DSURFACE_DESC desc;
  161. if (SUCCEEDED(pTexture->GetLevelDesc(0, &desc)))
  162. {
  163. nHeight = desc.Height;
  164. }
  165. }
  166. return nHeight;
  167. }
  168. int GetTextureWidth(IDirect3DTexture8 * pTexture)
  169. {
  170. int nWidth = 0;
  171. if (pTexture)
  172. {
  173. D3DSURFACE_DESC desc;
  174. if (SUCCEEDED(pTexture->GetLevelDesc(0, &desc)))
  175. {
  176. nWidth = desc.Width;
  177. }
  178. }
  179. return nWidth;
  180. }
  181. /////////////////////////////////////////////////////////////////////
  182. // Registry Helpers
  183. /////////////////////////////////////////////////////////////////////
  184. HRESULT HrRegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
  185. {
  186. DWORD dwError = RegOpenKeyEx(hKey, lpSubKey, ulOptions, samDesired, phkResult);
  187. return HRESULT_FROM_WIN32(dwError);
  188. }
  189. HRESULT HrRegCreateKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions,
  190. REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)
  191. {
  192. DWORD dwError = RegCreateKeyEx(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
  193. return HRESULT_FROM_WIN32(dwError);
  194. }
  195. HRESULT HrSHGetValue(IN HKEY hKey, IN LPCTSTR pszSubKey, OPTIONAL IN LPCTSTR pszValue, OPTIONAL OUT LPDWORD pdwType,
  196. OPTIONAL OUT LPVOID pvData, OPTIONAL OUT LPDWORD pcbData)
  197. {
  198. DWORD dwError = SHGetValue(hKey, pszSubKey, pszValue, pdwType, pvData, pcbData);
  199. return HRESULT_FROM_WIN32(dwError);
  200. }
  201. HRESULT HrSHSetValue(IN HKEY hkey, IN LPCTSTR pszSubKey, OPTIONAL IN LPCTSTR pszValue, DWORD dwType, OPTIONAL OUT LPVOID pvData, IN DWORD cbData)
  202. {
  203. DWORD dwError = SHSetValue(hkey, pszSubKey, pszValue, dwType, pvData, cbData);
  204. return HRESULT_FROM_WIN32(dwError);
  205. }
  206. HRESULT HrRegSetValueString(IN HKEY hKey, IN LPCTSTR pszSubKey, IN LPCTSTR pszValueName, OUT LPCWSTR pszString)
  207. {
  208. DWORD cbSize = ((lstrlenW(pszString) + 1) * sizeof(pszString[0]));
  209. return HrSHSetValue(hKey, pszSubKey, pszValueName, REG_SZ, (BYTE *)pszString, cbSize);
  210. }
  211. HRESULT HrRegGetValueString(IN HKEY hKey, IN LPCTSTR pszSubKey, IN LPCTSTR pszValueName, IN LPWSTR pszString, IN DWORD cchSize)
  212. {
  213. DWORD dwType;
  214. DWORD cbSize = (cchSize * sizeof(pszString[0]));
  215. HRESULT hr = HrSHGetValue(hKey, pszSubKey, pszValueName, &dwType, (BYTE *)pszString, &cbSize);
  216. if (SUCCEEDED(hr) && (REG_SZ != dwType))
  217. {
  218. hr = E_FAIL;
  219. }
  220. return hr;
  221. }
  222. HRESULT HrRegGetDWORD(IN HKEY hKey, IN LPCTSTR pszSubKey, OPTIONAL IN LPCTSTR pszValue, LPDWORD pdwValue, DWORD dwDefaultValue)
  223. {
  224. DWORD dwType;
  225. DWORD cbSize = sizeof(*pdwValue);
  226. HRESULT hr = HrSHGetValue(hKey, pszSubKey, pszValue, &dwType, (void *) pdwValue, &cbSize);
  227. if (FAILED(hr))
  228. {
  229. *pdwValue = dwDefaultValue;
  230. hr = S_OK;
  231. }
  232. return hr;
  233. }
  234. HRESULT HrRegSetDWORD(IN HKEY hKey, IN LPCTSTR pszSubKey, OPTIONAL IN LPCTSTR pszValue, DWORD dwValue)
  235. {
  236. return HrSHSetValue(hKey, pszSubKey, pszValue, REG_DWORD, (void *) &dwValue, sizeof(dwValue));
  237. }
  238. // UI Wrappers
  239. void SetCheckBox(HWND hwndDlg, UINT idControl, BOOL fChecked)
  240. {
  241. SendMessage((HWND)GetDlgItem(hwndDlg, idControl), BM_SETCHECK, (WPARAM)fChecked, 0);
  242. }
  243. BOOL GetCheckBox(HWND hwndDlg, UINT idControl)
  244. {
  245. return (BST_CHECKED == SendMessage((HWND)GetDlgItem(hwndDlg, idControl), BM_GETCHECK, 0, 0));
  246. }
  247. HRESULT ShellFolderParsePath(LPCWSTR pszPath, LPITEMIDLIST * ppidl)
  248. {
  249. IShellFolder * psf;
  250. HRESULT hr = SHGetDesktopFolder(&psf);
  251. if (SUCCEEDED(hr))
  252. {
  253. hr = psf->ParseDisplayName(NULL, NULL, (LPOLESTR) pszPath, NULL, ppidl, NULL);
  254. psf->Release();
  255. }
  256. return hr;
  257. }
  258. HRESULT ShellFolderGetPath(LPCITEMIDLIST pidl, LPWSTR pszPath, DWORD cchSize)
  259. {
  260. IShellFolder * psf;
  261. HRESULT hr = SHGetDesktopFolder(&psf);
  262. if (SUCCEEDED(hr))
  263. {
  264. IShellFolder * psfFolder;
  265. LPITEMIDLIST pidlParent = ILCloneParent(pidl);
  266. if (pidlParent)
  267. {
  268. hr = psf->BindToObject(pidlParent, NULL, IID_IShellFolder, (void **) &psfFolder);
  269. if (SUCCEEDED(hr))
  270. {
  271. STRRET strRet = {0};
  272. LPITEMIDLIST pidlLast = ILFindLastID(pidl);
  273. hr = psfFolder->GetDisplayNameOf(pidlLast, (SHGDN_NORMAL | SHGDN_FORPARSING), &strRet);
  274. if (SUCCEEDED(hr))
  275. {
  276. hr = StrRetToBuf(&strRet, pidlLast, pszPath, cchSize);
  277. }
  278. psfFolder->Release();
  279. }
  280. ILFree(pidlParent);
  281. }
  282. else
  283. {
  284. hr = E_OUTOFMEMORY;
  285. }
  286. psf->Release();
  287. }
  288. return hr;
  289. }
  290. BOOL PathDeleteDirectoryRecursively(LPCTSTR pszDir)
  291. {
  292. BOOL fReturn = FALSE;
  293. HANDLE hFind;
  294. WIN32_FIND_DATA wfd;
  295. TCHAR szTemp[MAX_PATH];
  296. StrCpyN(szTemp, pszDir, ARRAYSIZE(szTemp));
  297. PathAppend(szTemp, TEXT("*.*"));
  298. hFind = FindFirstFile(szTemp, &wfd);
  299. if (INVALID_HANDLE_VALUE != hFind)
  300. {
  301. do
  302. {
  303. if (!PathIsDotOrDotDot(wfd.cFileName))
  304. {
  305. // build the path of the directory or file found
  306. StrCpyN(szTemp, pszDir, ARRAYSIZE(szTemp));
  307. PathAppend(szTemp, wfd.cFileName);
  308. if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
  309. {
  310. // We found a directory - call this function recursively
  311. // Note that since we use recursion, this can only go so far
  312. // before it blows the stack. If you plan on going into deep
  313. // directories, put szTemp above on the heap.
  314. fReturn = PathDeleteDirectoryRecursively(szTemp);
  315. }
  316. else
  317. {
  318. DeleteFile(szTemp);
  319. }
  320. }
  321. }
  322. while (FindNextFile(hFind, &wfd));
  323. FindClose(hFind);
  324. }
  325. fReturn = RemoveDirectory(pszDir);
  326. return fReturn;
  327. }
  328. ULONGLONG PathGetFileSize(LPCTSTR pszPath)
  329. {
  330. ULONGLONG ullResult = 0;
  331. HANDLE hFile = CreateFile(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  332. if (INVALID_HANDLE_VALUE != hFile)
  333. {
  334. LARGE_INTEGER liFileSize;
  335. if (GetFileSizeEx(hFile, &liFileSize))
  336. {
  337. ullResult = liFileSize.QuadPart;
  338. }
  339. CloseHandle(hFile);
  340. }
  341. return ullResult;
  342. }
  343. void PrintLocation(LPTSTR pszTemplate, D3DXVECTOR3 vLoc, D3DXVECTOR3 vTangent)
  344. {
  345. TCHAR szOut[1024];
  346. TCHAR szVector1[90];
  347. TCHAR szVector2[90];
  348. TCHAR szFloat1[20];
  349. TCHAR szFloat2[20];
  350. TCHAR szFloat3[20];
  351. FloatToString(vLoc.x, 4, szFloat1, ARRAYSIZE(szFloat1));
  352. FloatToString(vLoc.y, 4, szFloat2, ARRAYSIZE(szFloat2));
  353. FloatToString(vLoc.z, 4, szFloat3, ARRAYSIZE(szFloat3));
  354. wnsprintf(szVector1, ARRAYSIZE(szVector1), TEXT("<%s, %s, %s>"), szFloat1, szFloat2, szFloat3);
  355. FloatToString(vTangent.x, 4, szFloat1, ARRAYSIZE(szFloat1));
  356. FloatToString(vTangent.y, 4, szFloat2, ARRAYSIZE(szFloat2));
  357. FloatToString(vTangent.z, 4, szFloat3, ARRAYSIZE(szFloat3));
  358. wnsprintf(szVector2, ARRAYSIZE(szVector2), TEXT("<%s, %s, %s>\n"), szFloat1, szFloat2, szFloat3);
  359. wnsprintf(szOut, ARRAYSIZE(szOut), pszTemplate, szVector1, szVector2);
  360. DXUtil_Trace(szOut);
  361. }
  362. //-----------------------------------------------------------------------------
  363. // Name: UpdateCullInfo()
  364. // Desc: Sets up the frustum planes, endpoints, and center for the frustum
  365. // defined by a given view matrix and projection matrix. This info will
  366. // be used when culling each object in CullObject().
  367. //-----------------------------------------------------------------------------
  368. VOID UpdateCullInfo( CULLINFO* pCullInfo, D3DXMATRIX* pMatView, D3DXMATRIX* pMatProj )
  369. {
  370. D3DXMATRIX mat;
  371. D3DXMatrixMultiply( &mat, pMatView, pMatProj );
  372. D3DXMatrixInverse( &mat, NULL, &mat );
  373. pCullInfo->vecFrustum[0] = D3DXVECTOR3(-1.0f, -1.0f, 0.0f); // xyz
  374. pCullInfo->vecFrustum[1] = D3DXVECTOR3( 1.0f, -1.0f, 0.0f); // Xyz
  375. pCullInfo->vecFrustum[2] = D3DXVECTOR3(-1.0f, 1.0f, 0.0f); // xYz
  376. pCullInfo->vecFrustum[3] = D3DXVECTOR3( 1.0f, 1.0f, 0.0f); // XYz
  377. pCullInfo->vecFrustum[4] = D3DXVECTOR3(-1.0f, -1.0f, 1.0f); // xyZ
  378. pCullInfo->vecFrustum[5] = D3DXVECTOR3( 1.0f, -1.0f, 1.0f); // XyZ
  379. pCullInfo->vecFrustum[6] = D3DXVECTOR3(-1.0f, 1.0f, 1.0f); // xYZ
  380. pCullInfo->vecFrustum[7] = D3DXVECTOR3( 1.0f, 1.0f, 1.0f); // XYZ
  381. pCullInfo->vecFrustumCenter = D3DXVECTOR3(0, 0, 0);
  382. for( INT i = 0; i < 8; i++ )
  383. {
  384. D3DXVec3TransformCoord( &pCullInfo->vecFrustum[i], &pCullInfo->vecFrustum[i], &mat );
  385. pCullInfo->vecFrustumCenter += pCullInfo->vecFrustum[i];
  386. }
  387. pCullInfo->vecFrustumCenter /= 8;
  388. D3DXPlaneFromPoints( &pCullInfo->planeFrustum[0], &pCullInfo->vecFrustum[0],
  389. &pCullInfo->vecFrustum[1], &pCullInfo->vecFrustum[2] ); // Near
  390. D3DXPlaneFromPoints( &pCullInfo->planeFrustum[1], &pCullInfo->vecFrustum[6],
  391. &pCullInfo->vecFrustum[7], &pCullInfo->vecFrustum[5] ); // Far
  392. D3DXPlaneFromPoints( &pCullInfo->planeFrustum[2], &pCullInfo->vecFrustum[2],
  393. &pCullInfo->vecFrustum[6], &pCullInfo->vecFrustum[4] ); // Left
  394. D3DXPlaneFromPoints( &pCullInfo->planeFrustum[3], &pCullInfo->vecFrustum[7],
  395. &pCullInfo->vecFrustum[3], &pCullInfo->vecFrustum[5] ); // Right
  396. D3DXPlaneFromPoints( &pCullInfo->planeFrustum[4], &pCullInfo->vecFrustum[2],
  397. &pCullInfo->vecFrustum[3], &pCullInfo->vecFrustum[6] ); // Top
  398. D3DXPlaneFromPoints( &pCullInfo->planeFrustum[5], &pCullInfo->vecFrustum[1],
  399. &pCullInfo->vecFrustum[0], &pCullInfo->vecFrustum[4] ); // Bottom
  400. }
  401. //-----------------------------------------------------------------------------
  402. // Name: CullObject()
  403. // Desc: Determine the cullstate for an object.
  404. //-----------------------------------------------------------------------------
  405. CULLSTATE CullObject( CULLINFO* pCullInfo, D3DXVECTOR3* pVecBounds,
  406. D3DXPLANE* pPlaneBounds )
  407. {
  408. BYTE bOutside[8];
  409. ZeroMemory( &bOutside, sizeof(bOutside) );
  410. // Check boundary vertices against all 6 frustum planes,
  411. // and store result (1 if outside) in a bitfield
  412. for( int iPoint = 0; iPoint < 8; iPoint++ )
  413. {
  414. for( int iPlane = 0; iPlane < 6; iPlane++ )
  415. {
  416. if( pCullInfo->planeFrustum[iPlane].a * pVecBounds[iPoint].x +
  417. pCullInfo->planeFrustum[iPlane].b * pVecBounds[iPoint].y +
  418. pCullInfo->planeFrustum[iPlane].c * pVecBounds[iPoint].z +
  419. pCullInfo->planeFrustum[iPlane].d < 0)
  420. {
  421. bOutside[iPoint] |= (1 << iPlane);
  422. }
  423. }
  424. // If any point is inside all 6 frustum planes, it is inside
  425. // the frustum, so the object must be rendered.
  426. if( bOutside[iPoint] == 0 )
  427. return CS_INSIDE;
  428. }
  429. // If all points are outside any single frustum plane, the object is
  430. // outside the frustum
  431. if( (bOutside[0] & bOutside[1] & bOutside[2] & bOutside[3] &
  432. bOutside[4] & bOutside[5] & bOutside[6] & bOutside[7]) != 0 )
  433. {
  434. return CS_OUTSIDE;
  435. }
  436. // Now see if any of the frustum edges penetrate any of the faces of
  437. // the bounding box
  438. D3DXVECTOR3 edge[12][2] =
  439. {
  440. pCullInfo->vecFrustum[0], pCullInfo->vecFrustum[1], // front bottom
  441. pCullInfo->vecFrustum[2], pCullInfo->vecFrustum[3], // front top
  442. pCullInfo->vecFrustum[0], pCullInfo->vecFrustum[2], // front left
  443. pCullInfo->vecFrustum[1], pCullInfo->vecFrustum[3], // front right
  444. pCullInfo->vecFrustum[4], pCullInfo->vecFrustum[5], // back bottom
  445. pCullInfo->vecFrustum[6], pCullInfo->vecFrustum[7], // back top
  446. pCullInfo->vecFrustum[4], pCullInfo->vecFrustum[6], // back left
  447. pCullInfo->vecFrustum[5], pCullInfo->vecFrustum[7], // back right
  448. pCullInfo->vecFrustum[0], pCullInfo->vecFrustum[4], // left bottom
  449. pCullInfo->vecFrustum[2], pCullInfo->vecFrustum[6], // left top
  450. pCullInfo->vecFrustum[1], pCullInfo->vecFrustum[5], // right bottom
  451. pCullInfo->vecFrustum[3], pCullInfo->vecFrustum[7], // right top
  452. };
  453. D3DXVECTOR3 face[6][4] =
  454. {
  455. pVecBounds[0], pVecBounds[2], pVecBounds[3], pVecBounds[1], // front
  456. pVecBounds[4], pVecBounds[5], pVecBounds[7], pVecBounds[6], // back
  457. pVecBounds[0], pVecBounds[4], pVecBounds[6], pVecBounds[2], // left
  458. pVecBounds[1], pVecBounds[3], pVecBounds[7], pVecBounds[5], // right
  459. pVecBounds[2], pVecBounds[6], pVecBounds[7], pVecBounds[3], // top
  460. pVecBounds[0], pVecBounds[4], pVecBounds[5], pVecBounds[1], // bottom
  461. };
  462. D3DXVECTOR3* pEdge;
  463. D3DXVECTOR3* pFace;
  464. pEdge = &edge[0][0];
  465. for( INT iEdge = 0; iEdge < 12; iEdge++ )
  466. {
  467. pFace = &face[0][0];
  468. for( INT iFace = 0; iFace < 6; iFace++ )
  469. {
  470. if( EdgeIntersectsFace( pEdge, pFace, &pPlaneBounds[iFace] ) )
  471. {
  472. return CS_INSIDE_SLOW;
  473. }
  474. pFace += 4;
  475. }
  476. pEdge += 2;
  477. }
  478. // Now see if frustum is contained in bounding box
  479. // If the frustum center is outside any plane of the bounding box,
  480. // the frustum is not contained in the bounding box, so the object
  481. // is outside the frustum
  482. for( INT iPlane = 0; iPlane < 6; iPlane++ )
  483. {
  484. if( pPlaneBounds[iPlane].a * pCullInfo->vecFrustumCenter.x +
  485. pPlaneBounds[iPlane].b * pCullInfo->vecFrustumCenter.y +
  486. pPlaneBounds[iPlane].c * pCullInfo->vecFrustumCenter.z +
  487. pPlaneBounds[iPlane].d < 0 )
  488. {
  489. return CS_OUTSIDE_SLOW;
  490. }
  491. }
  492. // Bounding box must contain the frustum, so render the object
  493. return CS_INSIDE_SLOW;
  494. }
  495. //-----------------------------------------------------------------------------
  496. // Name: EdgeIntersectsFace()
  497. // Desc: Determine if the edge bounded by the two vectors in pEdges intersects
  498. // the quadrilateral described by the four vectors in pFacePoints.
  499. // Note: pPlanePoints could be derived from pFacePoints using
  500. // D3DXPlaneFromPoints, but it is precomputed in advance for greater
  501. // speed.
  502. //-----------------------------------------------------------------------------
  503. BOOL EdgeIntersectsFace( D3DXVECTOR3* pEdges, D3DXVECTOR3* pFacePoints,
  504. D3DXPLANE* pPlane )
  505. {
  506. // If both edge points are on the same side of the plane, the edge does
  507. // not intersect the face
  508. FLOAT fDist1;
  509. FLOAT fDist2;
  510. fDist1 = pPlane->a * pEdges[0].x + pPlane->b * pEdges[0].y +
  511. pPlane->c * pEdges[0].z + pPlane->d;
  512. fDist2 = pPlane->a * pEdges[1].x + pPlane->b * pEdges[1].y +
  513. pPlane->c * pEdges[1].z + pPlane->d;
  514. if( fDist1 > 0 && fDist2 > 0 ||
  515. fDist1 < 0 && fDist2 < 0 )
  516. {
  517. return FALSE;
  518. }
  519. // Find point of intersection between edge and face plane (if they're
  520. // parallel, edge does not intersect face and D3DXPlaneIntersectLine
  521. // returns NULL)
  522. D3DXVECTOR3 ptIntersection;
  523. if( NULL == D3DXPlaneIntersectLine( &ptIntersection, pPlane, &pEdges[0], &pEdges[1] ) )
  524. return FALSE;
  525. // Project onto a 2D plane to make the pt-in-poly test easier
  526. FLOAT fAbsA = (pPlane->a > 0 ? pPlane->a : -pPlane->a);
  527. FLOAT fAbsB = (pPlane->b > 0 ? pPlane->b : -pPlane->b);
  528. FLOAT fAbsC = (pPlane->c > 0 ? pPlane->c : -pPlane->c);
  529. D3DXVECTOR2 facePoints[4];
  530. D3DXVECTOR2 point;
  531. if( fAbsA > fAbsB && fAbsA > fAbsC )
  532. {
  533. // Plane is mainly pointing along X axis, so use Y and Z
  534. for( INT i = 0; i < 4; i++)
  535. {
  536. facePoints[i].x = pFacePoints[i].y;
  537. facePoints[i].y = pFacePoints[i].z;
  538. }
  539. point.x = ptIntersection.y;
  540. point.y = ptIntersection.z;
  541. }
  542. else if( fAbsB > fAbsA && fAbsB > fAbsC )
  543. {
  544. // Plane is mainly pointing along Y axis, so use X and Z
  545. for( INT i = 0; i < 4; i++)
  546. {
  547. facePoints[i].x = pFacePoints[i].x;
  548. facePoints[i].y = pFacePoints[i].z;
  549. }
  550. point.x = ptIntersection.x;
  551. point.y = ptIntersection.z;
  552. }
  553. else
  554. {
  555. // Plane is mainly pointing along Z axis, so use X and Y
  556. for( INT i = 0; i < 4; i++)
  557. {
  558. facePoints[i].x = pFacePoints[i].x;
  559. facePoints[i].y = pFacePoints[i].y;
  560. }
  561. point.x = ptIntersection.x;
  562. point.y = ptIntersection.y;
  563. }
  564. // If point is on the outside of any of the face edges, it is
  565. // outside the face.
  566. // We can do this by taking the determinant of the following matrix:
  567. // | x0 y0 1 |
  568. // | x1 y1 1 |
  569. // | x2 y2 1 |
  570. // where (x0,y0) and (x1,y1) are points on the face edge and (x2,y2)
  571. // is our test point. If this value is positive, the test point is
  572. // "to the left" of the line. To determine whether a point needs to
  573. // be "to the right" or "to the left" of the four lines to qualify as
  574. // inside the face, we need to see if the faces are specified in
  575. // clockwise or counter-clockwise order (it could be either, since the
  576. // edge could be penetrating from either side). To determine this, we
  577. // do the same test to see if the third point is "to the right" or
  578. // "to the left" of the line formed by the first two points.
  579. // See http://forum.swarthmore.edu/dr.math/problems/scott5.31.96.html
  580. FLOAT x0, x1, x2, y0, y1, y2;
  581. x0 = facePoints[0].x;
  582. y0 = facePoints[0].y;
  583. x1 = facePoints[1].x;
  584. y1 = facePoints[1].y;
  585. x2 = facePoints[2].x;
  586. y2 = facePoints[2].y;
  587. BOOL bClockwise = FALSE;
  588. if( x1*y2 - y1*x2 - x0*y2 + y0*x2 + x0*y1 - y0*x1 < 0 )
  589. bClockwise = TRUE;
  590. x2 = point.x;
  591. y2 = point.y;
  592. for( INT i = 0; i < 4; i++ )
  593. {
  594. x0 = facePoints[i].x;
  595. y0 = facePoints[i].y;
  596. if( i < 3 )
  597. {
  598. x1 = facePoints[i+1].x;
  599. y1 = facePoints[i+1].y;
  600. }
  601. else
  602. {
  603. x1 = facePoints[0].x;
  604. y1 = facePoints[0].y;
  605. }
  606. if( ( x1*y2 - y1*x2 - x0*y2 + y0*x2 + x0*y1 - y0*x1 > 0 ) == bClockwise )
  607. return FALSE;
  608. }
  609. // If we get here, the point is inside all four face edges,
  610. // so it's inside the face.
  611. return TRUE;
  612. }
  613. BOOL Is3DRectViewable(CULLINFO* pCullInfo, D3DXMATRIX* pMatWorld,
  614. D3DXVECTOR3 vecMin, D3DXVECTOR3 vecMax)
  615. {
  616. BOOL fViewable = TRUE;
  617. D3DXVECTOR3 vecBoundsLocal[8];
  618. D3DXVECTOR3 vecBoundsWorld[8];
  619. D3DXPLANE planeBoundsWorld[6];
  620. CULLSTATE cs;
  621. vecBoundsLocal[0] = D3DXVECTOR3( vecMin.x, vecMin.y, vecMin.z ); // xyz
  622. vecBoundsLocal[1] = D3DXVECTOR3( vecMax.x, vecMin.y, vecMin.z ); // Xyz
  623. vecBoundsLocal[2] = D3DXVECTOR3( vecMin.x, vecMax.y, vecMin.z ); // xYz
  624. vecBoundsLocal[3] = D3DXVECTOR3( vecMax.x, vecMax.y, vecMin.z ); // XYz
  625. vecBoundsLocal[4] = D3DXVECTOR3( vecMin.x, vecMin.y, vecMax.z ); // xyZ
  626. vecBoundsLocal[5] = D3DXVECTOR3( vecMax.x, vecMin.y, vecMax.z ); // XyZ
  627. vecBoundsLocal[6] = D3DXVECTOR3( vecMin.x, vecMax.y, vecMax.z ); // xYZ
  628. vecBoundsLocal[7] = D3DXVECTOR3( vecMax.x, vecMax.y, vecMax.z ); // XYZ
  629. for( int i = 0; i < 8; i++ )
  630. {
  631. D3DXVec3TransformCoord( &vecBoundsWorld[i], &vecBoundsLocal[i], pMatWorld );
  632. }
  633. // Determine planes of bounding box coords
  634. D3DXPlaneFromPoints( &planeBoundsWorld[0], &vecBoundsWorld[0], &vecBoundsWorld[1], &vecBoundsWorld[2] ); // Near
  635. D3DXPlaneFromPoints( &planeBoundsWorld[1], &vecBoundsWorld[6], &vecBoundsWorld[7], &vecBoundsWorld[5] ); // Far
  636. D3DXPlaneFromPoints( &planeBoundsWorld[2], &vecBoundsWorld[2], &vecBoundsWorld[6], &vecBoundsWorld[4] ); // Left
  637. D3DXPlaneFromPoints( &planeBoundsWorld[3], &vecBoundsWorld[7], &vecBoundsWorld[3], &vecBoundsWorld[5] ); // Right
  638. D3DXPlaneFromPoints( &planeBoundsWorld[4], &vecBoundsWorld[2], &vecBoundsWorld[3], &vecBoundsWorld[6] ); // Top
  639. D3DXPlaneFromPoints( &planeBoundsWorld[5], &vecBoundsWorld[1], &vecBoundsWorld[0], &vecBoundsWorld[4] ); // Bottom
  640. cs = CullObject( pCullInfo, vecBoundsWorld, planeBoundsWorld );
  641. fViewable = (cs != CS_OUTSIDE && cs != CS_OUTSIDE_SLOW);
  642. return fViewable;
  643. }
  644. HRESULT GetCurrentUserCustomName(LPWSTR pszDisplayName, DWORD cchSize)
  645. {
  646. HRESULT hr = S_OK;
  647. ULONG cchUserSize = cchSize;
  648. if (GetUserNameEx(NameDisplay, pszDisplayName, &cchUserSize))
  649. {
  650. // It succeeded, so use it.
  651. }
  652. else
  653. {
  654. // It failed, so load "My". It's better than nothing.
  655. LoadString(HINST_THISDLL, IDS_LOBBY_TITLE, pszDisplayName, cchSize);
  656. }
  657. return hr;
  658. }
  659. D3DXVECTOR3 D3DXVec3Multiply(CONST D3DXVECTOR3 v1, CONST D3DXVECTOR3 v2)
  660. {
  661. D3DXVECTOR3 vResults;
  662. vResults.x = (v1.x * v2.x);
  663. vResults.y = (v1.y * v2.y);
  664. vResults.z = (v1.z * v2.z);
  665. return vResults;
  666. }
  667. void FloatToString(float fValue, int nDecimalDigits, LPTSTR pszString, DWORD cchSize)
  668. {
  669. int nIntValue = (int) fValue;
  670. float fDecimalValue = (float)((fValue - (float)nIntValue) * (pow(10, nDecimalDigits)));
  671. int nDecimalValue = (int) fDecimalValue;
  672. if (0 == nDecimalDigits)
  673. {
  674. wnsprintf(pszString, cchSize, TEXT("%d"), nIntValue);
  675. }
  676. else
  677. {
  678. wnsprintf(pszString, cchSize, TEXT("%d.%d"), nIntValue, nDecimalValue);
  679. }
  680. }
  681. ///////
  682. // Critical section helper stuff
  683. //
  684. #ifdef DEBUG
  685. UINT g_CriticalSectionCount = 0;
  686. DWORD g_CriticalSectionOwner = 0;
  687. #ifdef STACKBACKTRACE
  688. DBstkback g_CriticalSectionLastCall[4] = { 0 };
  689. #endif
  690. void Dll_EnterCriticalSection(CRITICAL_SECTION * pcsDll)
  691. {
  692. #ifdef STACKBACKTRACE
  693. int var0; // *must* be 1st on frame
  694. #endif
  695. EnterCriticalSection(pcsDll);
  696. if (g_CriticalSectionCount++ == 0)
  697. {
  698. g_CriticalSectionOwner = GetCurrentThreadId();
  699. #ifdef STACKBACKTRACE
  700. int fp = (int) (1 + (int *)&var0);
  701. DBGetStackBack(&fp, g_CriticalSectionLastCall, ARRAYSIZE(g_CriticalSectionLastCall));
  702. #endif
  703. }
  704. }
  705. void Dll_LeaveCriticalSection(CRITICAL_SECTION * pcsDll)
  706. {
  707. if (--g_CriticalSectionCount == 0)
  708. g_CriticalSectionOwner = 0;
  709. LeaveCriticalSection(pcsDll);
  710. }
  711. #endif
  712. #include <string.h>
  713. #include <wchar.h>
  714. #include <tchar.h>
  715. #include <stdio.h>
  716. #include <stdlib.h>