Leaked source code of windows server 2003
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.

1182 lines
40 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dphal.c
  6. * Content: DrawPrimitive implementation for DrawPrimitive HALs
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #include "drawprim.hpp"
  12. #include "clipfunc.h"
  13. #include "d3dfei.h"
  14. #ifndef WIN95
  15. #include <ntgdistr.h>
  16. #endif
  17. #define ALIGN32(x) x = ((DWORD)(x + 31)) & (~31);
  18. //---------------------------------------------------------------------
  19. // Handles strides and FVF
  20. //
  21. #undef DPF_MODNAME
  22. #define DPF_MODNAME "D3DFE_updateExtents"
  23. void D3DFE_updateExtents(LPDIRECT3DDEVICEI lpDevI)
  24. {
  25. int i;
  26. D3DVECTOR *v = (D3DVECTOR*)lpDevI->position.lpvData;
  27. DWORD stride = lpDevI->position.dwStride;
  28. for (i = lpDevI->dwNumVertices; i; i--)
  29. {
  30. if (v->x < lpDevI->rExtents.x1)
  31. lpDevI->rExtents.x1 = v->x;
  32. if (v->x > lpDevI->rExtents.x2)
  33. lpDevI->rExtents.x2 = v->x;
  34. if (v->y < lpDevI->rExtents.y1)
  35. lpDevI->rExtents.y1 = v->y;
  36. if (v->y > lpDevI->rExtents.y2)
  37. lpDevI->rExtents.y2 = v->y;
  38. v = (D3DVECTOR*)((char*)v + stride);
  39. }
  40. }
  41. #if DBG
  42. //---------------------------------------------------------------------
  43. #undef DPF_MODNAME
  44. #define DPF_MODNAME "CheckDrawPrimitive"
  45. HRESULT CheckDrawPrimitive(LPDIRECT3DDEVICEI lpDevI)
  46. {
  47. D3DFE_PROCESSVERTICES* data = lpDevI;
  48. HRESULT ret = CheckDeviceSettings(lpDevI);
  49. if (ret != D3D_OK)
  50. return ret;
  51. if (!data->dwNumVertices)
  52. {
  53. D3D_ERR( "Invalid dwNumVertices in DrawPrimitive" );
  54. return DDERR_INVALIDPARAMS;
  55. }
  56. if(data->position.lpvData==NULL) {
  57. D3D_ERR( "Invalid lpvVertices param in DrawPrimitive" );
  58. return DDERR_INVALIDPARAMS;
  59. }
  60. switch (data->primType)
  61. {
  62. case D3DPT_POINTLIST:
  63. break;
  64. case D3DPT_LINELIST:
  65. if (data->dwNumVertices & 1)
  66. {
  67. D3D_ERR( "DrawPrimitive: bad vertex count" );
  68. return DDERR_INVALIDPARAMS;
  69. }
  70. break;
  71. case D3DPT_LINESTRIP:
  72. if (data->dwNumVertices == 1)
  73. {
  74. D3D_ERR( "DrawPrimitive: bad vertex count" );
  75. return DDERR_INVALIDPARAMS;
  76. }
  77. break;
  78. case D3DPT_TRIANGLEFAN:
  79. case D3DPT_TRIANGLESTRIP:
  80. if (data->dwNumVertices < 3)
  81. {
  82. D3D_ERR( "DrawPrimitive: bad vertex count" );
  83. return DDERR_INVALIDPARAMS;
  84. }
  85. break;
  86. case D3DPT_TRIANGLELIST:
  87. if ( (data->dwNumVertices % 3) != 0 )
  88. {
  89. D3D_ERR( "DrawPrimitive: bad vertex count" );
  90. return DDERR_INVALIDPARAMS;
  91. }
  92. break;
  93. default:
  94. D3D_ERR( "Unknown or unsupported primitive type requested of DrawPrimitive" );
  95. return D3DERR_INVALIDPRIMITIVETYPE;
  96. }
  97. if (lpDevI->dwNumVertices > MAX_DX6_VERTICES)
  98. {
  99. D3D_ERR("D3D for DX6 cannot handle greater than 64K vertices");
  100. return D3DERR_TOOMANYVERTICES;
  101. }
  102. return D3D_OK;
  103. }
  104. //---------------------------------------------------------------------
  105. #undef DPF_MODNAME
  106. #define DPF_MODNAME "CheckDrawIndexedPrimitive"
  107. HRESULT
  108. CheckDrawIndexedPrimitive(LPDIRECT3DDEVICEI lpDevI, DWORD dwStartVertex)
  109. {
  110. D3DFE_PROCESSVERTICES *data = lpDevI;
  111. DWORD i;
  112. HRESULT ret = CheckDeviceSettings(lpDevI);
  113. if (ret != D3D_OK)
  114. return ret;
  115. if (data->dwNumVertices <= 0 || data->dwNumIndices <= 0)
  116. {
  117. D3D_ERR( "Invalid dwNumVertices or dwNumIndices in DrawIndexedPrimitive" );
  118. return DDERR_INVALIDPARAMS;
  119. }
  120. if (data->dwNumVertices > 65535ul )
  121. {
  122. D3D_ERR( "DrawIndexedPrimitive vertex array > 64K" );
  123. return DDERR_INVALIDPARAMS;
  124. }
  125. if((data->lpwIndices==NULL) || IsBadReadPtr(data->lpwIndices,data->dwNumIndices*sizeof(WORD))) {
  126. D3D_ERR( "Invalid lpwIndices param in DrawIndexedPrimitive" );
  127. return DDERR_INVALIDPARAMS;
  128. }
  129. if(data->position.lpvData==NULL) {
  130. D3D_ERR( "Invalid lpvVertices param in DrawIndexedPrimitive" );
  131. return DDERR_INVALIDPARAMS;
  132. }
  133. switch (data->primType)
  134. {
  135. case D3DPT_LINELIST:
  136. if (data->dwNumIndices & 1)
  137. {
  138. D3D_ERR( "DrawIndexedPrimitive: bad index count" );
  139. return DDERR_INVALIDPARAMS;
  140. }
  141. break;
  142. case D3DPT_LINESTRIP:
  143. if (data->dwNumIndices == 1)
  144. {
  145. D3D_ERR( "DrawIndexedPrimitive: bad index count" );
  146. return DDERR_INVALIDPARAMS;
  147. }
  148. break;
  149. case D3DPT_TRIANGLEFAN:
  150. case D3DPT_TRIANGLESTRIP:
  151. if (data->dwNumIndices < 3)
  152. {
  153. D3D_ERR( "DrawIndexedPrimitive: bad index count" );
  154. return DDERR_INVALIDPARAMS;
  155. }
  156. break;
  157. case D3DPT_TRIANGLELIST:
  158. if ( (data->dwNumIndices % 3) != 0 )
  159. {
  160. D3D_ERR( "DrawIndexedPrimitive: bad index count" );
  161. return DDERR_INVALIDPARAMS;
  162. }
  163. break;
  164. default:
  165. D3D_ERR( "Unknown or unsupported primitive type requested of DrawIndexedPrimitive" );
  166. return D3DERR_INVALIDPRIMITIVETYPE;
  167. }
  168. for (i=0; i < data->dwNumIndices; i++)
  169. {
  170. if (data->lpwIndices[i] >= data->dwNumVertices)
  171. {
  172. D3D_ERR( "Invalid index value in DrawIndexedPrimitive" );
  173. return DDERR_INVALIDPARAMS;
  174. }
  175. }
  176. if (lpDevI->dwNumPrimitives > MAX_DX6_PRIMCOUNT)
  177. {
  178. D3D_ERR("D3D for DX6 cannot handle greater than 64K sized primitives");
  179. return D3DERR_TOOMANYPRIMITIVES;
  180. }
  181. if (lpDevI->dwNumIndices * INDEX_BATCH_SCALE < lpDevI->dwNumVertices &&
  182. !FVF_TRANSFORMED(lpDevI->dwVIDIn))
  183. {
  184. D3D_WARN(1, "The number of indices is much less than the number of vertices.");
  185. D3D_WARN(1, "This will likely be inefficient. Consider using vertex buffers.");
  186. }
  187. return D3D_OK;
  188. }
  189. #endif // DBG
  190. //---------------------------------------------------------------------
  191. #undef DPF_MODNAME
  192. #define DPF_MODNAME "DoDrawPrimitive"
  193. HRESULT DoDrawPrimitive(LPD3DFE_PROCESSVERTICES pv)
  194. {
  195. HRESULT ret;
  196. if (!CheckIfNeedClipping(pv))
  197. return pv->DrawPrim();
  198. // Preserve primitive type for large begin-end primitives
  199. // Primitive type could be changed by the clipper
  200. D3DPRIMITIVETYPE oldPrimType = pv->primType;
  201. switch (pv->primType)
  202. {
  203. case D3DPT_POINTLIST:
  204. ret = ProcessClippedPoints(pv);
  205. break;
  206. case D3DPT_LINELIST:
  207. ret = ProcessClippedLine(pv);
  208. break;
  209. case D3DPT_LINESTRIP:
  210. ret = ProcessClippedLine(pv);
  211. break;
  212. case D3DPT_TRIANGLELIST:
  213. ret = ProcessClippedTriangleList(pv);
  214. break;
  215. case D3DPT_TRIANGLESTRIP:
  216. ret = ProcessClippedTriangleStrip(pv);
  217. break;
  218. case D3DPT_TRIANGLEFAN:
  219. ret = ProcessClippedTriangleFan(pv);
  220. break;
  221. default:
  222. D3D_ERR( "Unknown primitive type in DrawPrimitive" );
  223. ret = DDERR_GENERIC;
  224. break;
  225. }
  226. ClampExtents(pv);
  227. pv->primType = oldPrimType;
  228. return ret;
  229. }
  230. //---------------------------------------------------------------------
  231. #undef DPF_MODNAME
  232. #define DPF_MODNAME "DoDrawIndexedPrimitive"
  233. HRESULT DoDrawIndexedPrimitive(LPD3DFE_PROCESSVERTICES pv)
  234. {
  235. HRESULT ret;
  236. if (!CheckIfNeedClipping(pv))
  237. return pv->DrawIndexPrim();
  238. // Preserve primitive type for large begin-end primitives
  239. // Primitive type could be changed by the clipper
  240. D3DPRIMITIVETYPE oldPrimType = pv->primType;
  241. switch (pv->primType)
  242. {
  243. case D3DPT_LINELIST:
  244. ret = ProcessClippedIndexedLine(pv);
  245. break;
  246. case D3DPT_LINESTRIP:
  247. ret = ProcessClippedIndexedLine(pv);
  248. break;
  249. case D3DPT_TRIANGLELIST:
  250. ret = ProcessClippedIndexedTriangleList(pv);
  251. break;
  252. case D3DPT_TRIANGLEFAN:
  253. ret = ProcessClippedIndexedTriangleFan(pv);
  254. break;
  255. case D3DPT_TRIANGLESTRIP:
  256. ret = ProcessClippedIndexedTriangleStrip(pv);
  257. break;
  258. default:
  259. break;
  260. }
  261. ClampExtents(pv);
  262. pv->primType = oldPrimType;
  263. return ret;
  264. }
  265. //---------------------------------------------------------------------
  266. // API calls
  267. //---------------------------------------------------------------------
  268. //---------------------------------------------------------------------
  269. #undef DPF_MODNAME
  270. #define DPF_MODNAME "DrawPrimitiveStrided"
  271. HRESULT D3DAPI
  272. DIRECT3DDEVICEI::DrawPrimitiveStrided(
  273. D3DPRIMITIVETYPE PrimitiveType,
  274. DWORD dwVertexType,
  275. LPD3DDRAWPRIMITIVESTRIDEDDATA lpDrawData,
  276. DWORD dwNumVertices,
  277. DWORD dwFlags)
  278. {
  279. HRESULT ret = D3D_OK;
  280. try
  281. {
  282. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock.
  283. #if DBG
  284. if (ValidateFVF(dwVertexType) != D3D_OK || !IsDPFlagsValid(dwFlags))
  285. return DDERR_INVALIDPARAMS;
  286. Profile(PROF_DRAWPRIMITIVESTRIDED,PrimitiveType,dwVertexType);
  287. #endif
  288. //note: this check should be done in retail as well as dbg build
  289. if((dwVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)
  290. return D3DERR_INVALIDVERTEXTYPE;
  291. this->primType = PrimitiveType;
  292. this->position = lpDrawData->position;
  293. this->normal = lpDrawData->normal;
  294. this->diffuse = lpDrawData->diffuse;
  295. this->specular = lpDrawData->specular;
  296. this->dwNumVertices = dwNumVertices;
  297. this->dwFlags = dwFlags;
  298. if (this->dwVIDIn != dwVertexType || !(this->dwDeviceFlags & D3DDEV_STRIDE))
  299. {
  300. this->dwDeviceFlags |= D3DDEV_STRIDE;
  301. this->dwVIDIn = dwVertexType;
  302. ret = this->SetupFVFData(NULL);
  303. if (ret != D3D_OK)
  304. return ret;
  305. }
  306. for (DWORD i=0; i < this->nTexCoord; i++)
  307. this->textures[i] = lpDrawData->textureCoords[i];
  308. GetNumPrim(this, dwNumVertices); // Calculate dwNumPrimitives and update stats
  309. #if DBG
  310. ret = CheckDrawPrimitive(this);
  311. if (ret != D3D_OK)
  312. {
  313. return ret;
  314. }
  315. #endif
  316. return this->ProcessPrimitive();
  317. }
  318. catch (HRESULT ret)
  319. {
  320. return ret;
  321. }
  322. } // end of DrawPrimitiveStrided()
  323. //---------------------------------------------------------------------
  324. #undef DPF_MODNAME
  325. #define DPF_MODNAME "DrawIndexedPrimitiveStrided"
  326. HRESULT D3DAPI
  327. DIRECT3DDEVICEI::DrawIndexedPrimitiveStrided(
  328. D3DPRIMITIVETYPE PrimitiveType,
  329. DWORD dwVertexType,
  330. LPD3DDRAWPRIMITIVESTRIDEDDATA lpDrawData,
  331. DWORD dwNumVertices,
  332. LPWORD lpwIndices,
  333. DWORD dwNumIndices,
  334. DWORD dwFlags)
  335. {
  336. HRESULT ret = D3D_OK;
  337. try
  338. {
  339. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock.
  340. #if DBG
  341. if (ValidateFVF(dwVertexType) != D3D_OK || !IsDPFlagsValid(dwFlags))
  342. return DDERR_INVALIDPARAMS;
  343. Profile(PROF_DRAWINDEXEDPRIMITIVESTRIDED,PrimitiveType,dwVertexType);
  344. #endif
  345. //note: this check should be done in retail as well as dbg build
  346. if((dwVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)
  347. return D3DERR_INVALIDVERTEXTYPE;
  348. this->primType = PrimitiveType;
  349. this->position = lpDrawData->position;
  350. this->normal = lpDrawData->normal;
  351. this->diffuse = lpDrawData->diffuse;
  352. this->specular = lpDrawData->specular;
  353. this->dwNumVertices = dwNumVertices;
  354. this->lpwIndices = lpwIndices;
  355. this->dwNumIndices = dwNumIndices;
  356. this->dwFlags = dwFlags;
  357. if (this->dwVIDIn != dwVertexType || !(this->dwDeviceFlags & D3DDEV_STRIDE))
  358. {
  359. this->dwDeviceFlags |= D3DDEV_STRIDE;
  360. this->dwVIDIn = dwVertexType;
  361. ret = this->SetupFVFData(NULL);
  362. if (ret != D3D_OK)
  363. return ret;
  364. }
  365. for (DWORD i=0; i < this->nTexCoord; i++)
  366. this->textures[i] = lpDrawData->textureCoords[i];
  367. GetNumPrim(this, dwNumIndices); // Calculate dwNumPrimitives and update stats
  368. #if DBG
  369. ret = CheckDrawIndexedPrimitive(this);
  370. if (ret != D3D_OK)
  371. {
  372. return ret;
  373. }
  374. #endif
  375. return this->ProcessPrimitive(__PROCPRIMOP_INDEXEDPRIM);
  376. }
  377. catch (HRESULT ret)
  378. {
  379. return ret;
  380. }
  381. } // end of DrawIndexedPrimitiveStrided()
  382. //---------------------------------------------------------------------
  383. #undef DPF_MODNAME
  384. #define DPF_MODNAME "DrawPrimitive3"
  385. HRESULT D3DAPI
  386. DIRECT3DDEVICEI::DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType,
  387. DWORD dwVertexType,
  388. LPVOID lpvVertices,
  389. DWORD dwNumVertices,
  390. DWORD dwFlags)
  391. {
  392. HRESULT ret = D3D_OK;
  393. try
  394. {
  395. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock.
  396. #if DBG
  397. if (ValidateFVF(dwVertexType) != D3D_OK || !IsDPFlagsValid(dwFlags))
  398. return DDERR_INVALIDPARAMS;
  399. Profile(PROF_DRAWPRIMITIVEDEVICE3,PrimitiveType,dwVertexType);
  400. #endif
  401. /* This stuff is mandatory for the call */
  402. this->primType = PrimitiveType;
  403. this->position.lpvData = lpvVertices;
  404. this->dwNumVertices = dwNumVertices;
  405. this->dwFlags = dwFlags;
  406. /* This stuff depends upon the vertex type */
  407. if (this->dwVIDIn != dwVertexType || this->dwDeviceFlags & D3DDEV_STRIDE)
  408. {
  409. this->dwDeviceFlags &= ~D3DDEV_STRIDE;
  410. this->dwVIDIn = dwVertexType;
  411. ret = SetupFVFData(&this->position.dwStride);
  412. if (ret != D3D_OK)
  413. {
  414. return ret;
  415. }
  416. }
  417. GetNumPrim(this, dwNumVertices); // Calculate dwNumPrimitives and update stats
  418. #if DBG
  419. ret = CheckDrawPrimitive(this);
  420. if (ret != D3D_OK)
  421. {
  422. return ret;
  423. }
  424. #endif
  425. return this->ProcessPrimitive();
  426. }
  427. catch (HRESULT ret)
  428. {
  429. return ret;
  430. }
  431. }
  432. //---------------------------------------------------------------------
  433. #undef DPF_MODNAME
  434. #define DPF_MODNAME "Direct3DDevice::DrawIndexedPrimitive"
  435. HRESULT D3DAPI
  436. DIRECT3DDEVICEI::DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType,
  437. DWORD dwVertexType,
  438. LPVOID lpvVertices, DWORD dwNumVertices,
  439. LPWORD lpwIndices, DWORD dwNumIndices,
  440. DWORD dwFlags)
  441. {
  442. HRESULT ret = D3D_OK;
  443. try
  444. {
  445. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock.
  446. #if DBG
  447. if (ValidateFVF(dwVertexType) != D3D_OK || !IsDPFlagsValid(dwFlags))
  448. return DDERR_INVALIDPARAMS;
  449. Profile(PROF_DRAWINDEXEDPRIMITIVEDEVICE3,PrimitiveType,dwVertexType);
  450. #endif
  451. // Mandatory part
  452. this->primType = PrimitiveType;
  453. this->dwNumVertices = dwNumVertices;
  454. this->lpwIndices = lpwIndices;
  455. this->dwNumIndices = dwNumIndices;
  456. this->dwFlags = dwFlags;
  457. this->position.lpvData = lpvVertices;
  458. // Stuff that depends upon dwVIDIn
  459. if (this->dwVIDIn != dwVertexType || this->dwDeviceFlags & D3DDEV_STRIDE)
  460. {
  461. this->dwDeviceFlags &= ~D3DDEV_STRIDE;
  462. this->dwVIDIn = dwVertexType;
  463. ret = SetupFVFData(&this->position.dwStride);
  464. if (ret != D3D_OK)
  465. {
  466. return ret;
  467. }
  468. }
  469. GetNumPrim(this, dwNumIndices); // Calculate dwNumPrimitives and update stats
  470. #if DBG
  471. ret = CheckDrawIndexedPrimitive(this);
  472. if (ret != D3D_OK)
  473. {
  474. return ret;
  475. }
  476. #endif
  477. return this->ProcessPrimitive(__PROCPRIMOP_INDEXEDPRIM);
  478. }
  479. catch (HRESULT ret)
  480. {
  481. return ret;
  482. }
  483. }
  484. #ifdef VTABLE_HACK
  485. //----------------------------------------------------------------------
  486. // Dedicated DrawPrimitive Implementation for TL vertex case
  487. // Assumptions:
  488. // No clipping
  489. // No extents update
  490. // Single threaded app
  491. // No state change since last call
  492. // no FVF change since last call
  493. //
  494. //---------------------------------------------------------------------
  495. #undef DPF_MODNAME
  496. #define DPF_MODNAME "DrawPrimitiveTL"
  497. HRESULT D3DAPI
  498. CDirect3DDeviceIDP2::DrawPrimitiveTL(D3DPRIMITIVETYPE PrimitiveType,
  499. DWORD dwVertexType,
  500. LPVOID lpvVertices,
  501. DWORD dwNumVertices,
  502. DWORD dwFlags)
  503. {
  504. HRESULT ret;
  505. #if DBG
  506. if (ValidateFVF(dwVertexType) != D3D_OK || !IsDPFlagsValid(dwFlags))
  507. return DDERR_INVALIDPARAMS;
  508. Profile(PROF_DRAWPRIMITIVEDEVICE3,PrimitiveType,dwVertexType);
  509. #endif
  510. /* Make sure we can use the fast path */
  511. if (this->dwVIDIn != dwVertexType ||
  512. this->dwDeviceFlags & D3DDEV_STRIDE ||
  513. dwNumVertices >= LOWVERTICESNUMBER)
  514. {
  515. VtblDrawPrimitiveDefault();
  516. return DrawPrimitive(PrimitiveType, dwVertexType, lpvVertices, dwNumVertices, dwFlags);
  517. }
  518. /* This stuff is mandatory for the call */
  519. this->primType = PrimitiveType;
  520. this->dwFlags = dwFlags;
  521. this->dwNumVertices = dwNumVertices;
  522. GetNumPrim(this, dwNumVertices); // Calculate dwNumPrimitives
  523. #if DBG
  524. this->position.lpvData = lpvVertices;
  525. ret = CheckDrawPrimitive(this);
  526. if (ret != D3D_OK)
  527. {
  528. return ret;
  529. }
  530. #endif
  531. DWORD vertexPoolSize = dwNumVertices * this->dwOutputSize;
  532. if (vertexPoolSize > this->TLVbuf_GetSize())
  533. {
  534. // try
  535. // {
  536. if (this->TLVbuf_Grow(vertexPoolSize, true) != D3D_OK)
  537. {
  538. D3D_ERR( "Could not grow TL vertex buffer" );
  539. return DDERR_OUTOFMEMORY;
  540. }
  541. /* }
  542. catch (HRESULT ret)
  543. {
  544. return ret;
  545. }
  546. */ }
  547. this->dwVertexBase = this->dwDP2VertexCount;
  548. DDASSERT(this->dwVertexBase < MAX_DX6_VERTICES);
  549. this->dwDP2VertexCount = this->dwVertexBase + dwNumVertices;
  550. memcpy(this->TLVbuf_GetAddress(), lpvVertices, vertexPoolSize);
  551. // try
  552. // {
  553. ret = this->DrawPrim();
  554. /* }
  555. catch (HRESULT ret)
  556. {
  557. return ret;
  558. }
  559. */
  560. this->TLVbuf_Base() += vertexPoolSize;
  561. DDASSERT(TLVbuf_base <= TLVbuf_size);
  562. DDASSERT(TLVbuf_base == this->dwDP2VertexCount * this->dwOutputSize);
  563. return ret;
  564. }
  565. //----------------------------------------------------------------------
  566. // Dedicated DrawIndexedPrimitive Implementation for TL vertex case
  567. // Assumptions:
  568. // No clipping
  569. // No extents update
  570. // Single threaded app
  571. // No state change since last call
  572. // no FVF change since last call
  573. //
  574. //---------------------------------------------------------------------
  575. #undef DPF_MODNAME
  576. #define DPF_MODNAME "DrawIndexedPrimitiveTL"
  577. HRESULT D3DAPI
  578. CDirect3DDeviceIDP2::DrawIndexedPrimitiveTL(D3DPRIMITIVETYPE PrimitiveType,
  579. DWORD dwVertexType,
  580. LPVOID lpvVertices, DWORD dwNumVertices,
  581. LPWORD lpwIndices, DWORD dwNumIndices,
  582. DWORD dwFlags)
  583. {
  584. HRESULT ret;
  585. #if DBG
  586. if (ValidateFVF(dwVertexType) != D3D_OK || !IsDPFlagsValid(dwFlags))
  587. return DDERR_INVALIDPARAMS;
  588. Profile(PROF_DRAWINDEXEDPRIMITIVEDEVICE3,PrimitiveType,dwVertexType);
  589. #endif
  590. /* Make sure we can use the fast path */
  591. if (this->dwVIDIn != dwVertexType ||
  592. this->dwDeviceFlags & D3DDEV_STRIDE ||
  593. dwNumVertices >= LOWVERTICESNUMBER)
  594. {
  595. VtblDrawIndexedPrimitiveDefault();
  596. return DrawIndexedPrimitive(PrimitiveType, dwVertexType, lpvVertices,
  597. dwNumVertices, lpwIndices, dwNumIndices, dwFlags);
  598. }
  599. /* This stuff is mandatory for the call */
  600. this->primType = PrimitiveType;
  601. this->dwFlags = dwFlags;
  602. this->lpwIndices = lpwIndices;
  603. this->dwNumIndices = dwNumIndices;
  604. this->dwNumVertices = dwNumVertices;
  605. GetNumPrim(this, dwNumIndices); // Calculate dwNumPrimitives
  606. #if DBG
  607. this->position.lpvData = lpvVertices;
  608. ret = CheckDrawIndexedPrimitive(this);
  609. if (ret != D3D_OK)
  610. {
  611. return ret;
  612. }
  613. #endif
  614. DWORD vertexPoolSize = dwNumVertices * this->dwOutputSize;
  615. if (vertexPoolSize > this->TLVbuf_GetSize())
  616. {
  617. // try
  618. // {
  619. if (this->TLVbuf_Grow(vertexPoolSize, true) != D3D_OK)
  620. {
  621. D3D_ERR( "Could not grow TL vertex buffer" );
  622. return DDERR_OUTOFMEMORY;
  623. }
  624. /* }
  625. catch (HRESULT ret)
  626. {
  627. return ret;
  628. }
  629. */ }
  630. this->dwVertexBase = this->dwDP2VertexCount;
  631. DDASSERT(this->dwVertexBase < MAX_DX6_VERTICES);
  632. this->dwDP2VertexCount = this->dwVertexBase + dwNumVertices;
  633. memcpy(this->TLVbuf_GetAddress(), lpvVertices, vertexPoolSize);
  634. // try
  635. // {
  636. ret = this->DrawIndexPrim();
  637. /* }
  638. catch (HRESULT ret)
  639. {
  640. return ret;
  641. }
  642. */
  643. this->TLVbuf_Base() += vertexPoolSize;
  644. DDASSERT(TLVbuf_base <= TLVbuf_size);
  645. DDASSERT(TLVbuf_base == this->dwDP2VertexCount * this->dwOutputSize);
  646. return ret;
  647. }
  648. //----------------------------------------------------------------------
  649. // Dedicated DrawPrimitive Implementation for non-TL vertex case
  650. // Assumptions:
  651. // Single threaded app
  652. // No state change since last call
  653. // no FVF change since last call
  654. //
  655. //---------------------------------------------------------------------
  656. #undef DPF_MODNAME
  657. #define DPF_MODNAME "DrawPrimitiveFE"
  658. HRESULT D3DAPI
  659. CDirect3DDeviceIDP2::DrawPrimitiveFE(D3DPRIMITIVETYPE PrimitiveType,
  660. DWORD dwVertexType,
  661. LPVOID lpvVertices,
  662. DWORD dwNumVertices,
  663. DWORD dwFlags)
  664. {
  665. HRESULT ret;
  666. #if DBG
  667. if (ValidateFVF(dwVertexType) != D3D_OK || !IsDPFlagsValid(dwFlags))
  668. return DDERR_INVALIDPARAMS;
  669. Profile(PROF_DRAWPRIMITIVEDEVICE3,PrimitiveType,dwVertexType);
  670. #endif
  671. /* Make sure we can use the fast path */
  672. if (this->dwVIDIn != dwVertexType ||
  673. this->dwDeviceFlags & D3DDEV_STRIDE ||
  674. this->dwFEFlags & D3DFE_FRONTEND_DIRTY)
  675. {
  676. VtblDrawPrimitiveDefault();
  677. return DrawPrimitive(PrimitiveType, dwVertexType, lpvVertices, dwNumVertices, dwFlags);
  678. }
  679. /* This stuff is mandatory for the call */
  680. this->primType = PrimitiveType;
  681. this->dwFlags = this->dwLastFlags | dwFlags;
  682. this->dwNumVertices = dwNumVertices;
  683. this->position.lpvData = lpvVertices;
  684. #if DBG
  685. GetNumPrim(this, dwNumVertices); // Calculate dwNumPrimitives
  686. ret = CheckDrawPrimitive(this);
  687. if (ret != D3D_OK)
  688. {
  689. return ret;
  690. }
  691. #endif
  692. this->dwVertexPoolSize = dwNumVertices * this->dwOutputSize;
  693. if (this->dwVertexPoolSize > this->TLVbuf_GetSize())
  694. {
  695. // try
  696. // {
  697. if (this->TLVbuf_Grow(this->dwVertexPoolSize, true) != D3D_OK)
  698. {
  699. D3D_ERR( "Could not grow TL vertex buffer" );
  700. return DDERR_OUTOFMEMORY;
  701. }
  702. // }
  703. // catch (HRESULT ret)
  704. // {
  705. // return ret;
  706. // }
  707. }
  708. if (dwNumVertices * sizeof(D3DFE_CLIPCODE) > this->HVbuf.GetSize())
  709. {
  710. if (this->HVbuf.Grow(dwNumVertices * sizeof(D3DFE_CLIPCODE)) != D3D_OK)
  711. {
  712. D3D_ERR( "Could not grow clip buffer" );
  713. ret = DDERR_OUTOFMEMORY;
  714. return ret;
  715. }
  716. this->lpClipFlags = (D3DFE_CLIPCODE*)this->HVbuf.GetAddress();
  717. }
  718. this->dwVertexBase = this->dwDP2VertexCount;
  719. DDASSERT(this->dwVertexBase < MAX_DX6_VERTICES);
  720. this->dwDP2VertexCount = this->dwVertexBase + dwNumVertices;
  721. this->lpvOut = this->TLVbuf_GetAddress();
  722. // try
  723. // {
  724. switch (this->primType)
  725. {
  726. case D3DPT_POINTLIST:
  727. this->dwNumPrimitives = dwNumVertices;
  728. ret = this->pGeometryFuncs->ProcessPrimitive(this);
  729. break;
  730. case D3DPT_LINELIST:
  731. this->dwNumPrimitives = dwNumVertices >> 1;
  732. ret = this->pGeometryFuncs->ProcessPrimitive(this);
  733. break;
  734. case D3DPT_LINESTRIP:
  735. this->dwNumPrimitives = dwNumVertices - 1;
  736. ret = this->pGeometryFuncs->ProcessPrimitive(this);
  737. break;
  738. case D3DPT_TRIANGLEFAN:
  739. this->dwNumPrimitives = dwNumVertices - 2;
  740. ret = this->pGeometryFuncs->ProcessTriangleFan(this);
  741. break;
  742. case D3DPT_TRIANGLESTRIP:
  743. this->dwNumPrimitives = dwNumVertices - 2;
  744. ret = this->pGeometryFuncs->ProcessTriangleStrip(this);
  745. break;
  746. case D3DPT_TRIANGLELIST:
  747. #ifdef _X86_
  748. {
  749. DWORD tmp;
  750. __asm
  751. {
  752. mov eax, 0x55555555 // fractional part of 1.0/3.0
  753. mul dwNumVertices
  754. add eax, 0x80000000 // Rounding
  755. adc edx, 0
  756. mov tmp, edx
  757. }
  758. this->dwNumPrimitives = tmp;
  759. }
  760. #else
  761. this->dwNumPrimitives = dwNumVertices / 3;
  762. #endif
  763. ret = this->pGeometryFuncs->ProcessTriangleList(this);
  764. break;
  765. }
  766. /* }
  767. catch (HRESULT ret)
  768. {
  769. return ret;
  770. }*/
  771. D3DFE_UpdateClipStatus(this);
  772. this->TLVbuf_Base() += this->dwVertexPoolSize;
  773. DDASSERT(TLVbuf_base <= TLVbuf_size);
  774. DDASSERT(TLVbuf_base == this->dwDP2VertexCount * this->dwOutputSize);
  775. return ret;
  776. }
  777. //----------------------------------------------------------------------
  778. // Dedicated DrawIndexedPrimitive Implementation for non-TL vertex case
  779. // Assumptions:
  780. // Single threaded app
  781. // No state change since last call
  782. // no FVF change since last call
  783. //
  784. //---------------------------------------------------------------------
  785. #undef DPF_MODNAME
  786. #define DPF_MODNAME "DrawIndexedPrimitiveFE"
  787. HRESULT D3DAPI
  788. CDirect3DDeviceIDP2::DrawIndexedPrimitiveFE(D3DPRIMITIVETYPE PrimitiveType,
  789. DWORD dwVertexType,
  790. LPVOID lpvVertices, DWORD dwNumVertices,
  791. LPWORD lpwIndices, DWORD dwNumIndices,
  792. DWORD dwFlags)
  793. {
  794. HRESULT ret;
  795. #if DBG
  796. if (ValidateFVF(dwVertexType) != D3D_OK || !IsDPFlagsValid(dwFlags))
  797. return DDERR_INVALIDPARAMS;
  798. Profile(PROF_DRAWINDEXEDPRIMITIVEDEVICE3,PrimitiveType,dwVertexType);
  799. #endif
  800. /* Make sure we can use the fast path */
  801. if (this->dwVIDIn != dwVertexType ||
  802. this->dwDeviceFlags & D3DDEV_STRIDE ||
  803. this->dwFEFlags & D3DFE_FRONTEND_DIRTY)
  804. {
  805. VtblDrawIndexedPrimitiveDefault();
  806. return DrawIndexedPrimitive(PrimitiveType, dwVertexType, lpvVertices,
  807. dwNumVertices, lpwIndices, dwNumIndices, dwFlags);
  808. }
  809. /* This stuff is mandatory for the call */
  810. this->primType = PrimitiveType;
  811. this->dwFlags = this->dwLastFlags | dwFlags;
  812. this->lpwIndices = lpwIndices;
  813. this->dwNumIndices = dwNumIndices;
  814. this->dwNumVertices = dwNumVertices;
  815. this->position.lpvData = lpvVertices;
  816. GetNumPrim(this, dwNumIndices); // Calculate dwNumPrimitives
  817. #if DBG
  818. ret = CheckDrawIndexedPrimitive(this);
  819. if (ret != D3D_OK)
  820. {
  821. return ret;
  822. }
  823. #endif
  824. this->dwVertexPoolSize = dwNumVertices * this->dwOutputSize;
  825. if (this->dwVertexPoolSize > this->TLVbuf_GetSize())
  826. {
  827. // try
  828. // {
  829. if (this->TLVbuf_Grow(this->dwVertexPoolSize,
  830. (this->dwDeviceFlags & D3DDEV_DONOTCLIP)!=0) != D3D_OK)
  831. {
  832. D3D_ERR( "Could not grow TL vertex buffer" );
  833. return DDERR_OUTOFMEMORY;
  834. }
  835. // }
  836. // catch (HRESULT ret)
  837. // {
  838. // return ret;
  839. // }
  840. }
  841. if (dwNumVertices * sizeof(D3DFE_CLIPCODE) > this->HVbuf.GetSize())
  842. {
  843. if (this->HVbuf.Grow(dwNumVertices * sizeof(D3DFE_CLIPCODE)) != D3D_OK)
  844. {
  845. D3D_ERR( "Could not grow clip buffer" );
  846. ret = DDERR_OUTOFMEMORY;
  847. return ret;
  848. }
  849. this->lpClipFlags = (D3DFE_CLIPCODE*)this->HVbuf.GetAddress();
  850. }
  851. this->dwVertexBase = this->dwDP2VertexCount;
  852. DDASSERT(this->dwVertexBase < MAX_DX6_VERTICES);
  853. this->dwDP2VertexCount = this->dwVertexBase + dwNumVertices;
  854. this->lpvOut = this->TLVbuf_GetAddress();
  855. // try
  856. // {
  857. ret = this->pGeometryFuncs->ProcessIndexedPrimitive(this);
  858. /* }
  859. catch (HRESULT ret)
  860. {
  861. return ret;
  862. }*/
  863. D3DFE_UpdateClipStatus(this);
  864. this->TLVbuf_Base() += this->dwVertexPoolSize;
  865. DDASSERT(TLVbuf_base <= TLVbuf_size);
  866. DDASSERT(TLVbuf_base == this->dwDP2VertexCount * this->dwOutputSize);
  867. return ret;
  868. }
  869. #endif
  870. //---------------------------------------------------------------------
  871. #undef DPF_MODNAME
  872. #define DPF_MODNAME "DIRECT3DDEVICEI::ComputeSphereVisibility"
  873. HRESULT D3DAPI
  874. DIRECT3DDEVICEI::ComputeSphereVisibility(LPD3DVECTOR lpCenters,
  875. LPD3DVALUE lpRadii,
  876. DWORD dwNumSpheres,
  877. DWORD dwFlags,
  878. LPDWORD lpdwReturnValues)
  879. {
  880. try
  881. {
  882. CLockD3DMT lockObject(this, DPF_MODNAME, REMIND("")); // Takes D3D lock.
  883. #if DBG
  884. if (dwFlags != 0 || dwNumSpheres == 0 ||
  885. IsBadWritePtr(lpdwReturnValues, dwNumSpheres * sizeof(DWORD)) ||
  886. IsBadWritePtr(lpRadii, dwNumSpheres * sizeof(D3DVALUE)) ||
  887. IsBadWritePtr(lpCenters, dwNumSpheres * sizeof(LPD3DVECTOR)))
  888. {
  889. return DDERR_INVALIDPARAMS;
  890. }
  891. #endif
  892. this->dwFlags = 0;
  893. if (this->dwFEFlags & (D3DFE_TRANSFORM_DIRTY | D3DFE_CLIPPLANES_DIRTY))
  894. {
  895. DoUpdateState(this);
  896. }
  897. return this->pGeometryFuncs->ComputeSphereVisibility(this,
  898. lpCenters,
  899. lpRadii,
  900. dwNumSpheres,
  901. dwFlags,
  902. lpdwReturnValues);
  903. }
  904. catch (HRESULT ret)
  905. {
  906. return ret;
  907. }
  908. }
  909. //---------------------------------------------------------------------
  910. #undef DPF_MODNAME
  911. #define DPF_MODNAME "ID3DFE_PVFUNCS::ComputeSphereVisibility"
  912. HRESULT
  913. D3DFE_PVFUNCS::ComputeSphereVisibility(LPD3DFE_PROCESSVERTICES pv,
  914. LPD3DVECTOR lpCenters,
  915. LPD3DVALUE lpRadii,
  916. DWORD dwNumSpheres,
  917. DWORD dwFlags,
  918. LPDWORD lpdwReturnValues)
  919. {
  920. LPDIRECT3DDEVICEI lpDevI = static_cast<LPDIRECT3DDEVICEI>(pv);
  921. CD3DFPstate D3DFPstate; // Sets optimal FPU state for D3D.
  922. for (DWORD i=0; i < dwNumSpheres; i++)
  923. {
  924. const D3DVALUE x = lpCenters[i].x;
  925. const D3DVALUE y = lpCenters[i].y;
  926. const D3DVALUE z = lpCenters[i].z;
  927. const D3DVALUE r = lpRadii[i];
  928. const D3DVALUE xmin = x-r;
  929. const D3DVALUE ymin = y-r;
  930. const D3DVALUE zmin = z-r;
  931. const D3DVALUE xmax = x+r;
  932. const D3DVALUE ymax = y+r;
  933. const D3DVALUE zmax = z+r;
  934. D3DVECTOR v[8] =
  935. {
  936. {xmin, ymin, zmin},
  937. {xmax, ymin, zmin},
  938. {xmin, ymax, zmin},
  939. {xmax, ymax, zmin},
  940. {xmin, ymin, zmax},
  941. {xmax, ymin, zmax},
  942. {xmin, ymax, zmax},
  943. {xmax, ymax, zmax}
  944. };
  945. DWORD dwClipUnion =0;
  946. DWORD dwClipIntersection = ~0;
  947. lpDevI->CheckClipStatus((D3DVALUE*)v, sizeof(D3DVECTOR), 8,
  948. &dwClipUnion, &dwClipIntersection);
  949. lpdwReturnValues[i] = dwClipUnion + (dwClipIntersection << 12);
  950. }
  951. return D3D_OK;
  952. }
  953. /*
  954. //---------------------------------------------------------------------
  955. #undef DPF_MODNAME
  956. #define DPF_MODNAME "ID3DFE_PVFUNCS::ComputeSphereVisibility"
  957. HRESULT
  958. D3DFE_PVFUNCS::ComputeSphereVisibility(LPD3DFE_PROCESSVERTICES pv,
  959. LPD3DVECTOR lpCenters,
  960. LPD3DVALUE lpRadii,
  961. DWORD dwNumSpheres,
  962. DWORD dwFlags,
  963. LPDWORD lpdwReturnValues)
  964. {
  965. LPDIRECT3DDEVICEI lpDevI = static_cast<LPDIRECT3DDEVICEI>(pv);
  966. HRESULT ret = D3DERR_INVALIDMATRIX;
  967. #define transform lpDevI->transform
  968. if (pv->dwFlags & D3DPV_FRUSTUMPLANES_DIRTY)
  969. {
  970. transform.dwFlags &= ~D3DTRANS_VALIDFRUSTUM;
  971. if (Inverse4x4((D3DMATRIX*)&lpDevI->mCTM,
  972. (D3DMATRIX*)&transform.mCTMI))
  973. {
  974. D3D_ERR("Cannot invert current (World X View) matrix.");
  975. return ret;
  976. }
  977. // Transform the following clipping volume points to the model space by
  978. // multiplying by inverse CTM
  979. //
  980. // v1 = { 0, 0, 0, 1};
  981. // v2 = { 1, 0, 0, 1};
  982. // v3 = { 1, 1, 0, 1};
  983. // v4 = { 0, 1, 0, 1};
  984. // v5 = { 0, 0, 1, 1};
  985. // v6 = { 1, 0, 1, 1};
  986. // v7 = { 0, 1, 1, 1};
  987. //
  988. // We do it manually to speed up
  989. //
  990. D3DVECTORH v1 = {transform.mCTMI._41,
  991. transform.mCTMI._42,
  992. transform.mCTMI._43,
  993. transform.mCTMI._44};
  994. D3DVECTORH v2 = {transform.mCTMI._11 + transform.mCTMI._41,
  995. transform.mCTMI._12 + transform.mCTMI._42,
  996. transform.mCTMI._13 + transform.mCTMI._43,
  997. transform.mCTMI._14 + transform.mCTMI._44};
  998. D3DVECTORH v3 = {transform.mCTMI._11 + transform.mCTMI._21 + transform.mCTMI._41,
  999. transform.mCTMI._12 + transform.mCTMI._22 + transform.mCTMI._42,
  1000. transform.mCTMI._13 + transform.mCTMI._23 + transform.mCTMI._43,
  1001. transform.mCTMI._14 + transform.mCTMI._24 + transform.mCTMI._44};
  1002. D3DVECTORH v4 = {transform.mCTMI._21 + transform.mCTMI._41,
  1003. transform.mCTMI._22 + transform.mCTMI._42,
  1004. transform.mCTMI._23 + transform.mCTMI._43,
  1005. transform.mCTMI._24 + transform.mCTMI._44};
  1006. D3DVECTORH v5 = {transform.mCTMI._31 + transform.mCTMI._41,
  1007. transform.mCTMI._32 + transform.mCTMI._42,
  1008. transform.mCTMI._33 + transform.mCTMI._43,
  1009. transform.mCTMI._34 + transform.mCTMI._44};
  1010. D3DVECTORH v6 = {transform.mCTMI._11 + transform.mCTMI._31 + transform.mCTMI._41,
  1011. transform.mCTMI._12 + transform.mCTMI._32 + transform.mCTMI._42,
  1012. transform.mCTMI._13 + transform.mCTMI._33 + transform.mCTMI._43,
  1013. transform.mCTMI._14 + transform.mCTMI._34 + transform.mCTMI._44};
  1014. D3DVECTORH v7 = {transform.mCTMI._21 + transform.mCTMI._31 + transform.mCTMI._41,
  1015. transform.mCTMI._22 + transform.mCTMI._32 + transform.mCTMI._42,
  1016. transform.mCTMI._23 + transform.mCTMI._33 + transform.mCTMI._43,
  1017. transform.mCTMI._24 + transform.mCTMI._34 + transform.mCTMI._44};
  1018. // Convert vectors from homogeneous to 3D
  1019. if (Vector4to3D(&v1))
  1020. goto exit;
  1021. if (Vector4to3D(&v2))
  1022. goto exit;
  1023. if (Vector4to3D(&v3))
  1024. goto exit;
  1025. if (Vector4to3D(&v4))
  1026. goto exit;
  1027. if (Vector4to3D(&v5))
  1028. goto exit;
  1029. if (Vector4to3D(&v6))
  1030. goto exit;
  1031. if (Vector4to3D(&v7))
  1032. goto exit;
  1033. // Build frustum planes
  1034. // Left
  1035. if (MakePlane((D3DVECTOR*)&v1, (D3DVECTOR*)&v4, (D3DVECTOR*)&v5, &transform.frustum[0]))
  1036. goto exit;
  1037. // Right
  1038. if (MakePlane((D3DVECTOR*)&v2, (D3DVECTOR*)&v6, (D3DVECTOR*)&v3, &transform.frustum[1]))
  1039. goto exit;
  1040. // Top
  1041. if (MakePlane((D3DVECTOR*)&v4, (D3DVECTOR*)&v3, (D3DVECTOR*)&v7, &transform.frustum[2]))
  1042. goto exit;
  1043. // Bottom
  1044. if (MakePlane((D3DVECTOR*)&v1, (D3DVECTOR*)&v5, (D3DVECTOR*)&v2, &transform.frustum[3]))
  1045. goto exit;
  1046. // Near
  1047. if (MakePlane((D3DVECTOR*)&v1, (D3DVECTOR*)&v2, (D3DVECTOR*)&v3, &transform.frustum[4]))
  1048. goto exit;
  1049. // Far
  1050. if (MakePlane((D3DVECTOR*)&v6, (D3DVECTOR*)&v5, (D3DVECTOR*)&v7, &transform.frustum[5]))
  1051. goto exit;
  1052. transform.dwFlags |= D3DTRANS_VALIDFRUSTUM;
  1053. }
  1054. if (transform.dwFlags & D3DTRANS_VALIDFRUSTUM)
  1055. {
  1056. // Now we can check the spheres against the clipping planes
  1057. for (DWORD i=0; i < dwNumSpheres; i++)
  1058. {
  1059. lpdwReturnValues[i] = CheckSphere(lpDevI, &lpCenters[i], lpRadii[i]);
  1060. }
  1061. return D3D_OK;
  1062. }
  1063. exit:
  1064. D3D_ERR("Non-orthogonal (world X view) matrix");
  1065. return ret;
  1066. #undef transform
  1067. }
  1068. //---------------------------------------------------------------------
  1069. DWORD visResults[6][2] =
  1070. {
  1071. D3DVIS_INTERSECT_LEFT ,
  1072. D3DVIS_OUTSIDE_LEFT ,
  1073. D3DVIS_INTERSECT_RIGHT ,
  1074. D3DVIS_OUTSIDE_RIGHT ,
  1075. D3DVIS_INTERSECT_TOP ,
  1076. D3DVIS_OUTSIDE_TOP ,
  1077. D3DVIS_INTERSECT_BOTTOM ,
  1078. D3DVIS_OUTSIDE_BOTTOM ,
  1079. D3DVIS_INTERSECT_NEAR ,
  1080. D3DVIS_OUTSIDE_NEAR ,
  1081. D3DVIS_INTERSECT_FAR ,
  1082. D3DVIS_OUTSIDE_FAR
  1083. };
  1084. //---------------------------------------------------------------------
  1085. DWORD CheckSphere(LPDIRECT3DDEVICEI lpDevI, LPD3DVECTOR center, D3DVALUE radius)
  1086. {
  1087. DWORD result = 0;
  1088. for (int i=0; i < 6; i++)
  1089. {
  1090. // Compute a distance from the center to the plane
  1091. D3DVALUE d = lpDevI->transform.frustum[i].x*center->x +
  1092. lpDevI->transform.frustum[i].y*center->y +
  1093. lpDevI->transform.frustum[i].z*center->z +
  1094. lpDevI->transform.frustum[i].w;
  1095. if (d + radius < 0)
  1096. result |= visResults[i][1]; // Outside
  1097. else
  1098. if (d - radius < 0)
  1099. result |= visResults[i][0]; // Intersect
  1100. }
  1101. if (result & (D3DVIS_OUTSIDE_LEFT |
  1102. D3DVIS_OUTSIDE_RIGHT |
  1103. D3DVIS_OUTSIDE_TOP |
  1104. D3DVIS_OUTSIDE_BOTTOM |
  1105. D3DVIS_OUTSIDE_NEAR |
  1106. D3DVIS_OUTSIDE_FAR))
  1107. {
  1108. result |= D3DVIS_OUTSIDE_FRUSTUM;
  1109. }
  1110. else
  1111. if (result)
  1112. result |= D3DVIS_INTERSECT_FRUSTUM;
  1113. return result;
  1114. }
  1115. */