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.

1003 lines
32 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: clipper.c
  6. * Content: Clipper
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #include "clipper.h"
  12. #include "d3dfei.h"
  13. #define GET_NEW_CLIP_VERTEX \
  14. &pv->ClipperState.clip_vertices[pv->ClipperState.clip_vertices_used++];
  15. //---------------------------------------------------------------------
  16. void SetInterpolationFlags(LPD3DFE_PROCESSVERTICES pv)
  17. {
  18. // Figure out which pieces need to be interpolated in new vertices.
  19. pv->dwDeviceFlags &= ~(D3DDEV_INTERPOLATE_COLOR | D3DDEV_INTERPOLATE_SPECULAR);
  20. if (pv->lpdwRStates[D3DRENDERSTATE_SHADEMODE] == D3DSHADE_GOURAUD)
  21. {
  22. pv->dwDeviceFlags |= D3DDEV_INTERPOLATE_COLOR;
  23. if (pv->dwVIDOut & D3DFVF_SPECULAR)
  24. pv->dwDeviceFlags |= D3DDEV_INTERPOLATE_SPECULAR;
  25. }
  26. }
  27. //---------------------------------------------------------------------
  28. __inline void
  29. InterpolateColor(ClipVertex *p,
  30. ClipVertex *p1,
  31. ClipVertex *p2,
  32. D3DVALUE num_denom )
  33. {
  34. int r1, g1, b1, a1;
  35. int r2, g2, b2, a2;
  36. r1 = RGBA_GETRED(p1->color);
  37. g1 = RGBA_GETGREEN(p1->color);
  38. b1 = RGBA_GETBLUE(p1->color);
  39. a1 = RGBA_GETALPHA(p1->color);
  40. r2 = RGBA_GETRED(p2->color);
  41. g2 = RGBA_GETGREEN(p2->color);
  42. b2 = RGBA_GETBLUE(p2->color);
  43. a2 = RGBA_GETALPHA(p2->color);
  44. p->color = RGBA_MAKE((WORD)(r1 + (r2 - r1) * num_denom),
  45. (WORD)(g1 + (g2 - g1) * num_denom),
  46. (WORD)(b1 + (b2 - b1) * num_denom),
  47. (WORD)(a1 + (a2 - a1) * num_denom));
  48. }
  49. //---------------------------------------------------------------------
  50. __inline void
  51. InterpolateSpecular(ClipVertex *p,
  52. ClipVertex *p1,
  53. ClipVertex *p2,
  54. D3DVALUE num_denom )
  55. {
  56. int r1, g1, b1, a1;
  57. int r2, g2, b2, a2;
  58. r1 = RGBA_GETRED(p1->specular);
  59. g1 = RGBA_GETGREEN(p1->specular);
  60. b1 = RGBA_GETBLUE(p1->specular);
  61. a1 = RGBA_GETALPHA(p1->specular);
  62. r2 = RGBA_GETRED(p2->specular);
  63. g2 = RGBA_GETGREEN(p2->specular);
  64. b2 = RGBA_GETBLUE(p2->specular);
  65. a2 = RGBA_GETALPHA(p2->specular);
  66. p->specular = RGBA_MAKE((WORD)(r1 + (r2 - r1) * num_denom),
  67. (WORD)(g1 + (g2 - g1) * num_denom),
  68. (WORD)(b1 + (b2 - b1) * num_denom),
  69. (WORD)(a1 + (a2 - a1) * num_denom));
  70. }
  71. //---------------------------------------------------------------------
  72. __inline D3DVALUE
  73. InterpolateTexture(D3DVALUE t1,
  74. D3DVALUE t2,
  75. D3DVALUE num_denom,
  76. DWORD bWrap)
  77. {
  78. if (!bWrap)
  79. return ((t2 - t1) * num_denom + t1);
  80. else
  81. {
  82. D3DVALUE t = (TextureDiff(t2, t1, 1) * num_denom + t1);
  83. if (t > 1.0f)
  84. t -= 1.0f;
  85. return t;
  86. }
  87. }
  88. //---------------------------------------------------------------------
  89. void
  90. Interpolate(D3DFE_PROCESSVERTICES *pv,
  91. ClipVertex *p,
  92. ClipVertex *p1,
  93. ClipVertex *p2,
  94. int code,
  95. D3DVALUE num, D3DVALUE denom)
  96. {
  97. D3DVALUE num_denom = num / denom;
  98. p->clip = (((int)p1->clip & (int)p2->clip) & ~CLIPPED_ENABLE) | code;
  99. p->hx = p1->hx + (p2->hx - p1->hx) * num_denom;
  100. p->hy = p1->hy + (p2->hy - p1->hy) * num_denom;
  101. p->hz = p1->hz + (p2->hz - p1->hz) * num_denom;
  102. p->hw = p1->hw + (p2->hw - p1->hw) * num_denom;
  103. p->color = pv->ClipperState.clip_color;
  104. p->specular = pv->ClipperState.clip_specular;
  105. /*
  106. * Interpolate any other color model or quality dependent values.
  107. */
  108. if (pv->dwDeviceFlags & D3DDEV_INTERPOLATE_COLOR)
  109. {
  110. InterpolateColor(p, p1, p2, num_denom);
  111. }
  112. if (pv->dwDeviceFlags & D3DDEV_INTERPOLATE_SPECULAR)
  113. {
  114. InterpolateSpecular(p, p1, p2, num_denom);
  115. }
  116. // Assume that D3DRENDERSTATE_WRAPi are sequential
  117. D3DVALUE *pTexture1 = p1->tex;
  118. D3DVALUE *pTexture2 = p2->tex;
  119. D3DVALUE *pTexture = p->tex;
  120. for (DWORD i = 0; i < pv->nOutTexCoord; i++)
  121. {
  122. DWORD wrapState = pv->lpdwRStates[D3DRENDERSTATE_WRAP0 + i];
  123. DWORD n = (DWORD)(pv->dwTextureCoordSize[i] >> 2);
  124. DWORD dwWrapBit = 1;
  125. for (DWORD j=0; j < n; j++)
  126. {
  127. *pTexture = InterpolateTexture(*pTexture1, *pTexture2,
  128. num_denom, wrapState & dwWrapBit);
  129. dwWrapBit <<= 1;
  130. pTexture ++;
  131. pTexture1++;
  132. pTexture2++;
  133. }
  134. }
  135. }
  136. //------------------------------------------------------------------------------
  137. // Functions for clipping by frustum window
  138. //
  139. #define __CLIP_NAME ClipLeft
  140. #define __CLIP_LINE_NAME ClipLineLeft
  141. #define __CLIP_FLAG CLIPPED_LEFT
  142. #define __CLIP_COORD hx
  143. #include "clip.h"
  144. #define __CLIP_NAME ClipRight
  145. #define __CLIP_LINE_NAME ClipLineRight
  146. #define __CLIP_W
  147. #define __CLIP_FLAG CLIPPED_RIGHT
  148. #define __CLIP_COORD hx
  149. #include "clip.h"
  150. #define __CLIP_NAME ClipBottom
  151. #define __CLIP_LINE_NAME ClipLineBottom
  152. #define __CLIP_FLAG CLIPPED_BOTTOM
  153. #define __CLIP_COORD hy
  154. #include "clip.h"
  155. #define __CLIP_NAME ClipTop
  156. #define __CLIP_LINE_NAME ClipLineTop
  157. #define __CLIP_W
  158. #define __CLIP_FLAG CLIPPED_TOP
  159. #define __CLIP_COORD hy
  160. #include "clip.h"
  161. #define __CLIP_NAME ClipBack
  162. #define __CLIP_LINE_NAME ClipLineBack
  163. #define __CLIP_W
  164. #define __CLIP_FLAG CLIPPED_BACK
  165. #define __CLIP_COORD hz
  166. #include "clip.h"
  167. #define __CLIP_NAME ClipFront
  168. #define __CLIP_LINE_NAME ClipLineFront
  169. #define __CLIP_FLAG CLIPPED_FRONT
  170. #define __CLIP_COORD hz
  171. #include "clip.h"
  172. //------------------------------------------------------------------------------
  173. // Functions for guard band clipping
  174. //
  175. #define __CLIP_GUARDBAND
  176. #define __CLIP_NAME ClipLeftGB
  177. #define __CLIP_LINE_NAME ClipLineLeftGB
  178. #define __CLIP_FLAG CLIPPED_LEFT
  179. #define __CLIP_COORD hx
  180. #define __CLIP_SIGN -
  181. #define __CLIP_GBCOEF Kgbx1
  182. #include "clip.h"
  183. #define __CLIP_NAME ClipRightGB
  184. #define __CLIP_LINE_NAME ClipLineRightGB
  185. #define __CLIP_FLAG CLIPPED_RIGHT
  186. #define __CLIP_COORD hx
  187. #define __CLIP_GBCOEF Kgbx2
  188. #define __CLIP_SIGN +
  189. #include "clip.h"
  190. #define __CLIP_NAME ClipBottomGB
  191. #define __CLIP_LINE_NAME ClipLineBottomGB
  192. #define __CLIP_FLAG CLIPPED_BOTTOM
  193. #define __CLIP_COORD hy
  194. #define __CLIP_SIGN -
  195. #define __CLIP_GBCOEF Kgby1
  196. #include "clip.h"
  197. #define __CLIP_NAME ClipTopGB
  198. #define __CLIP_LINE_NAME ClipLineTopGB
  199. #define __CLIP_FLAG CLIPPED_TOP
  200. #define __CLIP_COORD hy
  201. #define __CLIP_GBCOEF Kgby2
  202. #define __CLIP_SIGN +
  203. #include "clip.h"
  204. #undef __CLIP_GUARDBAND
  205. //
  206. // Clipping a triangle by a plane
  207. //
  208. // Returns number of vertices in the clipped triangle
  209. //
  210. int ClipByPlane (D3DFE_PROCESSVERTICES *pv,
  211. ClipVertex **inv,
  212. ClipVertex **outv,
  213. D3DVECTORH *plane,
  214. DWORD dwClipFlag,
  215. int count)
  216. {
  217. int i;
  218. int out_count = 0;
  219. ClipVertex *curr, *prev;
  220. D3DVALUE curr_inside;
  221. D3DVALUE prev_inside;
  222. prev = inv[count-1];
  223. curr = *inv++;
  224. prev_inside = prev->hx*plane->x + prev->hy*plane->y +
  225. prev->hz*plane->z + prev->hw*plane->w;
  226. for (i = count; i; i--)
  227. {
  228. curr_inside = curr->hx*plane->x + curr->hy*plane->y +
  229. curr->hz*plane->z + curr->hw*plane->w;
  230. // We interpolate always from the inside vertex to the outside vertex
  231. // to reduce precision problems
  232. if (FLOAT_LTZ(prev_inside))
  233. { // first point is outside
  234. if (FLOAT_GEZ(curr_inside))
  235. { // second point is inside
  236. // Find intersection and insert in into the output buffer
  237. outv[out_count] = GET_NEW_CLIP_VERTEX;
  238. Interpolate(pv,
  239. outv[out_count],
  240. curr, prev,
  241. (prev->clip & CLIPPED_ENABLE) | dwClipFlag,
  242. curr_inside, curr_inside - prev_inside);
  243. out_count++;
  244. }
  245. } else
  246. { // first point is inside - put it to the output buffer first
  247. outv[out_count++] = prev;
  248. if (FLOAT_LTZ(curr_inside))
  249. { // second point is outside
  250. // Find intersection and put it to the output buffer
  251. outv[out_count] = GET_NEW_CLIP_VERTEX;
  252. Interpolate(pv,
  253. outv[out_count],
  254. prev, curr,
  255. dwClipFlag,
  256. prev_inside, prev_inside - curr_inside);
  257. out_count++;
  258. }
  259. }
  260. prev = curr;
  261. curr = *inv++;
  262. prev_inside = curr_inside;
  263. }
  264. return out_count;
  265. }
  266. //-------------------------------------------------------------------------
  267. // Clips a line by a plane
  268. //
  269. // Returns 1 if the line is outside the frustum, 0 otherwise
  270. //
  271. int ClipLineByPlane(D3DFE_PROCESSVERTICES *pv,
  272. ClipTriangle *line,
  273. D3DVECTORH *plane,
  274. DWORD dwClipBit)
  275. {
  276. D3DVALUE in1, in2;
  277. ClipVertex outv;
  278. in1 = line->v[0]->hx * plane->x +
  279. line->v[0]->hy * plane->y +
  280. line->v[0]->hz * plane->z +
  281. line->v[0]->hw * plane->w;
  282. in2 = line->v[1]->hx * plane->x +
  283. line->v[1]->hy * plane->y +
  284. line->v[1]->hz * plane->z +
  285. line->v[1]->hw * plane->w;
  286. if (in1 < 0)
  287. {
  288. if (in2 < 0)
  289. return 1;
  290. Interpolate(pv, &outv, line->v[0], line->v[1],
  291. dwClipBit, in1, in1 - in2);
  292. *line->v[0] = outv;
  293. }
  294. else
  295. {
  296. if (in2 < 0)
  297. {
  298. Interpolate(pv, &outv, line->v[0], line->v[1],
  299. dwClipBit, in1, in1 - in2);
  300. *line->v[1] = outv;
  301. }
  302. }
  303. return 0;
  304. }
  305. /*------------------------------------------------------------------------
  306. * Calculate the screen coords for any new vertices
  307. * introduced into the polygon.
  308. */
  309. void ComputeScreenCoordinates(D3DFE_PROCESSVERTICES *pv,
  310. ClipVertex **inv,
  311. int count, D3DRECTV *extent)
  312. {
  313. int i;
  314. BOOL updateExtent = !(pv->dwDeviceFlags & D3DDEV_DONOTUPDATEEXTENTS);
  315. D3DFE_VIEWPORTCACHE& VPORT = pv->vcache;
  316. for (i = 0; i < count; i++)
  317. {
  318. ClipVertex *p;
  319. p = inv[i];
  320. /*
  321. * Catch any vertices that need screen co-ordinates generated.
  322. * There are two possibilities
  323. * 1) Vertices generated during interpolation
  324. * 2) Vertices marked for clipping by the transform but
  325. * not clipped here due to the finite precision
  326. * of the floating point unit.
  327. */
  328. if (p->clip & ~CLIPPED_ENABLE)
  329. {
  330. D3DVALUE w;
  331. w = D3DVAL(1.0)/p->hw;
  332. switch ((int)p->clip & (CLIPPED_LEFT|CLIPPED_RIGHT))
  333. {
  334. case CLIPPED_LEFT: p->sx = VPORT.minXgb; break;
  335. case CLIPPED_RIGHT: p->sx = VPORT.maxXgb; break;
  336. default:
  337. p->sx = p->hx * VPORT.scaleX * w + VPORT.offsetX;
  338. if (p->sx < VPORT.minXgb)
  339. p->sx = VPORT.minXgb;
  340. if (p->sx > VPORT.maxXgb)
  341. p->sx = VPORT.maxXgb;
  342. }
  343. switch ((int)p->clip & (CLIPPED_TOP|CLIPPED_BOTTOM))
  344. {
  345. case CLIPPED_BOTTOM: p->sy = VPORT.maxYgb; break;
  346. case CLIPPED_TOP: p->sy = VPORT.minYgb; break;
  347. default:
  348. p->sy = p->hy * VPORT.scaleY * w + VPORT.offsetY;
  349. if (p->sy < VPORT.minYgb)
  350. p->sy = VPORT.minYgb;
  351. if (p->sy > VPORT.maxYgb)
  352. p->sy = VPORT.maxYgb;
  353. }
  354. p->sz = p->hz * w * pv->vcache.scaleZ + pv->vcache.offsetZ;
  355. p->rhw = w;
  356. if (updateExtent)
  357. {
  358. if (p->sx < extent->x1)
  359. extent->x1 = p->sx;
  360. if (p->sy < extent->y1)
  361. extent->y1 = p->sy;
  362. if (p->sx > extent->x2)
  363. extent->x2 = p->sx;
  364. if (p->sy > extent->y2)
  365. extent->y2 = p->sy;
  366. }
  367. }
  368. }
  369. }
  370. //---------------------------------------------------------------------
  371. inline DWORD ComputeClipCodeUserPlanes(D3DFE_PROCESSVERTICES *pv, ClipVertex *p)
  372. {
  373. DWORD clip = 0;
  374. DWORD dwClipBit = D3DCLIP_GEN0;
  375. for (DWORD i=0; i < pv->dwMaxUserClipPlanes; i++)
  376. {
  377. if ((p->hx*pv->userClipPlane[i].x +
  378. p->hy*pv->userClipPlane[i].y +
  379. p->hz*pv->userClipPlane[i].z +
  380. p->hw*pv->userClipPlane[i].w) < 0)
  381. {
  382. clip |= dwClipBit;
  383. }
  384. dwClipBit <<= 1;
  385. }
  386. return clip;
  387. }
  388. //---------------------------------------------------------------------
  389. inline DWORD ComputeClipCodeGB(D3DFE_PROCESSVERTICES *pv, ClipVertex *p)
  390. {
  391. DWORD clip = 0;
  392. if (p->hx < p->hw * pv->vcache.Kgbx1)
  393. clip |= __D3DCLIPGB_LEFT;
  394. if (p->hx > p->hw * pv->vcache.Kgbx2)
  395. clip |= __D3DCLIPGB_RIGHT;
  396. if (p->hy < p->hw * pv->vcache.Kgby1)
  397. clip |= __D3DCLIPGB_BOTTOM;
  398. if (p->hy > p->hw * pv->vcache.Kgby2)
  399. clip |= __D3DCLIPGB_TOP;
  400. if (p->hz > p->hw)
  401. clip |= D3DCLIP_BACK;
  402. clip |= ComputeClipCodeUserPlanes(pv, p);
  403. p->clip = (p->clip & (CLIPPED_ENABLE | CLIPPED_FRONT)) | clip;
  404. return clip;
  405. }
  406. //---------------------------------------------------------------------
  407. inline DWORD ComputeClipCode(D3DFE_PROCESSVERTICES *pv, ClipVertex *p)
  408. {
  409. DWORD clip = 0;
  410. if (FLOAT_LTZ(p->hx))
  411. clip |= D3DCLIP_LEFT;
  412. if (p->hx > p->hw)
  413. clip |= D3DCLIP_RIGHT;
  414. if (FLOAT_LTZ(p->hy))
  415. clip |= D3DCLIP_BOTTOM;
  416. if (p->hy > p->hw)
  417. clip |= D3DCLIP_TOP;
  418. if (p->hz > p->hw)
  419. clip |= D3DCLIP_BACK;
  420. clip |= ComputeClipCodeUserPlanes(pv, p);
  421. p->clip = (p->clip & (CLIPPED_ENABLE | CLIPPED_FRONT)) | clip;
  422. return clip;
  423. }
  424. //***********************************************************************
  425. //
  426. // Returns 0, if triangle is clipped. Number of vertices otherwise.
  427. //
  428. // Original vertices should not be modified inside the function
  429. //
  430. #undef DPF_MODNAME
  431. #define DPF_MODNAME "ClipSingleTriangle"
  432. int D3DFE_PVFUNCS::ClipSingleTriangle(D3DFE_PROCESSVERTICES *pv,
  433. ClipTriangle *tri,
  434. ClipVertex ***clipVertexPointer)
  435. {
  436. int accept;
  437. int i;
  438. int count;
  439. ClipVertex **inv;
  440. ClipVertex **outv;
  441. ClipVertex *p;
  442. ULONG_PTR swapv;
  443. CD3DFPstate D3DFPstate; // Sets optimal FPU state for D3D.
  444. accept = (tri->v[0]->clip | tri->v[1]->clip | tri->v[2]->clip);
  445. inv = tri->v;
  446. count = 3;
  447. outv = pv->ClipperState.clip_vbuf1;
  448. pv->ClipperState.clip_color = tri->v[0]->color;
  449. pv->ClipperState.clip_specular = tri->v[0]->specular;
  450. /*
  451. * XXX assumes sizeof(void*) == sizeof(unsigned long)
  452. */
  453. {
  454. ULONG_PTR tmp1;
  455. ULONG_PTR tmp2;
  456. tmp1 = (ULONG_PTR)pv->ClipperState.clip_vbuf1;
  457. tmp2 = (ULONG_PTR)pv->ClipperState.clip_vbuf2;
  458. swapv = tmp1 + tmp2;
  459. }
  460. pv->ClipperState.clip_vertices_used = 0;
  461. #define SWAP(inv, outv) \
  462. inv = outv; \
  463. outv = (ClipVertex**) (swapv - (ULONG_PTR) outv)
  464. if (accept & D3DCLIP_FRONT)
  465. {
  466. count = ClipFront(pv, inv, outv, count);
  467. if (count < 3)
  468. goto out_of_here;
  469. SWAP(inv, outv);
  470. }
  471. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
  472. {
  473. // If there was clipping by the front plane it is better to
  474. // compute clip code for new vertices and re-compute accept.
  475. // Otherwise we will try to clip by sides when it is not necessary
  476. if (accept & D3DCLIP_FRONT)
  477. {
  478. accept = 0;
  479. for (i = 0; i < count; i++)
  480. {
  481. ClipVertex *p;
  482. p = inv[i];
  483. if (p->clip & CLIPPED_FRONT)
  484. accept |= ComputeClipCodeGB(pv, p);
  485. else
  486. accept |= p->clip;
  487. }
  488. }
  489. if (accept & D3DCLIP_BACK)
  490. {
  491. count = ClipBack(pv, inv, outv, count);
  492. if (count < 3)
  493. goto out_of_here;
  494. SWAP(inv, outv);
  495. }
  496. if (accept & __D3DCLIPGB_LEFT)
  497. {
  498. count = ClipLeftGB(pv, inv, outv, count);
  499. if (count < 3)
  500. goto out_of_here;
  501. SWAP(inv, outv);
  502. }
  503. if (accept & __D3DCLIPGB_RIGHT)
  504. {
  505. count = ClipRightGB(pv, inv, outv, count);
  506. if (count < 3)
  507. goto out_of_here;
  508. SWAP(inv, outv);
  509. }
  510. if (accept & __D3DCLIPGB_BOTTOM)
  511. {
  512. count = ClipBottomGB(pv, inv, outv, count);
  513. if (count < 3)
  514. goto out_of_here;
  515. SWAP(inv, outv);
  516. }
  517. if (accept & __D3DCLIPGB_TOP)
  518. {
  519. count = ClipTopGB(pv, inv, outv, count);
  520. if (count < 3)
  521. goto out_of_here;
  522. SWAP(inv, outv);
  523. }
  524. }
  525. else
  526. {
  527. // If there was clipping by the front plane it is better to
  528. // compute clip code for new vertices and re-compute accept.
  529. // Otherwise we will try to clip by sides when it is not necessary
  530. if (accept & D3DCLIP_FRONT)
  531. {
  532. accept = 0;
  533. for (i = 0; i < count; i++)
  534. {
  535. ClipVertex *p;
  536. p = inv[i];
  537. if (p->clip & (CLIPPED_FRONT))
  538. accept |= ComputeClipCode(pv, p);
  539. else
  540. accept |= p->clip;
  541. }
  542. }
  543. if (accept & D3DCLIP_BACK)
  544. {
  545. count = ClipBack(pv, inv, outv, count);
  546. if (count < 3)
  547. goto out_of_here;
  548. SWAP(inv, outv);
  549. }
  550. if (accept & D3DCLIP_LEFT)
  551. {
  552. count = ClipLeft(pv, inv, outv, count);
  553. if (count < 3)
  554. goto out_of_here;
  555. SWAP(inv, outv);
  556. }
  557. if (accept & D3DCLIP_RIGHT)
  558. {
  559. count = ClipRight(pv, inv, outv, count);
  560. if (count < 3)
  561. goto out_of_here;
  562. SWAP(inv, outv);
  563. }
  564. if (accept & D3DCLIP_BOTTOM)
  565. {
  566. count = ClipBottom(pv, inv, outv, count);
  567. if (count < 3)
  568. goto out_of_here;
  569. SWAP(inv, outv);
  570. }
  571. if (accept & D3DCLIP_TOP)
  572. {
  573. count = ClipTop(pv, inv, outv, count);
  574. if (count < 3)
  575. goto out_of_here;
  576. SWAP(inv, outv);
  577. }
  578. }
  579. if (pv->dwMaxUserClipPlanes)
  580. {
  581. DWORD dwClipBit = D3DCLIP_GEN0;
  582. DWORD dwClippedBit = CLIPPED_GEN0;
  583. for (DWORD i=0; i < pv->dwMaxUserClipPlanes; i++)
  584. {
  585. if (accept & dwClipBit)
  586. {
  587. count = ClipByPlane(pv, inv, outv, &pv->userClipPlane[i],
  588. dwClippedBit, count);
  589. if (count < 3)
  590. goto out_of_here;
  591. SWAP(inv, outv);
  592. }
  593. dwClipBit <<= 1;
  594. dwClippedBit <<= 1;
  595. }
  596. }
  597. #undef SWAP
  598. ComputeScreenCoordinates(pv, inv, count, &pv->rExtents);
  599. *clipVertexPointer = inv;
  600. pv->ClipperState.current_vbuf = inv;
  601. return count;
  602. out_of_here:
  603. *clipVertexPointer = NULL;
  604. return 0;
  605. }
  606. //*************************************************************************
  607. //
  608. #undef DPF_MODNAME
  609. #define DPF_MODNAME "ClipSingleLine"
  610. int
  611. ClipSingleLine(D3DFE_PROCESSVERTICES *pv,
  612. ClipTriangle *line,
  613. D3DRECTV *extent)
  614. {
  615. int accept;
  616. D3DVALUE in1, in2;
  617. CD3DFPstate D3DFPstate; // Sets optimal FPU state for D3D.
  618. accept = (line->v[0]->clip | line->v[1]->clip);
  619. pv->ClipperState.clip_color = line->v[0]->color;
  620. pv->ClipperState.clip_specular = line->v[0]->specular;
  621. if (accept & D3DCLIP_FRONT)
  622. if (ClipLineFront(pv, line))
  623. goto out_of_here;
  624. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
  625. {
  626. // If there was clipping by the front plane it is better to
  627. // compute clip code for new vertices and re-compute accept.
  628. // Otherwise we will try to clip by sides when it is not necessary
  629. if (accept & D3DCLIP_FRONT)
  630. {
  631. ClipVertex * p;
  632. accept = 0;
  633. p = line->v[0];
  634. if (p->clip & CLIPPED_FRONT)
  635. accept |= ComputeClipCodeGB(pv, p);
  636. else
  637. accept |= p->clip;
  638. p = line->v[1];
  639. if (p->clip & CLIPPED_FRONT)
  640. accept |= ComputeClipCodeGB(pv, p);
  641. else
  642. accept |= p->clip;
  643. }
  644. if (accept & D3DCLIP_BACK)
  645. if (ClipLineBack(pv, line))
  646. goto out_of_here;
  647. if (accept & __D3DCLIPGB_LEFT)
  648. if (ClipLineLeftGB(pv, line))
  649. goto out_of_here;
  650. if (accept & __D3DCLIPGB_RIGHT)
  651. if (ClipLineRightGB(pv, line))
  652. goto out_of_here;
  653. if (accept & __D3DCLIPGB_TOP)
  654. if (ClipLineTopGB(pv, line))
  655. goto out_of_here;
  656. if (accept & __D3DCLIPGB_BOTTOM)
  657. if (ClipLineBottomGB(pv, line))
  658. goto out_of_here;
  659. }
  660. else
  661. {
  662. // If there was clipping by the front plane it is better to
  663. // compute clip code for new vertices and re-compute accept.
  664. // Otherwise we will try to clip by sides when it is not necessary
  665. if (accept & D3DCLIP_FRONT)
  666. {
  667. ClipVertex * p;
  668. accept = 0;
  669. p = line->v[0];
  670. if (p->clip & CLIPPED_FRONT)
  671. accept |= ComputeClipCode(pv, p);
  672. else
  673. accept |= p->clip;
  674. p = line->v[1];
  675. if (p->clip & CLIPPED_FRONT)
  676. accept |= ComputeClipCode(pv, p);
  677. else
  678. accept |= p->clip;
  679. }
  680. if (accept & D3DCLIP_BACK)
  681. if (ClipLineBack(pv, line))
  682. goto out_of_here;
  683. if (accept & D3DCLIP_LEFT)
  684. if (ClipLineLeft(pv, line))
  685. goto out_of_here;
  686. if (accept & D3DCLIP_RIGHT)
  687. if (ClipLineRight(pv, line))
  688. goto out_of_here;
  689. if (accept & D3DCLIP_TOP)
  690. if (ClipLineTop(pv, line))
  691. goto out_of_here;
  692. if (accept & D3DCLIP_BOTTOM)
  693. if (ClipLineBottom(pv, line))
  694. goto out_of_here;
  695. }
  696. if (pv->dwMaxUserClipPlanes)
  697. {
  698. DWORD dwClipBit = D3DCLIP_GEN0;
  699. DWORD dwClippedBit = CLIPPED_GEN0;
  700. for (DWORD i=0; i < pv->dwMaxUserClipPlanes; i++)
  701. {
  702. if (accept & dwClipBit)
  703. {
  704. if (ClipLineByPlane(pv, line, &pv->userClipPlane[i],
  705. dwClippedBit))
  706. goto out_of_here;
  707. }
  708. dwClipBit <<= 1;
  709. dwClippedBit <<= 1;
  710. }
  711. }
  712. ComputeScreenCoordinates(pv, line->v, 2, extent);
  713. return 1;
  714. out_of_here:
  715. return 0;
  716. } // ClipSingleLine
  717. //----------------------------------------------------------------------
  718. // GenClipFlags() Generates clip flags for a set of FVF
  719. //
  720. #undef DPF_MODNAME
  721. #define DPF_MODNAME "GenClipFlags"
  722. DWORD D3DFE_GenClipFlags(D3DFE_PROCESSVERTICES *pv)
  723. {
  724. DWORD clip_intersection, clip_union;
  725. float left = pv->vcache.minX;
  726. float top = pv->vcache.minY;
  727. float right = pv->vcache.maxX;
  728. float bottom = pv->vcache.maxY;
  729. float leftgb ; // Guard band window
  730. float topgb ;
  731. float rightgb ;
  732. float bottomgb;
  733. DWORD clipZF, clipZB;
  734. DWORD stride = pv->position.dwStride;
  735. clipZF = pv->lpdwRStates[D3DRENDERSTATE_ZENABLE] ? D3DCLIP_FRONT : 0;
  736. clipZB = pv->lpdwRStates[D3DRENDERSTATE_ZENABLE] ? D3DCLIP_BACK : 0;
  737. clip_intersection = (DWORD)~0;
  738. clip_union = (DWORD)0;
  739. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
  740. {
  741. leftgb = pv->vcache.minXgb;
  742. topgb = pv->vcache.minYgb;
  743. rightgb = pv->vcache.maxXgb;
  744. bottomgb = pv->vcache.maxYgb;
  745. }
  746. if (pv->dwDeviceFlags & D3DDEV_DONOTUPDATEEXTENTS)
  747. { /* Only generate clip flags */
  748. D3DTLVERTEX *lpVertices = (D3DTLVERTEX*)pv->position.lpvData;
  749. D3DFE_CLIPCODE *clipCode = pv->lpClipFlags;
  750. DWORD i;
  751. for (i = pv->dwNumVertices; i; i--)
  752. {
  753. DWORD clip = 0;
  754. D3DVALUE x,y,z;
  755. if (lpVertices->rhw < 0)
  756. {
  757. x = -lpVertices->sx;
  758. y = -lpVertices->sy;
  759. z = -lpVertices->sz;
  760. }
  761. else
  762. {
  763. x = lpVertices->sx;
  764. y = lpVertices->sy;
  765. z = lpVertices->sz;
  766. }
  767. if (x < left)
  768. clip |= D3DCLIP_LEFT;
  769. else
  770. if (x >= right)
  771. clip |= D3DCLIP_RIGHT;
  772. if (y < top)
  773. clip |= D3DCLIP_TOP;
  774. else
  775. if (y >= bottom)
  776. clip |= D3DCLIP_BOTTOM;
  777. if (z < 0.0f)
  778. clip |= clipZF;
  779. else
  780. if (z >= 1.0f)
  781. clip |= clipZB;
  782. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND && clip)
  783. {
  784. if (x < leftgb)
  785. clip |= __D3DCLIPGB_LEFT;
  786. else
  787. if (x >= rightgb)
  788. clip |= __D3DCLIPGB_RIGHT;
  789. if (y < topgb)
  790. clip |= __D3DCLIPGB_TOP;
  791. else
  792. if (y >= bottomgb)
  793. clip |= __D3DCLIPGB_BOTTOM;
  794. }
  795. clip_intersection &= clip;
  796. clip_union |= clip;
  797. *clipCode++ = (D3DFE_CLIPCODE)clip;
  798. lpVertices = (D3DTLVERTEX*)((char*)lpVertices + stride);
  799. }
  800. }
  801. else
  802. { /* Generate Clip Flags and Update Extents */
  803. DWORD i;
  804. float minx = pv->rExtents.x1;
  805. float miny = pv->rExtents.y1;
  806. float maxx = pv->rExtents.x2;
  807. float maxy = pv->rExtents.y2;
  808. D3DTLVERTEX *lpVertices = (D3DTLVERTEX*)pv->position.lpvData;
  809. D3DFE_CLIPCODE *clipCode = pv->lpClipFlags;
  810. for (i = pv->dwNumVertices; i; i--)
  811. {
  812. DWORD clip = 0;
  813. D3DVALUE x,y,z;
  814. if (lpVertices->rhw < 0)
  815. {
  816. x = -lpVertices->sx;
  817. y = -lpVertices->sy;
  818. z = -lpVertices->sz;
  819. }
  820. else
  821. {
  822. x = lpVertices->sx;
  823. y = lpVertices->sy;
  824. z = lpVertices->sz;
  825. }
  826. if (x < left)
  827. clip |= D3DCLIP_LEFT;
  828. else
  829. if (x >= right)
  830. clip |= D3DCLIP_RIGHT;
  831. if (y < top)
  832. clip |= D3DCLIP_TOP;
  833. else
  834. if (y >= bottom)
  835. clip |= D3DCLIP_BOTTOM;
  836. if (z < 0.0f)
  837. clip |= clipZF;
  838. else
  839. if (z >= 1.0f)
  840. clip |= clipZB;
  841. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND && clip)
  842. {
  843. if (x < leftgb)
  844. clip |= __D3DCLIPGB_LEFT;
  845. else
  846. if (x >= rightgb)
  847. clip |= __D3DCLIPGB_RIGHT;
  848. if (y < topgb)
  849. clip |= __D3DCLIPGB_TOP;
  850. else
  851. if (y >= bottomgb)
  852. clip |= __D3DCLIPGB_BOTTOM;
  853. }
  854. // Update extents only if the vertex is inside
  855. if (clip == 0 ||
  856. ((pv->dwDeviceFlags & D3DDEV_GUARDBAND) &&
  857. ((clip & ~__D3DCLIP_INGUARDBAND) == 0)))
  858. {
  859. if (x < minx)
  860. minx = x;
  861. if (x > maxx)
  862. maxx = x;
  863. if (y < miny)
  864. miny = y;
  865. if (y > maxy)
  866. maxy = y;
  867. }
  868. clip_intersection &= clip;
  869. clip_union |= clip;
  870. *clipCode++ = (D3DFE_CLIPCODE)clip;
  871. lpVertices = (D3DTLVERTEX*)((char*)lpVertices + stride);
  872. }
  873. pv->rExtents.x1 = minx;
  874. pv->rExtents.y1 = miny;
  875. pv->rExtents.x2 = maxx;
  876. pv->rExtents.y2 = maxy;
  877. }
  878. pv->dwClipIntersection = clip_intersection;
  879. pv->dwClipUnion = clip_union;
  880. return clip_intersection;
  881. } // end of GenClipFlags()
  882. //---------------------------------------------------------------------
  883. // Make clip vertex from D3D vertex
  884. //
  885. // device - DIRECT3DDEVICEI *
  886. // pp1 - clipVertex
  887. // p1 - TL vertex
  888. //
  889. void MAKE_CLIP_VERTEX_FVF(D3DFE_PROCESSVERTICES *pv, ClipVertex& pp1, BYTE* p1,
  890. DWORD clipFlag, BOOL transformed)
  891. {
  892. D3DFE_VIEWPORTCACHE& VPORT = pv->vcache;
  893. BYTE *v = (BYTE*)p1;
  894. if (transformed || !(clipFlag & pv->dwClipMaskOffScreen))
  895. {
  896. pp1.sx = ((D3DVALUE*)v)[0];
  897. pp1.sy = ((D3DVALUE*)v)[1];
  898. pp1.sz = ((D3DVALUE*)v)[2];
  899. pp1.rhw = ((D3DVALUE*)v)[3];
  900. pp1.hw = 1.0f / ((D3DVALUE*)v)[3];
  901. pp1.hx = (pp1.sx - VPORT.offsetX) * pp1.hw * VPORT.scaleXi;
  902. pp1.hy = (pp1.sy - VPORT.offsetY) * pp1.hw * VPORT.scaleYi;
  903. pp1.hz = (pp1.sz - VPORT.offsetZ) * pp1.hw * VPORT.scaleZi;
  904. }
  905. else
  906. {
  907. pp1.hx = ((D3DVALUE*)v)[0];
  908. pp1.hy = ((D3DVALUE*)v)[1];
  909. pp1.hz = ((D3DVALUE*)v)[2];
  910. pp1.hw = ((D3DVALUE*)v)[3];
  911. }
  912. v += sizeof(D3DVALUE) * 4;
  913. if (pv->dwVIDOut & D3DFVF_DIFFUSE)
  914. {
  915. pp1.color = *(DWORD*)v;
  916. v += sizeof(D3DVALUE);
  917. }
  918. if (pv->dwVIDOut & D3DFVF_SPECULAR)
  919. {
  920. pp1.specular= *(DWORD*)v;
  921. v += sizeof(DWORD);
  922. }
  923. memcpy(pp1.tex, v, pv->dwTextureCoordSizeTotal);
  924. pp1.clip = clipFlag;
  925. }
  926. //---------------------------------------------------------------------
  927. // Make TL vertex from clip vertex
  928. //
  929. // device - DIRECT3DDEVICEI *
  930. // in - clipVertex
  931. // out - TL vertex
  932. //
  933. void MAKE_TL_VERTEX_FVF(D3DFE_PROCESSVERTICES *pv, BYTE* out, ClipVertex* in)
  934. {
  935. *(D3DVECTORH*)out = *(D3DVECTORH*)&(in)->sx;
  936. *(DWORD*)&out[pv->diffuseOffsetOut] = (in)->color;
  937. *(DWORD*)&out[pv->specularOffsetOut] = (in)->specular;
  938. memcpy(&out[pv->texOffsetOut], in->tex, pv->dwTextureCoordSizeTotal);
  939. }