bitRender.cpp 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "core/bitRender.h"
  23. U32 openTable[32] = { 0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFC,0xFFFFFFF8,
  24. 0xFFFFFFF0,0xFFFFFFE0,0xFFFFFFC0,0xFFFFFF80,
  25. 0xFFFFFF00,0xFFFFFE00,0xFFFFFC00,0xFFFFF800,
  26. 0xFFFFF000,0xFFFFE000,0xFFFFC000,0xFFFF8000,
  27. 0xFFFF0000,0xFFFE0000,0xFFFC0000,0xFFF80000,
  28. 0xFFF00000,0xFFE00000,0xFFC00000,0xFF800000,
  29. 0xFF000000,0xFE000000,0xFC000000,0xF8000000,
  30. 0xF0000000,0xE0000000,0xC0000000,0x80000000 };
  31. U32 closeTable[32] = { 0x00000001,0x00000003,0x00000007,0x0000000F,
  32. 0x0000001F,0x0000003F,0x0000007F,0x000000FF,
  33. 0x000001FF,0x000003FF,0x000007FF,0x00000FFF,
  34. 0x00001FFF,0x00003FFF,0x00007FFF,0x0000FFFF,
  35. 0x0001FFFF,0x0003FFFF,0x0007FFFF,0x000FFFFF,
  36. 0x001FFFFF,0x003FFFFF,0x007FFFFF,0x00FFFFFF,
  37. 0x01FFFFFF,0x03FFFFFF,0x07FFFFFF,0x0FFFFFFF,
  38. 0x1FFFFFFF,0x3FFFFFFF,0x7FFFFFFF,0xFFFFFFFF };
  39. struct DrawStruct
  40. {
  41. S16 start;
  42. S16 num;
  43. };
  44. void BitRender::render_strips(const U8 * draw, S32 numDraw, S32 szDraw, const U16 * indices, const Point2I * points, S32 dim, U32 * bits)
  45. {
  46. const U8 * drawEnd = draw + numDraw*szDraw;
  47. // loop through strips...
  48. for (; draw<drawEnd; draw += szDraw)
  49. {
  50. const DrawStruct * drawStruct = (DrawStruct*)draw;
  51. const U16 * icurrent = indices + drawStruct->start;
  52. const U16 * iend = icurrent + drawStruct->num;
  53. const Point2I * vv0 = points + *(icurrent++);
  54. const Point2I * vv1;
  55. const Point2I * vv2 = points + *(icurrent++);
  56. const Point2I **nextPt = &vv1;
  57. while (icurrent<iend)
  58. {
  59. *nextPt = vv2;
  60. nextPt = (const Point2I**)( (dsize_t)nextPt ^ (dsize_t)&vv0 ^ (dsize_t)&vv1 );
  61. vv2 = points + *(icurrent++);
  62. // skip degenerate triangles...
  63. if (vv0==vv1 || vv1==vv2 || vv2==vv0)
  64. continue;
  65. // following copied from BitRender::render...indented to highlight this fact, no function to indentation
  66. {
  67. const Point2I * v0 = vv0;
  68. const Point2I * v1 = vv1;
  69. const Point2I * v2 = vv2;
  70. AssertFatal( v0->x>=0 && v0->x<dim && v0->y>=0 && v0->y<dim,"BitRender::render: v0 out of range");
  71. AssertFatal( v1->x>=0 && v1->x<dim && v1->y>=0 && v1->y<dim,"BitRender::render: v1 out of range");
  72. AssertFatal( v2->x>=0 && v2->x<dim && v2->y>=0 && v2->y<dim,"BitRender::render: v2 out of range");
  73. // back-face cull
  74. if ((v0->x-v1->x)*(v2->y-v1->y) > (v0->y-v1->y)*(v2->x-v1->x))
  75. continue;
  76. // rotate so that v0 holds topmost y coord
  77. // Note: The particular inequalities used ( <=, <, then <=) are important.
  78. // They guarantee that if there are two verts on the top row, that
  79. // they will be vert v0 and v1 (also could be three).
  80. if (v1->y <= v2->y)
  81. {
  82. if (v1->y < v0->y)
  83. {
  84. const Point2I * tmp = v0;
  85. v0 = v1;
  86. v1 = v2;
  87. v2 = tmp;
  88. }
  89. }
  90. else
  91. {
  92. if (v2->y <= v0->y)
  93. {
  94. const Point2I * tmp = v0;
  95. v0 = v2;
  96. v2 = v1;
  97. v1 = tmp;
  98. }
  99. }
  100. // all the control variables we have to set up...
  101. S32 leftDeltaY, xLeftInc, xLeftErrInc, xLeftDir, xLeft, xLeftErr = 0;
  102. S32 rightDeltaY, xRightInc, xRightErrInc, xRightDir, xRight, xRightErr = 0;
  103. S32 * changeThisDelta;
  104. S32 * changeThisInc;
  105. S32 * changeThisErrInc;
  106. S32 * changeThisDir;
  107. S32 toThisDelta;
  108. S32 toThisInc;
  109. S32 toThisErrInc;
  110. S32 toThisDir;
  111. S32 ySwitch;
  112. S32 yBottom;
  113. // check for special case where top row holds two verts
  114. if (v0->y==v1->y)
  115. {
  116. leftDeltaY = v2->y-v0->y;
  117. rightDeltaY = v2->y-v1->y;
  118. ySwitch = v2->y;
  119. yBottom = v2->y;
  120. if (v1->y==v2->y)
  121. {
  122. // special-special case where top row holds all three verts
  123. xLeft = getMin(getMin(v0->x,v1->x),v2->x);
  124. xRight = getMax(getMax(v0->x,v1->x),v2->x);
  125. xLeftInc = xRightInc = 0;
  126. xLeftErrInc = xRightErrInc = 0;
  127. xLeftDir = xRightDir = 1;
  128. }
  129. else
  130. {
  131. // standard-special case...v2 on different row from v0 and v1
  132. xLeft = v0->x;
  133. xLeftInc = (v2->x-v0->x) / leftDeltaY;
  134. xLeftErrInc = (v2->x-v0->x) - leftDeltaY*xLeftInc;
  135. xLeftDir = v2->x-v0->x > 0 ? 1 : -1;
  136. xRight = v1->x;
  137. xRightInc = (v2->x-v1->x) / rightDeltaY;
  138. xRightErrInc = (v2->x-v1->x) - rightDeltaY*xRightInc;
  139. xRightDir = v2->x-v1->x > 0 ? 1 : -1;
  140. }
  141. // set these variables to avoid a crash...
  142. changeThisDelta = &toThisDelta;
  143. changeThisInc = &toThisInc;
  144. changeThisErrInc = &toThisErrInc;
  145. changeThisDir = &toThisDir;
  146. }
  147. else
  148. {
  149. leftDeltaY = v2->y-v0->y;
  150. xLeftInc = (v2->x-v0->x) / leftDeltaY;
  151. xLeftErrInc = (v2->x-v0->x) - leftDeltaY*xLeftInc;
  152. xLeftDir = v2->x-v0->x > 0 ? 1 : -1;
  153. rightDeltaY = v1->y-v0->y;
  154. xRightInc = (v1->x-v0->x) / rightDeltaY;
  155. xRightErrInc = (v1->x-v0->x) - rightDeltaY*xRightInc;
  156. xRightDir = v1->x-v0->x > 0 ? 1 : -1;
  157. xLeft = xRight = v0->x;
  158. if (v1->y<v2->y)
  159. {
  160. // right edge bends
  161. changeThisDelta = &rightDeltaY;
  162. changeThisInc = &xRightInc;
  163. changeThisErrInc = &xRightErrInc;
  164. changeThisDir = &xRightDir;
  165. toThisDelta = v2->y-v1->y;
  166. toThisInc = (v2->x-v1->x) / toThisDelta;
  167. toThisErrInc = (v2->x-v1->x) - toThisDelta * toThisInc;
  168. toThisDir = v2->x-v1->x > 0 ? 1 : -1;
  169. ySwitch = v1->y-1;
  170. yBottom = v2->y;
  171. }
  172. else
  173. {
  174. // left edge bends
  175. changeThisDelta = &leftDeltaY;
  176. changeThisInc = &xLeftInc;
  177. changeThisErrInc = &xLeftErrInc;
  178. changeThisDir = &xLeftDir;
  179. toThisDelta = v1->y-v2->y;
  180. toThisInc = toThisDelta ? (v1->x-v2->x) / toThisDelta : 0;
  181. toThisErrInc = toThisDelta ? (v1->x-v2->x) - toThisDelta * toThisInc : 0;
  182. toThisDir = v1->x-v2->x > 0 ? 1 : -1;
  183. ySwitch = v2->y-1;
  184. yBottom = v1->y;
  185. }
  186. }
  187. xLeftErrInc *= xLeftDir;
  188. xRightErrInc *= xRightDir;
  189. toThisErrInc *= toThisDir;
  190. U32 * rowStart = bits + v0->y * (dim>>5);
  191. for (S32 y=v0->y; y<=yBottom;)
  192. {
  193. do
  194. {
  195. AssertFatal(xLeft<=xRight,"BitRender::render");
  196. U32 open = openTable[xLeft&31];
  197. U32 close = closeTable[xRight&31];
  198. if ( (xLeft^xRight) & ~31)
  199. {
  200. U32 * x = rowStart+(xLeft>>5);
  201. *x |= open;
  202. U32 * xEnd = rowStart+(xRight>>5);
  203. while (++x<xEnd)
  204. *x |= 0xFFFFFFFF;
  205. *x |= close;
  206. }
  207. else
  208. rowStart[xLeft>>5] |= open & close;
  209. xLeft += xLeftInc;
  210. xLeftErr += xLeftErrInc;
  211. if (xLeftErr >= leftDeltaY)
  212. {
  213. xLeft += xLeftDir;
  214. xLeftErr -= leftDeltaY;
  215. }
  216. xRight += xRightInc;
  217. xRightErr += xRightErrInc;
  218. if (xRightErr >= rightDeltaY)
  219. {
  220. xRight += xRightDir;
  221. xRightErr -= rightDeltaY;
  222. }
  223. rowStart += dim>>5;
  224. } while (y++<ySwitch);
  225. ySwitch=yBottom; // get here at most twice
  226. *changeThisDelta = toThisDelta;
  227. *changeThisInc = toThisInc;
  228. *changeThisErrInc = toThisErrInc;
  229. *changeThisDir = toThisDir;
  230. }
  231. }
  232. }
  233. }
  234. }
  235. void BitRender::render_tris(const U8 * draw, S32 numDraw, S32 szDraw, const U16 * indices, const Point2I * points, S32 dim, U32 * bits)
  236. {
  237. const U8 * drawEnd = draw + numDraw*szDraw;
  238. // loop through strips...
  239. for (; draw<drawEnd; draw += szDraw)
  240. {
  241. const DrawStruct * drawStruct = (DrawStruct*)draw;
  242. const U16 * icurrent = indices + drawStruct->start;
  243. const U16 * iend = icurrent + drawStruct->num;
  244. while (icurrent<iend)
  245. {
  246. const Point2I * v0 = points + *(icurrent++);
  247. const Point2I * v1 = points + *(icurrent++);
  248. const Point2I * v2 = points + *(icurrent++);
  249. // following copied from BitRender::render...indented to highlight this fact, no function to indentation
  250. {
  251. AssertFatal( v0->x>=0 && v0->x<dim && v0->y>=0 && v0->y<dim,"BitRender::render: v0 out of range");
  252. AssertFatal( v1->x>=0 && v1->x<dim && v1->y>=0 && v1->y<dim,"BitRender::render: v1 out of range");
  253. AssertFatal( v2->x>=0 && v2->x<dim && v2->y>=0 && v2->y<dim,"BitRender::render: v2 out of range");
  254. // back-face cull
  255. if ((v0->x-v1->x)*(v2->y-v1->y) > (v0->y-v1->y)*(v2->x-v1->x))
  256. return;
  257. // rotate so that v0 holds topmost y coord
  258. // Note: The particular inequalities used ( <=, <, then <=) are important.
  259. // They guarantee that if there are two verts on the top row, that
  260. // they will be vert v0 and v1 (also could be three).
  261. if (v1->y <= v2->y)
  262. {
  263. if (v1->y < v0->y)
  264. {
  265. const Point2I * tmp = v0;
  266. v0 = v1;
  267. v1 = v2;
  268. v2 = tmp;
  269. }
  270. }
  271. else
  272. {
  273. if (v2->y <= v0->y)
  274. {
  275. const Point2I * tmp = v0;
  276. v0 = v2;
  277. v2 = v1;
  278. v1 = tmp;
  279. }
  280. }
  281. // all the control variables we have to set up...
  282. S32 leftDeltaY, xLeftInc = 0, xLeftErrInc, xLeftDir = 0, xLeft, xLeftErr = 0;
  283. S32 rightDeltaY, xRightInc = 0, xRightErrInc, xRightDir = 0, xRight, xRightErr = 0;
  284. S32 * changeThisDelta;
  285. S32 * changeThisInc;
  286. S32 * changeThisErrInc;
  287. S32 * changeThisDir;
  288. S32 toThisDelta;
  289. S32 toThisInc;
  290. S32 toThisErrInc;
  291. S32 toThisDir;
  292. S32 ySwitch;
  293. S32 yBottom;
  294. // check for special case where top row holds two verts
  295. if (v0->y==v1->y)
  296. {
  297. leftDeltaY = v2->y-v0->y;
  298. rightDeltaY = v2->y-v1->y;
  299. ySwitch = v2->y;
  300. yBottom = v2->y;
  301. if (v1->y==v2->y)
  302. {
  303. // special-special case where top row holds all three verts
  304. xLeft = getMin(getMin(v0->x,v1->x),v2->x);
  305. xRight = getMax(getMax(v0->x,v1->x),v2->x);
  306. xLeftErrInc = xRightErrInc = 0;
  307. }
  308. else
  309. {
  310. // standard-special case...v2 on different row from v0 and v1
  311. xLeft = v0->x;
  312. xLeftInc = (v2->x-v0->x) / leftDeltaY;
  313. xLeftErrInc = (v2->x-v0->x) - leftDeltaY*xLeftInc;
  314. xLeftDir = v2->x-v0->x > 0 ? 1 : -1;
  315. xRight = v1->x;
  316. xRightInc = (v2->x-v1->x) / rightDeltaY;
  317. xRightErrInc = (v2->x-v1->x) - rightDeltaY*xRightInc;
  318. xRightDir = v2->x-v1->x > 0 ? 1 : -1;
  319. }
  320. // set these variables to avoid a crash...
  321. changeThisDelta = &toThisDelta;
  322. changeThisInc = &toThisInc;
  323. changeThisErrInc = &toThisErrInc;
  324. changeThisDir = &toThisDir;
  325. }
  326. else
  327. {
  328. leftDeltaY = v2->y-v0->y;
  329. xLeftInc = (v2->x-v0->x) / leftDeltaY;
  330. xLeftErrInc = (v2->x-v0->x) - leftDeltaY*xLeftInc;
  331. xLeftDir = v2->x-v0->x > 0 ? 1 : -1;
  332. rightDeltaY = v1->y-v0->y;
  333. xRightInc = (v1->x-v0->x) / rightDeltaY;
  334. xRightErrInc = (v1->x-v0->x) - rightDeltaY*xRightInc;
  335. xRightDir = v1->x-v0->x > 0 ? 1 : -1;
  336. xLeft = xRight = v0->x;
  337. if (v1->y<v2->y)
  338. {
  339. // right edge bends
  340. changeThisDelta = &rightDeltaY;
  341. changeThisInc = &xRightInc;
  342. changeThisErrInc = &xRightErrInc;
  343. changeThisDir = &xRightDir;
  344. toThisDelta = v2->y-v1->y;
  345. toThisInc = (v2->x-v1->x) / toThisDelta;
  346. toThisErrInc = (v2->x-v1->x) - toThisDelta * toThisInc;
  347. toThisDir = v2->x-v1->x > 0 ? 1 : -1;
  348. ySwitch = v1->y-1;
  349. yBottom = v2->y;
  350. }
  351. else
  352. {
  353. // left edge bends
  354. changeThisDelta = &leftDeltaY;
  355. changeThisInc = &xLeftInc;
  356. changeThisErrInc = &xLeftErrInc;
  357. changeThisDir = &xLeftDir;
  358. toThisDelta = v1->y-v2->y;
  359. toThisInc = toThisDelta ? (v1->x-v2->x) / toThisDelta : 0;
  360. toThisErrInc = toThisDelta ? (v1->x-v2->x) - toThisDelta * toThisInc : 0;
  361. toThisDir = v1->x-v2->x > 0 ? 1 : -1;
  362. ySwitch = v2->y-1;
  363. yBottom = v1->y;
  364. }
  365. }
  366. xLeftErrInc *= xLeftDir;
  367. xRightErrInc *= xRightDir;
  368. toThisErrInc *= toThisDir;
  369. U32 * rowStart = bits + v0->y * (dim>>5);
  370. for (S32 y=v0->y; y<=yBottom;)
  371. {
  372. do
  373. {
  374. AssertFatal(xLeft<=xRight,"BitRender::render");
  375. U32 open = openTable[xLeft&31];
  376. U32 close = closeTable[xRight&31];
  377. if ( (xLeft^xRight) & ~31)
  378. {
  379. U32 * x = rowStart+(xLeft>>5);
  380. *x |= open;
  381. U32 * xEnd = rowStart+(xRight>>5);
  382. while (++x<xEnd)
  383. *x |= 0xFFFFFFFF;
  384. *x |= close;
  385. }
  386. else
  387. rowStart[xLeft>>5] |= open & close;
  388. xLeft += xLeftInc;
  389. xLeftErr += xLeftErrInc;
  390. if (xLeftErr >= leftDeltaY)
  391. {
  392. xLeft += xLeftDir;
  393. xLeftErr -= leftDeltaY;
  394. }
  395. xRight += xRightInc;
  396. xRightErr += xRightErrInc;
  397. if (xRightErr >= rightDeltaY)
  398. {
  399. xRight += xRightDir;
  400. xRightErr -= rightDeltaY;
  401. }
  402. rowStart += dim>>5;
  403. } while (y++<ySwitch);
  404. ySwitch=yBottom; // get here at most twice
  405. *changeThisDelta = toThisDelta;
  406. *changeThisInc = toThisInc;
  407. *changeThisErrInc = toThisErrInc;
  408. *changeThisDir = toThisDir;
  409. }
  410. }
  411. }
  412. }
  413. }
  414. // assumes coords are in range
  415. void BitRender::render(const Point2I * v0, const Point2I * v1, const Point2I * v2, S32 dim, U32 * bits)
  416. {
  417. AssertFatal( v0->x>=0 && v0->x<dim && v0->y>=0 && v0->y<dim,"BitRender::render: v0 out of range");
  418. AssertFatal( v1->x>=0 && v1->x<dim && v1->y>=0 && v1->y<dim,"BitRender::render: v1 out of range");
  419. AssertFatal( v2->x>=0 && v2->x<dim && v2->y>=0 && v2->y<dim,"BitRender::render: v2 out of range");
  420. // back-face cull
  421. if ((v0->x-v1->x)*(v2->y-v1->y) > (v0->y-v1->y)*(v2->x-v1->x))
  422. return;
  423. // rotate so that v0 holds topmost y coord
  424. // Note: The particular inequalities used ( <=, <, then <=) are important.
  425. // They guarantee that if there are two verts on the top row, that
  426. // they will be vert v0 and v1 (also could be three).
  427. if (v1->y <= v2->y)
  428. {
  429. if (v1->y < v0->y)
  430. {
  431. const Point2I * tmp = v0;
  432. v0 = v1;
  433. v1 = v2;
  434. v2 = tmp;
  435. }
  436. }
  437. else
  438. {
  439. if (v2->y <= v0->y)
  440. {
  441. const Point2I * tmp = v0;
  442. v0 = v2;
  443. v2 = v1;
  444. v1 = tmp;
  445. }
  446. }
  447. // all the control variables we have to set up...
  448. S32 leftDeltaY, xLeftInc = 0, xLeftErrInc, xLeftDir = 0, xLeft, xLeftErr = 0;
  449. S32 rightDeltaY, xRightInc = 0, xRightErrInc, xRightDir = 0, xRight, xRightErr = 0;
  450. S32 * changeThisDelta;
  451. S32 * changeThisInc;
  452. S32 * changeThisErrInc;
  453. S32 * changeThisDir;
  454. S32 toThisDelta;
  455. S32 toThisInc;
  456. S32 toThisErrInc;
  457. S32 toThisDir;
  458. S32 ySwitch;
  459. S32 yBottom;
  460. // check for special case where top row holds two verts
  461. if (v0->y==v1->y)
  462. {
  463. leftDeltaY = v2->y-v0->y;
  464. rightDeltaY = v2->y-v1->y;
  465. ySwitch = v2->y;
  466. yBottom = v2->y;
  467. if (v1->y==v2->y)
  468. {
  469. // special-special case where top row holds all three verts
  470. xLeft = getMin(getMin(v0->x,v1->x),v2->x);
  471. xRight = getMax(getMax(v0->x,v1->x),v2->x);
  472. xLeftErrInc = xRightErrInc = 0;
  473. }
  474. else
  475. {
  476. // standard-special case...v2 on different row from v0 and v1
  477. xLeft = v0->x;
  478. xLeftInc = (v2->x-v0->x) / leftDeltaY;
  479. xLeftErrInc = (v2->x-v0->x) - leftDeltaY*xLeftInc;
  480. xLeftDir = v2->x-v0->x > 0 ? 1 : -1;
  481. xRight = v1->x;
  482. xRightInc = (v2->x-v1->x) / rightDeltaY;
  483. xRightErrInc = (v2->x-v1->x) - rightDeltaY*xRightInc;
  484. xRightDir = v2->x-v1->x > 0 ? 1 : -1;
  485. }
  486. // set these variables to avoid a crash...
  487. changeThisDelta = &toThisDelta;
  488. changeThisInc = &toThisInc;
  489. changeThisErrInc = &toThisErrInc;
  490. changeThisDir = &toThisDir;
  491. }
  492. else
  493. {
  494. leftDeltaY = v2->y-v0->y;
  495. xLeftInc = (v2->x-v0->x) / leftDeltaY;
  496. xLeftErrInc = (v2->x-v0->x) - leftDeltaY*xLeftInc;
  497. xLeftDir = v2->x-v0->x > 0 ? 1 : -1;
  498. rightDeltaY = v1->y-v0->y;
  499. xRightInc = (v1->x-v0->x) / rightDeltaY;
  500. xRightErrInc = (v1->x-v0->x) - rightDeltaY*xRightInc;
  501. xRightDir = v1->x-v0->x > 0 ? 1 : -1;
  502. xLeft = xRight = v0->x;
  503. if (v1->y<v2->y)
  504. {
  505. // right edge bends
  506. changeThisDelta = &rightDeltaY;
  507. changeThisInc = &xRightInc;
  508. changeThisErrInc = &xRightErrInc;
  509. changeThisDir = &xRightDir;
  510. toThisDelta = v2->y-v1->y;
  511. toThisInc = (v2->x-v1->x) / toThisDelta;
  512. toThisErrInc = (v2->x-v1->x) - toThisDelta * toThisInc;
  513. toThisDir = v2->x-v1->x > 0 ? 1 : -1;
  514. ySwitch = v1->y-1;
  515. yBottom = v2->y;
  516. }
  517. else
  518. {
  519. // left edge bends
  520. changeThisDelta = &leftDeltaY;
  521. changeThisInc = &xLeftInc;
  522. changeThisErrInc = &xLeftErrInc;
  523. changeThisDir = &xLeftDir;
  524. toThisDelta = v1->y-v2->y;
  525. toThisInc = toThisDelta ? (v1->x-v2->x) / toThisDelta : 0;
  526. toThisErrInc = toThisDelta ? (v1->x-v2->x) - toThisDelta * toThisInc : 0;
  527. toThisDir = v1->x-v2->x > 0 ? 1 : -1;
  528. ySwitch = v2->y-1;
  529. yBottom = v1->y;
  530. }
  531. }
  532. xLeftErrInc *= xLeftDir;
  533. xRightErrInc *= xRightDir;
  534. toThisErrInc *= toThisDir;
  535. U32 * rowStart = bits + v0->y * (dim>>5);
  536. for (S32 y=v0->y; y<=yBottom;)
  537. {
  538. do
  539. {
  540. AssertFatal(xLeft<=xRight,"BitRender::render");
  541. U32 open = openTable[xLeft&31];
  542. U32 close = closeTable[xRight&31];
  543. if ( (xLeft^xRight) & ~31)
  544. {
  545. U32 * x = rowStart+(xLeft>>5);
  546. *x |= open;
  547. U32 * xEnd = rowStart+(xRight>>5);
  548. while (++x<xEnd)
  549. *x |= 0xFFFFFFFF;
  550. *x |= close;
  551. }
  552. else
  553. rowStart[xLeft>>5] |= open & close;
  554. xLeft += xLeftInc;
  555. xLeftErr += xLeftErrInc;
  556. if (xLeftErr >= leftDeltaY)
  557. {
  558. xLeft += xLeftDir;
  559. xLeftErr -= leftDeltaY;
  560. }
  561. xRight += xRightInc;
  562. xRightErr += xRightErrInc;
  563. if (xRightErr >= rightDeltaY)
  564. {
  565. xRight += xRightDir;
  566. xRightErr -= rightDeltaY;
  567. }
  568. rowStart += dim>>5;
  569. } while (y++<ySwitch);
  570. ySwitch=yBottom; // get here at most twice
  571. *changeThisDelta = toThisDelta;
  572. *changeThisInc = toThisInc;
  573. *changeThisErrInc = toThisErrInc;
  574. *changeThisDir = toThisDir;
  575. }
  576. }
  577. // These macros currently define how black the shadows get
  578. // Set the shift factor to zero results in totally black
  579. // shadows. Be nice to have this dynamic...
  580. #define SF(x) ((x) >> 2)
  581. #define SF32(a,b,c,d) {SF(a),SF(b),SF(c),SF(d)}
  582. /*
  583. // endian-ordering version of the SF macro, for the blur methods.
  584. #if PLATFORM_LITTLE_ENDIAN
  585. #define SF32E(a,b,c,d) SF32(a,b,c,d)
  586. #else
  587. #define SF32E(a,b,c,d) SF32(d,c,b,a)
  588. #endif
  589. */
  590. U8 bitTable[16][4] =
  591. {
  592. SF32( 0, 0, 0, 0), // 0
  593. SF32(255, 0, 0, 0), // 1
  594. SF32( 0,255, 0, 0), // 2
  595. SF32(255,255, 0, 0), // 3
  596. SF32( 0, 0,255, 0), // 4
  597. SF32(255, 0,255, 0), // 5
  598. SF32( 0,255,255, 0), // 6
  599. SF32(255,255,255, 0), // 7
  600. SF32( 0, 0, 0,255), // 8
  601. SF32(255, 0, 0,255), // 9
  602. SF32( 0,255, 0,255), // 10
  603. SF32(255,255, 0,255), // 11
  604. SF32( 0, 0,255,255), // 12
  605. SF32(255, 0,255,255), // 13
  606. SF32( 0,255,255,255), // 14
  607. SF32(255,255,255,255), // 15
  608. };
  609. void BitRender::bitTo8Bit(U32 * bits, U32 * eightBits, S32 dim)
  610. {
  611. dim *= dim>>5;
  612. for (S32 i=0; i<dim; i++)
  613. {
  614. U32 val = *bits++;
  615. *eightBits++ = *(U32*)&bitTable[val&0xF];
  616. val >>= 4;
  617. *eightBits++ = *(U32*)&bitTable[val&0xF];
  618. val >>= 4;
  619. *eightBits++ = *(U32*)&bitTable[val&0xF];
  620. val >>= 4;
  621. *eightBits++ = *(U32*)&bitTable[val&0xF];
  622. val >>= 4;
  623. *eightBits++ = *(U32*)&bitTable[val&0xF];
  624. val >>= 4;
  625. *eightBits++ = *(U32*)&bitTable[val&0xF];
  626. val >>= 4;
  627. *eightBits++ = *(U32*)&bitTable[val&0xF];
  628. val >>= 4;
  629. *eightBits++ = *(U32*)&bitTable[val&0xF];
  630. val >>= 4;
  631. }
  632. }
  633. U8 bitTableA[16][4] =
  634. {
  635. SF32( 0, 0, 0, 0), // 0
  636. SF32( 0, 0, 0, 0), // 1
  637. SF32( 0, 0, 0, 0), // 2
  638. SF32( 0, 0, 0, 0), // 3
  639. SF32( 0, 0, 0, 0), // 4
  640. SF32( 0, 0, 0, 0), // 5
  641. SF32( 0, 0, 0, 0), // 6
  642. SF32( 0, 0, 0, 0), // 7
  643. SF32( 17, 0, 0, 0), // 8
  644. SF32( 17, 0, 0, 0), // 9
  645. SF32( 17, 0, 0, 0), // 10
  646. SF32( 17, 0, 0, 0), // 11
  647. SF32( 17, 0, 0, 0), // 12
  648. SF32( 17, 0, 0, 0), // 13
  649. SF32( 17, 0, 0, 0), // 14
  650. SF32( 17, 0, 0, 0), // 15
  651. };
  652. U8 bitTableB[16][4] =
  653. {
  654. SF32( 0, 0, 0, 0), // 0
  655. SF32( 34, 17, 0, 0), // 1
  656. SF32( 17, 34, 17, 0), // 2
  657. SF32( 51, 51, 17, 0), // 3
  658. SF32( 0, 17, 34, 17), // 4
  659. SF32( 34, 34, 34, 17), // 5
  660. SF32( 17, 51, 51, 17), // 6
  661. SF32( 51, 68, 51, 17), // 7
  662. SF32( 0, 0, 17, 34), // 8
  663. SF32( 34, 17, 17, 34), // 9
  664. SF32( 17, 34, 34, 34), // 10
  665. SF32( 51, 51, 34, 34), // 11
  666. SF32( 0, 17, 51, 51), // 12
  667. SF32( 34, 34, 51, 51), // 13
  668. SF32( 17, 51, 68, 51), // 14
  669. SF32( 51, 68, 68, 51), // 15
  670. };
  671. U8 bitTableC[16][4] =
  672. {
  673. SF32( 0, 0, 0, 0), // 0
  674. SF32( 0, 0, 0, 17), // 1
  675. SF32( 0, 0, 0, 0), // 2
  676. SF32( 0, 0, 0, 17), // 3
  677. SF32( 0, 0, 0, 0), // 4
  678. SF32( 0, 0, 0, 17), // 5
  679. SF32( 0, 0, 0, 0), // 6
  680. SF32( 0, 0, 0, 17), // 7
  681. SF32( 0, 0, 0, 0), // 8
  682. SF32( 0, 0, 0, 17), // 9
  683. SF32( 0, 0, 0, 0), // 10
  684. SF32( 0, 0, 0, 17), // 11
  685. SF32( 0, 0, 0, 0), // 12
  686. SF32( 0, 0, 0, 17), // 13
  687. SF32( 0, 0, 0, 0), // 14
  688. SF32( 0, 0, 0, 17), // 15
  689. };
  690. U8 bitTableE[16][4] =
  691. {
  692. SF32( 0, 0, 0, 0), // 0
  693. SF32( 51, 34, 0, 0), // 1
  694. SF32( 34, 51, 34, 0), // 2
  695. SF32( 85, 85, 34, 0), // 3
  696. SF32( 0, 34, 51, 34), // 4
  697. SF32( 51, 68, 51, 34), // 5
  698. SF32( 34, 85, 85, 34), // 6
  699. SF32( 85,119, 85, 34), // 7
  700. SF32( 0, 0, 34, 51), // 8
  701. SF32( 51, 34, 34, 51), // 9
  702. SF32( 34, 51, 68, 51), // 10
  703. SF32( 85, 85, 68, 51), // 11
  704. SF32( 0, 34, 85, 85), // 12
  705. SF32( 51, 68, 85, 85), // 13
  706. SF32( 34, 85,119, 85), // 14
  707. SF32( 85,119,119, 85), // 15
  708. };
  709. void BitRender::bitTo8Bit_3(U32 * bits, U32 * eightBits, S32 dim)
  710. {
  711. #if defined(TORQUE_BIG_ENDIAN)
  712. #define MAX_SHADOW_TEXELS (256 + 4) //256 seems big enough, +4 so we can run off end of buffer.
  713. // slow fake gaussian
  714. S32 i, j, c;
  715. U8 tmpLine[3][MAX_SHADOW_TEXELS];
  716. U8 *src0, *src1, *src2;
  717. U8 *s0, *s1, *s2;
  718. U32 dimS2 = dim>>2;
  719. U32 *src32;
  720. U32 *currLine = bits;
  721. U32 currVal;
  722. U32 sampleVal;
  723. U8 c00, c01, c02, c10, c11, c12, c20, c21, c22;
  724. S32 openBuf;
  725. src0 = tmpLine[0];
  726. src1 = tmpLine[1];
  727. src2 = tmpLine[2];
  728. openBuf = 2; // the one src2 is using right now.
  729. // pre-process two rows into our tmp buffers.
  730. src32 = (U32*)(src0);
  731. for(i=0; i<(dimS2>>3); i++) // walk 4 bytes at a time, 4 bits at a time.
  732. {
  733. currVal = *currLine++;
  734. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  735. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  736. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  737. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  738. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  739. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  740. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  741. *src32++ = *(U32*)&bitTable[currVal];
  742. }
  743. src32 = (U32*)(src1);
  744. for(i=0; i<(dimS2>>3); i++)
  745. {
  746. currVal = *currLine++;
  747. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  748. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  749. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  750. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  751. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  752. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  753. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  754. *src32++ = *(U32*)&bitTable[currVal];
  755. }
  756. // pre-clear first row of depth buffer.
  757. for (i=0; i<dimS2; i++)
  758. *eightBits++ = 0L;
  759. // start.
  760. j = dim - 2; // we pre-process two lines, and only really do the internal -2 rows
  761. while (j>0)
  762. {
  763. j--;
  764. // process new line (currLine) into new tmp buffer (src2)
  765. src32 = (U32*)(src2);
  766. for(i=0; i<(dimS2>>3); i++) // 8 at a time.
  767. {
  768. currVal = *currLine++;
  769. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  770. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  771. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  772. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  773. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  774. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  775. *src32++ = *(U32*)&bitTable[0x0F & currVal]; currVal >>= 4;
  776. *src32++ = *(U32*)&bitTable[currVal];
  777. }
  778. // blur & copy current src1 to current dest
  779. #if NO_BLUR
  780. // test for basic functionality.
  781. srcTmp = src1;
  782. src32 = (U32*)srcTmp;
  783. for (i=0; i<dimS2; i++)
  784. *eightBits++ = *src32++;
  785. #else
  786. s0 = src0;
  787. s1 = src1;
  788. s2 = src2;
  789. // c#0 will be copied in at end of loop...
  790. c00 = 0; c01 = *s0++;
  791. c10 = 0; c11 = *s1++;
  792. c20 = 0; c21 = *s2++;
  793. for (i=0; i<dimS2; i++) // process samples in 32bit inc.
  794. {
  795. currVal = 0L;
  796. for (c=0; c<4; c++)
  797. {
  798. // update right-edge samples -- for very last pixel this reads off end of real data.
  799. c02 = *s0++;
  800. c12 = *s1++;
  801. c22 = *s2++;
  802. // process sample i*4+c
  803. if (!i && !c) // very first pixel
  804. sampleVal = 0; //c11; // take mid as it's the right thing.
  805. else
  806. if (i==(dimS2-1) && c==3) // very last pixel
  807. sampleVal = 0; //c12; // take end.
  808. else // inner pixel
  809. {
  810. const S32 wXP = 3; // corners
  811. const S32 wPP = 4; // plus/NSEW
  812. const S32 wCP = 4; // center
  813. sampleVal = (c00+c02+c20+c22)*wXP + (c01+c10+c12+c21)*wPP + c11*wCP;
  814. sampleVal >>= 5; // div by 32 subsamples
  815. }
  816. // mix into val store to hold.
  817. currVal |= sampleVal << (8*(3-c));
  818. c00 = c01; c01 = c02;
  819. c10 = c11; c11 = c12;
  820. c20 = c21; c21 = c22;
  821. //c#2 defd next time round
  822. }
  823. // put samples into dest buffer.
  824. *eightBits++ = currVal;
  825. }
  826. #endif
  827. // flip around ptrs for next row processing.
  828. openBuf++;
  829. if (openBuf>2)
  830. openBuf = 0;
  831. src0 = src1;
  832. src1 = src2;
  833. src2 = tmpLine[openBuf];
  834. }
  835. // clear last dest buffer row
  836. for (i=0; i<dimS2; i++)
  837. *eightBits++ = 0L;
  838. #else // the old windows implementation, which isn't working on Mac right now.
  839. // clear out first row of dest
  840. U32 * end32 = eightBits + (dim>>2);
  841. do { *eightBits++=0; } while (eightBits<end32);
  842. end32 += (dim>>2)*(dim-1);
  843. U8 * p0 = (U8*)bits;
  844. U8 bitLo10 = 0x0F & *p0;
  845. U8 bitHi10 = (*p0) >> 4;
  846. p0++;
  847. U8 * p1 = (U8*)bits + (dim>>3);
  848. U8 bitLo11 = 0x0F & *p1;
  849. U8 bitHi11 = (*p1) >> 4;
  850. p1++;
  851. U8 * p2 = (U8*)bits + (dim>>2);
  852. U8 bitLo12 = 0x0F & *p2;
  853. U8 bitHi12 = (*p2) >> 4;
  854. p2++;
  855. U8 bitLo20, bitHi20;
  856. U8 bitLo21, bitHi21;
  857. U8 bitLo22, bitHi22;
  858. U8 bitHi00 = 0;
  859. U8 bitHi01 = 0;
  860. U8 bitHi02 = 0;
  861. // go thru penultimate row (but stop before last entry in that row)
  862. U8 * end = (U8*)bits + dim*(dim>>3) - 1;
  863. do
  864. {
  865. bitLo20 = 0x0F & *p0;
  866. bitHi20 = (*p0) >> 4;
  867. bitLo21 = 0x0F & *p1;
  868. bitHi21 = (*p1) >> 4;
  869. bitLo22 = 0x0F & *p2;
  870. bitHi22 = (*p2) >> 4;
  871. *eightBits++ = *(U32*)&bitTableA[bitHi00] + *(U32*)&bitTableB[bitLo10] + *(U32*)&bitTableC[bitHi10] +
  872. *(U32*)&bitTableA[bitHi01]*2 + *(U32*)&bitTableE[bitLo11] + *(U32*)&bitTableC[bitHi11]*2 +
  873. *(U32*)&bitTableA[bitHi02] + *(U32*)&bitTableB[bitLo12] + *(U32*)&bitTableC[bitHi12];
  874. *eightBits++ = *(U32*)&bitTableA[bitLo10] + *(U32*)&bitTableB[bitHi10] + *(U32*)&bitTableC[bitLo20] +
  875. *(U32*)&bitTableA[bitLo11]*2 + *(U32*)&bitTableE[bitHi11] + *(U32*)&bitTableC[bitLo21]*2 +
  876. *(U32*)&bitTableA[bitLo12] + *(U32*)&bitTableB[bitHi12] + *(U32*)&bitTableC[bitLo22];
  877. bitHi00 = bitHi10;
  878. bitLo10 = bitLo20;
  879. bitHi10 = bitHi20;
  880. bitHi01 = bitHi11;
  881. bitLo11 = bitLo21;
  882. bitHi11 = bitHi21;
  883. bitHi02 = bitHi12;
  884. bitLo12 = bitLo22;
  885. bitHi12 = bitHi22;
  886. p0++;
  887. p1++;
  888. p2++;
  889. }
  890. while (p2<end);
  891. // clear out last row of dest
  892. do { *eightBits++=0; } while (eightBits<end32);
  893. #endif
  894. }