D3DWND.H
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:41k
源码类别:

Windows编程

开发平台:

Visual C++

  1. // D3DWnd.h : Declaration of CDirect3DWindow & CD3DMatrix
  2. //
  3. // This is a part of the Active Template Library.
  4. // Copyright (C) 1996-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Active Template Library Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Active Template Library product.
  12. #include <math.h>
  13. #include <ddraw.h>
  14. #include <d3d.h>
  15. #include "resource.h"
  16. /***********************************************************************
  17.  *
  18.  * Constants
  19.  *
  20.  ***********************************************************************/
  21. /*
  22.  * Half height of the view window.
  23.  */
  24. #define HALF_HEIGHT           D3DVAL(0.5)
  25. /*
  26.  * Front and back clipping planes.
  27.  */
  28. #define FRONT_CLIP            D3DVAL(1.0)
  29. #define BACK_CLIP             D3DVAL(1000.0)
  30. #define MAX_DEVICE_NAME       256
  31. #define MAX_DEVICE_DESC       256
  32. /*
  33.  * Amount to rotate per frame.
  34.  */
  35. #define M_PI                  3.14159265359
  36. #define M_2PI                 6.28318530718
  37. #define ROTATE_ANGLE_DELTA    (M_2PI / 150.0)
  38. /*
  39.  * Execute buffer contents
  40.  */
  41. #define NUM_VERTICES          3UL
  42. #define NUM_INSTRUCTIONS      6UL
  43. #define NUM_STATES            8UL
  44. #define NUM_PROCESSVERTICES   1UL
  45. #define NUM_TRIANGLES         1UL
  46. /***********************************************************************
  47.  *
  48.  * Macro funtions.
  49.  *
  50.  ***********************************************************************/
  51. /*
  52.  * Extract the error code from an HRESULT
  53.  */
  54. #define CODEFROMHRESULT(hRes) ((hRes) & 0x0000FFFFUL)
  55. /*
  56.  * Globals used for selecting the Direct3D device. They are
  57.  * globals as it makes it easy for the enumeration callback
  58.  * to read and write from them.
  59.  */
  60. extern BOOL          fDeviceFound;
  61. extern DWORD         dwDeviceBitDepth;
  62. extern GUID          guidDevice;
  63. extern char          szDeviceName[MAX_DEVICE_NAME];
  64. extern char          szDeviceDesc[MAX_DEVICE_DESC];
  65. extern D3DDEVICEDESC d3dHWDeviceDesc;
  66. extern D3DDEVICEDESC d3dSWDeviceDesc;
  67. class CD3DMatrix : public _D3DMATRIX
  68. {
  69. public:
  70. CD3DMatrix(
  71. D3DVALUE v11, D3DVALUE v12, D3DVALUE v13, D3DVALUE v14,
  72. D3DVALUE v21, D3DVALUE v22, D3DVALUE v23, D3DVALUE v24,
  73. D3DVALUE v31, D3DVALUE v32, D3DVALUE v33, D3DVALUE v34,
  74. D3DVALUE v41, D3DVALUE v42, D3DVALUE v43, D3DVALUE v44)
  75. {
  76. _11 = v11;
  77. _12 = v12;
  78. _13 = v13;
  79. _14 = v14;
  80. _21 = v21;
  81. _22 = v22;
  82. _23 = v23;
  83. _24 = v24;
  84. _31 = v31;
  85. _32 = v32;
  86. _33 = v33;
  87. _34 = v34;
  88. _41 = v41;
  89. _42 = v42;
  90. _43 = v43;
  91. _44 = v44;
  92. }
  93. };
  94. class CDirect3DWindow
  95. {
  96. public:
  97. CDirect3DWindow();
  98. ~CDirect3DWindow()
  99. {
  100. // Clean everything up.
  101. ReleaseScene();
  102. ReleaseDevice();
  103. ReleasePrimary();
  104. ReleaseDirect3D();
  105. }
  106. void ReportError(HWND hwnd, LPSTR lpszMessage, HRESULT hRes)
  107. {
  108. TCHAR szBuffer[256];
  109. TCHAR szError[128];
  110. int  nStrID;
  111. // Turn the animation loop off.
  112. m_bIsSuspended = TRUE;
  113. // We issue sensible error messages for common run time errors. For
  114. // errors which are internal or coding errors we simply issue an
  115. // error number (they should never occur).
  116. switch (hRes)
  117. {
  118. case DDERR_EXCEPTION:        nStrID = IDS_ERR_EXCEPTION;        break;
  119. case DDERR_GENERIC:          nStrID = IDS_ERR_GENERIC;          break;
  120. case DDERR_OUTOFMEMORY:      nStrID = IDS_ERR_OUTOFMEMORY;      break;
  121. case DDERR_OUTOFVIDEOMEMORY: nStrID = IDS_ERR_OUTOFVIDEOMEMORY; break;
  122. case DDERR_SURFACEBUSY:      nStrID = IDS_ERR_SURFACEBUSY;      break;
  123. case DDERR_SURFACELOST:      nStrID = IDS_ERR_SURFACELOST;      break;
  124. case DDERR_WRONGMODE:        nStrID = IDS_ERR_WRONGMODE;        break;
  125. default:                     nStrID = IDS_ERR_INTERNALERROR;    break;
  126. }
  127. LoadString(_Module.GetResourceInstance(), nStrID, szError, sizeof(szError));
  128. // Convert the error code into a string.
  129. wsprintf(szBuffer, _T("%sn%s (Error #%d)"), lpszMessage, szError, CODEFROMHRESULT(hRes));
  130. MessageBox(hwnd, szBuffer, _T(""), MB_OK | MB_APPLMODAL);
  131. }
  132. /***********************************************************************/
  133. void FatalError(HWND hwnd, LPSTR lpszMessage, HRESULT hRes)
  134. {
  135. // Report the error.
  136. ReportError(hwnd, lpszMessage, hRes);
  137. // And shut down.
  138. // NOTE: We don't attempt to clean up. That will be done
  139. // in the destructor
  140. m_bShuttingDown = TRUE;
  141. }
  142. /***********************************************************************/
  143. DWORD BitDepthToFlags(DWORD dwBitDepth)
  144. {
  145. switch (dwBitDepth)
  146. {
  147. case  1UL: return DDBD_1;
  148. case  2UL: return DDBD_2;
  149. case  4UL: return DDBD_4;
  150. case  8UL: return DDBD_8;
  151. case 16UL: return DDBD_16;
  152. case 24UL: return DDBD_24;
  153. case 32UL: return DDBD_32;
  154. default:   return 0UL;
  155. }
  156. }
  157. /***********************************************************************/
  158. /*
  159.  * Convert bit depth flags to an acutal bit count. Selects the smallest
  160.  * bit count in the mask if more than one flag is present.
  161.  */
  162. DWORD FlagsToBitDepth(DWORD dwFlags)
  163. {
  164. if (dwFlags & DDBD_1)
  165. return 1UL;
  166. else if (dwFlags & DDBD_2)
  167. return 2UL;
  168. else if (dwFlags & DDBD_4)
  169. return 4UL;
  170. else if (dwFlags & DDBD_8)
  171. return 8UL;
  172. else if (dwFlags & DDBD_16)
  173. return 16UL;
  174. else if (dwFlags & DDBD_24)
  175. return 24UL;
  176. else if (dwFlags & DDBD_32)
  177. return 32UL;
  178. else
  179. return 0UL; /* Oh, please... */
  180. }
  181. /***********************************************************************/
  182. void SetPerspectiveProjection(LPD3DMATRIX lpd3dMatrix,
  183.  double      dHalfHeight,
  184.  double      dFrontClipping,
  185.  double      dBackClipping)
  186. {
  187. double dTmp1;
  188. double dTmp2;
  189. ATLASSERT(NULL != lpd3dMatrix);
  190. dTmp1 = dHalfHeight / dFrontClipping;
  191. dTmp2 = dBackClipping / (dBackClipping - dFrontClipping);
  192. lpd3dMatrix->_11 =  D3DVAL(2.0);
  193. lpd3dMatrix->_12 =  D3DVAL(0.0);
  194. lpd3dMatrix->_13 =  D3DVAL(0.0);
  195. lpd3dMatrix->_14 =  D3DVAL(0.0);
  196. lpd3dMatrix->_21 =  D3DVAL(0.0);
  197. lpd3dMatrix->_22 =  D3DVAL(2.0);
  198. lpd3dMatrix->_23 =  D3DVAL(0.0);
  199. lpd3dMatrix->_24 =  D3DVAL(0.0);
  200. lpd3dMatrix->_31 =  D3DVAL(0.0);
  201. lpd3dMatrix->_32 =  D3DVAL(0.0);
  202. lpd3dMatrix->_33 =  D3DVAL(dTmp1 * dTmp2);
  203. lpd3dMatrix->_34 =  D3DVAL(dTmp1);
  204. lpd3dMatrix->_41 =  D3DVAL(0.0);
  205. lpd3dMatrix->_42 =  D3DVAL(0.0);
  206. lpd3dMatrix->_43 =  D3DVAL(-dHalfHeight * dTmp2);
  207. lpd3dMatrix->_44 =  D3DVAL(0.0);
  208. }
  209. /***********************************************************************/
  210. void SetRotationAboutY(LPD3DMATRIX lpd3dMatrix, double dAngleOfRotation)
  211. {
  212. D3DVALUE dvCos;
  213. D3DVALUE dvSin;
  214. ATLASSERT(NULL != lpd3dMatrix);
  215. dvCos = D3DVAL(cos(dAngleOfRotation));
  216. dvSin = D3DVAL(sin(dAngleOfRotation));
  217. lpd3dMatrix->_11 =  dvCos;
  218. lpd3dMatrix->_12 =  D3DVAL(0.0);
  219. lpd3dMatrix->_13 = -dvSin;
  220. lpd3dMatrix->_14 =  D3DVAL(0.0);
  221. lpd3dMatrix->_21 =  D3DVAL(0.0);
  222. lpd3dMatrix->_22 =  D3DVAL(1.0);
  223. lpd3dMatrix->_23 =  D3DVAL(0.0);
  224. lpd3dMatrix->_24 =  D3DVAL(0.0);
  225. lpd3dMatrix->_31 =  dvSin;
  226. lpd3dMatrix->_32 =  D3DVAL(0.0);
  227. lpd3dMatrix->_33 =  dvCos;
  228. lpd3dMatrix->_34 =  D3DVAL(0.0);
  229. lpd3dMatrix->_41 =  D3DVAL(0.0);
  230. lpd3dMatrix->_42 =  D3DVAL(0.0);
  231. lpd3dMatrix->_43 =  D3DVAL(0.0);
  232. lpd3dMatrix->_44 =  D3DVAL(1.0);
  233. }
  234. /***********************************************************************/
  235. HRESULT CreateDirect3D(HWND hwnd)
  236. {
  237. HRESULT hRes;
  238. ATLASSERT(NULL == lpdd);
  239. ATLASSERT(NULL == lpd3d);
  240. hRes = DirectDrawCreate(NULL, &lpdd, NULL);
  241. if (FAILED(hRes))
  242. return hRes;
  243. hRes = lpdd->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
  244. if (FAILED(hRes))
  245. return hRes;
  246. hRes = lpdd->QueryInterface(IID_IDirect3D, (void**)&lpd3d);
  247. if (FAILED(hRes))
  248. return hRes;
  249. return DD_OK;
  250. }
  251. /***********************************************************************/
  252. HRESULT ReleaseDirect3D(void)
  253. {
  254. if (NULL != lpd3d)
  255. {
  256. lpd3d->Release();
  257. lpd3d = NULL;
  258. }
  259. if (NULL != lpdd)
  260. {
  261. lpdd->Release();
  262. lpdd = NULL;
  263. }
  264. return DD_OK;
  265. }
  266. /***********************************************************************/
  267. HRESULT CreatePrimary(HWND hwnd)
  268. {
  269. HRESULT             hRes;
  270. DDSURFACEDESC       ddsd;
  271. LPDIRECTDRAWCLIPPER lpddClipper;
  272. HDC                 hdc;
  273. int                 i;
  274. PALETTEENTRY        peColorTable[256];
  275. ATLASSERT(NULL != hwnd);
  276. ATLASSERT(NULL != lpdd);
  277. ATLASSERT(NULL == lpddPrimary);
  278. ATLASSERT(NULL == lpddPalette);
  279. /*
  280.  * Create the primary surface.
  281.  */
  282. ZeroMemory(&ddsd, sizeof(ddsd));
  283. ddsd.dwSize         = sizeof(ddsd);
  284. ddsd.dwFlags        = DDSD_CAPS;
  285. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  286. hRes = lpdd->CreateSurface(&ddsd, &lpddPrimary, NULL);
  287. if (FAILED(hRes))
  288. return hRes;
  289. /*
  290.  * Create the clipper. We bind the application's window to the
  291.  * clipper and attach it to the primary. This ensures then when we
  292.  * blit from the rendering surface to the primary we don't write
  293.  * outside the visible region of the window.
  294.  */
  295. hRes = DirectDrawCreateClipper(0UL, &lpddClipper, NULL);
  296. if (FAILED(hRes))
  297. return hRes;
  298. hRes = lpddClipper->SetHWnd(0UL, hwnd);
  299. if (FAILED(hRes))
  300. {
  301. lpddClipper->Release();
  302. return hRes;
  303. }
  304. hRes = lpddPrimary->SetClipper(lpddClipper);
  305. if (FAILED(hRes))
  306. {
  307. lpddClipper->Release();
  308. return hRes;
  309. }
  310. /*
  311.  * We release the clipper interface after attaching it to the surface
  312.  * as we don't need to use it again and the surface holds a reference
  313.  * to the clipper when its been attached. The clipper will therefore
  314.  * be released when the surface is released.
  315.  */
  316. lpddClipper->Release();
  317. /*
  318.  * If the primary is palettized then so will the rendering target (we
  319.  * ensure the rendering target has the same pixel format as the primary
  320.  * for optimal performance). Hence, if the primary is palettized we
  321.  * need to create a palette and attach it to the primary (and eventually
  322.  * to the rendering target).
  323.  *
  324.  * NOTE: We don't initialize the color table of the palette. We leave
  325.  * that upto Direct3D.
  326.  */
  327. ZeroMemory(&ddsd, sizeof(ddsd));
  328. ddsd.dwSize = sizeof(ddsd);
  329. hRes = lpddPrimary->GetSurfaceDesc(&ddsd);
  330. if (FAILED(hRes))
  331. return hRes;
  332. if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
  333. {
  334. /*
  335.  * The primary is palettized so create a palette and attach it to
  336.  * the primary.
  337.  */
  338. hdc = GetDC(NULL);
  339. GetSystemPaletteEntries(hdc, 0, 256, peColorTable);
  340. ReleaseDC(NULL, hdc);
  341. for (i = 0; i < 10; i++)
  342. peColorTable[i].peFlags = D3DPAL_READONLY;
  343. for (i = 10; i < 246; i++)
  344. peColorTable[i].peFlags = D3DPAL_FREE | PC_RESERVED;
  345. for (i = 246; i < 256; i++)
  346. peColorTable[i].peFlags = D3DPAL_READONLY;
  347. hRes = lpdd->CreatePalette(DDPCAPS_8BIT,
  348.    peColorTable,
  349.    &lpddPalette,
  350.    NULL);
  351. if (FAILED(hRes))
  352. return hRes;
  353. hRes = lpddPrimary->SetPalette(lpddPalette);
  354. return hRes;
  355. }
  356. return DD_OK;
  357. }
  358. /***********************************************************************/
  359. HRESULT RestorePrimary(void)
  360. {
  361. ATLASSERT(NULL != lpddPrimary);
  362. return lpddPrimary->Restore();
  363. }
  364. /***********************************************************************/
  365. HRESULT ReleasePrimary(void)
  366. {
  367. if (NULL != lpddPalette)
  368. {
  369. lpddPalette->Release();
  370. lpddPalette = NULL;
  371. }
  372. if (NULL != lpddPrimary)
  373. {
  374. lpddPrimary->Release();
  375. lpddPrimary = NULL;
  376. }
  377. return DD_OK;
  378. }
  379. /***********************************************************************/
  380. static HRESULT WINAPI EnumDeviceCallback(
  381. LPGUID          lpGUID,
  382. LPSTR           lpszDeviceDesc,
  383. LPSTR           lpszDeviceName,
  384. LPD3DDEVICEDESC lpd3dHWDeviceDesc,
  385. LPD3DDEVICEDESC lpd3dSWDeviceDesc,
  386. LPVOID          /* lpUserArg */)
  387. {
  388. BOOL            fIsHardware;
  389. LPD3DDEVICEDESC lpd3dDeviceDesc;
  390. /*
  391.  * If there is no hardware support then the color model is zero.
  392.  */
  393. fIsHardware     = (0UL != lpd3dHWDeviceDesc->dcmColorModel);
  394. lpd3dDeviceDesc = (fIsHardware ? lpd3dHWDeviceDesc : lpd3dSWDeviceDesc);
  395. /*
  396.  * Does the device render at the depth we want?
  397.  */
  398. if (0UL == (lpd3dDeviceDesc->dwDeviceRenderBitDepth & dwDeviceBitDepth))
  399. {
  400. /*
  401.  * No skip this device.
  402.  */
  403. return D3DENUMRET_OK;
  404. }
  405. /*
  406.  * The device must support gouraud shaded triangles.
  407.  */
  408. if (D3DCOLOR_MONO == lpd3dDeviceDesc->dcmColorModel)
  409. {
  410. if (!(lpd3dDeviceDesc->dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_COLORGOURAUDMONO))
  411. {
  412. /*
  413.  * No gouraud shading. Skip this device.
  414.  */
  415. return D3DENUMRET_OK;
  416. }
  417. }
  418. else
  419. {
  420. if (!(lpd3dDeviceDesc->dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_COLORGOURAUDRGB))
  421. {
  422. /*
  423.  * No gouraud shading. Skip this device.
  424.  */
  425. return D3DENUMRET_OK;
  426. }
  427. }
  428. if (!fIsHardware && fDeviceFound && (D3DCOLOR_RGB == lpd3dDeviceDesc->dcmColorModel))
  429. {
  430. /*
  431.  * If this is software RGB and we already have found a software
  432.  * mono already then we are not interested. Skip it.
  433.  */
  434. return D3DENUMRET_OK;
  435. }
  436. /*
  437.  * This is a device we are interested in. Cache its details away.
  438.  */
  439. fDeviceFound = TRUE;
  440. CopyMemory(&guidDevice, lpGUID, sizeof(GUID));
  441. strcpy(szDeviceDesc, lpszDeviceDesc);
  442. strcpy(szDeviceName, lpszDeviceName);
  443. CopyMemory(&d3dHWDeviceDesc, lpd3dHWDeviceDesc, sizeof(D3DDEVICEDESC));
  444. CopyMemory(&d3dSWDeviceDesc, lpd3dSWDeviceDesc, sizeof(D3DDEVICEDESC));
  445. /*
  446.  * If this is a hardware device we have found what we are looking
  447.  * for.
  448.  */
  449. if (fIsHardware)
  450. return D3DENUMRET_CANCEL;
  451. /*
  452.  * Keep going.
  453.  */
  454. return D3DENUMRET_OK;
  455. }
  456. /***********************************************************************/
  457. HRESULT ChooseDevice(void)
  458. {
  459. DDSURFACEDESC ddsd;
  460. HRESULT       hRes;
  461. ATLASSERT(NULL != lpd3d);
  462. ATLASSERT(NULL != lpddPrimary);
  463. /*
  464.  * As we are running in a window we will not be changing the screen
  465.  * depth and hence the pixel format of the rendering target must match
  466.  * the pixel format of the current primary. Therefore, we need to
  467.  * determine the pixel format of the primary.
  468.  */
  469. ZeroMemory(&ddsd, sizeof(ddsd));
  470. ddsd.dwSize = sizeof(ddsd);
  471. hRes = lpddPrimary->GetSurfaceDesc(&ddsd);
  472. if (FAILED(hRes))
  473. return hRes;
  474. dwDeviceBitDepth = BitDepthToFlags(ddsd.ddpfPixelFormat.dwRGBBitCount);
  475. /*
  476.  * Now we will enumerate the devices and pick the best match. The
  477.  * criteria for selecting the device are pretty simple. They are
  478.  * as follows:
  479.  *
  480.  * 1) Discard any device which does not support rendering at the
  481.  *    primary's display depth.
  482.  * 2) Favour hardware rasterizers over software ones unless we
  483.  *    are debugging (fDebug == TRUE) in which case we always
  484.  *    pick a software device.
  485.  */
  486. fDeviceFound = FALSE;
  487. hRes = lpd3d->EnumDevices(EnumDeviceCallback, &fDeviceFound);
  488. if (FAILED(hRes))
  489. return hRes;
  490. if (!fDeviceFound)
  491. {
  492. /*
  493.  * No suitable device was found. We have not alternative but to
  494.  * fail creation entirely.
  495.  */
  496. return DDERR_NOTFOUND;
  497. }
  498. return DD_OK;
  499. }
  500. /***********************************************************************/
  501. HRESULT CreateDevice(DWORD dwWidth, DWORD dwHeight)
  502. {
  503. LPD3DDEVICEDESC      lpd3dDeviceDesc;
  504. DWORD                dwDeviceMemType;
  505. DWORD                dwZBufferMemType;
  506. DDSURFACEDESC        ddsd;
  507. HRESULT              hRes;
  508. DWORD                dwZBufferBitDepth;
  509. ATLASSERT(NULL != lpdd);
  510. ATLASSERT(NULL != lpd3d);
  511. ATLASSERT(NULL != lpddPrimary);
  512. ATLASSERT(NULL == lpddDevice);
  513. /*
  514.  * The first step is to determine the kind of memory (system or
  515.  * video) from which the rendering target surface should be
  516.  * allocated.
  517.  */
  518. if (0UL != d3dHWDeviceDesc.dcmColorModel)
  519. {
  520. lpd3dDeviceDesc = &d3dHWDeviceDesc;
  521. /*
  522.  * Device has a hardware rasterizer. Currently this means that
  523.  * the rendering target must be in video memory.
  524.  */
  525. dwDeviceMemType  = DDSCAPS_VIDEOMEMORY;
  526. dwZBufferMemType = DDSCAPS_VIDEOMEMORY;
  527. }
  528. else
  529. {
  530. lpd3dDeviceDesc = &d3dSWDeviceDesc;
  531. /*
  532.  * Device has a software rasterizer. We will let DirectDraw
  533.  * decide where the rendering target resides unless we are
  534.  * running in debug mode in which case we will force it into
  535.  * system memory. For a software rasterizer the z-buffer should
  536.  * always go into system memory. A z-buffer in video memory will
  537.  * kill performance.
  538.  */
  539. dwDeviceMemType  = (m_bDebug ? DDSCAPS_SYSTEMMEMORY : 0UL);
  540. dwZBufferMemType = DDSCAPS_SYSTEMMEMORY;
  541. }
  542. /*
  543.  * Create the rendering target. The pixel format will be identical
  544.  * to the primary so we don't have to explicitly specify it. We do
  545.  * need to explicity specify the size, memory type and capabilities
  546.  * of the surface.
  547.  */
  548. ZeroMemory(&ddsd, sizeof(ddsd));
  549. ddsd.dwSize         = sizeof(ddsd);
  550. ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  551. ddsd.dwWidth        = dwWidth;
  552. ddsd.dwHeight       = dwHeight;
  553. ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN | dwDeviceMemType;
  554. hRes = lpdd->CreateSurface(&ddsd, &lpddDevice, NULL);
  555. if (FAILED(hRes))
  556. return hRes;
  557. /*
  558.  * If we have created a palette then we have already determined that
  559.  * the primary (and hence the rendering target) is palettized so
  560.  * attach the palette to the back buffer (its already attached to the
  561.  * front buffer).
  562.  */
  563. if (NULL != lpddPalette)
  564. {
  565. hRes = lpddDevice->SetPalette(lpddPalette);
  566. if (FAILED(hRes))
  567. return hRes;
  568. }
  569. /*
  570.  * We now determine whether we need a z-buffer or not and if so
  571.  * its depth and the kind of memory from which the z-buffer should
  572.  * be allocated.
  573.  */
  574. if (0UL != lpd3dDeviceDesc->dwDeviceZBufferBitDepth)
  575. {
  576. /*
  577.  * The device supports z-buffering. Determine the depth. We
  578.  * select the lowest supported z-buffer resolution to save
  579.  * memory. Accuracy is not too important for this demo.
  580.  */
  581. dwZBufferBitDepth = FlagsToBitDepth(lpd3dDeviceDesc->dwDeviceZBufferBitDepth);
  582. /*
  583.  * Create the z-buffer.
  584.  */
  585. ZeroMemory(&ddsd, sizeof(ddsd));
  586. ddsd.dwSize            = sizeof(ddsd);
  587. ddsd.dwFlags           = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
  588. ddsd.ddsCaps.dwCaps    = DDSCAPS_ZBUFFER | dwZBufferMemType;
  589. ddsd.dwWidth           = dwWidth;
  590. ddsd.dwHeight          = dwHeight;
  591. ddsd.dwZBufferBitDepth = dwZBufferBitDepth;
  592. hRes = lpdd->CreateSurface(&ddsd, &lpddZBuffer, NULL);
  593. if (FAILED(hRes))
  594. return hRes;
  595. /*
  596.  * Attach it to the rendering target.
  597.  */
  598. hRes = lpddDevice->AddAttachedSurface(lpddZBuffer);
  599. if (FAILED(hRes))
  600. return hRes;
  601. }
  602. /*
  603.  * Now we can actually get the Direct3D device interface.
  604.  */
  605. hRes = lpddDevice->QueryInterface(guidDevice, (void**)&lpd3dDevice);
  606. if (FAILED(hRes))
  607. return hRes;
  608. return DD_OK;
  609. }
  610. /***********************************************************************/
  611. HRESULT RestoreDevice(void)
  612. {
  613. HRESULT hRes;
  614. ATLASSERT(NULL != lpddZBuffer);
  615. ATLASSERT(NULL != lpddDevice);
  616. hRes = lpddZBuffer->Restore();
  617. if (FAILED(hRes))
  618. return hRes;
  619. hRes = lpddDevice->Restore();
  620. if (FAILED(hRes))
  621. return hRes;
  622. return DD_OK;
  623. }
  624. /***********************************************************************/
  625. HRESULT ReleaseDevice(void)
  626. {
  627. if (NULL != lpd3dDevice)
  628. {
  629. lpd3dDevice->Release();
  630. lpd3dDevice = NULL;
  631. }
  632. if (NULL != lpddZBuffer)
  633. {
  634. lpddZBuffer->Release();
  635. lpddZBuffer = NULL;
  636. }
  637. if (NULL != lpddDevice)
  638. {
  639. lpddDevice->Release();
  640. lpddDevice = NULL;
  641. }
  642. return DD_OK;
  643. }
  644. /***********************************************************************/
  645. HRESULT FillExecuteBuffer(void)
  646. {
  647. HRESULT              hRes;
  648. D3DEXECUTEBUFFERDESC d3dExeBufDesc;
  649. LPD3DVERTEX          lpVertex;
  650. LPD3DINSTRUCTION     lpInstruction;
  651. LPD3DPROCESSVERTICES lpProcessVertices;
  652. LPD3DTRIANGLE        lpTriangle;
  653. LPD3DSTATE           lpState;
  654. ATLASSERT(NULL != lpd3dExecuteBuffer);
  655. ATLASSERT(0UL  != hd3dSurfaceMaterial);
  656. ATLASSERT(0UL  != hd3dWorldMatrix);
  657. ATLASSERT(0UL  != hd3dViewMatrix);
  658. ATLASSERT(0UL  != hd3dProjMatrix);
  659. /*
  660.  * Lock the execute buffer.
  661.  */
  662. ZeroMemory(&d3dExeBufDesc, sizeof(d3dExeBufDesc));
  663. d3dExeBufDesc.dwSize = sizeof(d3dExeBufDesc);
  664. hRes = lpd3dExecuteBuffer->Lock(&d3dExeBufDesc);
  665. if (FAILED(hRes))
  666. return hRes;
  667. lpVertex = (LPD3DVERTEX)d3dExeBufDesc.lpData;
  668. /*
  669.  * First vertex.
  670.  */
  671. lpVertex->dvX  = D3DVAL( 0.0);
  672. lpVertex->dvY  = D3DVAL( 1.0);
  673. lpVertex->dvZ  = D3DVAL( 0.0);
  674. lpVertex->dvNX = D3DVAL( 0.0);
  675. lpVertex->dvNY = D3DVAL( 0.0);
  676. lpVertex->dvNZ = D3DVAL(-1.0);
  677. lpVertex->dvTU = D3DVAL( 0.0);
  678. lpVertex->dvTV = D3DVAL( 1.0);
  679. lpVertex++;
  680. /*
  681.  * Second vertex.
  682.  */
  683. lpVertex->dvX  = D3DVAL(-1.0);
  684. lpVertex->dvY  = D3DVAL(-1.0);
  685. lpVertex->dvZ  = D3DVAL( 0.0); // -0.3
  686. lpVertex->dvNX = D3DVAL( 0.0);
  687. lpVertex->dvNY = D3DVAL( 0.0);
  688. lpVertex->dvNZ = D3DVAL(-1.0);
  689. lpVertex->dvTU = D3DVAL( 1.0);
  690. lpVertex->dvTV = D3DVAL( 1.0);
  691. lpVertex++;
  692. /*
  693.  * Third vertex.
  694.  */
  695. lpVertex->dvX  = D3DVAL( 1.0);
  696. lpVertex->dvY  = D3DVAL(-1.0);
  697. lpVertex->dvZ  = D3DVAL( 0.0); // -0.3
  698. lpVertex->dvNX = D3DVAL( 0.0);
  699. lpVertex->dvNY = D3DVAL( 0.0);
  700. lpVertex->dvNZ = D3DVAL(-1.0);
  701. lpVertex->dvTU = D3DVAL( 1.0);
  702. lpVertex->dvTV = D3DVAL( 0.0);
  703. lpVertex++;
  704. #if 0
  705. /*
  706.  * Fourth vertex.
  707.  */
  708. lpVertex->dvX  = D3DVAL( 0.0);
  709. lpVertex->dvY  = D3DVAL(-1.0);
  710. lpVertex->dvZ  = D3DVAL( 1.044);
  711. lpVertex->dvNX = D3DVAL( 0.0);
  712. lpVertex->dvNY = D3DVAL( 0.0);
  713. lpVertex->dvNZ = D3DVAL(-1.0);
  714. lpVertex->dvTU = D3DVAL( 1.0);
  715. lpVertex->dvTV = D3DVAL( 0.0);
  716. lpVertex++;
  717. #endif
  718. /*
  719.  * Transform state - world, view and projection.
  720.  */
  721. lpInstruction = (LPD3DINSTRUCTION)lpVertex;
  722. lpInstruction->bOpcode = D3DOP_STATETRANSFORM;
  723. lpInstruction->bSize   = sizeof(D3DSTATE);
  724. lpInstruction->wCount  = 3U;
  725. lpInstruction++;
  726. lpState = (LPD3DSTATE)lpInstruction;
  727. lpState->dtstTransformStateType = D3DTRANSFORMSTATE_WORLD;
  728. lpState->dwArg[0] = hd3dWorldMatrix;
  729. lpState++;
  730. lpState->dtstTransformStateType = D3DTRANSFORMSTATE_VIEW;
  731. lpState->dwArg[0] = hd3dViewMatrix;
  732. lpState++;
  733. lpState->dtstTransformStateType = D3DTRANSFORMSTATE_PROJECTION;
  734. lpState->dwArg[0] = hd3dProjMatrix;
  735. lpState++;
  736. /*
  737.  * Lighting state.
  738.  */
  739. lpInstruction = (LPD3DINSTRUCTION)lpState;
  740. lpInstruction->bOpcode = D3DOP_STATELIGHT;
  741. lpInstruction->bSize   = sizeof(D3DSTATE);
  742. lpInstruction->wCount  = 2U;
  743. lpInstruction++;
  744. lpState = (LPD3DSTATE)lpInstruction;
  745. lpState->dlstLightStateType = D3DLIGHTSTATE_MATERIAL;
  746. lpState->dwArg[0] = hd3dSurfaceMaterial;
  747. lpState++;
  748. lpState->dlstLightStateType = D3DLIGHTSTATE_AMBIENT;
  749. lpState->dwArg[0] = RGBA_MAKE(128, 128, 128, 128);
  750. lpState++;
  751. /*
  752.  * Render state.
  753.  */
  754. lpInstruction = (LPD3DINSTRUCTION)lpState;
  755. lpInstruction->bOpcode = D3DOP_STATERENDER;
  756. lpInstruction->bSize = sizeof(D3DSTATE);
  757. lpInstruction->wCount = 3U;
  758. lpInstruction++;
  759. lpState = (LPD3DSTATE)lpInstruction;
  760. lpState->drstRenderStateType = D3DRENDERSTATE_FILLMODE;
  761. lpState->dwArg[0] = D3DFILL_SOLID;
  762. lpState++;
  763. lpState->drstRenderStateType = D3DRENDERSTATE_SHADEMODE;
  764. lpState->dwArg[0] = D3DSHADE_GOURAUD;
  765. lpState++;
  766. lpState->drstRenderStateType = D3DRENDERSTATE_DITHERENABLE;
  767. lpState->dwArg[0] = FALSE;
  768. lpState++;
  769. lpInstruction = (LPD3DINSTRUCTION)lpState;
  770. lpInstruction->bOpcode = D3DOP_PROCESSVERTICES;
  771. lpInstruction->bSize   = sizeof(D3DPROCESSVERTICES);
  772. lpInstruction->wCount  = 1U;
  773. lpInstruction++;
  774. lpProcessVertices = (LPD3DPROCESSVERTICES)lpInstruction;
  775. lpProcessVertices->dwFlags    = D3DPROCESSVERTICES_TRANSFORMLIGHT;
  776. lpProcessVertices->wStart     = 0U;
  777. lpProcessVertices->wDest      = 0U;
  778. lpProcessVertices->dwCount    = NUM_VERTICES;
  779. lpProcessVertices->dwReserved = 0UL;
  780. lpProcessVertices++;
  781. /*
  782.  * Triangle.
  783.  */
  784. lpInstruction = (LPD3DINSTRUCTION)lpProcessVertices;
  785. lpInstruction->bOpcode = D3DOP_TRIANGLE;
  786. lpInstruction->bSize   = sizeof(D3DTRIANGLE);
  787. lpInstruction->wCount  = NUM_TRIANGLES;
  788. lpInstruction++;
  789. lpTriangle = (LPD3DTRIANGLE)lpInstruction;
  790. lpTriangle->wV1    = 2U;
  791. lpTriangle->wV2    = 1U;
  792. lpTriangle->wV3    = 0U;
  793. lpTriangle->wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE;
  794. lpTriangle++;
  795. #if 0
  796. lpTriangle->wV1    = 2U;
  797. lpTriangle->wV2    = 0U;
  798. lpTriangle->wV3    = 3U;
  799. lpTriangle->wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE || D3DTRIFLAG_EVEN;
  800. lpTriangle++;
  801. lpTriangle->wV1    = 3U;
  802. lpTriangle->wV2    = 0U;
  803. lpTriangle->wV3    = 1U;
  804. lpTriangle->wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE || D3DTRIFLAG_ODD;
  805. lpTriangle++;
  806. #endif
  807. lpInstruction = (LPD3DINSTRUCTION)lpTriangle;
  808. lpInstruction->bOpcode = D3DOP_EXIT;
  809. lpInstruction->bSize   = 0UL;
  810. lpInstruction->wCount  = 0U;
  811. /*
  812.  * Unlock the execute buffer.
  813.  */
  814. lpd3dExecuteBuffer->Unlock();
  815. return DD_OK;
  816. }
  817. /***********************************************************************/
  818. HRESULT CreateScene(void)
  819. {
  820. HRESULT              hRes;
  821. D3DMATERIAL          d3dMaterial;
  822. D3DLIGHT             d3dLight;
  823. DWORD                dwVertexSize;
  824. DWORD                dwInstructionSize;
  825. DWORD                dwExecuteBufferSize;
  826. D3DEXECUTEBUFFERDESC d3dExecuteBufferDesc;
  827. D3DEXECUTEDATA       d3dExecuteData;
  828. ATLASSERT(NULL != lpd3d);
  829. ATLASSERT(NULL != lpd3dDevice);
  830. ATLASSERT(NULL == lpd3dViewport);
  831. ATLASSERT(NULL == lpd3dMaterial);
  832. ATLASSERT(NULL == lpd3dBackgroundMaterial);
  833. ATLASSERT(NULL == lpd3dExecuteBuffer);
  834. ATLASSERT(NULL == lpd3dLight);
  835. ATLASSERT(0UL  == hd3dWorldMatrix);
  836. ATLASSERT(0UL  == hd3dViewMatrix);
  837. ATLASSERT(0UL  == hd3dProjMatrix);
  838. /*
  839.  * Create a light.
  840.  */
  841. hRes = lpd3d->CreateLight(&lpd3dLight, NULL);
  842. if (FAILED(hRes))
  843. return hRes;
  844. ZeroMemory(&d3dLight, sizeof(d3dLight));
  845. d3dLight.dwSize = sizeof(d3dLight);
  846. d3dLight.dltType = D3DLIGHT_POINT;
  847. d3dLight.dcvColor.dvR    = D3DVAL( 1.0);
  848. d3dLight.dcvColor.dvG    = D3DVAL( 1.0);
  849. d3dLight.dcvColor.dvB    = D3DVAL( 1.0);
  850. d3dLight.dcvColor.dvA    = D3DVAL( 1.0);
  851. d3dLight.dvPosition.dvX  = D3DVAL( 1.0);
  852. d3dLight.dvPosition.dvY  = D3DVAL(-1.0);
  853. d3dLight.dvPosition.dvZ  = D3DVAL(-1.0);
  854. d3dLight.dvAttenuation0  = D3DVAL( 1.0);
  855. d3dLight.dvAttenuation1  = D3DVAL( 0.1);
  856. d3dLight.dvAttenuation2  = D3DVAL( 0.0);
  857. hRes = lpd3dLight->SetLight(&d3dLight);
  858. if (FAILED(hRes))
  859. return hRes;
  860. /*
  861.  * Create the background material.
  862.  */
  863. hRes = lpd3d->CreateMaterial(&lpd3dBackgroundMaterial, NULL);
  864. if (FAILED(hRes))
  865. return hRes;
  866. ZeroMemory(&d3dMaterial, sizeof(d3dMaterial));
  867. d3dMaterial.dwSize = sizeof(d3dMaterial);
  868. d3dMaterial.dcvDiffuse.r  = D3DVAL(0.0);
  869. d3dMaterial.dcvDiffuse.g  = D3DVAL(0.0);
  870. d3dMaterial.dcvDiffuse.b  = D3DVAL(0.0);
  871. d3dMaterial.dcvAmbient.r  = D3DVAL(0.0);
  872. d3dMaterial.dcvAmbient.g  = D3DVAL(0.0);
  873. d3dMaterial.dcvAmbient.b  = D3DVAL(0.0);
  874. d3dMaterial.dcvSpecular.r = D3DVAL(0.0);
  875. d3dMaterial.dcvSpecular.g = D3DVAL(0.0);
  876. d3dMaterial.dcvSpecular.b = D3DVAL(0.0);
  877. d3dMaterial.dvPower       = D3DVAL(0.0);
  878. d3dMaterial.dwRampSize    = 1UL;
  879. hRes = lpd3dBackgroundMaterial->SetMaterial(&d3dMaterial);
  880. if (FAILED(hRes))
  881. return hRes;
  882. hRes = lpd3dBackgroundMaterial->GetHandle(lpd3dDevice, &hd3dBackgroundMaterial);
  883. if (FAILED(hRes))
  884. return hRes;
  885. /*
  886.  * Create the viewport.
  887.  */
  888. hRes = lpd3d->CreateViewport(&lpd3dViewport, NULL);
  889. if (FAILED(hRes))
  890. return hRes;
  891. hRes = lpd3dDevice->AddViewport(lpd3dViewport);
  892. if (FAILED(hRes))
  893. return hRes;
  894. hRes = lpd3dViewport->SetBackground(hd3dBackgroundMaterial);
  895. if (FAILED(hRes))
  896. return hRes;
  897. hRes = lpd3dViewport->AddLight(lpd3dLight);
  898. if (FAILED(hRes))
  899. return hRes;
  900. /*
  901.  * Create the matrices.
  902.  */
  903. hRes = lpd3dDevice->CreateMatrix(&hd3dWorldMatrix);
  904. if (FAILED(hRes))
  905. return hRes;
  906. hRes = lpd3dDevice->SetMatrix(hd3dWorldMatrix, &d3dWorldMatrix);
  907. if (FAILED(hRes))
  908. return hRes;
  909. hRes = lpd3dDevice->CreateMatrix(&hd3dViewMatrix);
  910. if (FAILED(hRes))
  911. return hRes;
  912. hRes = lpd3dDevice->SetMatrix(hd3dViewMatrix, &d3dViewMatrix);
  913. if (FAILED(hRes))
  914. return hRes;
  915. hRes = lpd3dDevice->CreateMatrix(&hd3dProjMatrix);
  916. if (FAILED(hRes))
  917. return hRes;
  918. SetPerspectiveProjection(&d3dProjMatrix, HALF_HEIGHT, FRONT_CLIP, BACK_CLIP);
  919. hRes = lpd3dDevice->SetMatrix(hd3dProjMatrix, &d3dProjMatrix);
  920. if (FAILED(hRes))
  921. return hRes;
  922. /*
  923.  * Create the material.
  924.  */
  925. hRes = lpd3d->CreateMaterial(&lpd3dMaterial, NULL);
  926. if (FAILED(hRes))
  927. return hRes;
  928. ZeroMemory(&d3dMaterial, sizeof(d3dMaterial));
  929. d3dMaterial.dwSize = sizeof(d3dMaterial);
  930. /*
  931.  * Base green with white specular.
  932.  */
  933. d3dMaterial.dcvDiffuse.r  = D3DVAL(0.0);
  934. d3dMaterial.dcvDiffuse.g  = D3DVAL(1.0);
  935. d3dMaterial.dcvDiffuse.b  = D3DVAL(0.0);
  936. d3dMaterial.dcvAmbient.r  = D3DVAL(0.0);
  937. d3dMaterial.dcvAmbient.g  = D3DVAL(0.4);
  938. d3dMaterial.dcvAmbient.b  = D3DVAL(0.0);
  939. d3dMaterial.dcvSpecular.r = D3DVAL(1.0);
  940. d3dMaterial.dcvSpecular.g = D3DVAL(1.0);
  941. d3dMaterial.dcvSpecular.b = D3DVAL(1.0);
  942. d3dMaterial.dvPower       = D3DVAL(20.0);
  943. d3dMaterial.dwRampSize    = 256UL;
  944. hRes = lpd3dMaterial->SetMaterial(&d3dMaterial);
  945. if (FAILED(hRes))
  946. return hRes;
  947. hRes = lpd3dMaterial->GetHandle(lpd3dDevice, &hd3dSurfaceMaterial);
  948. if (FAILED(hRes))
  949. return hRes;
  950. /*
  951.  * Build the execute buffer.
  952.  */
  953. dwVertexSize        = (NUM_VERTICES        * sizeof(D3DVERTEX));
  954. dwInstructionSize   = (NUM_INSTRUCTIONS    * sizeof(D3DINSTRUCTION))     +
  955.   (NUM_STATES          * sizeof(D3DSTATE))           +
  956.   (NUM_PROCESSVERTICES * sizeof(D3DPROCESSVERTICES)) +
  957.   (NUM_TRIANGLES       * sizeof(D3DTRIANGLE));
  958. dwExecuteBufferSize = dwVertexSize + dwInstructionSize;
  959. ZeroMemory(&d3dExecuteBufferDesc, sizeof(d3dExecuteBufferDesc));
  960. d3dExecuteBufferDesc.dwSize       = sizeof(d3dExecuteBufferDesc);
  961. d3dExecuteBufferDesc.dwFlags      = D3DDEB_BUFSIZE;
  962. d3dExecuteBufferDesc.dwBufferSize = dwExecuteBufferSize;
  963. hRes = lpd3dDevice->CreateExecuteBuffer(&d3dExecuteBufferDesc,
  964. &lpd3dExecuteBuffer,
  965. NULL);
  966. if (FAILED(hRes))
  967. return hRes;
  968. hRes = FillExecuteBuffer();
  969. if (FAILED(hRes))
  970. return hRes;
  971. ZeroMemory(&d3dExecuteData, sizeof(d3dExecuteData));
  972. d3dExecuteData.dwSize = sizeof(d3dExecuteData);
  973. d3dExecuteData.dwVertexCount       = NUM_VERTICES;
  974. d3dExecuteData.dwInstructionOffset = dwVertexSize;
  975. d3dExecuteData.dwInstructionLength = dwInstructionSize;
  976. hRes = lpd3dExecuteBuffer->SetExecuteData(&d3dExecuteData);
  977. if (FAILED(hRes))
  978. return hRes;
  979. return DD_OK;
  980. }
  981. /***********************************************************************/
  982. HRESULT ReleaseScene(void)
  983. {
  984. if (NULL != lpd3dExecuteBuffer)
  985. {
  986. lpd3dExecuteBuffer->Release();
  987. lpd3dExecuteBuffer = NULL;
  988. }
  989. if (NULL != lpd3dBackgroundMaterial)
  990. {
  991. lpd3dBackgroundMaterial->Release();
  992. lpd3dBackgroundMaterial = NULL;
  993. }
  994. if (NULL != lpd3dMaterial)
  995. {
  996. lpd3dMaterial->Release();
  997. lpd3dMaterial = NULL;
  998. }
  999. if (0UL != hd3dWorldMatrix)
  1000. {
  1001. lpd3dDevice->DeleteMatrix(hd3dWorldMatrix);
  1002. hd3dWorldMatrix = 0UL;
  1003. }
  1004. if (0UL != hd3dViewMatrix)
  1005. {
  1006. lpd3dDevice->DeleteMatrix(hd3dViewMatrix);
  1007. hd3dViewMatrix = 0UL;
  1008. }
  1009. if (0UL != hd3dProjMatrix)
  1010. {
  1011. lpd3dDevice->DeleteMatrix(hd3dProjMatrix);
  1012. hd3dProjMatrix = 0UL;
  1013. }
  1014. if (NULL != lpd3dLight)
  1015. {
  1016. lpd3dLight->Release();
  1017. lpd3dLight = NULL;
  1018. }
  1019. if (NULL != lpd3dViewport)
  1020. {
  1021. lpd3dViewport->Release();
  1022. lpd3dViewport = NULL;
  1023. }
  1024. return DD_OK;
  1025. }
  1026. /***********************************************************************/
  1027. HRESULT TickScene(void)
  1028. {
  1029. HRESULT hRes;
  1030. ATLASSERT(NULL != lpd3dDevice);
  1031. ATLASSERT(0UL  != hd3dWorldMatrix);
  1032. /*
  1033.  * We rotate the triangle by setting thr world transform to a
  1034.  * rotation matrix.
  1035.  */
  1036. SetRotationAboutY(&d3dWorldMatrix, m_dAngleOfRotation);
  1037. m_dAngleOfRotation += ROTATE_ANGLE_DELTA;
  1038. hRes = lpd3dDevice->SetMatrix(hd3dWorldMatrix, &d3dWorldMatrix);
  1039. if (FAILED(hRes))
  1040. return hRes;
  1041. return DD_OK;
  1042. }
  1043. /***********************************************************************/
  1044. HRESULT UpdateViewport(void)
  1045. {
  1046. D3DVIEWPORT d3dViewport;
  1047. ATLASSERT(NULL != lpd3dViewport);
  1048. ZeroMemory(&d3dViewport, sizeof(d3dViewport));
  1049. d3dViewport.dwSize   = sizeof(d3dViewport);
  1050. d3dViewport.dwX      = 0UL;
  1051. d3dViewport.dwY      = 0UL;
  1052. d3dViewport.dwWidth  = (DWORD)m_rcSrc.right;
  1053. d3dViewport.dwHeight = (DWORD)m_rcSrc.bottom;
  1054. d3dViewport.dvScaleX = D3DVAL((float)d3dViewport.dwWidth / 2.0);
  1055. d3dViewport.dvScaleY = D3DVAL((float)d3dViewport.dwHeight / 2.0);
  1056. d3dViewport.dvMaxX   = D3DVAL(1.0);
  1057. d3dViewport.dvMaxY   = D3DVAL(1.0);
  1058. return lpd3dViewport->SetViewport(&d3dViewport);
  1059. }
  1060. /***********************************************************************/
  1061. HRESULT RenderScene(void)
  1062. {
  1063. HRESULT hRes;
  1064. D3DRECT d3dRect;
  1065. ATLASSERT(NULL != lpd3dViewport);
  1066. ATLASSERT(NULL != lpd3dDevice);
  1067. ATLASSERT(NULL != lpd3dExecuteBuffer);
  1068. /*
  1069.  * Clear both back and z-buffer.
  1070.  */
  1071. d3dRect.lX1 = m_rcSrc.left;
  1072. d3dRect.lX2 = m_rcSrc.right;
  1073. d3dRect.lY1 = m_rcSrc.top;
  1074. d3dRect.lY2 = m_rcSrc.bottom;
  1075. hRes = lpd3dViewport->Clear(1UL,
  1076. &d3dRect,
  1077. D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
  1078. if (FAILED(hRes))
  1079. return hRes;
  1080. /*
  1081.  * Start the scene.
  1082.  */
  1083. hRes = lpd3dDevice->BeginScene();
  1084. if (FAILED(hRes))
  1085. return hRes;
  1086. /*
  1087.  * Submit the execute buffer.
  1088.  */
  1089. hRes = lpd3dDevice->Execute(lpd3dExecuteBuffer,
  1090. lpd3dViewport,
  1091. D3DEXECUTE_CLIPPED);
  1092. if (FAILED(hRes))
  1093. {
  1094. lpd3dDevice->EndScene();
  1095. return hRes;
  1096. }
  1097. /*
  1098.  * End the scene.
  1099.  */
  1100. hRes = lpd3dDevice->EndScene();
  1101. if (FAILED(hRes))
  1102. return hRes;
  1103. return DD_OK;
  1104. }
  1105. /***********************************************************************/
  1106. HRESULT DoFrame(void)
  1107. {
  1108. HRESULT hRes;
  1109. hRes = RenderScene();
  1110. if (SUCCEEDED(hRes))
  1111. hRes = PaintClient();
  1112. while (DDERR_SURFACELOST == hRes)
  1113. {
  1114. hRes = RestoreSurfaces();
  1115. if (SUCCEEDED(hRes))
  1116. hRes = RenderScene();
  1117. if (SUCCEEDED(hRes))
  1118. hRes = PaintClient();
  1119. }
  1120. return hRes;
  1121. }
  1122. /***********************************************************************/
  1123. HRESULT PaintClient(void)
  1124. {
  1125. if ((NULL != lpddPrimary) && (NULL != lpddDevice))
  1126. {
  1127. return lpddPrimary->Blt(&m_rcDst,
  1128.    lpddDevice,
  1129.    &m_rcSrc,
  1130.    DDBLT_WAIT,
  1131.    NULL);
  1132. }
  1133. else
  1134. {
  1135. return DD_OK;
  1136. }
  1137. }
  1138. /***********************************************************************/
  1139. LRESULT RestoreSurfaces(void)
  1140. {
  1141. HRESULT hRes;
  1142. hRes = RestorePrimary();
  1143. if (FAILED(hRes))
  1144. return hRes;
  1145. hRes = RestoreDevice();
  1146. if (FAILED(hRes))
  1147. return hRes;
  1148. return DD_OK;
  1149. }
  1150. /***********************************************************************/
  1151. LRESULT OnCreate(HWND hwnd, const RECT& rcPos)
  1152. {
  1153. HRESULT hRes;
  1154. // Store our initial position
  1155. m_rcDst = rcPos;
  1156. hRes = CreateDirect3D(hwnd);
  1157. if (FAILED(hRes))
  1158. {
  1159. ReportError(hwnd, "Could not initialize DirectDraw and Direct3D", hRes);
  1160. return -1L;
  1161. }
  1162. hRes = CreatePrimary(hwnd);
  1163. if (FAILED(hRes))
  1164. {
  1165. ReportError(hwnd, "Could not create the primary surface", hRes);
  1166. return -1L;
  1167. }
  1168. hRes = ChooseDevice();
  1169. if (FAILED(hRes))
  1170. {
  1171. ReportError(hwnd, "Could not find a suitable Direct3D device", hRes);
  1172. return -1L;
  1173. }
  1174. return 0L;
  1175. }
  1176. /***********************************************************************/
  1177. LRESULT OnMove(HWND /* hwnd */, int x, int y)
  1178. {
  1179. int     xDelta;
  1180. int     yDelta;
  1181. /*
  1182.  * Don't bother doing any of this stuff if we are shutting down.
  1183.  */
  1184. if (!m_bShuttingDown)
  1185. {
  1186. /*
  1187.  * Update the destination rectangle for the new client position.
  1188.  */
  1189. xDelta = x - m_rcDst.left;
  1190. yDelta = y - m_rcDst.top;
  1191. m_rcDst.left   += xDelta;
  1192. m_rcDst.top    += yDelta;
  1193. m_rcDst.right  += xDelta;
  1194. m_rcDst.bottom += yDelta;
  1195. }
  1196. return 0L;
  1197. }
  1198. /***********************************************************************/
  1199. LRESULT OnSize(HWND hwnd, int w, int h)
  1200. {
  1201. HRESULT       hRes;
  1202. DDSURFACEDESC ddsd;
  1203. /*
  1204.  * Again no point in doing this stuff if we are in the process
  1205.  * of shutting down.
  1206.  */
  1207. if (!m_bIsSuspended && !m_bShuttingDown)
  1208. {
  1209. m_rcDst.right  = m_rcDst.left + w;
  1210. m_rcDst.bottom = m_rcDst.top  + h;
  1211. m_rcSrc.top = 0;
  1212. m_rcSrc.left    = 0;
  1213. m_rcSrc.right  = w;
  1214. m_rcSrc.bottom = h;
  1215. if (NULL != lpd3dDevice)
  1216. {
  1217. /*
  1218.  * We already have a device. But is it big enough for the the
  1219.  * new window client size?
  1220.  */
  1221. ZeroMemory(&ddsd, sizeof(ddsd));
  1222. ddsd.dwSize = sizeof(ddsd);
  1223. hRes = lpddDevice->GetSurfaceDesc(&ddsd);
  1224. if (FAILED(hRes))
  1225. {
  1226. FatalError(hwnd, "Could not get the size of the 3D surface", hRes);
  1227. return 0L;
  1228. }
  1229. if ((w > (int)ddsd.dwWidth) || (h > (int)ddsd.dwHeight))
  1230. {
  1231. /*
  1232.  * Nope, the device is too small. We need to shut it down
  1233.  * and rebuild it.
  1234.  */
  1235. ReleaseScene();
  1236. ReleaseDevice();
  1237. }
  1238. }
  1239. if (NULL == lpd3dDevice)
  1240. {
  1241. /*
  1242.  * No Direct3D device yet. This is either because this is the
  1243.  * first time through the loop or because we discarded the
  1244.  * existing device because it was not big enough for the new
  1245.  * window client size.
  1246.  */
  1247. hRes = CreateDevice((DWORD)w, (DWORD)h);
  1248. if (FAILED(hRes))
  1249. {
  1250. FatalError(hwnd, "Could not recreate the Direct3D device", hRes);
  1251. return 0L;
  1252. }
  1253. hRes = CreateScene();
  1254. if (FAILED(hRes))
  1255. {
  1256. FatalError(hwnd, "Could not recreate the 3D scene", hRes);
  1257. return 0L;
  1258. }
  1259. }
  1260. hRes = UpdateViewport();
  1261. if (FAILED(hRes))
  1262. {
  1263. FatalError(hwnd, "Could not update the 3D viewport", hRes);
  1264. return 0L;
  1265. }
  1266. #if 0
  1267. hRes = DoFrame();
  1268. if (FAILED(hRes))
  1269. {
  1270. FatalError(hwnd, "Could not show the 3D scene", hRes);
  1271. return 0L;
  1272. }
  1273. #endif
  1274. }
  1275. return 0L;
  1276. }
  1277. /***********************************************************************/
  1278. LRESULT OnPaint(HWND hwnd, HDC /* hdc */, LPPAINTSTRUCT /* lpps */)
  1279. {
  1280. HRESULT hRes;
  1281. if (m_bIsActive && !m_bIsSuspended & !m_bShuttingDown)
  1282. {
  1283. hRes = DoFrame();
  1284. if (FAILED(hRes))
  1285. {
  1286. FatalError(hwnd, "Could not show the 3D scene", hRes);
  1287. return 0L;
  1288. }
  1289. }
  1290. return 0L;
  1291. }
  1292. /***********************************************************************/
  1293. LRESULT SetPalette()
  1294. {
  1295. if (m_bIsActive && !m_bIsSuspended && !m_bShuttingDown)
  1296. {
  1297. if (NULL != lpddPalette)
  1298. lpddPrimary->SetPalette(lpddPalette);
  1299. }
  1300. return 0L;
  1301. }
  1302. /***********************************************************************/
  1303. private:
  1304. // DirectDraw interfaces
  1305. LPDIRECTDRAW            lpdd;
  1306. LPDIRECTDRAWSURFACE     lpddPrimary;
  1307. LPDIRECTDRAWSURFACE     lpddDevice;
  1308. LPDIRECTDRAWSURFACE     lpddZBuffer;
  1309. LPDIRECTDRAWPALETTE     lpddPalette;
  1310. // Direct3D interfaces
  1311. LPDIRECT3D              lpd3d;
  1312. LPDIRECT3DDEVICE        lpd3dDevice;
  1313. LPDIRECT3DMATERIAL      lpd3dMaterial;
  1314. LPDIRECT3DMATERIAL      lpd3dBackgroundMaterial;
  1315. LPDIRECT3DVIEWPORT      lpd3dViewport;
  1316. LPDIRECT3DLIGHT         lpd3dLight;
  1317. LPDIRECT3DEXECUTEBUFFER lpd3dExecuteBuffer;
  1318. // Direct3D handles
  1319. D3DMATRIXHANDLE         hd3dWorldMatrix;
  1320. D3DMATRIXHANDLE         hd3dViewMatrix;
  1321. D3DMATRIXHANDLE         hd3dProjMatrix;
  1322. D3DMATERIALHANDLE       hd3dSurfaceMaterial;
  1323. D3DMATERIALHANDLE       hd3dBackgroundMaterial;
  1324. // The screen coordinates of the client area of the window. This
  1325. // rectangle defines the destination into which we blit to update
  1326. // the client area of the window with the results of the 3D rendering.
  1327. RECT m_rcDst;
  1328. // This rectangle defines the portion of the rendering target surface
  1329. // into which we render. The top left coordinates of this rectangle
  1330. // are always zero and the right and bottom give the size of the
  1331. // viewport.
  1332. RECT m_rcSrc;
  1333. BOOL m_bIsActive;
  1334. BOOL m_bIsSuspended;
  1335. BOOL m_bShuttingDown;
  1336. BOOL m_bDebug;
  1337. // Angle of rotation of the world matrix.
  1338. double m_dAngleOfRotation;
  1339. // Predefined transformations
  1340. CD3DMatrix d3dWorldMatrix;
  1341. CD3DMatrix d3dViewMatrix;
  1342. CD3DMatrix d3dProjMatrix;
  1343. };