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.

1199 lines
27 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name
  4. trimesh.cxx
  5. Abstract:
  6. Implement triangle mesh API
  7. Author:
  8. Mark Enstrom (marke) 23-Jun-1996
  9. Enviornment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. #include "dciman.h"
  15. #pragma hdrstop
  16. #if !(_WIN32_WINNT >= 0x500)
  17. /******************************Public*Routine******************************\
  18. * vHorizontalLine
  19. *
  20. * Record information for horizontal line.
  21. * Colors are recorded as fixed point 8.56
  22. *
  23. * Arguments:
  24. *
  25. * pv1 - vertex 1
  26. * pv2 - vertex 2
  27. * ptData - triangle data
  28. * ptridda - dda data
  29. *
  30. * Return Value:
  31. *
  32. * none
  33. *
  34. * History:
  35. *
  36. * 11/20/1996 Mark Enstrom [marke]
  37. *
  38. \**************************************************************************/
  39. VOID
  40. vHorizontalLine(
  41. PTRIVERTEX pv1,
  42. PTRIVERTEX pv2,
  43. PTRIANGLEDATA ptData,
  44. PTRIDDA ptridda
  45. )
  46. {
  47. LONG yPosition = ptridda->N0;
  48. LONG yIndex = yPosition - ptData->y0;
  49. //
  50. // check if this line is whithin clipping in y
  51. //
  52. if (
  53. (yPosition >= ptData->rcl.top) &&
  54. (yPosition < ptData->rcl.bottom)
  55. )
  56. {
  57. //
  58. // find left edge
  59. //
  60. if (pv1->x <= pv2->x)
  61. {
  62. //
  63. // left edge
  64. //
  65. ptData->TriEdge[yIndex].xLeft = pv1->x;
  66. ptData->TriEdge[yIndex].llRed = ((LONGLONG)pv1->Red) << 48;
  67. ptData->TriEdge[yIndex].llGreen = ((LONGLONG)pv1->Green) << 48;
  68. ptData->TriEdge[yIndex].llBlue = ((LONGLONG)pv1->Blue) << 48;
  69. ptData->TriEdge[yIndex].llAlpha = ((LONGLONG)pv1->Alpha) << 48;
  70. //
  71. // right edge
  72. //
  73. ptData->TriEdge[yIndex].xRight = pv2->x;
  74. }
  75. else
  76. {
  77. //
  78. // left edge
  79. //
  80. ptData->TriEdge[yIndex].xLeft = pv2->x;
  81. ptData->TriEdge[yIndex].llRed = pv2->Red << 48;
  82. ptData->TriEdge[yIndex].llGreen = pv2->Green << 48;
  83. ptData->TriEdge[yIndex].llBlue = pv2->Blue << 48;
  84. ptData->TriEdge[yIndex].llAlpha = pv2->Alpha << 48;
  85. //
  86. // right edge
  87. //
  88. ptData->TriEdge[yIndex].xRight = pv1->x;
  89. }
  90. }
  91. }
  92. /******************************Public*Routine******************************\
  93. * vEdgeDDA
  94. *
  95. * Run line DDA down an edge of the triangle recording edge
  96. * position and color
  97. *
  98. * Arguments:
  99. *
  100. * ptData - triangle data
  101. * ptridda - line dda information
  102. *
  103. * Return Value:
  104. *
  105. * None
  106. *
  107. * History:
  108. *
  109. * 11/20/1996 Mark Enstrom [marke]
  110. *
  111. \**************************************************************************/
  112. VOID
  113. vEdgeDDA(
  114. PTRIANGLEDATA ptData,
  115. PTRIDDA ptridda
  116. )
  117. {
  118. LONG NumScanLines = ptridda->NumScanLines;
  119. LONG yIndex = ptridda->yIndex;
  120. LONGLONG llRed = ptridda->llRed;
  121. LONGLONG llGreen = ptridda->llGreen;
  122. LONGLONG llBlue = ptridda->llBlue;
  123. LONGLONG llAlpha = ptridda->llAlpha;
  124. LONG L = ptridda->L;
  125. LONG Rb = ptridda->Rb;
  126. //
  127. // Scan all lines, only record lines contained by
  128. // the clipping in ptData->rcl (y)
  129. //
  130. while (NumScanLines--)
  131. {
  132. //
  133. // check for and record left edge
  134. //
  135. if (yIndex >= 0)
  136. {
  137. if (L < ptData->TriEdge[yIndex].xLeft)
  138. {
  139. ptData->TriEdge[yIndex].xLeft = L;
  140. ptData->TriEdge[yIndex].llRed = llRed;
  141. ptData->TriEdge[yIndex].llGreen = llGreen;
  142. ptData->TriEdge[yIndex].llBlue = llBlue;
  143. ptData->TriEdge[yIndex].llAlpha = llAlpha;
  144. }
  145. if (L > ptData->TriEdge[yIndex].xRight)
  146. {
  147. ptData->TriEdge[yIndex].xRight = L;
  148. }
  149. }
  150. //
  151. // inc y by one scan line, inc x(L) by integer step
  152. // and inc error term by dR
  153. //
  154. yIndex++;
  155. L += ptridda->dL;
  156. Rb -= ptridda->dR;
  157. //
  158. // inc color components by y and integer x components
  159. //
  160. llRed += (ptridda->lldxyRed);
  161. llGreen += (ptridda->lldxyGreen);
  162. llBlue += (ptridda->lldxyBlue);
  163. llAlpha += (ptridda->lldxyAlpha);
  164. //
  165. // check for DDA error term overflow, add one
  166. // more step in x and color if true,
  167. // and correct error term
  168. //
  169. if (Rb < 0)
  170. {
  171. //
  172. // fraction step in x
  173. //
  174. L += ptridda->Linc;
  175. //
  176. // fraction step in color components
  177. //
  178. llRed += ptData->lldRdX;
  179. llGreen += ptData->lldGdX;
  180. llBlue += ptData->lldBdX;
  181. llAlpha += ptData->lldAdX;
  182. //
  183. // adjust error term
  184. //
  185. Rb += ptridda->dN;
  186. }
  187. }
  188. }
  189. /******************************Public*Routine******************************\
  190. * vCalulateLine
  191. *
  192. * calculate bounding line
  193. *
  194. * Arguments:
  195. *
  196. * pv1 - vertex 1
  197. * pv2 - vertex 2
  198. * ptData - triangle data
  199. *
  200. * Return Value:
  201. *
  202. * none
  203. *
  204. * History:
  205. *
  206. * 11/20/1996 Mark Enstrom [marke]
  207. *
  208. \**************************************************************************/
  209. VOID
  210. vCalculateLine(
  211. PTRIVERTEX pv1,
  212. PTRIVERTEX pv2,
  213. PTRIANGLEDATA ptData
  214. )
  215. {
  216. TRIDDA tridda;
  217. //
  218. // initial y component
  219. //
  220. tridda.lldxyRed = ptData->lldRdY;
  221. tridda.lldxyGreen = ptData->lldGdY;
  222. tridda.lldxyBlue = ptData->lldBdY;
  223. tridda.lldxyAlpha = ptData->lldAdY;
  224. //
  225. // N0 = integer y starting location
  226. // M0 = integer x starting location
  227. // dN = integer delta y
  228. // dM = integer delta x
  229. //
  230. // Arrange lines, must run DDA in positive delta y.
  231. //
  232. if (pv2->y >= pv1->y)
  233. {
  234. tridda.dN = pv2->y - pv1->y;
  235. tridda.dM = pv2->x - pv1->x;
  236. tridda.N0 = pv1->y;
  237. tridda.M0 = pv1->x;
  238. }
  239. else
  240. {
  241. tridda.dN = pv1->y - pv2->y;
  242. tridda.dM = pv1->x - pv2->x;
  243. tridda.N0 = pv2->y;
  244. tridda.M0 = pv2->x;
  245. }
  246. //
  247. // caclulate initial color value at stating vertex
  248. //
  249. tridda.llRed = ptData->lldRdY * (tridda.N0 - ptData->ptColorCalcOrg.y) +
  250. ptData->lldRdX * (tridda.M0 - ptData->ptColorCalcOrg.x) +
  251. ptData->llRA;
  252. tridda.llGreen = ptData->lldGdY * (tridda.N0 - ptData->ptColorCalcOrg.y) +
  253. ptData->lldGdX * (tridda.M0 - ptData->ptColorCalcOrg.x) +
  254. ptData->llGA;
  255. tridda.llBlue = ptData->lldBdY * (tridda.N0 - ptData->ptColorCalcOrg.y) +
  256. ptData->lldBdX * (tridda.M0 - ptData->ptColorCalcOrg.x) +
  257. ptData->llBA;
  258. tridda.llAlpha = ptData->lldAdY * (tridda.N0 - ptData->ptColorCalcOrg.y) +
  259. ptData->lldAdX * (tridda.M0 - ptData->ptColorCalcOrg.x) +
  260. ptData->llAA;
  261. //
  262. // Check for horizontal line, dN == 0 is a horizontal line.
  263. // In this case just record the end points.
  264. //
  265. if (tridda.dN == 0)
  266. {
  267. vHorizontalLine(pv1,pv2,ptData,&tridda);
  268. }
  269. else
  270. {
  271. LONGLONG l0,Frac;
  272. tridda.Linc = 1;
  273. //
  274. // yIndex is the offset into the edge array for
  275. // the current line. Calc number of scan lines
  276. // and maximum y position
  277. //
  278. tridda.yIndex = tridda.N0 - ptData->y0;
  279. tridda.NumScanLines = tridda.dN;
  280. LONG NMax = tridda.N0 + tridda.NumScanLines;
  281. //
  282. // make sure scan lines do not overrun buffer due to
  283. // clipping
  284. //
  285. if (
  286. (tridda.N0 > ptData->rcl.bottom) ||
  287. (NMax < ptData->rcl.top)
  288. )
  289. {
  290. //
  291. // nothing to draw
  292. //
  293. return;
  294. }
  295. else if (NMax > ptData->rcl.bottom)
  296. {
  297. //
  298. // clipped number of scan lines !!! only clipped against bottom, what about top !!!
  299. //
  300. tridda.NumScanLines = tridda.NumScanLines - (NMax - ptData->rcl.bottom);
  301. }
  302. tridda.j = tridda.N0;
  303. tridda.C = ((LONGLONG)tridda.M0 * (LONGLONG)tridda.dN) - ((LONGLONG)tridda.N0 * (LONGLONG)tridda.dM) -1;
  304. tridda.C = tridda.C + tridda.dN;
  305. LONGLONG LongL;
  306. if (tridda.dM > 0)
  307. {
  308. tridda.dL = tridda.dM / tridda.dN;
  309. tridda.dR = tridda.dM - tridda.dL * tridda.dN;
  310. }
  311. else if (tridda.dM < 0)
  312. {
  313. //
  314. // negative divide
  315. //
  316. LONG dLQ,dLR;
  317. tridda.dM = -tridda.dM;
  318. dLQ = (tridda.dM - 1) / tridda.dN;
  319. dLR = tridda.dM - 1 - (dLQ * tridda.dN);
  320. tridda.dL = -(dLQ + 1);
  321. tridda.dR = tridda.dN - dLR - 1;
  322. }
  323. else
  324. {
  325. //
  326. // dM = 0
  327. //
  328. tridda.dL = 0;
  329. tridda.dR = 0;
  330. }
  331. l0 = tridda.j * tridda.dL;
  332. LongL = tridda.j * tridda.dR + tridda.C;
  333. if (LongL > 0)
  334. {
  335. Frac = (LONG)(LongL/tridda.dN);
  336. }
  337. else if (LongL < 0)
  338. {
  339. LONGLONG Q = ((-LongL - 1)/tridda.dN);
  340. Frac = -(Q + 1);
  341. }
  342. else
  343. {
  344. Frac = 0;
  345. }
  346. tridda.R = (LONG)(LongL - (Frac * tridda.dN));
  347. tridda.L = (LONG)(l0 + Frac);
  348. tridda.Rb = tridda.dN - tridda.R - 1;
  349. //
  350. // Calculate color steps for dx
  351. //
  352. tridda.lldxyRed = tridda.lldxyRed + (ptData->lldRdX * tridda.dL);
  353. tridda.lldxyGreen = tridda.lldxyGreen + (ptData->lldGdX * tridda.dL);
  354. tridda.lldxyBlue = tridda.lldxyBlue + (ptData->lldBdX * tridda.dL);
  355. tridda.lldxyAlpha = tridda.lldxyAlpha + (ptData->lldAdX * tridda.dL);
  356. //
  357. // run edge dda
  358. //
  359. vEdgeDDA(ptData,&tridda);
  360. }
  361. }
  362. /**************************************************************************\
  363. * bCalulateColorGradient
  364. *
  365. * Calculate all color gradients
  366. *
  367. * Arguments:
  368. *
  369. * pv0,pv1,pv2 - triangle verticies
  370. * ptData - triangel data
  371. *
  372. * Return Value:
  373. *
  374. * status
  375. *
  376. * History:
  377. *
  378. * 5/22/1997 Kirk Olnyk [kirko]
  379. *
  380. \**************************************************************************/
  381. BOOL
  382. bCalulateColorGradient(
  383. PTRIVERTEX pv0,
  384. PTRIVERTEX pv1,
  385. PTRIVERTEX pv2,
  386. PTRIANGLEDATA ptData
  387. )
  388. {
  389. GRADSTRUCT g;
  390. LONGLONG d;
  391. LONG z;
  392. g.x1 = pv1->x;
  393. g.y1 = pv1->y;
  394. g.x2 = pv2->x;
  395. g.y2 = pv2->y;
  396. z = pv0->x;
  397. g.x1 -= z;
  398. g.x2 -= z;
  399. z = pv0->y;
  400. g.y1 -= z;
  401. g.y2 -= z;
  402. g.d = g.x1 * g.y2 - g.x2 * g.y1;
  403. LONG tx = MIN(g.x1,0);
  404. LONG ty = MIN(g.y1,0);
  405. g.m = MIN(tx,g.x2) + MIN(ty,g.y2);
  406. d = (LONGLONG) ABS(g.d);
  407. g.Q = (LONGLONG)TWO_TO_THE_48TH / d;
  408. g.R = (LONGLONG)TWO_TO_THE_48TH % d;
  409. ptData->ptColorCalcOrg.x = pv0->x;
  410. ptData->ptColorCalcOrg.y = pv0->y;
  411. bDoGradient( &ptData->lldRdX // &A
  412. , &ptData->lldRdY // &B
  413. , &ptData->llRA // &C
  414. , pv0->Red // R0
  415. , pv1->Red // R1
  416. , pv2->Red // R2
  417. , &g );
  418. bDoGradient( &ptData->lldGdX
  419. , &ptData->lldGdY
  420. , &ptData->llGA
  421. , pv0->Green
  422. , pv1->Green
  423. , pv2->Green
  424. , &g );
  425. bDoGradient( &ptData->lldBdX
  426. , &ptData->lldBdY
  427. , &ptData->llBA
  428. , pv0->Blue
  429. , pv1->Blue
  430. , pv2->Blue
  431. , &g );
  432. bDoGradient( &ptData->lldAdX
  433. , &ptData->lldAdY
  434. , &ptData->llAA
  435. , pv0->Alpha
  436. , pv1->Alpha
  437. , pv2->Alpha
  438. , &g );
  439. return(TRUE);
  440. }
  441. /**************************************************************************\
  442. * MDiv64
  443. * 64 bit mul-div
  444. *
  445. * Arguments:
  446. *
  447. * return = (a * b) / c
  448. *
  449. * Return Value:
  450. *
  451. *
  452. *
  453. * History:
  454. *
  455. * 5/22/1997 Kirk Olnyk [kirko]
  456. *
  457. \**************************************************************************/
  458. LONGLONG
  459. MDiv64(
  460. LONGLONG a,
  461. LONGLONG b,
  462. LONGLONG c)
  463. {
  464. LONGLONG Result;
  465. int isNegative=0;
  466. Result = 0;
  467. if (a != 0 && b != 0)
  468. {
  469. if (a < 0)
  470. {
  471. a = -a;
  472. isNegative = 1;
  473. }
  474. else if (b < 0)
  475. {
  476. b = -b;
  477. isNegative = 1;
  478. }
  479. a = a * b - (LONGLONG) isNegative;
  480. Result = a / c;
  481. if (isNegative)
  482. {
  483. Result = - Result - 1;
  484. }
  485. }
  486. return(Result);
  487. }
  488. /**************************************************************************\
  489. * bDoGradient
  490. *
  491. * calc color gradient for one color
  492. *
  493. * Arguments:
  494. *
  495. * pA
  496. * pB
  497. * pC
  498. * g0
  499. * g1
  500. * g2
  501. * pg
  502. *
  503. * Return Value:
  504. *
  505. * status
  506. *
  507. * History:
  508. *
  509. * 5/22/1997 Kirk Olnyk [kirko]
  510. *
  511. \**************************************************************************/
  512. BOOL
  513. bDoGradient(
  514. LONGLONG *pA,
  515. LONGLONG *pB,
  516. LONGLONG *pC,
  517. LONG g0,
  518. LONG g1,
  519. LONG g2,
  520. GRADSTRUCT *pg
  521. )
  522. {
  523. BOOL bDiv(LONGLONG*, LONGLONG, LONG);
  524. LONGLONG a,b,c,d;
  525. g1 = g1 - g0;
  526. g2 = g2 - g0;
  527. a = g1 * pg->y2 - g2 * pg->y1;
  528. b = g2 * pg->x1 - g1 * pg->x2;
  529. d = pg->d;
  530. if (d < 0)
  531. {
  532. a = -a;
  533. b = -b;
  534. d = -d;
  535. }
  536. *pA = pg->Q * a + MDiv64(a, pg->R, d);
  537. *pB = pg->Q * b + MDiv64(b, pg->R, d);
  538. c = (d >> 1) + 1;
  539. a = c * pg->R - pg->m - 1;
  540. a /= d;
  541. a += c * pg->Q;
  542. a += pg->m;
  543. *pC = a + (((LONGLONG) g0) << 48);
  544. return(TRUE);
  545. }
  546. /**************************************************************************\
  547. * lCalculateTriangleArea
  548. *
  549. * Arguments:
  550. *
  551. * pv0 - vertex
  552. * pv1 - vertex
  553. * pv2 - vertex
  554. * ptData - triangle data
  555. *
  556. * Return Value:
  557. *
  558. * < 0 = negative area
  559. * 0 = 0 area
  560. * > 0 = positive area
  561. *
  562. * History:
  563. *
  564. * 2/26/1997 Mark Enstrom [marke]
  565. *
  566. \**************************************************************************/
  567. LONG
  568. lCalculateTriangleArea(
  569. PTRIVERTEX pv0,
  570. PTRIVERTEX pv1,
  571. PTRIVERTEX pv2,
  572. PTRIANGLEDATA ptData
  573. )
  574. {
  575. LONG lRet;
  576. //
  577. // calc area, color gradients in x,y
  578. //
  579. // area = (v2-v0) X (v1 - v2)
  580. //
  581. LONGLONG v12x = pv1->x - pv2->x;
  582. LONGLONG v12y = pv1->y - pv2->y;
  583. LONGLONG v02x = pv0->x - pv2->x;
  584. LONGLONG v02y = pv0->y - pv2->y;
  585. LONGLONG Area = (v12y * v02x) - (v12x * v02y);
  586. if (Area == 0)
  587. {
  588. lRet = 0;
  589. }
  590. else if (Area > 0)
  591. {
  592. lRet = 1;
  593. if (ptData != NULL)
  594. {
  595. ptData->Area = Area;
  596. }
  597. }
  598. else
  599. {
  600. lRet = -1;
  601. }
  602. return(lRet);
  603. }
  604. /**************************************************************************\
  605. * LIMIT_COLOR
  606. *
  607. * Actual input colors are limited to 0x0000 - 0xff00
  608. * 256 * (0x00 - 0xff)
  609. *
  610. * Arguments:
  611. *
  612. * pv - vertex
  613. *
  614. * History:
  615. *
  616. * 2/26/1997 Mark Enstrom [marke]
  617. *
  618. \**************************************************************************/
  619. #define LIMIT_COLOR(pv) \
  620. \
  621. if (pv->Red > 0xff00) \
  622. { \
  623. pv->Red = 0xff00; \
  624. } \
  625. \
  626. if (pv->Green > 0xff00) \
  627. { \
  628. pv->Green = 0xff00; \
  629. } \
  630. \
  631. if (pv->Blue > 0xff00) \
  632. { \
  633. pv->Blue = 0xff00; \
  634. }
  635. /**************************************************************************\
  636. * bIsTriangleInBounds
  637. *
  638. * Is triangle inside bounding rect
  639. *
  640. * Arguments:
  641. *
  642. * pInV0 - vertex 0
  643. * pInV1 - vertex 1
  644. * pInV2 - vertex 2
  645. * ptData - triangle data
  646. *
  647. * Return Value:
  648. *
  649. * TRUE in any of the triangle is contained in bounding rect
  650. *
  651. * History:
  652. *
  653. * 5/8/1997 Mark Enstrom [marke]
  654. *
  655. \**************************************************************************/
  656. BOOL
  657. bIsTriangleInBounds(
  658. PTRIVERTEX pInV0,
  659. PTRIVERTEX pInV1,
  660. PTRIVERTEX pInV2,
  661. PTRIANGLEDATA ptData
  662. )
  663. {
  664. PRECTL prclClip = &ptData->rcl;
  665. RECTL rclTri;
  666. rclTri.left = MIN(pInV0->x,pInV1->x);
  667. rclTri.right = MAX(pInV0->x,pInV1->x);
  668. rclTri.top = MIN(pInV0->y,pInV1->y);
  669. rclTri.bottom = MAX(pInV0->y,pInV1->y);
  670. rclTri.left = MIN(rclTri.left,pInV2->x);
  671. rclTri.right = MAX(rclTri.right,pInV2->x);
  672. rclTri.top = MIN(rclTri.top,pInV2->y);
  673. rclTri.bottom = MAX(rclTri.bottom,pInV2->y);
  674. if ((rclTri.left >= prclClip->right) ||
  675. (rclTri.right <= prclClip->left) ||
  676. (rclTri.top >= prclClip->bottom) ||
  677. (rclTri.bottom <= prclClip->top))
  678. {
  679. return(FALSE);
  680. }
  681. return(TRUE);
  682. }
  683. /**************************************************************************\
  684. * bTriangleNeedSplit
  685. * determine whether triangle needs split
  686. *
  687. * Arguments:
  688. *
  689. * pv0,pv1,pv2 - triangle vertex
  690. *
  691. * Return Value:
  692. *
  693. * TRUE if triangle needs to be split
  694. *
  695. * History:
  696. *
  697. * 5/8/1997 Mark Enstrom [marke]
  698. *
  699. \**************************************************************************/
  700. BOOL
  701. bTriangleNeedsSplit(
  702. PTRIVERTEX pv0,
  703. PTRIVERTEX pv1,
  704. PTRIVERTEX pv2
  705. )
  706. {
  707. //
  708. // calc dx,dy for each leg
  709. //
  710. LONG dx01 = ABS(pv0->x - pv1->x);
  711. LONG dy01 = ABS(pv0->y - pv1->y);
  712. LONG dx02 = ABS(pv0->x - pv2->x);
  713. LONG dy02 = ABS(pv0->y - pv2->y);
  714. LONG dx12 = ABS(pv1->x - pv2->x);
  715. LONG dy12 = ABS(pv1->y - pv2->y);
  716. //
  717. // if any length is longer than max, break triangle into two pieces
  718. // and call this routine for each
  719. //
  720. if (
  721. (
  722. (dx01 > MAX_EDGE_LENGTH) || (dy01 > MAX_EDGE_LENGTH) ||
  723. (dx02 > MAX_EDGE_LENGTH) || (dy02 > MAX_EDGE_LENGTH) ||
  724. (dx12 > MAX_EDGE_LENGTH) || (dy12 > MAX_EDGE_LENGTH)
  725. )
  726. )
  727. {
  728. return(TRUE);
  729. }
  730. return(FALSE);
  731. }
  732. /**************************************************************************\
  733. * bSplitTriangle
  734. * Determine is triangle must be split.
  735. * Split triangle along longest edge
  736. *
  737. * Arguments:
  738. *
  739. * pv0,pv1,pv2 - triangle
  740. * pvNew - new vertex
  741. * pGrad - mesh
  742. *
  743. * Return Value:
  744. *
  745. * TRUE if split, FALSE otherwise
  746. *
  747. * History:
  748. *
  749. * 5/8/1997 Mark Enstrom [marke]
  750. *
  751. \**************************************************************************/
  752. BOOL
  753. bSplitTriangle(
  754. PTRIVERTEX pVert,
  755. PULONG pFreeVert,
  756. PGRADIENT_TRIANGLE pMesh,
  757. PULONG pFreeMesh,
  758. PULONG pRecurseLevel
  759. )
  760. {
  761. BOOL bStatus = FALSE;
  762. ULONG CurrentMesh = (*pFreeMesh) - 1;
  763. ULONG ulTM0 = pMesh[CurrentMesh].Vertex1;
  764. ULONG ulTM1 = pMesh[CurrentMesh].Vertex2;
  765. ULONG ulTM2 = pMesh[CurrentMesh].Vertex3;
  766. PTRIVERTEX pv0 = &pVert[ulTM0];
  767. PTRIVERTEX pv1 = &pVert[ulTM1];
  768. PTRIVERTEX pv2 = &pVert[ulTM2];
  769. PTRIVERTEX pvT0 = pv0;
  770. PTRIVERTEX pvT1 = pv1;
  771. PTRIVERTEX pvT2 = pv2;
  772. TRIVERTEX triNew;
  773. //
  774. // find longest edge
  775. //
  776. LONGLONG dx01 = ABS(pv0->x - pv1->x);
  777. LONGLONG dy01 = ABS(pv0->y - pv1->y);
  778. LONGLONG dx02 = ABS(pv0->x - pv2->x);
  779. LONGLONG dy02 = ABS(pv0->y - pv2->y);
  780. LONGLONG dx12 = ABS(pv1->x - pv2->x);
  781. LONGLONG dy12 = ABS(pv1->y - pv2->y);
  782. //
  783. // determine if triangle needs to be split
  784. //
  785. if (
  786. (
  787. (dx01 > MAX_EDGE_LENGTH) || (dy01 > MAX_EDGE_LENGTH) ||
  788. (dx02 > MAX_EDGE_LENGTH) || (dy02 > MAX_EDGE_LENGTH) ||
  789. (dx12 > MAX_EDGE_LENGTH) || (dy12 > MAX_EDGE_LENGTH)
  790. )
  791. )
  792. {
  793. //
  794. // make sure this is a triangle
  795. //
  796. if (lCalculateTriangleArea(pv0,pv1,pv2,NULL) != 0)
  797. {
  798. //
  799. // Find longest edge, swap verticies so edge 0-1 is
  800. // longest.
  801. //
  802. LONGLONG d01Max = dx01 * dx01 + dy01 * dy01;
  803. LONGLONG d02Max = dx02 * dx02 + dy02 * dy02;
  804. LONGLONG d12Max = dx12 * dx12 + dy12 * dy12;
  805. if (d01Max > d02Max)
  806. {
  807. if (d01Max > d12Max)
  808. {
  809. //
  810. // d01 largest, default
  811. //
  812. }
  813. else
  814. {
  815. //
  816. // d12 largest, swap 0 and 2
  817. //
  818. pvT0 = pv2;
  819. pvT2 = pv0;
  820. ulTM0 = pMesh[CurrentMesh].Vertex3;
  821. ulTM2 = pMesh[CurrentMesh].Vertex1;
  822. }
  823. }
  824. else
  825. {
  826. if (d02Max > d12Max)
  827. {
  828. //
  829. // d02 largest, swap 1,2
  830. //
  831. pvT1 = pv2;
  832. pvT2 = pv1;
  833. ulTM1 = pMesh[CurrentMesh].Vertex3;
  834. ulTM2 = pMesh[CurrentMesh].Vertex2;
  835. }
  836. else
  837. {
  838. //
  839. // d12 largest, swap 0,2
  840. //
  841. pvT0 = pv2;
  842. pvT2 = pv0;
  843. ulTM0 = pMesh[CurrentMesh].Vertex3;
  844. ulTM2 = pMesh[CurrentMesh].Vertex1;
  845. }
  846. }
  847. //
  848. // 2 new triangles 0,2,N and 1,2,N (float)
  849. //
  850. triNew.x = pvT0->x + ((pvT1->x - pvT0->x)/2);
  851. triNew.y = pvT0->y + ((pvT1->y - pvT0->y)/2);
  852. triNew.Red = pvT0->Red + ((pvT1->Red - pvT0->Red )/2);
  853. triNew.Green = pvT0->Green + ((pvT1->Green - pvT0->Green)/2);
  854. triNew.Blue = pvT0->Blue + ((pvT1->Blue - pvT0->Blue )/2);
  855. triNew.Alpha = pvT0->Alpha + ((pvT1->Alpha - pvT0->Alpha)/2);
  856. //
  857. // add new entry to vertex array and two new entries to mesh array
  858. //
  859. // 0,2,New and 1,2,New
  860. //
  861. ULONG FreeVert = *pFreeVert;
  862. ULONG FreeMesh = *pFreeMesh;
  863. pVert[FreeVert] = triNew;
  864. pMesh[FreeMesh].Vertex1 = ulTM0;
  865. pMesh[FreeMesh].Vertex2 = ulTM2;
  866. pMesh[FreeMesh].Vertex3 = FreeVert;
  867. pMesh[FreeMesh+1].Vertex1 = ulTM1;
  868. pMesh[FreeMesh+1].Vertex2 = ulTM2;
  869. pMesh[FreeMesh+1].Vertex3 = FreeVert;
  870. pRecurseLevel[FreeMesh] = 1;
  871. pRecurseLevel[FreeMesh+1] = 0;
  872. *pFreeMesh += 2;
  873. *pFreeVert += 1;
  874. bStatus = TRUE;
  875. }
  876. else
  877. {
  878. WARNING("bSplitTriangle:Error: triangle area = 0\n\n");
  879. }
  880. }
  881. return(bStatus);
  882. }
  883. /******************************Public*Routine******************************\
  884. * bCalculateAndDrawTriangle
  885. *
  886. * if triangle is too largre, break it in into 2 triangles and call this
  887. * routine on each
  888. *
  889. * Calculate color gradients, then scan the three lines that make up the
  890. * triangle. Fill out a structure that can later be used to fill in the
  891. * interior of the triangle.
  892. *
  893. * Arguments:
  894. *
  895. * pSurfDst - destination surface
  896. * pInV0 - vertex
  897. * pInV1 - vertex
  898. * pInV2 - vertex
  899. * ptData - triangle data
  900. * pfnG - surface gradient draw routine
  901. *
  902. * Return Value:
  903. *
  904. * status
  905. *
  906. * History:
  907. *
  908. * 17-Jul-1996 -by- Mark Enstrom [marke]
  909. *
  910. \**************************************************************************/
  911. BOOL
  912. bCalculateAndDrawTriangle(
  913. PDIBINFO pDibDst,
  914. PTRIVERTEX pInV0,
  915. PTRIVERTEX pInV1,
  916. PTRIVERTEX pInV2,
  917. PTRIANGLEDATA ptData,
  918. PFN_TRIFILL pfnG
  919. )
  920. {
  921. BOOL bStatus = TRUE;
  922. LONG index;
  923. LONG lStatus;
  924. PTRIVERTEX pv0 = pInV0;
  925. PTRIVERTEX pv1 = pInV1;
  926. PTRIVERTEX pv2 = pInV2;
  927. {
  928. PTRIVERTEX pvt;
  929. //
  930. // sort in y for line processing
  931. //
  932. if (pv0->y > pv1->y)
  933. {
  934. SWAP_VERTEX(pv0,pv1,pvt);
  935. }
  936. if (pv1->y > pv2->y)
  937. {
  938. SWAP_VERTEX(pv1,pv2,pvt);
  939. }
  940. if (pv0->y > pv1->y)
  941. {
  942. SWAP_VERTEX(pv0,pv1,pvt);
  943. }
  944. lStatus = lCalculateTriangleArea(pv0,pv1,pv2,ptData);
  945. //
  946. // if area is zero then this is a degenerate triangle
  947. //
  948. if (lStatus == 0)
  949. {
  950. return(FALSE);
  951. }
  952. else if (lStatus <0)
  953. {
  954. //
  955. // negative area, swap pv1 and pv2 and recalcualte
  956. //
  957. SWAP_VERTEX(pv1,pv2,pvt);
  958. lStatus = lCalculateTriangleArea(pv0,pv1,pv2,ptData);
  959. if (lStatus == 0)
  960. {
  961. return(FALSE);
  962. }
  963. else if (lStatus <0)
  964. {
  965. WARNING1("Triangle Area still negative after vertex swap\n");
  966. return(FALSE);
  967. }
  968. }
  969. //
  970. // calc min and max drawing y
  971. //
  972. ptData->y0 = MAX(pv0->y,ptData->rcl.top);
  973. LONG MaxY = MAX(pv1->y,pv2->y);
  974. ptData->y1 = MIN(MaxY,ptData->rcl.bottom);
  975. {
  976. //
  977. // init ptdata
  978. //
  979. LONG lIndex;
  980. for (lIndex=0;lIndex<(ptData->y1-ptData->y0);lIndex++)
  981. {
  982. ptData->TriEdge[lIndex].xLeft = LONG_MAX;
  983. ptData->TriEdge[lIndex].xRight = LONG_MIN;
  984. }
  985. }
  986. //
  987. // calculate color gradients for each color. There is a little redundant
  988. // work here with calculation of deltas. Should make this one call or
  989. // do it in place.
  990. //
  991. LIMIT_COLOR(pv0);
  992. LIMIT_COLOR(pv1);
  993. LIMIT_COLOR(pv2);
  994. bCalulateColorGradient(pv0,pv1,pv2,ptData);
  995. //
  996. // draw lines into data array
  997. //
  998. vCalculateLine(pv0,pv1,ptData);
  999. vCalculateLine(pv1,pv2,ptData);
  1000. vCalculateLine(pv2,pv0,ptData);
  1001. pfnG(pDibDst,ptData);
  1002. }
  1003. return(bStatus);
  1004. }
  1005. #endif