PageRenderTime 1873ms CodeModel.GetById 211ms app.highlight 1486ms RepoModel.GetById 169ms app.codeStats 0ms

/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
 39
 40#include "stdafx.h"
 41#include "Context.h"
 42#include "fixed.h"
 43#include "Rasterizer.h"
 44
 45using namespace EGL;
 46
 47
 48// --------------------------------------------------------------------------
 49// Triangles
 50// --------------------------------------------------------------------------
 51
 52
 53void Context :: RenderTriangles(GLint first, GLsizei count) {
 54
 55	m_Rasterizer->PrepareTriangle();
 56
 57	while (count >= 3) {
 58		count -= 3;
 59
 60		RasterPos pos0, pos1, pos2;
 61		SelectArrayElement(first++);
 62		CurrentValuesToRasterPos(&pos0);
 63		SelectArrayElement(first++);
 64		CurrentValuesToRasterPos(&pos1);
 65		SelectArrayElement(first++);
 66		CurrentValuesToRasterPos(&pos2);
 67
 68		RenderTriangle(pos0, pos1, pos2);
 69	}
 70}
 71
 72
 73void Context :: RenderTriangles(GLsizei count, const GLubyte * indices) {
 74
 75	m_Rasterizer->PrepareTriangle();
 76
 77	while (count >= 3) {
 78		count -= 3;
 79
 80		RasterPos pos0, pos1, pos2;
 81		SelectArrayElement(*indices++);
 82		CurrentValuesToRasterPos(&pos0);
 83		SelectArrayElement(*indices++);
 84		CurrentValuesToRasterPos(&pos1);
 85		SelectArrayElement(*indices++);
 86		CurrentValuesToRasterPos(&pos2);
 87
 88		RenderTriangle(pos0, pos1, pos2);
 89	}
 90}
 91
 92
 93void Context :: RenderTriangles(GLsizei count, const GLushort * indices) {
 94
 95	m_Rasterizer->PrepareTriangle();
 96
 97	while (count >= 3) {
 98		count -= 3;
 99
100		RasterPos pos0, pos1, pos2;
101		SelectArrayElement(*indices++);
102		CurrentValuesToRasterPos(&pos0);
103		SelectArrayElement(*indices++);
104		CurrentValuesToRasterPos(&pos1);
105		SelectArrayElement(*indices++);
106		CurrentValuesToRasterPos(&pos2);
107
108		RenderTriangle(pos0, pos1, pos2);
109	}
110}
111
112
113// --------------------------------------------------------------------------
114// Triangle Strips
115// --------------------------------------------------------------------------
116
117
118void Context :: RenderTriangleStrip(GLint first, GLsizei count) {
119
120	if (count < 3) {
121		return;
122	}
123
124	m_Rasterizer->PrepareTriangle();
125
126	RasterPos pos0, pos1, pos2;
127
128	SelectArrayElement(first++);
129	CurrentValuesToRasterPos(&pos0);
130	SelectArrayElement(first++);
131	CurrentValuesToRasterPos(&pos1);
132
133	count -= 2;
134
135	while (count >= 6) {
136		count -= 6;
137
138		SelectArrayElement(first++);
139		CurrentValuesToRasterPos(&pos2);
140		RenderTriangle(pos0, pos1, pos2);
141
142		SelectArrayElement(first++);
143		CurrentValuesToRasterPos(&pos0);
144		RenderTriangle(pos2, pos1, pos0);
145
146		SelectArrayElement(first++);
147		CurrentValuesToRasterPos(&pos1);
148		RenderTriangle(pos2, pos0, pos1);
149
150		SelectArrayElement(first++);
151		CurrentValuesToRasterPos(&pos2);
152		RenderTriangle(pos1, pos0, pos2);
153
154		SelectArrayElement(first++);
155		CurrentValuesToRasterPos(&pos0);
156		RenderTriangle(pos1, pos2, pos0);
157
158		SelectArrayElement(first++);
159		CurrentValuesToRasterPos(&pos1);
160		RenderTriangle(pos0, pos2, pos1);
161	}
162
163	if (count >= 1) {
164		SelectArrayElement(first++);
165		CurrentValuesToRasterPos(&pos2);
166		RenderTriangle(pos0, pos1, pos2);
167	}
168
169	if (count >= 2) {
170		SelectArrayElement(first++);
171		CurrentValuesToRasterPos(&pos0);
172		RenderTriangle(pos2, pos1, pos0);
173	}
174
175	if (count >= 3) {
176		SelectArrayElement(first++);
177		CurrentValuesToRasterPos(&pos1);
178		RenderTriangle(pos2, pos0, pos1);
179	}
180
181	if (count >= 4) {
182		SelectArrayElement(first++);
183		CurrentValuesToRasterPos(&pos2);
184		RenderTriangle(pos1, pos0, pos2);
185	}
186
187	if (count >= 5) {
188		SelectArrayElement(first++);
189		CurrentValuesToRasterPos(&pos0);
190		RenderTriangle(pos1, pos2, pos0);
191	}
192
193}
194
195
196void Context :: RenderTriangleStrip(GLsizei count, const GLubyte * indices) {
197
198	if (count < 3) {
199		return;
200	}
201
202	m_Rasterizer->PrepareTriangle();
203
204	RasterPos pos0, pos1, pos2;
205
206	SelectArrayElement(*indices++);
207	CurrentValuesToRasterPos(&pos0);
208	SelectArrayElement(*indices++);
209	CurrentValuesToRasterPos(&pos1);
210
211	count -= 2;
212
213	while (count >= 6) {
214		count -= 6;
215
216		SelectArrayElement(*indices++);
217		CurrentValuesToRasterPos(&pos2);
218		RenderTriangle(pos0, pos1, pos2);
219
220		SelectArrayElement(*indices++);
221		CurrentValuesToRasterPos(&pos0);
222		RenderTriangle(pos2, pos1, pos0);
223
224		SelectArrayElement(*indices++);
225		CurrentValuesToRasterPos(&pos1);
226		RenderTriangle(pos2, pos0, pos1);
227
228		SelectArrayElement(*indices++);
229		CurrentValuesToRasterPos(&pos2);
230		RenderTriangle(pos1, pos0, pos2);
231
232		SelectArrayElement(*indices++);
233		CurrentValuesToRasterPos(&pos0);
234		RenderTriangle(pos1, pos2, pos0);
235
236		SelectArrayElement(*indices++);
237		CurrentValuesToRasterPos(&pos1);
238		RenderTriangle(pos0, pos2, pos1);
239	}
240
241	if (count >= 1) {
242		SelectArrayElement(*indices++);
243		CurrentValuesToRasterPos(&pos2);
244		RenderTriangle(pos0, pos1, pos2);
245	}
246
247	if (count >= 2) {
248		SelectArrayElement(*indices++);
249		CurrentValuesToRasterPos(&pos0);
250		RenderTriangle(pos2, pos1, pos0);
251	}
252
253	if (count >= 3) {
254		SelectArrayElement(*indices++);
255		CurrentValuesToRasterPos(&pos1);
256		RenderTriangle(pos2, pos0, pos1);
257	}
258
259	if (count >= 4) {
260		SelectArrayElement(*indices++);
261		CurrentValuesToRasterPos(&pos2);
262		RenderTriangle(pos1, pos0, pos2);
263	}
264
265	if (count >= 5) {
266		SelectArrayElement(*indices++);
267		CurrentValuesToRasterPos(&pos0);
268		RenderTriangle(pos1, pos2, pos0);
269	}
270
271}
272
273
274void Context :: RenderTriangleStrip(GLsizei count, const GLushort * indices) {
275
276	if (count < 3) {
277		return;
278	}
279
280	m_Rasterizer->PrepareTriangle();
281
282	RasterPos pos0, pos1, pos2;
283
284	SelectArrayElement(*indices++);
285	CurrentValuesToRasterPos(&pos0);
286	SelectArrayElement(*indices++);
287	CurrentValuesToRasterPos(&pos1);
288
289	count -= 2;
290
291	while (count >= 6) {
292		count -= 6;
293
294		SelectArrayElement(*indices++);
295		CurrentValuesToRasterPos(&pos2);
296		RenderTriangle(pos0, pos1, pos2);
297
298		SelectArrayElement(*indices++);
299		CurrentValuesToRasterPos(&pos0);
300		RenderTriangle(pos2, pos1, pos0);
301
302		SelectArrayElement(*indices++);
303		CurrentValuesToRasterPos(&pos1);
304		RenderTriangle(pos2, pos0, pos1);
305
306		SelectArrayElement(*indices++);
307		CurrentValuesToRasterPos(&pos2);
308		RenderTriangle(pos1, pos0, pos2);
309
310		SelectArrayElement(*indices++);
311		CurrentValuesToRasterPos(&pos0);
312		RenderTriangle(pos1, pos2, pos0);
313
314		SelectArrayElement(*indices++);
315		CurrentValuesToRasterPos(&pos1);
316		RenderTriangle(pos0, pos2, pos1);
317	}
318
319	if (count >= 1) {
320		SelectArrayElement(*indices++);
321		CurrentValuesToRasterPos(&pos2);
322		RenderTriangle(pos0, pos1, pos2);
323	}
324
325	if (count >= 2) {
326		SelectArrayElement(*indices++);
327		CurrentValuesToRasterPos(&pos0);
328		RenderTriangle(pos2, pos1, pos0);
329	}
330
331	if (count >= 3) {
332		SelectArrayElement(*indices++);
333		CurrentValuesToRasterPos(&pos1);
334		RenderTriangle(pos2, pos0, pos1);
335	}
336
337	if (count >= 4) {
338		SelectArrayElement(*indices++);
339		CurrentValuesToRasterPos(&pos2);
340		RenderTriangle(pos1, pos0, pos2);
341	}
342
343	if (count >= 5) {
344		SelectArrayElement(*indices++);
345		CurrentValuesToRasterPos(&pos0);
346		RenderTriangle(pos1, pos2, pos0);
347	}
348
349}
350
351
352// --------------------------------------------------------------------------
353// Triangle Fans
354// --------------------------------------------------------------------------
355
356
357void Context :: RenderTriangleFan(GLint first, GLsizei count) {
358
359	if (count < 3) {
360		return;
361	}
362
363	m_Rasterizer->PrepareTriangle();
364
365	RasterPos pos0, pos1, pos2;
366
367	SelectArrayElement(first++);
368	CurrentValuesToRasterPos(&pos0);
369	SelectArrayElement(first++);
370	CurrentValuesToRasterPos(&pos1);
371
372	count -= 2;
373
374	while (count >= 2) {
375		count -= 2;
376
377		SelectArrayElement(first++);
378		CurrentValuesToRasterPos(&pos2);
379		RenderTriangle(pos0, pos1, pos2);
380
381		SelectArrayElement(first++);
382		CurrentValuesToRasterPos(&pos1);
383		RenderTriangle(pos0, pos2, pos1);
384	}
385
386	if (count >= 1) {
387		SelectArrayElement(first++);
388		CurrentValuesToRasterPos(&pos2);
389		RenderTriangle(pos0, pos1, pos2);
390	}
391}
392
393
394void Context :: RenderTriangleFan(GLsizei count, const GLubyte * indices) {
395
396	if (count < 3) {
397		return;
398	}
399
400	m_Rasterizer->PrepareTriangle();
401
402	RasterPos pos0, pos1, pos2;
403
404	SelectArrayElement(*indices++);
405	CurrentValuesToRasterPos(&pos0);
406	SelectArrayElement(*indices++);
407	CurrentValuesToRasterPos(&pos1);
408
409	count -= 2;
410
411	while (count >= 2) {
412		count -= 2;
413
414		SelectArrayElement(*indices++);
415		CurrentValuesToRasterPos(&pos2);
416		RenderTriangle(pos0, pos1, pos2);
417
418		SelectArrayElement(*indices++);
419		CurrentValuesToRasterPos(&pos1);
420		RenderTriangle(pos0, pos2, pos1);
421	}
422
423	if (count >= 1) {
424		SelectArrayElement(*indices++);
425		CurrentValuesToRasterPos(&pos2);
426		RenderTriangle(pos0, pos1, pos2);
427	}
428}
429
430
431void Context :: RenderTriangleFan(GLsizei count, const GLushort * indices) {
432
433	if (count < 3) {
434		return;
435	}
436
437	m_Rasterizer->PrepareTriangle();
438
439	RasterPos pos0, pos1, pos2;
440
441	SelectArrayElement(*indices++);
442	CurrentValuesToRasterPos(&pos0);
443	SelectArrayElement(*indices++);
444	CurrentValuesToRasterPos(&pos1);
445
446	count -= 2;
447
448	while (count >= 2) {
449		count -= 2;
450
451		SelectArrayElement(*indices++);
452		CurrentValuesToRasterPos(&pos2);
453		RenderTriangle(pos0, pos1, pos2);
454
455		SelectArrayElement(*indices++);
456		CurrentValuesToRasterPos(&pos1);
457		RenderTriangle(pos0, pos2, pos1);
458	}
459
460	if (count >= 1) {
461		SelectArrayElement(*indices++);
462		CurrentValuesToRasterPos(&pos2);
463		RenderTriangle(pos0, pos1, pos2);
464	}
465}
466
467
468namespace {
469
470	inline EGL_Fixed Interpolate(EGL_Fixed x0, EGL_Fixed x1, EGL_Fixed num, EGL_Fixed denom) {
471		return static_cast<EGL_Fixed>(x1 + (((I64)(x0-x1))*num)/denom);
472	}
473
474	inline void Interpolate(RasterPos& result, const RasterPos& dst, const RasterPos& src, EGL_Fixed num, EGL_Fixed denom) {
475		result.m_ClipCoords.setX(Interpolate(dst.m_ClipCoords.x(), src.m_ClipCoords.x(), num, denom));
476		result.m_ClipCoords.setY(Interpolate(dst.m_ClipCoords.y(), src.m_ClipCoords.y(), num, denom));
477		result.m_ClipCoords.setZ(Interpolate(dst.m_ClipCoords.z(), src.m_ClipCoords.z(), num, denom));
478		result.m_ClipCoords.setW(Interpolate(dst.m_ClipCoords.w(), src.m_ClipCoords.w(), num, denom));
479		result.m_Color.r = Interpolate(dst.m_Color.r, src.m_Color.r, num, denom);
480		result.m_Color.g = Interpolate(dst.m_Color.g, src.m_Color.g, num, denom);
481		result.m_Color.b = Interpolate(dst.m_Color.b, src.m_Color.b, num, denom);
482		result.m_Color.a = Interpolate(dst.m_Color.a, src.m_Color.a, num, denom);
483
484		for (size_t index = 0; index < EGL_NUM_TEXTURE_UNITS; ++index) {
485			result.m_TextureCoords[index].tu = Interpolate(dst.m_TextureCoords[index].tu, src.m_TextureCoords[index].tu, num, denom);
486			result.m_TextureCoords[index].tv = Interpolate(dst.m_TextureCoords[index].tv, src.m_TextureCoords[index].tv, num, denom);
487		}
488
489		result.m_FogDensity = Interpolate(dst.m_FogDensity, src.m_FogDensity, num, denom);
490	}
491
492	inline void InterpolateWithEye(RasterPos& result, const RasterPos& dst, const RasterPos& src, EGL_Fixed num, EGL_Fixed denom) {
493		result.m_EyeCoords.setX(Interpolate(dst.m_EyeCoords.x(), src.m_EyeCoords.x(), num, denom));
494		result.m_EyeCoords.setY(Interpolate(dst.m_EyeCoords.y(), src.m_EyeCoords.y(), num, denom));
495		result.m_EyeCoords.setZ(Interpolate(dst.m_EyeCoords.z(), src.m_EyeCoords.z(), num, denom));
496		result.m_EyeCoords.setW(Interpolate(dst.m_EyeCoords.w(), src.m_EyeCoords.w(), num, denom));
497		Interpolate(result, dst, src, num, denom);
498	}
499
500	inline size_t ClipXLow(RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
501
502#		define SET_COORDINATE setX
503#		define COORDINATE x()
504#		include "TriangleClipperLow.inc"
505#		undef COORDINATE
506#		undef SET_COORDINATE
507
508	}
509
510	inline size_t ClipXHigh(RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
511
512#		define SET_COORDINATE setX
513#		define COORDINATE x()
514#		include "TriangleClipperHigh.inc"
515#		undef COORDINATE
516#		undef SET_COORDINATE
517
518	}
519
520	inline size_t ClipYLow(RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
521
522#		define SET_COORDINATE setY
523#		define COORDINATE y()
524#		include "TriangleClipperLow.inc"
525#		undef COORDINATE
526#		undef SET_COORDINATE
527
528	}
529
530	inline size_t ClipYHigh(RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
531
532#		define SET_COORDINATE setY
533#		define COORDINATE y()
534#		include "TriangleClipperHigh.inc"
535#		undef COORDINATE
536#		undef SET_COORDINATE
537
538	}
539
540	inline size_t ClipZLow(RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
541
542#		define SET_COORDINATE setZ
543#		define COORDINATE z()
544#		include "TriangleClipperLow.inc"
545#		undef COORDINATE
546#		undef SET_COORDINATE
547
548	}
549
550	inline size_t ClipZHigh(RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
551
552#		define SET_COORDINATE setZ
553#		define COORDINATE z()
554#		include "TriangleClipperHigh.inc"
555#		undef COORDINATE
556#		undef SET_COORDINATE
557
558	}
559
560
561	size_t ClipUser(const Vec4D& plane, RasterPos * input[], size_t inputCount, RasterPos * output[], RasterPos *& nextTemporary) {
562		if (inputCount < 3) {
563			return 0;
564		}
565
566		RasterPos * previous = input[inputCount - 1];
567		RasterPos * current;
568		int resultCount = 0;
569
570		for (size_t index = 0; index < inputCount; ++index) {
571
572			current = input[index];
573
574			EGL_Fixed c = current->m_EyeCoords * plane;
575			EGL_Fixed p = previous->m_EyeCoords * plane;
576
577			if (c >= 0) {
578				if (p >= 0) {
579					// line segment between previous and current is fully contained in cube
580					output[resultCount++] = current;
581				} else {
582					// line segment between previous and current is intersected;
583					// create vertex at intersection, then add current
584					RasterPos & newVertex = *nextTemporary++;
585					output[resultCount++] = &newVertex;
586										
587					InterpolateWithEye(newVertex, *current, *previous, p, p - c); 
588					output[resultCount++] = current;
589				}
590			} else {
591				if (p >= 0) {
592					// line segment between previous and current is intersected;
593					// create vertex at intersection and add it
594					RasterPos & newVertex = *nextTemporary++;
595					output[resultCount++] = &newVertex;
596					
597					InterpolateWithEye(newVertex, *current, *previous, p, p - c); 
598				}
599			}
600
601			previous = current;
602		}
603
604		return resultCount;
605	}
606
607
608	inline I64 MulLong(EGL_Fixed a, EGL_Fixed b) {
609		return (((I64) a * (I64) b)  >> EGL_PRECISION);
610	}
611
612	inline EGL_Fixed Round(EGL_Fixed value) {
613		return (value + 8) >> 4;
614	}
615
616}
617
618
619void Context :: FrontFace(GLenum mode) { 
620
621	switch (mode) {
622		case GL_CW:
623			m_ReverseFaceOrientation = true;
624			break;
625
626		case GL_CCW:
627			m_ReverseFaceOrientation = false;
628			break;
629
630		default:
631			RecordError(GL_INVALID_ENUM);
632			break;
633	}
634}
635
636void Context :: CullFace(GLenum mode) { 
637
638	switch (mode) { 
639		case GL_FRONT:
640			m_CullMode = CullModeFront;
641			break;
642
643		case GL_BACK:
644			m_CullMode = CullModeBack;
645			break;
646
647		case GL_FRONT_AND_BACK:
648			m_CullMode = CullModeBackAndFront;
649			break;
650
651		default:
652			RecordError(GL_INVALID_ENUM);
653			break;
654	}
655}
656
657
658inline bool Context :: IsCulled(RasterPos& a, RasterPos& b, RasterPos& c) {
659
660	EGL_Fixed x0 = a.m_ClipCoords.w();
661	EGL_Fixed x1 = a.m_ClipCoords.x();
662	EGL_Fixed x2 = a.m_ClipCoords.y();
663								
664	EGL_Fixed y0 = b.m_ClipCoords.w();
665	EGL_Fixed y1 = b.m_ClipCoords.x();
666	EGL_Fixed y2 = b.m_ClipCoords.y();
667								
668	EGL_Fixed z0 = c.m_ClipCoords.w();
669	EGL_Fixed z1 = c.m_ClipCoords.x();
670	EGL_Fixed z2 = c.m_ClipCoords.y();
671
672	I64 sign,t;
673	
674	if (((x0 & 0xff000000) == 0 || (x0 & 0xff000000) == 0xff000000) &&
675		((y0 & 0xff000000) == 0 || (y0 & 0xff000000) == 0xff000000) &&
676		((z0 & 0xff000000) == 0 || (z0 & 0xff000000) == 0xff000000)) {
677         sign=Round(x0);
678         sign*=MulLong(Round(y1), Round(z2)) - MulLong(Round(z1), Round(y2));
679         t=Round(y0);
680         t*=MulLong(Round(x1), Round(z2)) - MulLong(Round(z1), Round(x2));
681         sign-=t;
682         t=Round(z0);
683         t*=MulLong(Round(x1), Round(y2)) - MulLong(Round(y1), Round(x2));
684         sign+=t;
685	} else {
686         sign=Round(x0>>6);
687         sign*=MulLong(Round(y1), Round(z2)) - MulLong(Round(z1), Round(y2));
688         t=Round(y0>>6);
689         t*=MulLong(Round(x1), Round(z2)) - MulLong(Round(z1), Round(x2));
690         sign-=t;
691         t=Round(z0>>6);
692         t*=MulLong(Round(x1), Round(y2)) - MulLong(Round(y1), Round(x2));
693         sign+=t;
694	}
695
696	switch (m_CullMode) {
697		case CullModeBack:
698			return (sign < 0) ^ m_ReverseFaceOrientation;
699
700		case CullModeFront:
701			return (sign > 0) ^ m_ReverseFaceOrientation;
702
703		default:
704		case CullModeBackAndFront:
705			return true;
706	}
707}
708
709
710void Context :: RenderTriangle(RasterPos& a, RasterPos& b, RasterPos& c) {
711
712	bool culled = IsCulled(a, b, c);
713
714	if (m_CullFaceEnabled) {
715		if (culled) {
716			return;
717		}
718	} 
719	
720	if (m_RasterizerState.GetShadeModel() == RasterizerState::ShadeModelSmooth) {
721		if (m_TwoSidedLightning && culled) {
722			a.m_Color = a.m_BackColor;
723			b.m_Color = b.m_BackColor;
724			c.m_Color = c.m_BackColor;
725		} else {
726			a.m_Color = a.m_FrontColor;
727			b.m_Color = b.m_FrontColor;
728			c.m_Color = c.m_FrontColor;
729		}
730	} else {
731		if (m_TwoSidedLightning && culled) {
732			a.m_Color =  b.m_Color = c.m_Color = c.m_BackColor;
733		} else {
734			a.m_Color = b.m_Color = c.m_Color = c.m_FrontColor;
735		}
736	}
737
738	RasterPos * array1[16];
739	array1[0] = &a;
740	array1[1] = &b;
741	array1[2] = &c;
742	RasterPos * array2[16];
743	RasterPos * tempVertices = m_Temporary;
744
745	size_t numVertices = 3;
746
747	if (m_ClipPlaneEnabled) {
748		for (size_t index = 0, mask = 1; index < NUM_CLIP_PLANES; ++index, mask <<= 1) {
749			if (m_ClipPlaneEnabled & mask) {
750				numVertices = ClipUser(m_ClipPlanes[index], array1, numVertices, array2, tempVertices);
751
752				if (!numVertices) {
753					return;
754				}
755
756				for (size_t idx = 0; idx < numVertices; ++idx) {
757					array1[idx] = array2[idx];
758				}
759			}
760		}
761	}
762
763	numVertices = ClipXLow(array1, numVertices, array2, tempVertices);
764	numVertices = ClipXHigh(array2, numVertices, array1, tempVertices);
765	numVertices = ClipYLow(array1, numVertices, array2, tempVertices);
766	numVertices = ClipYHigh(array2, numVertices, array1, tempVertices);
767	numVertices = ClipZLow(array1, numVertices, array2, tempVertices);
768	numVertices = ClipZHigh(array2, numVertices, array1, tempVertices);
769
770	if (numVertices >= 3) {
771		ClipCoordsToWindowCoords(*array1[0]);
772		ClipCoordsToWindowCoords(*array1[1]);
773
774		for (size_t index = 2; index < numVertices; ++index) {
775			ClipCoordsToWindowCoords(*array1[index]);
776			m_Rasterizer->RasterTriangle(*array1[0], *array1[index - 1], *array1[index]);
777		}
778	}
779}
780
781
782