/opengles/src/ContextTriangles.cpp

http://ftk.googlecode.com/ · C++ · 782 lines · 535 code · 196 blank · 51 comment · 73 complexity · 2790dcacc5812559aa7eae624b21ebfe MD5 · raw file

  1. // ==========================================================================
  2. //
  3. // triangles.cpp Rendering Context Class for 3D Rendering Library
  4. //
  5. // Rendering Operations for Triangles
  6. //
  7. // --------------------------------------------------------------------------
  8. //
  9. // 08-12-2003 Hans-Martin Will initial version
  10. //
  11. // --------------------------------------------------------------------------
  12. //
  13. // Copyright (c) 2004, Hans-Martin Will. All rights reserved.
  14. //
  15. // Redistribution and use in source and binary forms, with or without
  16. // modification, are permitted provided that the following conditions are
  17. // met:
  18. //
  19. // * Redistributions of source code must retain the above copyright
  20. // notice, this list of conditions and the following disclaimer.
  21. // * Redistributions in binary form must reproduce the above copyright
  22. // notice, this list of conditions and the following disclaimer in the
  23. // documentation and/or other materials provided with the distribution.
  24. //
  25. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  26. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  29. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  30. // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  35. // THE POSSIBILITY OF SUCH DAMAGE.
  36. //
  37. // ==========================================================================
  38. #include "stdafx.h"
  39. #include "Context.h"
  40. #include "fixed.h"
  41. #include "Rasterizer.h"
  42. using namespace EGL;
  43. // --------------------------------------------------------------------------
  44. // Triangles
  45. // --------------------------------------------------------------------------
  46. void Context :: RenderTriangles(GLint first, GLsizei count) {
  47. m_Rasterizer->PrepareTriangle();
  48. while (count >= 3) {
  49. count -= 3;
  50. RasterPos pos0, pos1, pos2;
  51. SelectArrayElement(first++);
  52. CurrentValuesToRasterPos(&pos0);
  53. SelectArrayElement(first++);
  54. CurrentValuesToRasterPos(&pos1);
  55. SelectArrayElement(first++);
  56. CurrentValuesToRasterPos(&pos2);
  57. RenderTriangle(pos0, pos1, pos2);
  58. }
  59. }
  60. void Context :: RenderTriangles(GLsizei count, const GLubyte * indices) {
  61. m_Rasterizer->PrepareTriangle();
  62. while (count >= 3) {
  63. count -= 3;
  64. RasterPos pos0, pos1, pos2;
  65. SelectArrayElement(*indices++);
  66. CurrentValuesToRasterPos(&pos0);
  67. SelectArrayElement(*indices++);
  68. CurrentValuesToRasterPos(&pos1);
  69. SelectArrayElement(*indices++);
  70. CurrentValuesToRasterPos(&pos2);
  71. RenderTriangle(pos0, pos1, pos2);
  72. }
  73. }
  74. void Context :: RenderTriangles(GLsizei count, const GLushort * indices) {
  75. m_Rasterizer->PrepareTriangle();
  76. while (count >= 3) {
  77. count -= 3;
  78. RasterPos pos0, pos1, pos2;
  79. SelectArrayElement(*indices++);
  80. CurrentValuesToRasterPos(&pos0);
  81. SelectArrayElement(*indices++);
  82. CurrentValuesToRasterPos(&pos1);
  83. SelectArrayElement(*indices++);
  84. CurrentValuesToRasterPos(&pos2);
  85. RenderTriangle(pos0, pos1, pos2);
  86. }
  87. }
  88. // --------------------------------------------------------------------------
  89. // Triangle Strips
  90. // --------------------------------------------------------------------------
  91. void Context :: RenderTriangleStrip(GLint first, GLsizei count) {
  92. if (count < 3) {
  93. return;
  94. }
  95. m_Rasterizer->PrepareTriangle();
  96. RasterPos pos0, pos1, pos2;
  97. SelectArrayElement(first++);
  98. CurrentValuesToRasterPos(&pos0);
  99. SelectArrayElement(first++);
  100. CurrentValuesToRasterPos(&pos1);
  101. count -= 2;
  102. while (count >= 6) {
  103. count -= 6;
  104. SelectArrayElement(first++);
  105. CurrentValuesToRasterPos(&pos2);
  106. RenderTriangle(pos0, pos1, pos2);
  107. SelectArrayElement(first++);
  108. CurrentValuesToRasterPos(&pos0);
  109. RenderTriangle(pos2, pos1, pos0);
  110. SelectArrayElement(first++);
  111. CurrentValuesToRasterPos(&pos1);
  112. RenderTriangle(pos2, pos0, pos1);
  113. SelectArrayElement(first++);
  114. CurrentValuesToRasterPos(&pos2);
  115. RenderTriangle(pos1, pos0, pos2);
  116. SelectArrayElement(first++);
  117. CurrentValuesToRasterPos(&pos0);
  118. RenderTriangle(pos1, pos2, pos0);
  119. SelectArrayElement(first++);
  120. CurrentValuesToRasterPos(&pos1);
  121. RenderTriangle(pos0, pos2, pos1);
  122. }
  123. if (count >= 1) {
  124. SelectArrayElement(first++);
  125. CurrentValuesToRasterPos(&pos2);
  126. RenderTriangle(pos0, pos1, pos2);
  127. }
  128. if (count >= 2) {
  129. SelectArrayElement(first++);
  130. CurrentValuesToRasterPos(&pos0);
  131. RenderTriangle(pos2, pos1, pos0);
  132. }
  133. if (count >= 3) {
  134. SelectArrayElement(first++);
  135. CurrentValuesToRasterPos(&pos1);
  136. RenderTriangle(pos2, pos0, pos1);
  137. }
  138. if (count >= 4) {
  139. SelectArrayElement(first++);
  140. CurrentValuesToRasterPos(&pos2);
  141. RenderTriangle(pos1, pos0, pos2);
  142. }
  143. if (count >= 5) {
  144. SelectArrayElement(first++);
  145. CurrentValuesToRasterPos(&pos0);
  146. RenderTriangle(pos1, pos2, pos0);
  147. }
  148. }
  149. void Context :: RenderTriangleStrip(GLsizei count, const GLubyte * indices) {
  150. if (count < 3) {
  151. return;
  152. }
  153. m_Rasterizer->PrepareTriangle();
  154. RasterPos pos0, pos1, pos2;
  155. SelectArrayElement(*indices++);
  156. CurrentValuesToRasterPos(&pos0);
  157. SelectArrayElement(*indices++);
  158. CurrentValuesToRasterPos(&pos1);
  159. count -= 2;
  160. while (count >= 6) {
  161. count -= 6;
  162. SelectArrayElement(*indices++);
  163. CurrentValuesToRasterPos(&pos2);
  164. RenderTriangle(pos0, pos1, pos2);
  165. SelectArrayElement(*indices++);
  166. CurrentValuesToRasterPos(&pos0);
  167. RenderTriangle(pos2, pos1, pos0);
  168. SelectArrayElement(*indices++);
  169. CurrentValuesToRasterPos(&pos1);
  170. RenderTriangle(pos2, pos0, pos1);
  171. SelectArrayElement(*indices++);
  172. CurrentValuesToRasterPos(&pos2);
  173. RenderTriangle(pos1, pos0, pos2);
  174. SelectArrayElement(*indices++);
  175. CurrentValuesToRasterPos(&pos0);
  176. RenderTriangle(pos1, pos2, pos0);
  177. SelectArrayElement(*indices++);
  178. CurrentValuesToRasterPos(&pos1);
  179. RenderTriangle(pos0, pos2, pos1);
  180. }
  181. if (count >= 1) {
  182. SelectArrayElement(*indices++);
  183. CurrentValuesToRasterPos(&pos2);
  184. RenderTriangle(pos0, pos1, pos2);
  185. }
  186. if (count >= 2) {
  187. SelectArrayElement(*indices++);
  188. CurrentValuesToRasterPos(&pos0);
  189. RenderTriangle(pos2, pos1, pos0);
  190. }
  191. if (count >= 3) {
  192. SelectArrayElement(*indices++);
  193. CurrentValuesToRasterPos(&pos1);
  194. RenderTriangle(pos2, pos0, pos1);
  195. }
  196. if (count >= 4) {
  197. SelectArrayElement(*indices++);
  198. CurrentValuesToRasterPos(&pos2);
  199. RenderTriangle(pos1, pos0, pos2);
  200. }
  201. if (count >= 5) {
  202. SelectArrayElement(*indices++);
  203. CurrentValuesToRasterPos(&pos0);
  204. RenderTriangle(pos1, pos2, pos0);
  205. }
  206. }
  207. void Context :: RenderTriangleStrip(GLsizei count, const GLushort * indices) {
  208. if (count < 3) {
  209. return;
  210. }
  211. m_Rasterizer->PrepareTriangle();
  212. RasterPos pos0, pos1, pos2;
  213. SelectArrayElement(*indices++);
  214. CurrentValuesToRasterPos(&pos0);
  215. SelectArrayElement(*indices++);
  216. CurrentValuesToRasterPos(&pos1);
  217. count -= 2;
  218. while (count >= 6) {
  219. count -= 6;
  220. SelectArrayElement(*indices++);
  221. CurrentValuesToRasterPos(&pos2);
  222. RenderTriangle(pos0, pos1, pos2);
  223. SelectArrayElement(*indices++);
  224. CurrentValuesToRasterPos(&pos0);
  225. RenderTriangle(pos2, pos1, pos0);
  226. SelectArrayElement(*indices++);
  227. CurrentValuesToRasterPos(&pos1);
  228. RenderTriangle(pos2, pos0, pos1);
  229. SelectArrayElement(*indices++);
  230. CurrentValuesToRasterPos(&pos2);
  231. RenderTriangle(pos1, pos0, pos2);
  232. SelectArrayElement(*indices++);
  233. CurrentValuesToRasterPos(&pos0);
  234. RenderTriangle(pos1, pos2, pos0);
  235. SelectArrayElement(*indices++);
  236. CurrentValuesToRasterPos(&pos1);
  237. RenderTriangle(pos0, pos2, pos1);
  238. }
  239. if (count >= 1) {
  240. SelectArrayElement(*indices++);
  241. CurrentValuesToRasterPos(&pos2);
  242. RenderTriangle(pos0, pos1, pos2);
  243. }
  244. if (count >= 2) {
  245. SelectArrayElement(*indices++);
  246. CurrentValuesToRasterPos(&pos0);
  247. RenderTriangle(pos2, pos1, pos0);
  248. }
  249. if (count >= 3) {
  250. SelectArrayElement(*indices++);
  251. CurrentValuesToRasterPos(&pos1);
  252. RenderTriangle(pos2, pos0, pos1);
  253. }
  254. if (count >= 4) {
  255. SelectArrayElement(*indices++);
  256. CurrentValuesToRasterPos(&pos2);
  257. RenderTriangle(pos1, pos0, pos2);
  258. }
  259. if (count >= 5) {
  260. SelectArrayElement(*indices++);
  261. CurrentValuesToRasterPos(&pos0);
  262. RenderTriangle(pos1, pos2, pos0);
  263. }
  264. }
  265. // --------------------------------------------------------------------------
  266. // Triangle Fans
  267. // --------------------------------------------------------------------------
  268. void Context :: RenderTriangleFan(GLint first, GLsizei count) {
  269. if (count < 3) {
  270. return;
  271. }
  272. m_Rasterizer->PrepareTriangle();
  273. RasterPos pos0, pos1, pos2;
  274. SelectArrayElement(first++);
  275. CurrentValuesToRasterPos(&pos0);
  276. SelectArrayElement(first++);
  277. CurrentValuesToRasterPos(&pos1);
  278. count -= 2;
  279. while (count >= 2) {
  280. count -= 2;
  281. SelectArrayElement(first++);
  282. CurrentValuesToRasterPos(&pos2);
  283. RenderTriangle(pos0, pos1, pos2);
  284. SelectArrayElement(first++);
  285. CurrentValuesToRasterPos(&pos1);
  286. RenderTriangle(pos0, pos2, pos1);
  287. }
  288. if (count >= 1) {
  289. SelectArrayElement(first++);
  290. CurrentValuesToRasterPos(&pos2);
  291. RenderTriangle(pos0, pos1, pos2);
  292. }
  293. }
  294. void Context :: RenderTriangleFan(GLsizei count, const GLubyte * indices) {
  295. if (count < 3) {
  296. return;
  297. }
  298. m_Rasterizer->PrepareTriangle();
  299. RasterPos pos0, pos1, pos2;
  300. SelectArrayElement(*indices++);
  301. CurrentValuesToRasterPos(&pos0);
  302. SelectArrayElement(*indices++);
  303. CurrentValuesToRasterPos(&pos1);
  304. count -= 2;
  305. while (count >= 2) {
  306. count -= 2;
  307. SelectArrayElement(*indices++);
  308. CurrentValuesToRasterPos(&pos2);
  309. RenderTriangle(pos0, pos1, pos2);
  310. SelectArrayElement(*indices++);
  311. CurrentValuesToRasterPos(&pos1);
  312. RenderTriangle(pos0, pos2, pos1);
  313. }
  314. if (count >= 1) {
  315. SelectArrayElement(*indices++);
  316. CurrentValuesToRasterPos(&pos2);
  317. RenderTriangle(pos0, pos1, pos2);
  318. }
  319. }
  320. void Context :: RenderTriangleFan(GLsizei count, const GLushort * indices) {
  321. if (count < 3) {
  322. return;
  323. }
  324. m_Rasterizer->PrepareTriangle();
  325. RasterPos pos0, pos1, pos2;
  326. SelectArrayElement(*indices++);
  327. CurrentValuesToRasterPos(&pos0);
  328. SelectArrayElement(*indices++);
  329. CurrentValuesToRasterPos(&pos1);
  330. count -= 2;
  331. while (count >= 2) {
  332. count -= 2;
  333. SelectArrayElement(*indices++);
  334. CurrentValuesToRasterPos(&pos2);
  335. RenderTriangle(pos0, pos1, pos2);
  336. SelectArrayElement(*indices++);
  337. CurrentValuesToRasterPos(&pos1);
  338. RenderTriangle(pos0, pos2, pos1);
  339. }
  340. if (count >= 1) {
  341. SelectArrayElement(*indices++);
  342. CurrentValuesToRasterPos(&pos2);
  343. RenderTriangle(pos0, pos1, pos2);
  344. }
  345. }
  346. namespace {
  347. inline EGL_Fixed Interpolate(EGL_Fixed x0, EGL_Fixed x1, EGL_Fixed num, EGL_Fixed denom) {
  348. return static_cast<EGL_Fixed>(x1 + (((I64)(x0-x1))*num)/denom);
  349. }
  350. inline void Interpolate(RasterPos& result, const RasterPos& dst, const RasterPos& src, EGL_Fixed num, EGL_Fixed denom) {
  351. result.m_ClipCoords.setX(Interpolate(dst.m_ClipCoords.x(), src.m_ClipCoords.x(), num, denom));
  352. result.m_ClipCoords.setY(Interpolate(dst.m_ClipCoords.y(), src.m_ClipCoords.y(), num, denom));
  353. result.m_ClipCoords.setZ(Interpolate(dst.m_ClipCoords.z(), src.m_ClipCoords.z(), num, denom));
  354. result.m_ClipCoords.setW(Interpolate(dst.m_ClipCoords.w(), src.m_ClipCoords.w(), num, denom));
  355. result.m_Color.r = Interpolate(dst.m_Color.r, src.m_Color.r, num, denom);
  356. result.m_Color.g = Interpolate(dst.m_Color.g, src.m_Color.g, num, denom);
  357. result.m_Color.b = Interpolate(dst.m_Color.b, src.m_Color.b, num, denom);
  358. result.m_Color.a = Interpolate(dst.m_Color.a, src.m_Color.a, num, denom);
  359. for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
  360. result.m_TextureCoords[index].tu = Interpolate(dst.m_TextureCoords[index].tu, src.m_TextureCoords[index].tu, num, denom);
  361. result.m_TextureCoords[index].tv = Interpolate(dst.m_TextureCoords[index].tv, src.m_TextureCoords[index].tv, num, denom);
  362. }
  363. result.m_FogDensity = Interpolate(dst.m_FogDensity, src.m_FogDensity, num, denom);
  364. }
  365. inline void InterpolateWithEye(RasterPos& result, const RasterPos& dst, const RasterPos& src, EGL_Fixed num, EGL_Fixed denom) {
  366. result.m_EyeCoords.setX(Interpolate(dst.m_EyeCoords.x(), src.m_EyeCoords.x(), num, denom));
  367. result.m_EyeCoords.setY(Interpolate(dst.m_EyeCoords.y(), src.m_EyeCoords.y(), num, denom));
  368. result.m_EyeCoords.setZ(Interpolate(dst.m_EyeCoords.z(), src.m_EyeCoords.z(), num, denom));
  369. result.m_EyeCoords.setW(Interpolate(dst.m_EyeCoords.w(), src.m_EyeCoords.w(), num, denom));
  370. Interpolate(result, dst, src, num, denom);
  371. }
  372. inline size_t ClipXLow(RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
  373. # define SET_COORDINATE setX
  374. # define COORDINATE x()
  375. # include "TriangleClipperLow.inc"
  376. # undef COORDINATE
  377. # undef SET_COORDINATE
  378. }
  379. inline size_t ClipXHigh(RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
  380. # define SET_COORDINATE setX
  381. # define COORDINATE x()
  382. # include "TriangleClipperHigh.inc"
  383. # undef COORDINATE
  384. # undef SET_COORDINATE
  385. }
  386. inline size_t ClipYLow(RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
  387. # define SET_COORDINATE setY
  388. # define COORDINATE y()
  389. # include "TriangleClipperLow.inc"
  390. # undef COORDINATE
  391. # undef SET_COORDINATE
  392. }
  393. inline size_t ClipYHigh(RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
  394. # define SET_COORDINATE setY
  395. # define COORDINATE y()
  396. # include "TriangleClipperHigh.inc"
  397. # undef COORDINATE
  398. # undef SET_COORDINATE
  399. }
  400. inline size_t ClipZLow(RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
  401. # define SET_COORDINATE setZ
  402. # define COORDINATE z()
  403. # include "TriangleClipperLow.inc"
  404. # undef COORDINATE
  405. # undef SET_COORDINATE
  406. }
  407. inline size_t ClipZHigh(RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
  408. # define SET_COORDINATE setZ
  409. # define COORDINATE z()
  410. # include "TriangleClipperHigh.inc"
  411. # undef COORDINATE
  412. # undef SET_COORDINATE
  413. }
  414. size_t ClipUser(const Vec4D& plane, RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
  415. if (inputCount < 3) {
  416. return 0;
  417. }
  418. RasterPos * previous = input[inputCount - 1];
  419. RasterPos * current;
  420. int resultCount = 0;
  421. for (size_t index = 0; index < inputCount; ++index) {
  422. current = input[index];
  423. EGL_Fixed c = current->m_EyeCoords * plane;
  424. EGL_Fixed p = previous->m_EyeCoords * plane;
  425. if (c >= 0) {
  426. if (p >= 0) {
  427. // line segment between previous and current is fully contained in cube
  428. output[resultCount++] = current;
  429. } else {
  430. // line segment between previous and current is intersected;
  431. // create vertex at intersection, then add current
  432. RasterPos & newVertex = *nextTemporary++;
  433. output[resultCount++] = &newVertex;
  434. InterpolateWithEye(newVertex, *current, *previous, p, p - c);
  435. output[resultCount++] = current;
  436. }
  437. } else {
  438. if (p >= 0) {
  439. // line segment between previous and current is intersected;
  440. // create vertex at intersection and add it
  441. RasterPos & newVertex = *nextTemporary++;
  442. output[resultCount++] = &newVertex;
  443. InterpolateWithEye(newVertex, *current, *previous, p, p - c);
  444. }
  445. }
  446. previous = current;
  447. }
  448. return resultCount;
  449. }
  450. inline I64 MulLong(EGL_Fixed a, EGL_Fixed b) {
  451. return (((I64) a * (I64) b) >> EGL_PRECISION);
  452. }
  453. inline EGL_Fixed Round(EGL_Fixed value) {
  454. return (value + 8) >> 4;
  455. }
  456. }
  457. void Context :: FrontFace(GLenum mode) {
  458. switch (mode) {
  459. case GL_CW:
  460. m_ReverseFaceOrientation = true;
  461. break;
  462. case GL_CCW:
  463. m_ReverseFaceOrientation = false;
  464. break;
  465. default:
  466. RecordError(GL_INVALID_ENUM);
  467. break;
  468. }
  469. }
  470. void Context :: CullFace(GLenum mode) {
  471. switch (mode) {
  472. case GL_FRONT:
  473. m_CullMode = CullModeFront;
  474. break;
  475. case GL_BACK:
  476. m_CullMode = CullModeBack;
  477. break;
  478. case GL_FRONT_AND_BACK:
  479. m_CullMode = CullModeBackAndFront;
  480. break;
  481. default:
  482. RecordError(GL_INVALID_ENUM);
  483. break;
  484. }
  485. }
  486. inline bool Context :: IsCulled(RasterPos& a, RasterPos& b, RasterPos& c) {
  487. EGL_Fixed x0 = a.m_ClipCoords.w();
  488. EGL_Fixed x1 = a.m_ClipCoords.x();
  489. EGL_Fixed x2 = a.m_ClipCoords.y();
  490. EGL_Fixed y0 = b.m_ClipCoords.w();
  491. EGL_Fixed y1 = b.m_ClipCoords.x();
  492. EGL_Fixed y2 = b.m_ClipCoords.y();
  493. EGL_Fixed z0 = c.m_ClipCoords.w();
  494. EGL_Fixed z1 = c.m_ClipCoords.x();
  495. EGL_Fixed z2 = c.m_ClipCoords.y();
  496. I64 sign,t;
  497. if (((x0 & 0xff000000) == 0 || (x0 & 0xff000000) == 0xff000000) &&
  498. ((y0 & 0xff000000) == 0 || (y0 & 0xff000000) == 0xff000000) &&
  499. ((z0 & 0xff000000) == 0 || (z0 & 0xff000000) == 0xff000000)) {
  500. sign=Round(x0);
  501. sign*=MulLong(Round(y1), Round(z2)) - MulLong(Round(z1), Round(y2));
  502. t=Round(y0);
  503. t*=MulLong(Round(x1), Round(z2)) - MulLong(Round(z1), Round(x2));
  504. sign-=t;
  505. t=Round(z0);
  506. t*=MulLong(Round(x1), Round(y2)) - MulLong(Round(y1), Round(x2));
  507. sign+=t;
  508. } else {
  509. sign=Round(x0>>6);
  510. sign*=MulLong(Round(y1), Round(z2)) - MulLong(Round(z1), Round(y2));
  511. t=Round(y0>>6);
  512. t*=MulLong(Round(x1), Round(z2)) - MulLong(Round(z1), Round(x2));
  513. sign-=t;
  514. t=Round(z0>>6);
  515. t*=MulLong(Round(x1), Round(y2)) - MulLong(Round(y1), Round(x2));
  516. sign+=t;
  517. }
  518. switch (m_CullMode) {
  519. case CullModeBack:
  520. return (sign < 0) ^ m_ReverseFaceOrientation;
  521. case CullModeFront:
  522. return (sign > 0) ^ m_ReverseFaceOrientation;
  523. default:
  524. case CullModeBackAndFront:
  525. return true;
  526. }
  527. }
  528. void Context :: RenderTriangle(RasterPos& a, RasterPos& b, RasterPos& c) {
  529. bool culled = IsCulled(a, b, c);
  530. if (m_CullFaceEnabled) {
  531. if (culled) {
  532. return;
  533. }
  534. }
  535. if (m_RasterizerState.GetShadeModel() == RasterizerState::ShadeModelSmooth) {
  536. if (m_TwoSidedLightning && culled) {
  537. a.m_Color = a.m_BackColor;
  538. b.m_Color = b.m_BackColor;
  539. c.m_Color = c.m_BackColor;
  540. } else {
  541. a.m_Color = a.m_FrontColor;
  542. b.m_Color = b.m_FrontColor;
  543. c.m_Color = c.m_FrontColor;
  544. }
  545. } else {
  546. if (m_TwoSidedLightning && culled) {
  547. a.m_Color = b.m_Color = c.m_Color = c.m_BackColor;
  548. } else {
  549. a.m_Color = b.m_Color = c.m_Color = c.m_FrontColor;
  550. }
  551. }
  552. RasterPos * array1[16];
  553. array1[0] = &a;
  554. array1[1] = &b;
  555. array1[2] = &c;
  556. RasterPos * array2[16];
  557. RasterPos * tempVertices = m_Temporary;
  558. size_t numVertices = 3;
  559. if (m_ClipPlaneEnabled) {
  560. for (size_t index = 0, mask = 1; index < NUM_CLIP_PLANES; ++index, mask <<= 1) {
  561. if (m_ClipPlaneEnabled & mask) {
  562. numVertices = ClipUser(m_ClipPlanes[index], array1, numVertices, array2, tempVertices);
  563. if (!numVertices) {
  564. return;
  565. }
  566. for (size_t idx = 0; idx < numVertices; ++idx) {
  567. array1[idx] = array2[idx];
  568. }
  569. }
  570. }
  571. }
  572. numVertices = ClipXLow(array1, numVertices, array2, tempVertices);
  573. numVertices = ClipXHigh(array2, numVertices, array1, tempVertices);
  574. numVertices = ClipYLow(array1, numVertices, array2, tempVertices);
  575. numVertices = ClipYHigh(array2, numVertices, array1, tempVertices);
  576. numVertices = ClipZLow(array1, numVertices, array2, tempVertices);
  577. numVertices = ClipZHigh(array2, numVertices, array1, tempVertices);
  578. if (numVertices >= 3) {
  579. ClipCoordsToWindowCoords(*array1[0]);
  580. ClipCoordsToWindowCoords(*array1[1]);
  581. for (size_t index = 2; index < numVertices; ++index) {
  582. ClipCoordsToWindowCoords(*array1[index]);
  583. m_Rasterizer->RasterTriangle(*array1[0], *array1[index - 1], *array1[index]);
  584. }
  585. }
  586. }