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.

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