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.

564 lines
19 KiB

  1. /*****************************************************************************\
  2. FILE: object.cpp
  3. DESCRIPTION:
  4. The caller will tell us what shape they want. Normally a rectangle on a
  5. plane or a sphere. We will then create the number vertexs the caller wants
  6. for that objectand create texture coordinates.
  7. BryanSt 12/24/2000
  8. Copyright (C) Microsoft Corp 2000-2001. All rights reserved.
  9. \*****************************************************************************/
  10. #include "stdafx.h"
  11. #include "util.h"
  12. #include "room.h"
  13. #include "object.h"
  14. int g_nTrianglesRenderedInThisFrame = 0;
  15. C3DObject::C3DObject(CMSLogoDXScreenSaver * pMain)
  16. {
  17. // Initialize member variables
  18. m_pTexture = NULL;
  19. m_pdwIndices = NULL;
  20. m_dwNumVer = 0;
  21. m_dwNumIndeces = 0;
  22. m_pvVertexs = NULL;
  23. m_pMain = pMain;
  24. for (int nIndex = 0; nIndex < ARRAYSIZE(m_pIndexBuff); nIndex++)
  25. {
  26. m_pVB[nIndex] = NULL;
  27. m_pIndexBuff[nIndex] = NULL;
  28. }
  29. m_pNextObject = NULL;
  30. }
  31. C3DObject::~C3DObject()
  32. {
  33. SAFE_RELEASE(m_pTexture);
  34. SAFE_DELETE(m_pdwIndices);
  35. SAFE_DELETE(m_pvVertexs);
  36. SAFE_DELETE(m_pNextObject);
  37. _PurgeDeviceObjects();
  38. }
  39. HRESULT C3DObject::InitPlaneStretch(CTexture * pTexture, IDirect3DDevice8 * pD3DDevice, D3DXVECTOR3 vLocation, D3DXVECTOR3 vSize, D3DXVECTOR3 vNormal,
  40. int nNumVertexX, int nNumVertexY, DWORD dwMaxPixelSize)
  41. {
  42. D3DXVECTOR3 vWidth;
  43. D3DXVECTOR3 vHeight;
  44. if (vNormal.x)
  45. {
  46. vWidth = D3DXVECTOR3(0, 0, 1);
  47. vHeight = D3DXVECTOR3(0, 1, 0);
  48. }
  49. else if (vNormal.y)
  50. {
  51. vWidth = D3DXVECTOR3(0, 0, 1);
  52. vHeight = D3DXVECTOR3(1, 0, 0);
  53. }
  54. else
  55. {
  56. vWidth = D3DXVECTOR3(1, 0, 0);
  57. vHeight = D3DXVECTOR3(0, 1, 0);
  58. }
  59. float fTextureX = (1.0f / AddVectorComponents(D3DXVec3Multiply(vSize, vWidth)));
  60. float fTextureY = (1.0f / AddVectorComponents(D3DXVec3Multiply(vSize, vHeight)));
  61. return InitPlane(pTexture, pD3DDevice, vLocation, vSize, vNormal, nNumVertexX, nNumVertexY,
  62. fTextureX, fTextureY, dwMaxPixelSize, 0.0f);
  63. }
  64. /*****************************************************************************\
  65. DESCRIPTION:
  66. This function needs to force pvSize to be positive, but ajusting pvLocation.
  67. This is necessary in order to get the normal vectors for the verticies correct
  68. or the triangle will be culled from the user's view.
  69. \*****************************************************************************/
  70. HRESULT C3DObject::_ForPositiveSize(D3DXVECTOR3 * pvLocation, D3DXVECTOR3 * pvSize)
  71. {
  72. if (0 > pvSize->x)
  73. {
  74. pvLocation->x += pvSize->x;
  75. pvSize->x = -pvSize->x;
  76. }
  77. if (0 > pvSize->y)
  78. {
  79. pvLocation->y += pvSize->y;
  80. pvSize->y = -pvSize->y;
  81. }
  82. if (0 > pvSize->z)
  83. {
  84. pvLocation->z += pvSize->z;
  85. pvSize->z = -pvSize->z;
  86. }
  87. return S_OK;
  88. }
  89. /*****************************************************************************\
  90. DESCRIPTION:
  91. This function will create an object which is a plane with pTexture on the
  92. surface. It will be a grid of nNumVertexX by nNumVertexY.
  93. PARAMETERS:
  94. fTextureScaleX: This is the number patterns to repeat in a 1.0f of space.
  95. \*****************************************************************************/
  96. HRESULT C3DObject::InitPlane(CTexture * pTexture, IDirect3DDevice8 * pD3DDevice, D3DXVECTOR3 vLocation, D3DXVECTOR3 vSize, D3DXVECTOR3 vNormal,
  97. int nNumVertexX, int nNumVertexY, float fTextureScaleX, float fTextureScaleY,
  98. DWORD dwMaxPixelSize, float fVisibleRadius)
  99. {
  100. HRESULT hr = E_INVALIDARG;
  101. _ForPositiveSize(&vLocation, &vSize);
  102. _PurgeDeviceObjects();
  103. m_vMin = vLocation;
  104. m_vMax = vLocation + vSize;
  105. SAFE_DELETE(m_pdwIndices);
  106. SAFE_DELETE(m_pvVertexs);
  107. if (pD3DDevice && (nNumVertexX > 1) && (nNumVertexY > 1))
  108. {
  109. D3DXVECTOR3 vWidth;
  110. D3DXVECTOR3 vHeight;
  111. BOOL fFlipOrder = FALSE;
  112. BOOL fFlipTexture = FALSE;
  113. IUnknown_Set((IUnknown **) &m_pTexture, (IUnknown *) pTexture);
  114. //AssertMsg(((nNumVertexX > 1) && (nNumVertexY > 1)), TEXT("Grid needs to be larger."));
  115. if (vNormal.x)
  116. {
  117. // Flip the order of the triangle vectors.
  118. vWidth = D3DXVECTOR3(0, 0, 1);
  119. vHeight = D3DXVECTOR3(0, 1, 0);
  120. }
  121. else if (vNormal.y)
  122. {
  123. fFlipOrder = TRUE;
  124. vWidth = D3DXVECTOR3(0, 0, 1);
  125. vHeight = D3DXVECTOR3(1, 0, 0);
  126. }
  127. else
  128. {
  129. // Flip the order of the triangle vectors.
  130. fFlipOrder = TRUE;
  131. vWidth = D3DXVECTOR3(1, 0, 0);
  132. vHeight = D3DXVECTOR3(0, 1, 0);
  133. }
  134. if ((0 > vNormal.x) || (0 < vNormal.z))
  135. {
  136. fFlipTexture = TRUE;
  137. }
  138. if (0 < AddVectorComponents(vNormal))
  139. {
  140. fFlipOrder = !fFlipOrder;
  141. }
  142. D3DXMatrixIdentity(&m_matIdentity);
  143. m_dwNumVer = (nNumVertexX * nNumVertexY);
  144. m_dwNumIndeces = (6 * ((nNumVertexX - 1) * (nNumVertexY - 1)));
  145. m_pdwIndices = new WORD[m_dwNumIndeces];
  146. if (m_pdwIndices)
  147. {
  148. m_pvVertexs = new MYVERTEX[m_dwNumVer];
  149. if (m_pvVertexs)
  150. {
  151. int nVerticies = 0;
  152. hr = S_OK;
  153. for (int nCurrentY = 0; nCurrentY < nNumVertexY; nCurrentY++)
  154. {
  155. for (int nCurrentX = 0; nCurrentX < nNumVertexX; nCurrentX++)
  156. {
  157. D3DXVECTOR3 vThisSize = ( D3DXVec3Multiply( (((float)nCurrentY)*vHeight), (vSize / ((float)(nNumVertexY - 1))) ) +
  158. D3DXVec3Multiply( (((float)nCurrentX) *vWidth), (vSize / ((float)(nNumVertexX - 1))) ));
  159. D3DXVECTOR3 vThisLocation = (vLocation + vThisSize);
  160. float fTextureX = ((fTextureScaleX*AddVectorComponents(D3DXVec3Multiply(vThisSize, vWidth))) * (fFlipTexture ? -1 : 1));
  161. float fTextureY = (-fTextureScaleY*AddVectorComponents(D3DXVec3Multiply(vThisSize, vHeight)));
  162. m_pvVertexs[(nCurrentY * nNumVertexX) + nCurrentX] = MYVERTEX(vThisLocation, vNormal, fTextureX, fTextureY);
  163. if (( (int)m_dwNumIndeces > (nVerticies * 6)) &&
  164. (nCurrentY < (nNumVertexY - 1)) &&
  165. (nCurrentX < (nNumVertexX - 1)))
  166. {
  167. // The number of indexs will not have the last row.
  168. m_pdwIndices[(nVerticies * 6) + 0] = (((nCurrentY + 1) * nNumVertexY) + nCurrentX);
  169. m_pdwIndices[(nVerticies * 6) + 1] = ((nCurrentY * nNumVertexY) + nCurrentX);
  170. m_pdwIndices[(nVerticies * 6) + 2] = (((nCurrentY + 0) * nNumVertexY) + nCurrentX + 1);
  171. m_pdwIndices[(nVerticies * 6) + 3] = (((nCurrentY + 1) * nNumVertexY) + nCurrentX);
  172. m_pdwIndices[(nVerticies * 6) + 4] = (((nCurrentY + 0) * nNumVertexY) + nCurrentX + 1);
  173. m_pdwIndices[(nVerticies * 6) + 5] = (((nCurrentY + 1) * nNumVertexY) + nCurrentX + 1);
  174. if (fFlipOrder)
  175. {
  176. WORD wTemp = m_pdwIndices[(nVerticies * 6) + 0];
  177. m_pdwIndices[(nVerticies * 6) + 0] = m_pdwIndices[(nVerticies * 6) + 2];
  178. m_pdwIndices[(nVerticies * 6) + 2] = wTemp;
  179. wTemp = m_pdwIndices[(nVerticies * 6) + 3];
  180. m_pdwIndices[(nVerticies * 6) + 3] = m_pdwIndices[(nVerticies * 6) + 5];
  181. m_pdwIndices[(nVerticies * 6) + 5] = wTemp;
  182. }
  183. nVerticies++;
  184. }
  185. }
  186. }
  187. }
  188. }
  189. else
  190. {
  191. hr = E_OUTOFMEMORY;
  192. }
  193. }
  194. return hr;
  195. }
  196. HRESULT C3DObject::_PurgeDeviceObjects(void)
  197. {
  198. for (int nIndex = 0; nIndex < ARRAYSIZE(m_pIndexBuff); nIndex++)
  199. {
  200. SAFE_RELEASE(m_pVB[nIndex]);
  201. SAFE_RELEASE(m_pIndexBuff[nIndex]);
  202. }
  203. return S_OK;
  204. }
  205. HRESULT C3DObject::_GenerateDeviceObjects(void)
  206. {
  207. HRESULT hr = E_INVALIDARG;
  208. if (m_pMain)
  209. {
  210. int nCurrMonitor = m_pMain->GetCurrMonitorIndex();
  211. IDirect3DDevice8 * pD3DDevice = m_pMain->GetD3DDevice();
  212. hr = S_OK;
  213. if (pD3DDevice && (!m_pVB[nCurrMonitor] || !m_pIndexBuff[nCurrMonitor]))
  214. {
  215. SAFE_RELEASE(m_pVB[nCurrMonitor]); // Make sure both are set or both clear.
  216. SAFE_RELEASE(m_pIndexBuff[nCurrMonitor]);
  217. hr = pD3DDevice->CreateVertexBuffer((m_dwNumVer*sizeof(MYVERTEX)), D3DUSAGE_WRITEONLY, D3DFVF_MYVERTEX, D3DPOOL_MANAGED, &m_pVB[nCurrMonitor]);
  218. if (SUCCEEDED(hr))
  219. {
  220. MYVERTEX * pVertexArray;
  221. hr = m_pVB[nCurrMonitor]->Lock(0, 0, (BYTE **)&pVertexArray, 0);
  222. if (SUCCEEDED(hr))
  223. {
  224. hr = pD3DDevice->CreateIndexBuffer((m_dwNumIndeces*sizeof(WORD)), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_pIndexBuff[nCurrMonitor]);
  225. if (SUCCEEDED(hr))
  226. {
  227. WORD * pwIndexes;
  228. hr = m_pIndexBuff[nCurrMonitor]->Lock(0, (m_dwNumIndeces*sizeof(WORD)), (BYTE **)&pwIndexes, 0);
  229. if (SUCCEEDED(hr))
  230. {
  231. // 1. Copy m_pvVertexs to pVertexArray
  232. DWORD cbSize = (m_dwNumVer*sizeof(MYVERTEX));
  233. CopyMemory(pVertexArray, m_pvVertexs, cbSize);
  234. // 2. Copy m_pdwIndices[(nVerticies * 6) + 0] to y
  235. cbSize = (m_dwNumIndeces*sizeof(WORD));
  236. CopyMemory(pwIndexes, m_pdwIndices, cbSize);
  237. m_pIndexBuff[nCurrMonitor]->Unlock();
  238. }
  239. }
  240. m_pVB[nCurrMonitor]->Unlock();
  241. }
  242. if (FAILED(hr))
  243. {
  244. SAFE_RELEASE(m_pVB[nCurrMonitor]); // Make sure both are set or both clear.
  245. SAFE_RELEASE(m_pIndexBuff[nCurrMonitor]);
  246. }
  247. }
  248. }
  249. }
  250. return hr;
  251. }
  252. HRESULT C3DObject::CombineObject(IDirect3DDevice8 * pD3DDevice, C3DObject * pObjToMerge)
  253. {
  254. HRESULT hr = E_INVALIDARG;
  255. if (pObjToMerge && m_pdwIndices && m_dwNumIndeces && pObjToMerge->m_pdwIndices && pObjToMerge->m_dwNumIndeces)
  256. {
  257. hr = _PurgeDeviceObjects();
  258. if (pObjToMerge->m_vMin.x < m_vMin.x)
  259. m_vMin.x = pObjToMerge->m_vMin.x;
  260. if (pObjToMerge->m_vMin.y < m_vMin.y)
  261. m_vMin.y = pObjToMerge->m_vMin.y;
  262. if (pObjToMerge->m_vMin.z < m_vMin.z)
  263. m_vMin.z = pObjToMerge->m_vMin.z;
  264. if (pObjToMerge->m_vMax.x > m_vMax.x)
  265. m_vMax.x = pObjToMerge->m_vMax.x;
  266. if (pObjToMerge->m_vMax.y > m_vMax.y)
  267. m_vMax.y = pObjToMerge->m_vMax.y;
  268. if (pObjToMerge->m_vMax.z > m_vMax.z)
  269. m_vMax.z = pObjToMerge->m_vMax.z;
  270. if (SUCCEEDED(hr))
  271. {
  272. LPWORD pdwIndicesOld = m_pdwIndices;
  273. DWORD dwNumIndecesOld = m_dwNumIndeces;
  274. MYVERTEX * pvVertexsOld = m_pvVertexs;
  275. DWORD dwNumVerOld = m_dwNumVer;
  276. m_dwNumIndeces += pObjToMerge->m_dwNumIndeces;
  277. m_pdwIndices = new WORD[m_dwNumIndeces];
  278. m_dwNumVer += pObjToMerge->m_dwNumVer;
  279. m_pvVertexs = new MYVERTEX[m_dwNumIndeces];
  280. if (m_pvVertexs && m_pdwIndices)
  281. {
  282. DWORD dwCurrent;
  283. // Copy the original Index values.
  284. for (dwCurrent = 0; dwCurrent < dwNumIndecesOld; dwCurrent++)
  285. {
  286. m_pdwIndices[dwCurrent] = pdwIndicesOld[dwCurrent];
  287. }
  288. // Append the new Index values.
  289. for (dwCurrent = 0; dwCurrent < pObjToMerge->m_dwNumIndeces; dwCurrent++)
  290. {
  291. m_pdwIndices[dwCurrent + dwNumIndecesOld] = (pObjToMerge->m_pdwIndices[dwCurrent] + (WORD) dwNumVerOld);
  292. }
  293. // Copy the original vertex values.
  294. for (dwCurrent = 0; dwCurrent < dwNumVerOld; dwCurrent++)
  295. {
  296. m_pvVertexs[dwCurrent] = pvVertexsOld[dwCurrent];
  297. }
  298. // Append the new vertex values.
  299. for (dwCurrent = 0; dwCurrent < pObjToMerge->m_dwNumVer; dwCurrent++)
  300. {
  301. m_pvVertexs[dwCurrent + dwNumVerOld] = pObjToMerge->m_pvVertexs[dwCurrent];
  302. }
  303. }
  304. else
  305. {
  306. hr = E_OUTOFMEMORY;
  307. }
  308. SAFE_DELETE(pdwIndicesOld);
  309. SAFE_DELETE(pvVertexsOld);
  310. }
  311. }
  312. else
  313. {
  314. SAFE_DELETE(m_pvVertexs);
  315. SAFE_DELETE(m_pdwIndices);
  316. hr = E_OUTOFMEMORY;
  317. }
  318. if (SUCCEEDED(hr) && pObjToMerge && pObjToMerge->m_pNextObject)
  319. {
  320. hr = CombineObject(pD3DDevice, pObjToMerge->m_pNextObject);
  321. }
  322. return hr;
  323. }
  324. //-----------------------------------------------------------------------------
  325. // Name: FinalCleanup()
  326. // Desc: Called before the app exits, this function gives the app the chance
  327. // to cleanup after itself.
  328. //-----------------------------------------------------------------------------
  329. HRESULT C3DObject::FinalCleanup(void)
  330. {
  331. return S_OK;
  332. }
  333. //-----------------------------------------------------------------------------
  334. // Name: DeleteDeviceObjects()
  335. // Desc: Called when the app is exitting, or the device is being changed,
  336. // this function deletes any device dependant objects.
  337. //-----------------------------------------------------------------------------
  338. HRESULT C3DObject::DeleteDeviceObjects(void)
  339. {
  340. return S_OK;
  341. }
  342. BOOL C3DObject::IsObjectViewable(IDirect3DDevice8 * pD3DDevice)
  343. {
  344. D3DXMATRIX matWorld;
  345. pD3DDevice->GetTransform( D3DTS_WORLD, &matWorld );
  346. return Is3DRectViewable( m_pMain->PCullInfo(), &matWorld, m_vMin, m_vMax );
  347. }
  348. //-----------------------------------------------------------------------------
  349. // Name: Render()
  350. // Desc: Called once per frame, the call is the entry point for 3d
  351. // rendering. This function sets up render states, clears the
  352. // viewport, and renders the scene.
  353. //-----------------------------------------------------------------------------
  354. HRESULT C3DObject::Render(IDirect3DDevice8 * pD3DDevice)
  355. {
  356. HRESULT hr = E_INVALIDARG;
  357. if (pD3DDevice && m_pMain && m_pdwIndices && m_pvVertexs)
  358. {
  359. int nCurrMonitor = m_pMain->GetCurrMonitorIndex();
  360. hr = _GenerateDeviceObjects(); // We may not have created them yet. Especially for the current device (monitor)
  361. if (SUCCEEDED(hr))
  362. {
  363. #ifdef RENDER_CORNERS
  364. D3DMATERIAL8 mtrl = {0};
  365. mtrl.Ambient.r = mtrl.Specular.r = mtrl.Diffuse.r = 1.0f;
  366. mtrl.Ambient.g = mtrl.Specular.g = mtrl.Diffuse.g = 1.0f;
  367. mtrl.Ambient.b = mtrl.Specular.b = mtrl.Diffuse.b = 1.0f;
  368. mtrl.Ambient.a = mtrl.Specular.a = mtrl.Diffuse.a = 1.0f;
  369. pD3DDevice->SetMaterial(&mtrl);
  370. LPD3DXMESH pMesh;
  371. if( FAILED( D3DXCreateSphere( pD3DDevice, 1.0f, 12, 12, &pMesh, NULL ) ) )
  372. return hr;
  373. D3DXComputeNormals( pMesh );
  374. D3DXMATRIX matWorldSave;
  375. D3DXMATRIX matWorld;
  376. pD3DDevice->GetTransform( D3DTS_WORLD, &matWorldSave );
  377. D3DXMatrixTranslation( &matWorld, m_vMax.x, m_vMax.y, m_vMax.z );
  378. pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );
  379. pMesh->DrawSubset( 0 );
  380. D3DXMatrixTranslation( &matWorld, m_vMin.x, m_vMax.y, m_vMax.z );
  381. pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );
  382. pMesh->DrawSubset( 0 );
  383. D3DXMatrixTranslation( &matWorld, m_vMax.x, m_vMax.y, m_vMin.z );
  384. pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );
  385. pMesh->DrawSubset( 0 );
  386. D3DXMatrixTranslation( &matWorld, m_vMin.x, m_vMax.y, m_vMin.z );
  387. pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );
  388. pMesh->DrawSubset( 0 );
  389. D3DXMatrixTranslation( &matWorld, m_vMax.x, m_vMin.y, m_vMax.z );
  390. pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );
  391. pMesh->DrawSubset( 0 );
  392. D3DXMatrixTranslation( &matWorld, m_vMin.x, m_vMin.y, m_vMax.z );
  393. pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );
  394. pMesh->DrawSubset( 0 );
  395. D3DXMatrixTranslation( &matWorld, m_vMax.x, m_vMin.y, m_vMin.z );
  396. pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );
  397. pMesh->DrawSubset( 0 );
  398. D3DXMatrixTranslation( &matWorld, m_vMin.x, m_vMin.y, m_vMin.z );
  399. pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );
  400. pMesh->DrawSubset( 0 );
  401. pD3DDevice->SetTransform( D3DTS_WORLD, &matWorldSave );
  402. SAFE_RELEASE( pMesh );
  403. #endif
  404. if (IsObjectViewable(pD3DDevice))
  405. {
  406. /////////////////////
  407. // Draw Object
  408. /////////////////////
  409. hr = pD3DDevice->SetTexture(0, (m_pTexture ? m_pTexture->GetTexture() : NULL));
  410. if (m_pTexture->GetTexture())
  411. {
  412. g_nTexturesRenderedInThisFrame++;
  413. }
  414. if (SUCCEEDED(hr) && m_pVB[nCurrMonitor] && m_pIndexBuff[nCurrMonitor])
  415. {
  416. hr = pD3DDevice->SetStreamSource(0, m_pVB[nCurrMonitor], sizeof(MYVERTEX));
  417. if (SUCCEEDED(hr))
  418. {
  419. hr = pD3DDevice->SetIndices(m_pIndexBuff[nCurrMonitor], 0);
  420. if (SUCCEEDED(hr))
  421. {
  422. hr = pD3DDevice->SetVertexShader(D3DFVF_MYVERTEX);
  423. if (SUCCEEDED(hr))
  424. {
  425. DWORD dwNumPrimitives = (m_dwNumIndeces / 3);
  426. g_nTrianglesRenderedInThisFrame += dwNumPrimitives;
  427. hr = pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, m_dwNumVer, 0, dwNumPrimitives);
  428. }
  429. }
  430. }
  431. }
  432. pD3DDevice->SetTexture(0, NULL);
  433. }
  434. else
  435. {
  436. hr = S_OK;
  437. }
  438. }
  439. }
  440. if (m_pNextObject)
  441. {
  442. m_pNextObject->Render(pD3DDevice);
  443. }
  444. return hr;
  445. }
  446. HRESULT C3DObject::SetNextObject(C3DObject * pNextObject)
  447. {
  448. _PurgeDeviceObjects();
  449. SAFE_DELETE(m_pNextObject);
  450. m_pNextObject = pNextObject;
  451. return S_OK;
  452. }