render.cpp 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. #include "System.h"
  19. #ifdef PATHS_IN_INCLUDES
  20. #include "GREEN/3D/render.h"
  21. #else
  22. #include "render.h"
  23. #endif
  24. typedef struct
  25. { RFixedS32 x; RFixedS32 y; RFixedS32 z;} RRenderPt32; // For internal use
  26. // Fog should be offset such that the first index occurs
  27. // at the minimum z-point of the full3d object being
  28. // rendered.
  29. // sX and sY are additional offsets into pimDst
  30. //
  31. void DrawTri_ZColorFog(UCHAR* pDstOffset,long lDstP,
  32. RP3d* p1,RP3d* p2,RP3d* p3,
  33. RZBuffer* pZB,UCHAR* pFog,
  34. short sOffsetX/* = 0*/, // In: 2D offset for pZB.
  35. short sOffsetY/* = 0*/) // In: 2D offset for pZB.
  36. {
  37. //////////////////////////////////////////////////////////////////
  38. //****************************************************************
  39. //====================== INITIAL SET UP ========================
  40. //****************************************************************
  41. //////////////////////////////////////////////////////////////////
  42. // copy the 3d points into screen coordinates:
  43. RRenderPt32 pt1,pt2,pt3;
  44. RRenderPt32 *pv1 = &pt1;
  45. RRenderPt32 *pv2 = &pt2;
  46. RRenderPt32 *pv3 = &pt3;
  47. // Cast from REAL to short in fp32 format:
  48. pt1.x.mod = short(p1->x);
  49. pt1.y.mod = short(p1->y);
  50. pt1.z.mod = short(p1->z);
  51. pt2.x.mod = short(p2->x);
  52. pt2.y.mod = short(p2->y);
  53. pt2.z.mod = short(p2->z);
  54. pt3.x.mod = short(p3->x);
  55. pt3.y.mod = short(p3->y);
  56. pt3.z.mod = short(p3->z);
  57. pt1.x.frac =
  58. pt2.x.frac =
  59. pt3.x.frac = USHORT(32768); // offset each by 1/2
  60. /*
  61. // Catch the special case of a single pixel
  62. // This is really only useful for POSTAL TM, where polygons are tiny:
  63. if (pt1.x.mod == pt2.x.mod) // hierarchal check to save time:
  64. {
  65. if ( (pt1.y.mod == pt2.y.mod) // WE'VE GOT A SINGLE SCREEN POINT!
  66. && (pt1.x.mod == pt3.x.mod)
  67. && (pt1.y.mod == pt3.y.mod) )
  68. {
  69. // Try to best mimick normal behavior by using highest Z;
  70. // THIS will not exactly mimick the non-point cloud base,
  71. // but SHOULD work appropriately:
  72. if (pt2.z.mod > pt1.z.mod) pt1.z.mod = pt2.z.mod;
  73. if (pt3.z.mod > pt1.z.mod) pt1.z.mod = pt3.z.mod;
  74. //***** PLOT THE SINGLE POINT!
  75. short* pBufZ = pZB -> GetZPtr
  76. (pt1.x.mod + sOffsetX, pt1.y.mod + sOffsetY);
  77. if (pt1.z.mod > *pBufZ)
  78. {
  79. UCHAR* pDst = pDstOffset + lDstP * pt1.y.mod + pt1.x.mod;
  80. *pDst = pFog[pt1.z.upper]; // can't forget to set the z-buffer!
  81. *pBufZ = pt1.z.mod;
  82. }
  83. return; // DONE THE FAST WAY!
  84. }
  85. }
  86. */
  87. // Let's assess general categories:
  88. // Single points:
  89. /*
  90. short sAbort = TRUE;
  91. if (pt1.x.mod == pt2.x.mod)
  92. {
  93. if ( (pt1.y.mod == pt2.y.mod) // WE'VE GOT A SINGLE SCREEN POINT!
  94. && (pt1.x.mod == pt3.x.mod)
  95. && (pt1.y.mod == pt3.y.mod) )
  96. {
  97. // single point
  98. sAbort = FALSE;
  99. }
  100. }
  101. // Vertical strips:
  102. if ( (pt1.x.mod == pt2.x.mod)
  103. && (pt1.x.mod == pt3.x.mod) )
  104. {
  105. // Vstrip:
  106. sAbort = FALSE;
  107. }
  108. // Horizontal strips:
  109. if ( (pt1.y.mod == pt2.y.mod)
  110. && (pt1.y.mod == pt3.y.mod) )
  111. {
  112. // Hstrip:
  113. sAbort = FALSE;
  114. }
  115. if (sAbort == TRUE) return; // isolate the effect!
  116. */
  117. // Now let's try simply not drawing horiz or verical strips at all:
  118. // Vertical strips:
  119. /*
  120. if ( (pt1.x.mod == pt2.x.mod)
  121. && (pt1.x.mod == pt3.x.mod) )
  122. {
  123. // Vstrip or point:
  124. return;
  125. }
  126. // Horizontal strips:
  127. if ( (pt1.y.mod == pt2.y.mod)
  128. && (pt1.y.mod == pt3.y.mod) )
  129. {
  130. // Hstrip:
  131. return;
  132. }
  133. */
  134. // sort the triangles and choose which mirror case to render.
  135. // Sort points lowest to highest by y-value:
  136. if (pv1->y.mod > pv2->y.mod) SWAP(pv1,pv2);
  137. if (pv1->y.mod > pv3->y.mod) SWAP(pv1,pv3);
  138. if (pv2->y.mod > pv3->y.mod) SWAP(pv2,pv3);
  139. // Get point 2 and 3's position relative to point 1:
  140. // Use 16 bit accuracy in y, 32-bit in x...
  141. short y1 = pv1->y.mod;
  142. short y2 = pv2->y.mod - y1;
  143. short y3 = pv3->y.mod - y1;
  144. short ybot = y3 - y2; // lower half delta
  145. if (y2 + y3 == 0) return; // don;t bother drawing horiz line
  146. // get relative floating point x coordinates: (32-bit differences)
  147. long fx1 = pv1->x.val;
  148. long fz1 = pv1->z.val;
  149. long fx2 = pv2->x.val - fx1;
  150. long fx3 = pv3->x.val - fx1;
  151. long fz2 = pv2->z.val - fz1;
  152. long fz3 = pv3->z.val - fz1;
  153. // calculate the top two edge slopes with 32-bit accuracy:
  154. long fx2inc,fz2inc;
  155. if (y2)
  156. {
  157. fx2inc = fx2 / y2; // stuck with division using fx32!
  158. fz2inc = fz2 / y2; // stuck with division using fx32!
  159. /* CANDIDATE FOR ONE_OVER!
  160. fx2inc = ULONG(fx2.mod) * CInitNum::OneOver[y2]; // stuck with division using fx32!
  161. fz2inc = ULONG(fz2.mod) * CInitNum::OneOver[y2]; // stuck with division using fx32!
  162. */
  163. }
  164. long fx3inc = fx3 / y3; // stuck with division using fx32!
  165. long fz3inc = fz3 / y3; // stuck with division using fx32!
  166. // Set the two absolute edge positions
  167. RFixedS32 x2,x3,z2,z3;
  168. x2.val = x3.val = pv1->x.frac; // preserve floating point x!
  169. z2.val = z3.val = pv1->z.frac; // preserve floating point z!
  170. short sBaseZ = pv1->z.mod;
  171. //TRACE("SBASE Zpt = %hd\n",pv1->z.mod);
  172. long lP = lDstP;
  173. // add in extra piece uv rounding!
  174. UCHAR* pDst = pDstOffset + lP * pv1->y.mod + pv1->x.mod + x2.mod;
  175. short* pBufZ = pZB -> GetZPtr(pv1->x.mod + x2.mod + sOffsetX, pv1->y.mod + sOffsetY);
  176. long lZP = pZB->m_lP; // in words!!!
  177. // Draw the upper triangle! (Assuming fx2inc < fx3inc.....)
  178. short x,y;
  179. RFixedS32 fz,fzinc; // for tracing across each scan line:
  180. short xdel;
  181. //////////////////////////////////////////////////////////////////
  182. //****************************************************************
  183. //====================== CHOOSE II CASES =======================
  184. //****************************************************************
  185. //////////////////////////////////////////////////////////////////
  186. //****************************************************************
  187. //====================== FLAT TOP TRIANGLE =====================
  188. //****************************************************************
  189. // Don't worry about the wasted calculations above!
  190. // (I STILL THINK YOU CAN STREAMLINE THIS AND INTEGRATE IT INTO
  191. // THE OTHER CASE -> THERE IS NO CALL FOR THIS!)
  192. if (y2 == 0) // p1.y == p2.y
  193. {
  194. long fx1inc,fz1inc;
  195. RFixedS32 x1,z1; // Absolute positions
  196. // Let point I be to the LEFT of point II:
  197. if (pv2->x.val < pv1->x.val) SWAP(pv1,pv2);
  198. // again, set initial points relative to p1(0,0):
  199. fx1 = pv1->x.val;
  200. fz1 = pv1->z.val;
  201. fx2 = pv2->x.val - fx1;
  202. fx3 = pv3->x.val - fx1;
  203. fz2 = pv2->z.val - fz1;
  204. fz3 = pv3->z.val - fz1;
  205. sBaseZ = pv1->z.mod;
  206. // This time, we want the end slopes:
  207. //******* CANDIDATE FOR ONE_OVER!
  208. fx1inc = fx3 / y3; // from pt 1 to pt 3
  209. fz1inc = fz3 / y3;
  210. fx2inc = (fx3 - fx2) / y3; // from pt 2 to pt 3
  211. fz2inc = (fz3 - fz2) / y3; // from pt 2 to pt 3
  212. x1.val = pv1->x.frac; // preserve floating point x!
  213. x2.val = fx2;
  214. z1.val = pv1->z.frac; // preserve floating point x!
  215. z2.val = fz2; // preserve floating point z!
  216. pDst = pDstOffset + lP * pv1->y.mod + pv1->x.mod + x1.mod; // add in extra piece uv rounding!
  217. pBufZ = pZB -> GetZPtr(pv1->x.mod + x1.mod + sOffsetX, pv1->y.mod + sOffsetY);
  218. for (y = y3;y;y--)
  219. {
  220. pDst += lP;
  221. pBufZ += lZP;
  222. x2.val += fx2inc;
  223. x1.val += fx1inc;
  224. z2.val += fz2inc;
  225. z1.val += fz1inc;
  226. // Now we scan z across (slow for now)
  227. fz.val = z1.val;
  228. fz.mod += sBaseZ; // ****** advance the z-value.
  229. xdel = x2.mod - x1.mod;
  230. //if (hzdel) hzinc.val = (z3.val - z2.val) / hzdel;
  231. //***************8 flipped the inc value:!
  232. if (xdel) fzinc.val = long(z2.mod - z1.mod) * RInitNum::OneOver[xdel];
  233. //if (hzdel) Mul(hzinc,z3.val - z2.val,CInitNum::OneOver[hzdel]);
  234. // Assume 2 to 3:
  235. for (x = x1.mod; x<= x2.mod;x++)
  236. {
  237. if (fz.mod > *(pBufZ+x) )
  238. {
  239. *(pDst+x) = pFog[fz.upper];// pFog[fz.upper]; // offset for fog
  240. *(pBufZ+x) = fz.mod; // set Z-buffer!
  241. }
  242. fz.val += fzinc.val;
  243. }
  244. }
  245. return;
  246. }
  247. //****************************************************************
  248. //====================== NORMAL TRIANGLE =======================
  249. //****************************************************************
  250. if (fx2inc <= fx3inc)
  251. {
  252. //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,y2,ucColor);
  253. for (y = y2;y;y--)
  254. {
  255. pDst += lP;
  256. pBufZ += lZP;
  257. x2.val += fx2inc;
  258. x3.val += fx3inc;
  259. z2.val += fz2inc;
  260. z3.val += fz3inc;
  261. //TRACE("SBASE Z = %hd\n",sBaseZ);
  262. // Assume 2 to 3:
  263. // Now we scan z across (slow for now)
  264. fz.val = z2.val;
  265. fz.mod += sBaseZ; // This is for coloring but it effects true z as well!
  266. xdel = x3.mod - x2.mod;
  267. //if (hzdel) hzinc.val = (z3.val - z2.val) / hzdel;
  268. if (xdel) fzinc.val = ULONG(z3.mod - z2.mod) * RInitNum::OneOver[xdel];
  269. //if (hzdel) Mul(hzinc,z3.val - z2.val,CInitNum::OneOver[hzdel]);
  270. // Assume 2 to 3:
  271. for (x = x2.mod; x<= x3.mod;x++)
  272. {
  273. if (fz.mod > *(pBufZ+x) )
  274. {
  275. *(pDst+x) = pFog[fz.upper];// pFog[fz.upper];
  276. *(pBufZ+x) = fz.mod;// set Z-buffer!
  277. }
  278. fz.val += fzinc.val;
  279. }
  280. }
  281. //===================================================================
  282. // Draw the lower triangle if applicatable:
  283. //===================================================================
  284. if (ybot)
  285. {
  286. // new x2 slope:
  287. fx2inc = (fx3 - fx2) / ybot; // stuck with division using fx32!
  288. fz2inc = (fz3 - fz2) / ybot; // stuck with division using fx32!
  289. /*
  290. fx2inc = ULONG(fx3.mod-fx2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
  291. fz2inc = ULONG(fz3.mod-fz2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
  292. */
  293. //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,yc,ucColor);
  294. for (y = ybot;y;y--)
  295. {
  296. pDst += lP;
  297. pBufZ += lZP;
  298. x2.val += fx2inc;
  299. x3.val += fx3inc;
  300. z2.val += fz2inc;
  301. z3.val += fz3inc;
  302. // Now we scan z across (slow for now)
  303. fz.val = z2.val;
  304. fz.mod += sBaseZ;
  305. xdel = x3.mod - x2.mod;
  306. //if (hzdel) hzinc.val = (z3.val - z2.val) / hzdel;
  307. if (xdel) fzinc.val = long(z3.mod - z2.mod) * RInitNum::OneOver[xdel];
  308. //if (hzdel) Mul(hzinc,z3.val - z2.val,CInitNum::OneOver[hzdel]);
  309. // Assume 2 to 3:
  310. for (x = x2.mod; x<= x3.mod;x++)
  311. {
  312. if (fz.mod > *(pBufZ+x) )
  313. {
  314. *(pDst+x) = pFog[fz.upper];// pFog[fz.upper];
  315. *(pBufZ+x) = fz.mod;// set Z-buffer!
  316. }
  317. fz.val += fzinc.val;
  318. }
  319. }
  320. }
  321. }
  322. else // flip the x drawing order:
  323. //===================================================================
  324. //============== DRAW MIRRORED VERION OF STANDARD TRIANGLE! =========
  325. //===================================================================
  326. {
  327. //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,y2,ucColor);
  328. for (y = y2;y;y--)
  329. {
  330. pDst += lP;
  331. pBufZ += lZP;
  332. x2.val += fx2inc;
  333. x3.val += fx3inc;
  334. z2.val += fz2inc;
  335. z3.val += fz3inc;
  336. // Assume 2 to 3:
  337. // Now we scan z across (slow for now)
  338. fz.val = z3.val;
  339. fz.mod += sBaseZ;
  340. xdel = x2.mod - x3.mod; //+ x to z
  341. //if (hzdel) hzinc.val = (z2.val - z3.val) / hzdel;
  342. if (xdel) fzinc.val = long(z2.mod - z3.mod) * RInitNum::OneOver[xdel];
  343. //if (hzdel) Mul(hzinc,z2.val - z3.val,CInitNum::OneOver[hzdel]);
  344. // Assume 2 to 3:
  345. for (x = x3.mod; x<= x2.mod;x++)
  346. {
  347. if (fz.mod > *(pBufZ+x) )
  348. {
  349. *(pDst+x) = pFog[fz.upper];// pFog[fz.upper];
  350. *(pBufZ+x) = fz.mod;// set Z-buffer!
  351. }
  352. fz.val += fzinc.val;
  353. }
  354. }
  355. //===================================================================
  356. // Draw the lower triangle if applicatable:
  357. //===================================================================
  358. if (ybot)
  359. {
  360. // new x2 slope:
  361. fx2inc = (fx3 - fx2) / ybot; // stuck with division using fx32!
  362. fz2inc = (fz3 - fz2) / ybot; // stuck with division using fx32!
  363. /*
  364. fx2inc = ULONG(fx3.mod-fx2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
  365. fz2inc = ULONG(fz3.mod-fz2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
  366. */
  367. //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,yc,ucColor);
  368. for (y = ybot;y;y--)
  369. {
  370. pDst += lP;
  371. pBufZ += lZP;
  372. x2.val += fx2inc;
  373. x3.val += fx3inc;
  374. z2.val += fz2inc;
  375. z3.val += fz3inc;
  376. // Now we scan z across (slow for now)
  377. fz.val = z3.val;
  378. fz.mod += sBaseZ;
  379. xdel = x2.mod - x3.mod;
  380. //if (hzdel) hzinc.val = (z2.val - z3.val) / hzdel;
  381. if (xdel) fzinc.val = ULONG(z2.mod - z3.mod) * RInitNum::OneOver[xdel];
  382. // Full accuracy fxMul!
  383. //if (hzdel) Mul(hzinc,z2.val - z3.val,CInitNum::OneOver[hzdel]);
  384. // Assume 2 to 3:
  385. for (x = x3.mod; x<= x2.mod;x++)
  386. {
  387. if (fz.mod > *(pBufZ+x) )
  388. {
  389. *(pDst+x) = pFog[fz.upper];// pFog[fz.upper];
  390. *(pBufZ+x) = fz.mod;// set Z-buffer!
  391. }
  392. fz.val += fzinc.val;
  393. }
  394. }
  395. }
  396. }
  397. }
  398. //==================================================
  399. // For debugging:
  400. void DrawTri_wire(RImage* pimDst,short sX,short sY,
  401. RP3d* p1,RP3d* p2,RP3d* p3,UCHAR ucColor)
  402. {
  403. rspLine(ucColor,pimDst,
  404. sX+short(p1->x),sY+short(p1->y),
  405. sX+short(p2->x),sY+short(p2->y));
  406. rspLine(ucColor,pimDst,
  407. sX+short(p1->x),sY+short(p1->y),
  408. sX+short(p3->x),sY+short(p3->y));
  409. rspLine(ucColor,pimDst,
  410. sX+short(p3->x),sY+short(p3->y),
  411. sX+short(p2->x),sY+short(p2->y));
  412. }
  413. //==================================================
  414. // For debugging:
  415. // FLAT SHADED!
  416. // sX and sY are additional offsets into pimDst
  417. //
  418. void DrawTri_ZColor(UCHAR* pDstOffset,long lDstP,
  419. RP3d* p1,RP3d* p2,RP3d* p3,
  420. RZBuffer* pZB,UCHAR ucFlatColor,
  421. short sOffsetX/* = 0*/, // In: 2D offset for pZB.
  422. short sOffsetY/* = 0*/) // In: 2D offset for pZB.
  423. {
  424. //////////////////////////////////////////////////////////////////
  425. //****************************************************************
  426. //====================== INITIAL SET UP ========================
  427. //****************************************************************
  428. //////////////////////////////////////////////////////////////////
  429. // copy the 3d points into screen coordinates:
  430. RRenderPt32 pt1,pt2,pt3;
  431. RRenderPt32 *pv1 = &pt1;
  432. RRenderPt32 *pv2 = &pt2;
  433. RRenderPt32 *pv3 = &pt3;
  434. // Cast from REAL to short in fp32 format:
  435. pt1.x.mod = short(p1->x);
  436. pt1.y.mod = short(p1->y);
  437. pt1.z.mod = short(p1->z);
  438. pt2.x.mod = short(p2->x);
  439. pt2.y.mod = short(p2->y);
  440. pt2.z.mod = short(p2->z);
  441. pt3.x.mod = short(p3->x);
  442. pt3.y.mod = short(p3->y);
  443. pt3.z.mod = short(p3->z);
  444. pt1.x.frac =
  445. pt2.x.frac =
  446. pt3.x.frac = USHORT(32768); // offset each by 1/2
  447. // sort the triangles and choose which mirror case to render.
  448. // Sort points lowest to highest by y-value:
  449. if (pv1->y.mod > pv2->y.mod) SWAP(pv1,pv2);
  450. if (pv1->y.mod > pv3->y.mod) SWAP(pv1,pv3);
  451. if (pv2->y.mod > pv3->y.mod) SWAP(pv2,pv3);
  452. // Get point 2 and 3's position relative to point 1:
  453. // Use 16 bit accuracy in y, 32-bit in x...
  454. short y1 = pv1->y.mod;
  455. short y2 = pv2->y.mod - y1;
  456. short y3 = pv3->y.mod - y1;
  457. short ybot = y3 - y2; // lower half delta
  458. if (y2 + y3 == 0) return; // don;t bother drawing horiz line
  459. // get relative floating point x coordinates: (32-bit differences)
  460. long fx1 = pv1->x.val;
  461. long fz1 = pv1->z.val;
  462. long fx2 = pv2->x.val - fx1;
  463. long fx3 = pv3->x.val - fx1;
  464. long fz2 = pv2->z.val - fz1;
  465. long fz3 = pv3->z.val - fz1;
  466. // calculate the top two edge slopes with 32-bit accuracy:
  467. long fx2inc,fz2inc;
  468. if (y2)
  469. {
  470. fx2inc = fx2 / y2; // stuck with division using fx32!
  471. fz2inc = fz2 / y2; // stuck with division using fx32!
  472. /* CANDIDATE FOR ONE_OVER!
  473. fx2inc = ULONG(fx2.mod) * CInitNum::OneOver[y2]; // stuck with division using fx32!
  474. fz2inc = ULONG(fz2.mod) * CInitNum::OneOver[y2]; // stuck with division using fx32!
  475. */
  476. }
  477. long fx3inc = fx3 / y3; // stuck with division using fx32!
  478. long fz3inc = fz3 / y3; // stuck with division using fx32!
  479. // Set the two absolute edge positions
  480. RFixedS32 x2,x3,z2,z3;
  481. x2.val = x3.val = pv1->x.frac; // preserve floating point x!
  482. z2.val = z3.val = pv1->z.frac; // preserve floating point z!
  483. short sBaseZ = pv1->z.mod;
  484. //TRACE("SBASE Zpt = %hd\n",pv1->z.mod);
  485. long lP = lDstP;
  486. // add in extra piece uv rounding!
  487. UCHAR* pDst = pDstOffset + lP * pv1->y.mod + pv1->x.mod + x2.mod;
  488. short* pBufZ = pZB -> GetZPtr(pv1->x.mod + x2.mod + sOffsetX, pv1->y.mod + sOffsetY);
  489. long lZP = pZB->m_lP; // in words!!!
  490. // Draw the upper triangle! (Assuming fx2inc < fx3inc.....)
  491. short x,y;
  492. RFixedS32 fz,fzinc; // for tracing across each scan line:
  493. short xdel;
  494. //////////////////////////////////////////////////////////////////
  495. //****************************************************************
  496. //====================== CHOOSE II CASES =======================
  497. //****************************************************************
  498. //////////////////////////////////////////////////////////////////
  499. //****************************************************************
  500. //====================== FLAT TOP TRIANGLE =====================
  501. //****************************************************************
  502. // Don't worry about the wasted calculations above!
  503. // (I STILL THINK YOU CAN STREAMLINE THIS AND INTEGRATE IT INTO
  504. // THE OTHER CASE -> THERE IS NO CALL FOR THIS!)
  505. if (y2 == 0) // p1.y == p2.y
  506. {
  507. long fx1inc,fz1inc;
  508. RFixedS32 x1,z1; // Absolute positions
  509. // Let point I be to the LEFT of point II:
  510. if (pv2->x.val < pv1->x.val) SWAP(pv1,pv2);
  511. // again, set initial points relative to p1(0,0):
  512. fx1 = pv1->x.val;
  513. fz1 = pv1->z.val;
  514. fx2 = pv2->x.val - fx1;
  515. fx3 = pv3->x.val - fx1;
  516. fz2 = pv2->z.val - fz1;
  517. fz3 = pv3->z.val - fz1;
  518. sBaseZ = pv1->z.mod;
  519. // This time, we want the end slopes:
  520. //******* CANDIDATE FOR ONE_OVER!
  521. fx1inc = fx3 / y3; // from pt 1 to pt 3
  522. fz1inc = fz3 / y3;
  523. fx2inc = (fx3 - fx2) / y3; // from pt 2 to pt 3
  524. fz2inc = (fz3 - fz2) / y3; // from pt 2 to pt 3
  525. x1.val = pv1->x.frac; // preserve floating point x!
  526. x2.val = fx2;
  527. z1.val = pv1->z.frac; // preserve floating point x!
  528. z2.val = fz2; // preserve floating point z!
  529. pDst = pDstOffset + lP * pv1->y.mod + pv1->x.mod + x1.mod; // add in extra piece uv rounding!
  530. pBufZ = pZB -> GetZPtr(pv1->x.mod + x1.mod + sOffsetX, pv1->y.mod + sOffsetY);
  531. for (y = y3;y;y--)
  532. {
  533. pDst += lP;
  534. pBufZ += lZP;
  535. x2.val += fx2inc;
  536. x1.val += fx1inc;
  537. z2.val += fz2inc;
  538. z1.val += fz1inc;
  539. // Now we scan z across (slow for now)
  540. fz.val = z1.val;
  541. fz.mod += sBaseZ; // ****** advance the z-value.
  542. xdel = x2.mod - x1.mod;
  543. //if (hzdel) hzinc.val = (z3.val - z2.val) / hzdel;
  544. //***************8 flipped the inc value:!
  545. if (xdel) fzinc.val = long(z2.mod - z1.mod) * RInitNum::OneOver[xdel];
  546. //if (hzdel) Mul(hzinc,z3.val - z2.val,CInitNum::OneOver[hzdel]);
  547. // Assume 2 to 3:
  548. for (x = x1.mod; x<= x2.mod;x++)
  549. {
  550. if (fz.mod > *(pBufZ+x) )
  551. {
  552. *(pDst+x) = ucFlatColor;// pFog[fz.upper]; // offset for fog
  553. *(pBufZ+x) = fz.mod; // set Z-buffer!
  554. }
  555. fz.val += fzinc.val;
  556. }
  557. }
  558. return;
  559. }
  560. //****************************************************************
  561. //====================== NORMAL TRIANGLE =======================
  562. //****************************************************************
  563. if (fx2inc <= fx3inc)
  564. {
  565. //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,y2,ucColor);
  566. for (y = y2;y;y--)
  567. {
  568. pDst += lP;
  569. pBufZ += lZP;
  570. x2.val += fx2inc;
  571. x3.val += fx3inc;
  572. z2.val += fz2inc;
  573. z3.val += fz3inc;
  574. //TRACE("SBASE Z = %hd\n",sBaseZ);
  575. // Assume 2 to 3:
  576. // Now we scan z across (slow for now)
  577. fz.val = z2.val;
  578. fz.mod += sBaseZ; // This is for coloring but it effects true z as well!
  579. xdel = x3.mod - x2.mod;
  580. //if (hzdel) hzinc.val = (z3.val - z2.val) / hzdel;
  581. if (xdel) fzinc.val = ULONG(z3.mod - z2.mod) * RInitNum::OneOver[xdel];
  582. //if (hzdel) Mul(hzinc,z3.val - z2.val,CInitNum::OneOver[hzdel]);
  583. // Assume 2 to 3:
  584. for (x = x2.mod; x<= x3.mod;x++)
  585. {
  586. if (fz.mod > *(pBufZ+x) )
  587. {
  588. *(pDst+x) = ucFlatColor;// pFog[fz.upper];
  589. *(pBufZ+x) = fz.mod;// set Z-buffer!
  590. }
  591. fz.val += fzinc.val;
  592. }
  593. }
  594. //===================================================================
  595. // Draw the lower triangle if applicatable:
  596. //===================================================================
  597. if (ybot)
  598. {
  599. // new x2 slope:
  600. fx2inc = (fx3 - fx2) / ybot; // stuck with division using fx32!
  601. fz2inc = (fz3 - fz2) / ybot; // stuck with division using fx32!
  602. /*
  603. fx2inc = ULONG(fx3.mod-fx2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
  604. fz2inc = ULONG(fz3.mod-fz2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
  605. */
  606. //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,yc,ucColor);
  607. for (y = ybot;y;y--)
  608. {
  609. pDst += lP;
  610. pBufZ += lZP;
  611. x2.val += fx2inc;
  612. x3.val += fx3inc;
  613. z2.val += fz2inc;
  614. z3.val += fz3inc;
  615. // Now we scan z across (slow for now)
  616. fz.val = z2.val;
  617. fz.mod += sBaseZ;
  618. xdel = x3.mod - x2.mod;
  619. //if (hzdel) hzinc.val = (z3.val - z2.val) / hzdel;
  620. if (xdel) fzinc.val = long(z3.mod - z2.mod) * RInitNum::OneOver[xdel];
  621. //if (hzdel) Mul(hzinc,z3.val - z2.val,CInitNum::OneOver[hzdel]);
  622. // Assume 2 to 3:
  623. for (x = x2.mod; x<= x3.mod;x++)
  624. {
  625. if (fz.mod > *(pBufZ+x) )
  626. {
  627. *(pDst+x) = ucFlatColor;// pFog[fz.upper];
  628. *(pBufZ+x) = fz.mod;// set Z-buffer!
  629. }
  630. fz.val += fzinc.val;
  631. }
  632. }
  633. }
  634. }
  635. else // flip the x drawing order:
  636. //===================================================================
  637. //============== DRAW MIRRORED VERION OF STANDARD TRIANGLE! =========
  638. //===================================================================
  639. {
  640. //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,y2,ucColor);
  641. for (y = y2;y;y--)
  642. {
  643. pDst += lP;
  644. pBufZ += lZP;
  645. x2.val += fx2inc;
  646. x3.val += fx3inc;
  647. z2.val += fz2inc;
  648. z3.val += fz3inc;
  649. // Assume 2 to 3:
  650. // Now we scan z across (slow for now)
  651. fz.val = z3.val;
  652. fz.mod += sBaseZ;
  653. xdel = x2.mod - x3.mod; //+ x to z
  654. //if (hzdel) hzinc.val = (z2.val - z3.val) / hzdel;
  655. if (xdel) fzinc.val = long(z2.mod - z3.mod) * RInitNum::OneOver[xdel];
  656. //if (hzdel) Mul(hzinc,z2.val - z3.val,CInitNum::OneOver[hzdel]);
  657. // Assume 2 to 3:
  658. for (x = x3.mod; x<= x2.mod;x++)
  659. {
  660. if (fz.mod > *(pBufZ+x) )
  661. {
  662. *(pDst+x) = ucFlatColor;// pFog[fz.upper];
  663. *(pBufZ+x) = fz.mod;// set Z-buffer!
  664. }
  665. fz.val += fzinc.val;
  666. }
  667. }
  668. //===================================================================
  669. // Draw the lower triangle if applicatable:
  670. //===================================================================
  671. if (ybot)
  672. {
  673. // new x2 slope:
  674. fx2inc = (fx3 - fx2) / ybot; // stuck with division using fx32!
  675. fz2inc = (fz3 - fz2) / ybot; // stuck with division using fx32!
  676. /*
  677. fx2inc = ULONG(fx3.mod-fx2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
  678. fz2inc = ULONG(fz3.mod-fz2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
  679. */
  680. //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,yc,ucColor);
  681. for (y = ybot;y;y--)
  682. {
  683. pDst += lP;
  684. pBufZ += lZP;
  685. x2.val += fx2inc;
  686. x3.val += fx3inc;
  687. z2.val += fz2inc;
  688. z3.val += fz3inc;
  689. // Now we scan z across (slow for now)
  690. fz.val = z3.val;
  691. fz.mod += sBaseZ;
  692. xdel = x2.mod - x3.mod;
  693. //if (hzdel) hzinc.val = (z2.val - z3.val) / hzdel;
  694. if (xdel) fzinc.val = ULONG(z2.mod - z3.mod) * RInitNum::OneOver[xdel];
  695. // Full accuracy fxMul!
  696. //if (hzdel) Mul(hzinc,z2.val - z3.val,CInitNum::OneOver[hzdel]);
  697. // Assume 2 to 3:
  698. for (x = x3.mod; x<= x2.mod;x++)
  699. {
  700. if (fz.mod > *(pBufZ+x) )
  701. {
  702. *(pDst+x) = ucFlatColor;// pFog[fz.upper];
  703. *(pBufZ+x) = fz.mod;// set Z-buffer!
  704. }
  705. fz.val += fzinc.val;
  706. }
  707. }
  708. }
  709. }
  710. }
  711. //==================================================
  712. // FLAT SHADED!
  713. // sX and sY are additional offsets into pimDst
  714. // There is NO Z_BUFFER here! It is JUST a polygon drawer
  715. //
  716. void DrawTri(UCHAR* pDstOffset,long lDstP,
  717. RP3d* p1,RP3d* p2,RP3d* p3,
  718. UCHAR ucFlatColor)
  719. {
  720. //////////////////////////////////////////////////////////////////
  721. //****************************************************************
  722. //====================== INITIAL SET UP ========================
  723. //****************************************************************
  724. //////////////////////////////////////////////////////////////////
  725. // copy the 3d points into screen coordinates:
  726. RRenderPt32 pt1,pt2,pt3;
  727. RRenderPt32 *pv1 = &pt1;
  728. RRenderPt32 *pv2 = &pt2;
  729. RRenderPt32 *pv3 = &pt3;
  730. // Cast from REAL to short in fp32 format:
  731. pt1.x.mod = short(p1->x);
  732. pt1.y.mod = short(p1->y);
  733. pt2.x.mod = short(p2->x);
  734. pt2.y.mod = short(p2->y);
  735. pt3.x.mod = short(p3->x);
  736. pt3.y.mod = short(p3->y);
  737. pt1.x.frac =
  738. pt2.x.frac =
  739. pt3.x.frac = USHORT(32768); // offset each by 1/2
  740. // sort the triangles and choose which mirror case to render.
  741. // Sort points lowest to highest by y-value:
  742. if (pv1->y.mod > pv2->y.mod) SWAP(pv1,pv2);
  743. if (pv1->y.mod > pv3->y.mod) SWAP(pv1,pv3);
  744. if (pv2->y.mod > pv3->y.mod) SWAP(pv2,pv3);
  745. // Get point 2 and 3's position relative to point 1:
  746. // Use 16 bit accuracy in y, 32-bit in x...
  747. short y1 = pv1->y.mod;
  748. short y2 = pv2->y.mod - y1;
  749. short y3 = pv3->y.mod - y1;
  750. short ybot = y3 - y2; // lower half delta
  751. if (y2 + y3 == 0) return; // don;t bother drawing horiz line
  752. // get relative floating point x coordinates: (32-bit differences)
  753. long fx1 = pv1->x.val;
  754. long fx2 = pv2->x.val - fx1;
  755. long fx3 = pv3->x.val - fx1;
  756. // calculate the top two edge slopes with 32-bit accuracy:
  757. long fx2inc;
  758. if (y2)
  759. {
  760. fx2inc = fx2 / y2; // stuck with division using fx32!
  761. /* CANDIDATE FOR ONE_OVER!
  762. fx2inc = ULONG(fx2.mod) * CInitNum::OneOver[y2]; // stuck with division using fx32!
  763. */
  764. }
  765. long fx3inc = fx3 / y3; // stuck with division using fx32!
  766. // Set the two absolute edge positions
  767. RFixedS32 x2,x3;
  768. x2.val = x3.val = pv1->x.frac; // preserve floating point x!
  769. long lP = lDstP;
  770. // add in extra piece uv rounding!
  771. UCHAR* pDst = pDstOffset + lP * pv1->y.mod + pv1->x.mod + x2.mod;
  772. // Draw the upper triangle! (Assuming fx2inc < fx3inc.....)
  773. short x,y;
  774. short xdel;
  775. //////////////////////////////////////////////////////////////////
  776. //****************************************************************
  777. //====================== CHOOSE II CASES =======================
  778. //****************************************************************
  779. //////////////////////////////////////////////////////////////////
  780. //****************************************************************
  781. //====================== FLAT TOP TRIANGLE =====================
  782. //****************************************************************
  783. // Don't worry about the wasted calculations above!
  784. // (I STILL THINK YOU CAN STREAMLINE THIS AND INTEGRATE IT INTO
  785. // THE OTHER CASE -> THERE IS NO CALL FOR THIS!)
  786. if (y2 == 0) // p1.y == p2.y
  787. {
  788. long fx1inc;
  789. RFixedS32 x1; // Absolute positions
  790. // Let point I be to the LEFT of point II:
  791. if (pv2->x.val < pv1->x.val) SWAP(pv1,pv2);
  792. // again, set initial points relative to p1(0,0):
  793. fx1 = pv1->x.val;
  794. fx2 = pv2->x.val - fx1;
  795. fx3 = pv3->x.val - fx1;
  796. // This time, we want the end slopes:
  797. //******* CANDIDATE FOR ONE_OVER!
  798. fx1inc = fx3 / y3; // from pt 1 to pt 3
  799. fx2inc = (fx3 - fx2) / y3; // from pt 2 to pt 3
  800. x1.val = pv1->x.frac; // preserve floating point x!
  801. x2.val = fx2;
  802. pDst = pDstOffset + lP * pv1->y.mod + pv1->x.mod + x1.mod; // add in extra piece uv rounding!
  803. for (y = y3;y;y--)
  804. {
  805. pDst += lP;
  806. x2.val += fx2inc;
  807. x1.val += fx1inc;
  808. xdel = x2.mod - x1.mod;
  809. //***************8 flipped the inc value:!
  810. // Assume 2 to 3:
  811. for (x = x1.mod; x<= x2.mod;x++) *(pDst+x) = ucFlatColor;
  812. }
  813. return;
  814. }
  815. //****************************************************************
  816. //====================== NORMAL TRIANGLE =======================
  817. //****************************************************************
  818. if (fx2inc <= fx3inc)
  819. {
  820. //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,y2,ucColor);
  821. for (y = y2;y;y--)
  822. {
  823. pDst += lP;
  824. x2.val += fx2inc;
  825. x3.val += fx3inc;
  826. // Assume 2 to 3:
  827. xdel = x3.mod - x2.mod;
  828. // Assume 2 to 3:
  829. for (x = x2.mod; x<= x3.mod;x++) *(pDst+x) = ucFlatColor;
  830. }
  831. //===================================================================
  832. // Draw the lower triangle if applicatable:
  833. //===================================================================
  834. if (ybot)
  835. {
  836. // new x2 slope:
  837. fx2inc = (fx3 - fx2) / ybot; // stuck with division using fx32!
  838. /*
  839. fx2inc = ULONG(fx3.mod-fx2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
  840. */
  841. //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,yc,ucColor);
  842. for (y = ybot;y;y--)
  843. {
  844. pDst += lP;
  845. x2.val += fx2inc;
  846. x3.val += fx3inc;
  847. xdel = x3.mod - x2.mod;
  848. // Assume 2 to 3:
  849. for (x = x2.mod; x<= x3.mod;x++) *(pDst+x) = ucFlatColor;
  850. }
  851. }
  852. }
  853. else // flip the x drawing order:
  854. //===================================================================
  855. //============== DRAW MIRRORED VERION OF STANDARD TRIANGLE! =========
  856. //===================================================================
  857. {
  858. //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,y2,ucColor);
  859. for (y = y2;y;y--)
  860. {
  861. pDst += lP;
  862. x2.val += fx2inc;
  863. x3.val += fx3inc;
  864. // Assume 2 to 3:
  865. xdel = x2.mod - x3.mod; //+ x to z
  866. // Assume 2 to 3:
  867. for (x = x3.mod; x<= x2.mod;x++) *(pDst+x) = ucFlatColor;
  868. }
  869. //===================================================================
  870. // Draw the lower triangle if applicatable:
  871. //===================================================================
  872. if (ybot)
  873. {
  874. // new x2 slope:
  875. fx2inc = (fx3 - fx2) / ybot; // stuck with division using fx32!
  876. /*
  877. fx2inc = ULONG(fx3.mod-fx2.mod) * CInitNum::OneOver[yc]; // stuck with division using fx32!
  878. */
  879. //_DrawTri(pDst,lP,x2,x3,fx2inc,fx3inc,yc,ucColor);
  880. for (y = ybot;y;y--)
  881. {
  882. pDst += lP;
  883. x2.val += fx2inc;
  884. x3.val += fx3inc;
  885. xdel = x2.mod - x3.mod;
  886. // Full accuracy fxMul!
  887. // Assume 2 to 3:
  888. for (x = x3.mod; x<= x2.mod;x++) *(pDst+x) = ucFlatColor;
  889. }
  890. }
  891. }
  892. }