1 #include "TREShapeGroup.h"
2 #include "TREVertexArray.h"
3 #include "TREVertexStore.h"
4 #include "TREModel.h"
5 #include "TREMainModel.h"
6 #include "TREGLExtensions.h"
7 #include <TCFoundation/TCVector.h>
8 #include <TCFoundation/TCMacros.h>
9 #include <TCFoundation/mystring.h>
10 #include <string.h>
11 
12 #ifdef WIN32
13 #if defined(_MSC_VER) && _MSC_VER >= 1400 && defined(_DEBUG)
14 #define new DEBUG_CLIENTBLOCK
15 #endif // _DEBUG
16 #endif // WIN32
17 
18 using namespace TREGLExtensionsNS;
19 
TREShapeGroup(void)20 TREShapeGroup::TREShapeGroup(void)
21 	: m_vertexStore(NULL)
22 	, m_indices(NULL)
23 	, m_controlPointIndices(NULL)
24 	, m_stripCounts(NULL)
25 	, m_multiDrawIndices(NULL)
26 	, m_shapesPresent(0)
27 	, m_mainModel(NULL)
28 	, m_bfc(false)
29 	, m_transferIndices(NULL)
30 {
31 }
32 
TREShapeGroup(const TREShapeGroup & other)33 TREShapeGroup::TREShapeGroup(const TREShapeGroup &other)
34 	: m_vertexStore(other.m_vertexStore)
35 	, m_indices(NULL)
36 	, m_controlPointIndices((TCULongArray *)TCObject::copy(
37 		other.m_controlPointIndices))
38 	, m_stripCounts((TCULongArrayArray *)TCObject::copy(other.m_stripCounts))
39 	, m_multiDrawIndices(NULL)
40 	, m_shapesPresent(other.m_shapesPresent)
41 	, m_mainModel(other.m_mainModel)
42 	, m_bfc(other.m_bfc)
43 	, m_transferIndices(TCObject::copy(other.m_transferIndices))
44 {
45 	m_vertexStore->retain();
46 	if (other.m_shapesPresent)
47 	{
48 		int i, j;
49 		int shapeTypeCount = other.m_indices->getCount();
50 		TREVertexArray *vertices = m_vertexStore->getVertices();
51 		TREVertexArray *normals = m_vertexStore->getNormals();
52 		TREVertexArray *textureCoords = m_vertexStore->getTextureCoords();
53 		TCULongArray *colors = m_vertexStore->getColors();
54 
55 		m_indices = new TCULongArrayArray(shapeTypeCount);
56 		for (i = 0; i < shapeTypeCount; i++)
57 		{
58 			TCULongArray *thoseIndices = (*other.m_indices)[i];
59 			int indexCount = thoseIndices->getCount();
60 			TCULongArray *theseIndices = new TCULongArray(indexCount);
61 
62 			m_indices->addObject(theseIndices);
63 			for (j = 0; j < indexCount; j++)
64 			{
65 				int index = (*thoseIndices)[j];
66 
67 				theseIndices->addValue(vertices->getCount());
68 				vertices->addVertex((*vertices)[index]);
69 				normals->addVertex((*normals)[index]);
70 				if (textureCoords)
71 				{
72 					textureCoords->addVertex((*textureCoords)[index]);
73 				}
74 				if (colors)
75 				{
76 					colors->addValue((*colors)[index]);
77 				}
78 			}
79 			theseIndices->release();
80 		}
81 	}
82 }
83 
~TREShapeGroup(void)84 TREShapeGroup::~TREShapeGroup(void)
85 {
86 }
87 
copy(void) const88 TCObject *TREShapeGroup::copy(void) const
89 {
90 	return new TREShapeGroup(*this);
91 }
92 
dealloc(void)93 void TREShapeGroup::dealloc(void)
94 {
95 	// ************************************************************************
96 	// The deleteMultiDrawIndices call MUST precede the release calls for
97 	// m_indices and m_stripCounts.
98 	deleteMultiDrawIndices();
99 	// ************************************************************************
100 	TCObject::release(m_vertexStore);
101 	TCObject::release(m_indices);
102 	TCObject::release(m_controlPointIndices);
103 	TCObject::release(m_stripCounts);
104 	TCObject::release(m_transferIndices);
105 	TCObject::dealloc();
106 }
107 
addShapeType(TREShapeType shapeType,int index)108 void TREShapeGroup::addShapeType(TREShapeType shapeType, int index)
109 {
110 	TCULongArray *newIndexArray = new TCULongArray;
111 
112 	if (!m_indices)
113 	{
114 		m_indices = new TCULongArrayArray;
115 	}
116 	m_indices->insertObject(newIndexArray, index);
117 	newIndexArray->release();
118 	m_shapesPresent |= shapeType;
119 	if (m_stripCounts == NULL)
120 	{
121 		m_stripCounts = new TCULongArrayArray;
122 	}
123 	if (shapeType >= TRESFirstStrip)
124 	{
125 		TCULongArray *newCountArray = new TCULongArray;
126 
127 		m_stripCounts->insertObject(newCountArray, index);
128 		newCountArray->release();
129 	}
130 	else
131 	{
132 		m_stripCounts->insertObject(NULL);
133 	}
134 }
135 
getControlPointIndices(bool create)136 TCULongArray *TREShapeGroup::getControlPointIndices(bool create)
137 {
138 	if (create && !m_controlPointIndices)
139 	{
140 		m_controlPointIndices = new TCULongArray;
141 	}
142 	return m_controlPointIndices;
143 }
144 
getIndices(TREShapeType shapeType,bool create)145 TCULongArray *TREShapeGroup::getIndices(TREShapeType shapeType, bool create)
146 {
147 	TCULong index = getShapeTypeIndex(shapeType);
148 
149 	if (!(m_shapesPresent & shapeType))
150 	{
151 		if (create)
152 		{
153 			addShapeType(shapeType, index);
154 		}
155 		else
156 		{
157 			return NULL;
158 		}
159 	}
160 	return m_indices->objectAtIndex(index);
161 }
162 
getStripCounts(TREShapeType shapeType,bool create)163 TCULongArray *TREShapeGroup::getStripCounts(TREShapeType shapeType, bool create)
164 {
165 	TCULong index = getShapeTypeIndex(shapeType);
166 
167 	if (!(m_shapesPresent & shapeType))
168 	{
169 		if (create)
170 		{
171 			addShapeType(shapeType, index);
172 		}
173 		else
174 		{
175 			return NULL;
176 		}
177 	}
178 	return m_stripCounts->objectAtIndex(index);
179 }
180 
getShapeTypeIndex(TREShapeType shapeType)181 TCULong TREShapeGroup::getShapeTypeIndex(TREShapeType shapeType)
182 {
183 	int bit;
184 	TCULong index = 0;
185 
186 	for (bit = 1; bit != shapeType; bit = bit << 1)
187 	{
188 		if (m_shapesPresent & bit)
189 		{
190 			index++;
191 		}
192 	}
193 	return index;
194 }
195 
addIndices(TCULongArray * indices,int firstIndex,int count)196 void TREShapeGroup::addIndices(TCULongArray *indices, int firstIndex, int count)
197 {
198 	int i;
199 
200 	for (i = 0; i < count; i++)
201 	{
202 		indices->addValue(firstIndex + i);
203 	}
204 }
205 
addShapeIndices(TREShapeType shapeType,int firstIndex,int count)206 void TREShapeGroup::addShapeIndices(TREShapeType shapeType, int firstIndex,
207 									int count)
208 {
209 	TCULongArray *indices = getIndices(shapeType, true);
210 
211 	addIndices(indices, firstIndex, count);
212 }
213 
addShapeStripCount(TREShapeType shapeType,int count)214 void TREShapeGroup::addShapeStripCount(TREShapeType shapeType, int count)
215 {
216 	TCULongArray *counts = getStripCounts(shapeType, true);
217 
218 	counts->addValue(count);
219 }
220 
modeForShapeType(TREShapeType shapeType)221 GLenum TREShapeGroup::modeForShapeType(TREShapeType shapeType)
222 {
223 	switch (shapeType)
224 	{
225 	case TRESLine:
226 		return GL_LINES;
227 		break;
228 	case TRESTriangle:
229 		return GL_TRIANGLES;
230 		break;
231 	case TRESQuad:
232 		return GL_QUADS;
233 		break;
234 	case TRESConditionalLine:
235 		return GL_LINES;
236 		break;
237 	case TRESTriangleStrip:
238 		return GL_TRIANGLE_STRIP;
239 		break;
240 	case TRESQuadStrip:
241 		return GL_QUAD_STRIP;
242 		break;
243 	case TRESTriangleFan:
244 		return GL_TRIANGLE_FAN;
245 		break;
246 	default:
247 		// We shouldn't ever get here.
248 		return GL_TRIANGLES;
249 		break;
250 	}
251 	// We can't ever get here, but GCC is apparently too stupid to realize this.
252 	return GL_TRIANGLES;
253 }
254 
numPointsForShapeType(TREShapeType shapeType)255 int TREShapeGroup::numPointsForShapeType(TREShapeType shapeType)
256 {
257 	switch (shapeType)
258 	{
259 	case TRESLine:
260 		return 2;
261 		break;
262 	case TRESTriangle:
263 		return 3;
264 		break;
265 	case TRESQuad:
266 		return 4;
267 		break;
268 	case TRESConditionalLine:
269 		return 2;
270 		break;
271 	default:
272 		// Strips are variable size
273 		return 0;
274 		break;
275 	}
276 	// We can't ever get here, but GCC is apparently too stupid to realize this.
277 	return 0;
278 }
279 
drawShapeType(TREShapeType shapeType,int offset,int count)280 void TREShapeGroup::drawShapeType(
281 	TREShapeType shapeType,
282 	int offset /*= 0*/,
283 	int count /*= -1*/)
284 {
285 	TCULongArray *indexArray = getIndices(shapeType);
286 
287 	if (indexArray)
288 	{
289 		int tempCount = indexArray->getCount();
290 
291 		if (!m_mainModel->onLastStep())
292 		{
293 			int step = m_mainModel->getStep();
294 			IntVector &stepCounts = m_stepCounts[shapeType];
295 
296 			if (stepCounts.size() > (size_t)step)
297 			{
298 				tempCount = stepCounts[step] - offset;
299 			}
300 		}
301 		if (count == -1 || tempCount < count)
302 		{
303 			count = tempCount;
304 		}
305 		glDrawElements(modeForShapeType(shapeType), count, GL_UNSIGNED_INT,
306 			&indexArray->getValues()[offset]);
307 		if (shapeType == TRESLine && m_mainModel->getActiveLineJoinsFlag())
308 		{
309 			glDrawElements(GL_POINTS, count, GL_UNSIGNED_INT,
310 				indexArray->getValues());
311 		}
312 		if (m_mainModel->getDrawNormalsFlag() && shapeType != TRESLine)
313 		{
314 			drawNormals(indexArray, count, offset);
315 		}
316 	}
317 }
318 
drawNormals(TCULongArray * indexArray,int count,int offset)319 void TREShapeGroup::drawNormals(
320 	TCULongArray *indexArray,
321 	int count,
322 	int offset /*= 0*/)
323 {
324 	TREVertexArray *vertices = m_vertexStore->getVertices();
325 	TREVertexArray *normals = m_vertexStore->getNormals();
326 
327 	glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT);
328 	glColor3ub(255, 0, 0);
329 	glDisable(GL_LIGHTING);
330 	if (vertices && normals)
331 	{
332 		int i;
333 
334 		glBegin(GL_LINES);
335 		for (i = 0; i < count; i++)
336 		{
337 			int index = (*indexArray)[i + offset];
338 			TCVector vertex = (*vertices)[index].v;
339 			TCVector normal = (*normals)[index].v;
340 
341 			treGlVertex3fv(vertex);
342 			treGlVertex3fv(vertex + (normal * 1.1f));
343 		}
344 		glEnd();
345 	}
346 	glPopAttrib();
347 }
348 
349 // This is really ugly, but I really need to use dynamic arrays while filling
350 // in the data.  Since that can't be passed to glMultiDrawElements, I have to
351 // create a new copy of the data and copy it here.
initMultiDrawIndices(void)352 void TREShapeGroup::initMultiDrawIndices(void)
353 {
354 	if (!m_multiDrawIndices)
355 	{
356 		int shapeTypeCount = m_indices->getCount();
357 		int i, j;
358 
359 		m_multiDrawIndices = new TCULong**[shapeTypeCount];
360 		for (i = 0; i < shapeTypeCount; i++)
361 		{
362 			TCULongArray *stripCounts = (*m_stripCounts)[i];
363 
364 			if (stripCounts)
365 			{
366 				TCULongArray *indices = (*m_indices)[i];
367 				int numStrips = stripCounts->getCount();
368 
369 				if (numStrips)
370 				{
371 					int indexOffset = 0;
372 
373 					m_multiDrawIndices[i] = new TCULong*[numStrips];
374 					for (j = 0; j < numStrips; j++)
375 					{
376 						int stripCount = (*stripCounts)[j];
377 
378 						if (stripCount)
379 						{
380 							m_multiDrawIndices[i][j] = new TCULong[stripCount];
381 							memcpy(m_multiDrawIndices[i][j],
382 								indices->getValues() + indexOffset,
383 								stripCount * sizeof(TCULong));
384 						}
385 						else
386 						{
387 							m_multiDrawIndices[i][j] = NULL;
388 						}
389 						indexOffset += stripCount;
390 					}
391 				}
392 				else
393 				{
394 					m_multiDrawIndices[i] = NULL;
395 				}
396 			}
397 			else
398 			{
399 				m_multiDrawIndices[i] = NULL;
400 			}
401 		}
402 	}
403 }
404 
405 // The m_multiDrawIndices array doesn't have any internal tracking of the size
406 // of the various nesting levels, so we just need to get that info from the
407 // other variables the same way we did when we originally created it.
deleteMultiDrawIndices(void)408 void TREShapeGroup::deleteMultiDrawIndices(void)
409 {
410 	if (m_multiDrawIndices)
411 	{
412 		int shapeTypeCount = m_indices->getCount();
413 		int i, j;
414 
415 		for (i = 0; i < shapeTypeCount; i++)
416 		{
417 			TCULongArray *stripCounts = (*m_stripCounts)[i];
418 
419 			if (stripCounts)
420 			{
421 				int numStrips = stripCounts->getCount();
422 
423 				if (numStrips)
424 				{
425 					for (j = 0; j < numStrips; j++)
426 					{
427 						if (m_multiDrawIndices[i][j])
428 						{
429 							delete[] m_multiDrawIndices[i][j];
430 						}
431 					}
432 				}
433 			}
434 			if (m_multiDrawIndices[i])
435 			{
436 				delete[] m_multiDrawIndices[i];
437 			}
438 		}
439 		delete[] m_multiDrawIndices;
440 	}
441 	m_multiDrawIndices = NULL;
442 }
443 
drawStripShapeType(TREShapeType shapeType)444 void TREShapeGroup::drawStripShapeType(TREShapeType shapeType)
445 {
446 	if (m_shapesPresent & shapeType)
447 	{
448 		TCULongArray *indexArray = getIndices(shapeType);
449 		TCULongArray *countArray = getStripCounts(shapeType);
450 
451 		if (indexArray && countArray)
452 		{
453 			int numStrips = countArray->getCount();
454 
455 			if (!m_mainModel->onLastStep())
456 			{
457 				int step = m_mainModel->getStep();
458 				IntVector &stepCounts = m_stepCounts[shapeType];
459 
460 				if (stepCounts.size() > (size_t)step)
461 				{
462 					numStrips = stepCounts[step];
463 				}
464 			}
465 			if (numStrips)
466 			{
467 				GLenum glMode = modeForShapeType(shapeType);
468 
469 				if (TREGLExtensions::haveMultiDrawArraysExtension())
470 				{
471 					int shapeTypeIndex = getShapeTypeIndex(shapeType);
472 
473 					if (!m_multiDrawIndices)
474 					{
475 						initMultiDrawIndices();
476 					}
477 					glMultiDrawElementsEXT(glMode,
478 						(GLsizei *)countArray->getValues(), GL_UNSIGNED_INT,
479 						(const void **)m_multiDrawIndices[shapeTypeIndex],
480 						numStrips);
481 				}
482 				else
483 				{
484 					TCULong *indices = indexArray->getValues();
485 					int indexOffset = 0;
486 					int i;
487 
488 					for (i = 0; i < numStrips; i++)
489 					{
490 						int stripCount = (*countArray)[i];
491 
492 						glDrawElements(glMode, stripCount, GL_UNSIGNED_INT,
493 							indices + indexOffset);
494 						indexOffset += stripCount;
495 					}
496 				}
497 			}
498 			if (m_mainModel->getDrawNormalsFlag())
499 			{
500 				drawNormals(indexArray, indexArray->getCount());
501 			}
502 		}
503 	}
504 }
505 
draw(bool skipTexmapped)506 void TREShapeGroup::draw(bool skipTexmapped /*= false*/)
507 {
508 	skipTexmapped = false;
509 	if (m_vertexStore && !skipTexmapped)
510 	{
511 		drawShapeType(TRESTriangle);
512 		drawShapeType(TRESQuad);
513 		drawStripShapeType(TRESTriangleStrip);
514 		drawStripShapeType(TRESQuadStrip);
515 		drawStripShapeType(TRESTriangleFan);
516 	}
517 }
518 
drawTextured(void)519 void TREShapeGroup::drawTextured(void)
520 {
521 	if (m_vertexStore)
522 	{
523 		drawShapeType(TRESTriangle);
524 		drawShapeType(TRESQuad);
525 	}
526 }
527 
drawLines(void)528 void TREShapeGroup::drawLines(void)
529 {
530 	if (m_vertexStore)
531 	{
532 		drawShapeType(TRESLine);
533 	}
534 }
535 
536 //***********************************************************************
537 // Return 1 if the v2 bends left of v1, -1 if right, 0 if straight ahead.
turnVector(TCFloat vx1,TCFloat vy1,TCFloat vx2,TCFloat vy2)538 int TREShapeGroup::turnVector(TCFloat vx1, TCFloat vy1, TCFloat vx2,
539 							  TCFloat vy2)
540 {
541 	// Pos for left bend, 0 = linear
542 	TCFloat vecProduct = (vx1 * vy2) - (vy1 * vx2);
543 
544 	if (vecProduct > 0.0)
545 	{
546 		return 1;
547 	}
548 	if (vecProduct < 0.0)
549 	{
550 		return -1;
551 	}
552 	return 0;
553 }
554 
transformPoint(const TCVector & point,const TCFloat * matrix,TCFloat * tx,TCFloat * ty)555 void TREShapeGroup::transformPoint(const TCVector &point, const TCFloat *matrix,
556 								   TCFloat *tx, TCFloat *ty)
557 {
558 	TCFloat x = point.get(0);
559 	TCFloat y = point.get(1);
560 	TCFloat z = point.get(2);
561 	TCFloat tw;
562 
563 //	x' = a*x + b*y + c*z + X
564 //	y' = d*x + e*y + f*z + Y
565 //	z' = g*x + h*y + i*z + Z
566 	tw = 1.0f / (matrix[3]*x + matrix[7]*y + matrix[11]*z + matrix[15]);
567 	*tx = (matrix[0]*x + matrix[4]*y + matrix[8]*z + matrix[12]) * tw;
568 	*ty = (matrix[1]*x + matrix[5]*y + matrix[9]*z + matrix[13]) * tw;
569 }
570 
shouldDrawConditional(TCULong index1,TCULong index2,TCULong cpIndex1,TCULong cpIndex2,const TCFloat * matrix)571 bool TREShapeGroup::shouldDrawConditional(TCULong index1, TCULong index2,
572 										  TCULong cpIndex1, TCULong cpIndex2,
573 										  const TCFloat *matrix)
574 {
575 	// Use matrix--which contains a combination of the projection and the
576 	// model-view matrix--to calculate coords in the plane of the screen, so
577 	// we can test optional lines.
578 	TCFloat s1x, s1y;
579 	TCFloat s2x, s2y;
580 	TCFloat s3x, s3y;
581 	TCFloat s4x, s4y;
582 	TREVertexArray *vertices = m_vertexStore->getVertices();
583 	TREVertexArray *controlPoints = vertices; //m_vertexStore->getControlPoints();
584 	const TREVertex &v1 = (*vertices)[index1];
585 	const TREVertex &v2 = (*vertices)[index2];
586 	const TREVertex &v3 = (*controlPoints)[cpIndex1];
587 	const TREVertex &v4 = (*controlPoints)[cpIndex2];
588 	TCVector p1 = TCVector(v1.v[0], v1.v[1], v1.v[2]);
589 	TCVector p2 = TCVector(v2.v[0], v2.v[1], v2.v[2]);
590 	TCVector p3 = TCVector(v3.v[0], v3.v[1], v3.v[2]);
591 	TCVector p4 = TCVector(v4.v[0], v4.v[1], v4.v[2]);
592 
593 	// Only draw optional line p1-p2 if p3 and p4 are on the same side of p1-p2.
594 	// Note that we don't actually adjust for the window size, because it
595 	// doesn't effect the calculation.  Also, we don't care what the z value is,
596 	// so we don't bother to compute it.
597 	transformPoint(p1, matrix, &s1x, &s1y);
598 	transformPoint(p2, matrix, &s2x, &s2y);
599 	transformPoint(p3, matrix, &s3x, &s3y);
600 	transformPoint(p4, matrix, &s4x, &s4y);
601 
602 	// If we do not turn the same direction \_/ for both test points
603 	// then they're on opposite sides of segment p1-p2 and we should
604 	// skip drawing this conditional line.
605 	if (turnVector(s2x-s1x, s2y-s1y, s3x-s2x, s3y-s2y) ==
606 		turnVector(s2x-s1x, s2y-s1y, s4x-s2x, s4y-s2y))
607 	{
608 		return true;	// Draw it
609 	}
610 	else
611 	{
612 		return false;	// Skip it.
613 	}
614 }
615 
616 /*
617 static void printULongArray(TCULongArray *array)
618 {
619 	if (array)
620 	{
621 		int i;
622 		int count = array->getCount();
623 
624 		for (i = 0; i < count; i++)
625 		{
626 			printf("%d\n", (*array)[i]);
627 		}
628 	}
629 }
630 
631 static void printVertices(TREVertexArray *vertices, TCULongArray *indices)
632 {
633 	if (vertices && indices)
634 	{
635 		int i;
636 		int count = indices->getCount();
637 
638 		for (i = 0; i < count; i++)
639 		{
640 			int index = (*indices)[i];
641 			const TREVertex &vertex = (*vertices)[index];
642 
643 			printf("%14.10f %14.10f %14.10f\n", vertex.v[0], vertex.v[1],
644 				vertex.v[2]);
645 		}
646 	}
647 }
648 */
649 
drawConditionalLines(void)650 void TREShapeGroup::drawConditionalLines(void)
651 {
652 	if (m_vertexStore)
653 	{
654 		TCULongArray *indices = getIndices(TRESConditionalLine);
655 
656 		if (indices)
657 		{
658 			bool showAllConditional =
659 				m_vertexStore->getShowAllConditionalFlag();
660 			bool showConditionalControlPoints =
661 				m_vertexStore->getConditionalControlPointsFlag();
662 			TCULongArray *activeIndices;
663 
664 			if (showAllConditional && !showConditionalControlPoints)
665 			{
666 				drawConditionalLines(indices);
667 			}
668 			else
669 			{
670 				if (m_mainModel->getStencilConditionalsFlag())
671 				{
672 					int i;
673 					int count = indices->getCount();
674 					TREVertexArray *vertices = m_vertexStore->getVertices();
675 
676 					activeIndices = new TCULongArray;
677 					glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT |
678 						GL_STENCIL_BUFFER_BIT | GL_POLYGON_BIT);
679 					glEnable(GL_STENCIL_TEST);
680 					glEnable(GL_CULL_FACE);
681 					glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
682 					glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
683 					glDepthMask(GL_FALSE);
684 					glStencilMask(0xFFFFFFFF);
685 					glStencilFunc(GL_ALWAYS, 0x7FFFFFFF, 0xFFFFFFFF);
686 					glStencilOp(GL_INVERT, GL_KEEP, GL_INVERT);
687 					glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
688 					if (!m_mainModel->getVertexArrayEdgeFlagsFlag())
689 					{
690 						glBegin(GL_TRIANGLES);
691 					}
692 					for (i = 0; i < count; i += 2)
693 					{
694 						TCULong index1 = (*indices)[i];
695 						TCULong index2 = (*indices)[i + 1];
696 						TCULong cpIndex1 = (*m_controlPointIndices)[i];
697 						TCULong cpIndex2 = (*m_controlPointIndices)[i + 1];
698 
699 						if (m_mainModel->getVertexArrayEdgeFlagsFlag())
700 						{
701 							activeIndices->addValue(index1);
702 							// Adding 1 to the index gives me the vertex with
703 							// the edge flag set to GL_FALSE
704 							activeIndices->addValue(index2 + 1);
705 							activeIndices->addValue(cpIndex1);
706 
707 							activeIndices->addValue(index2);
708 							// Adding 1 to the index gives me the vertex with
709 							// the edge flag set to GL_FALSE
710 							activeIndices->addValue(index1 + 1);
711 							activeIndices->addValue(cpIndex2);
712 						}
713 						else
714 						{
715 							treGlVertex3fv((*vertices)[index1].v);
716 							glEdgeFlag(GL_FALSE);
717 							treGlVertex3fv((*vertices)[index2].v);
718 							treGlVertex3fv((*m_vertexStore->
719 								getVertices())[cpIndex1].v);
720 
721 							treGlVertex3fv((*vertices)[index1].v);
722 							treGlVertex3fv((*m_vertexStore->
723 								getVertices())[cpIndex2].v);
724 							glEdgeFlag(GL_TRUE);
725 							treGlVertex3fv((*vertices)[index2].v);
726 						}
727 					}
728 					if (m_mainModel->getVertexArrayEdgeFlagsFlag())
729 					{
730 						if (activeIndices->getCount())
731 						{
732 							glDrawElements(GL_TRIANGLES,
733 								activeIndices->getCount(), GL_UNSIGNED_INT,
734 								activeIndices->getValues());
735 						}
736 					}
737 					else
738 					{
739 						glEnd();
740 					}
741 					TCObject::release(activeIndices);
742 					activeIndices = indices;
743 					activeIndices->retain();
744 					glPopAttrib(); // GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
745 					glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
746 					glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
747 				}
748 				else
749 				{
750 					if (m_mainModel->doingBackgroundConditionals())
751 					{
752 						for (int i = 0; i < 32; i++)
753 						{
754 							m_mainModel->waitForConditionals(i);
755 							if (isColored())
756 							{
757 								drawConditionalLines(
758 									m_mainModel->getActiveColorConditionals(i));
759 							}
760 							else
761 							{
762 								drawConditionalLines(
763 									m_mainModel->getActiveConditionals(i));
764 							}
765 						}
766 						return;
767 					}
768 					else
769 					{
770 						activeIndices = getActiveConditionalIndices(indices);
771 					}
772 				}
773 				drawConditionalLines(activeIndices);
774 				TCObject::release(activeIndices);
775 				if (m_mainModel->getStencilConditionalsFlag())
776 				{
777 					glPopAttrib();
778 				}
779 			}
780 		}
781 	}
782 }
783 
drawConditionalLines(const TCULongArray * activeIndices)784 void TREShapeGroup::drawConditionalLines(const TCULongArray *activeIndices)
785 {
786 	if (activeIndices)
787 	{
788 		int count = activeIndices->getCount();
789 
790 		if (count > 0)
791 		{
792 			glDrawElements(GL_LINES, activeIndices->getCount(),
793 				GL_UNSIGNED_INT, activeIndices->getValues());
794 			if (m_mainModel->getActiveLineJoinsFlag())
795 			{
796 				glDrawElements(GL_POINTS, activeIndices->getCount(),
797 					GL_UNSIGNED_INT, activeIndices->getValues());
798 			}
799 		}
800 	}
801 }
802 
getActiveConditionalIndices(TCULongArray * indices,const TCFloat * modelMatrix,int start,int count)803 TCULongArray *TREShapeGroup::getActiveConditionalIndices(
804 	TCULongArray *indices,
805 	const TCFloat *modelMatrix /*= NULL*/,
806 	int start /*= 0*/,
807 	int count /*= -1*/)
808 {
809 	int i;
810 	TCFloat modelViewMatrix[16];
811 	const TCFloat *projectionMatrix = m_mainModel->getCurrentProjectionMatrix();
812 	TCFloat matrix[16];
813 	TCULongArray *activeIndices = new TCULongArray;
814 	bool showAllConditional =
815 		m_vertexStore->getShowAllConditionalFlag();
816 	bool showConditionalControlPoints =
817 		m_vertexStore->getConditionalControlPointsFlag();
818 
819 	if (count == -1)
820 	{
821 		count = indices->getCount();
822 	}
823 	if (modelMatrix)
824 	{
825 		const TCFloat *mainModelViewMatrix =
826 			m_mainModel->getCurrentModelViewMatrix();
827 
828 		TCVector::multMatrix(mainModelViewMatrix, modelMatrix, modelViewMatrix);
829 	}
830 	else
831 	{
832 		treGlGetFloatv(GL_MODELVIEW_MATRIX, modelViewMatrix);
833 	}
834 	TCVector::multMatrix(projectionMatrix, modelViewMatrix, matrix);
835 	for (i = start; i < start + count; i += 2)
836 	{
837 		TCULong index1 = (*indices)[i];
838 		TCULong index2 = (*indices)[i + 1];
839 		TCULong cpIndex1 = (*m_controlPointIndices)[i];
840 		TCULong cpIndex2 = (*m_controlPointIndices)[i + 1];
841 
842 		if (showAllConditional ||
843 			shouldDrawConditional(index1, index2, cpIndex1,
844 			cpIndex2, matrix))
845 		{
846 			activeIndices->addValue(index1);
847 			activeIndices->addValue(index2);
848 			if (showConditionalControlPoints)
849 			{
850 				activeIndices->addValue(index1);
851 				activeIndices->addValue(cpIndex1);
852 				activeIndices->addValue(index1);
853 				activeIndices->addValue(cpIndex2);
854 			}
855 		}
856 	}
857 	return activeIndices;
858 }
859 
addShape(TREShapeType shapeType,const TCVector * vertices,int count)860 int TREShapeGroup::addShape(
861 	TREShapeType shapeType,
862 	const TCVector *vertices,
863 	int count)
864 {
865 	return addShape(shapeType, vertices, NULL, count);
866 }
867 
addShape(TREShapeType shapeType,const TCVector * vertices,const TCVector * normals,int count)868 int TREShapeGroup::addShape(
869 	TREShapeType shapeType,
870 	const TCVector *vertices,
871 	const TCVector *normals,
872 	int count)
873 {
874 	return addShape(shapeType, vertices, normals, NULL, count);
875 }
876 
addShape(TREShapeType shapeType,const TCVector * vertices,const TCVector * normals,const TCVector * textureCoords,int count)877 int TREShapeGroup::addShape(
878 	TREShapeType shapeType,
879 	const TCVector *vertices,
880 	const TCVector *normals,
881 	const TCVector *textureCoords,
882 	int count)
883 {
884 	int index;
885 
886 	if (textureCoords)
887 	{
888 		m_vertexStore->setupTextured();
889 	}
890 	else
891 	{
892 		m_vertexStore->setup();
893 		TREVertexArray *vsTextureCoords = m_vertexStore->getTextureCoords();
894 		if (vsTextureCoords != NULL)
895 		{
896 			vsTextureCoords->addEmptyValues(count);
897 		}
898 	}
899 	if (normals)
900 	{
901 		if (textureCoords)
902 		{
903 			index = m_vertexStore->addVertices(vertices, normals, textureCoords,
904 				count, m_mainModel->getCurStepIndex());
905 		}
906 		else
907 		{
908 			index = m_vertexStore->addVertices(vertices, normals, count,
909 				m_mainModel->getCurStepIndex());
910 		}
911 	}
912 	else
913 	{
914 		if (textureCoords)
915 		{
916 			index = m_vertexStore->addVertices(vertices, NULL, textureCoords,
917 				count, m_mainModel->getCurStepIndex());
918 		}
919 		else
920 		{
921 			index = m_vertexStore->addVertices(vertices, count,
922 				m_mainModel->getCurStepIndex());
923 		}
924 	}
925 	addShapeIndices(shapeType, index, count);
926 	return index;
927 }
928 
addConditionalLine(const TCVector * vertices,const TCVector * controlPoints)929 int TREShapeGroup::addConditionalLine(
930 	const TCVector *vertices,
931 	const TCVector *controlPoints)
932 {
933 	int index;
934 
935 	m_vertexStore->setup();
936 	if (!m_controlPointIndices)
937 	{
938 		m_controlPointIndices = new TCULongArray;
939 	}
940 	if (m_mainModel->getStencilConditionalsFlag() &&
941 		m_mainModel->getVertexArrayEdgeFlagsFlag())
942 	{
943 		m_vertexStore->setConditionalsFlag(true);
944 	}
945 	// The edge flag for control point vertices will always be GL_FALSE.
946 	index = m_vertexStore->addVertices(controlPoints, 2,
947 		m_mainModel->getCurStepIndex(), GL_FALSE);
948 	addIndices(m_controlPointIndices, index, 2);
949 	if (m_mainModel->getStencilConditionalsFlag() &&
950 		m_mainModel->getVertexArrayEdgeFlagsFlag())
951 	{
952 		index = m_vertexStore->addVertices(vertices, 1,
953 			m_mainModel->getCurStepIndex());
954 		addShapeIndices(TRESConditionalLine, index, 1);
955 		// We need a second copy, and this one needs to have the edge flag set
956 		// to GL_FALSE.  Note that these will always be accessed as index + 1.
957 		m_vertexStore->addVertices(vertices, 1,
958 			m_mainModel->getCurStepIndex(), GL_FALSE);
959 		index = m_vertexStore->addVertices(&vertices[1], 1,
960 			m_mainModel->getCurStepIndex());
961 		addShapeIndices(TRESConditionalLine, index, 1);
962 		index = m_vertexStore->addVertices(&vertices[1], 1,
963 			m_mainModel->getCurStepIndex(), GL_FALSE);
964 	}
965 	else
966 	{
967 		index = m_vertexStore->addVertices(vertices, 2,
968 			m_mainModel->getCurStepIndex());
969 		addShapeIndices(TRESConditionalLine, index, 2);
970 	}
971 	return index;
972 }
973 
addLine(const TCVector * vertices)974 int TREShapeGroup::addLine(const TCVector *vertices)
975 {
976 	return addShape(TRESLine, vertices, 2);
977 }
978 
addTriangle(const TCVector * vertices)979 int TREShapeGroup::addTriangle(const TCVector *vertices)
980 {
981 	return addShape(TRESTriangle, vertices, 3);
982 }
983 
addTriangle(const TCVector * vertices,const TCVector * normals)984 int TREShapeGroup::addTriangle(
985 	const TCVector *vertices,
986 	const TCVector *normals)
987 {
988 	return addShape(TRESTriangle, vertices, normals, 3);
989 }
990 
addTriangle(const TCVector * vertices,const TCVector * normals,const TCVector * textureCoords)991 int TREShapeGroup::addTriangle(
992 	const TCVector *vertices,
993 	const TCVector *normals,
994 	const TCVector *textureCoords)
995 {
996 	return addShape(TRESTriangle, vertices, normals, textureCoords, 3);
997 }
998 
addQuad(const TCVector * vertices)999 int TREShapeGroup::addQuad(const TCVector *vertices)
1000 {
1001 	return addShape(TRESQuad, vertices, 4);
1002 }
1003 
addQuad(const TCVector * vertices,const TCVector * normals)1004 int TREShapeGroup::addQuad(const TCVector *vertices, const TCVector *normals)
1005 {
1006 	return addShape(TRESQuad, vertices, normals, 4);
1007 }
1008 
addTriangleStrip(const TCVector * vertices,const TCVector * normals,int count)1009 int TREShapeGroup::addTriangleStrip(
1010 	const TCVector *vertices,
1011 	const TCVector *normals,
1012 	int count)
1013 {
1014 	return addStrip(TRESTriangleStrip, vertices, normals, count);
1015 }
1016 
addQuadStrip(const TCVector * vertices,const TCVector * normals,int count)1017 int TREShapeGroup::addQuadStrip(
1018 	const TCVector *vertices,
1019 	const TCVector *normals,
1020 	int count)
1021 {
1022 	return addStrip(TRESQuadStrip, vertices, normals, count);
1023 }
1024 
addTriangleFan(const TCVector * vertices,const TCVector * normals,int count)1025 int TREShapeGroup::addTriangleFan(
1026 	const TCVector *vertices,
1027 	const  TCVector *normals,
1028 	int count)
1029 {
1030 	return addStrip(TRESTriangleFan, vertices, normals, count);
1031 }
1032 
addTriangleFan(const TCVector * vertices,const TCVector * normals,const TCVector * textureCoords,int count)1033 int TREShapeGroup::addTriangleFan(
1034 	const TCVector *vertices,
1035 	const TCVector *normals,
1036 	const TCVector *textureCoords,
1037 	int count)
1038 {
1039 	return addStrip(TRESTriangleFan, vertices, normals, textureCoords, count);
1040 }
1041 
addStrip(TREShapeType shapeType,const TCVector * vertices,const TCVector * normals,int count)1042 int TREShapeGroup::addStrip(
1043 	TREShapeType shapeType,
1044 	const TCVector *vertices,
1045 	const TCVector *normals,
1046 	int count)
1047 {
1048 	return addStrip(shapeType, vertices, normals, NULL, count);
1049 }
1050 
addStrip(TREShapeType shapeType,const TCVector * vertices,const TCVector * normals,const TCVector * textureCoords,int count)1051 int TREShapeGroup::addStrip(
1052 	TREShapeType shapeType,
1053 	const TCVector *vertices,
1054 	const TCVector *normals,
1055 	const TCVector *textureCoords,
1056 	int count)
1057 {
1058 	int index;
1059 
1060 	if (textureCoords)
1061 	{
1062 		m_vertexStore->setupTextured();
1063 	}
1064 	else
1065 	{
1066 		m_vertexStore->setup();
1067 	}
1068 	if (textureCoords)
1069 	{
1070 		index = m_vertexStore->addVertices(vertices, normals, textureCoords,
1071 			count, m_mainModel->getCurStepIndex());
1072 	}
1073 	else
1074 	{
1075 		index = m_vertexStore->addVertices(vertices, normals, count,
1076 			m_mainModel->getCurStepIndex());
1077 	}
1078 	addShapeStripCount(shapeType, count);
1079 	addShapeIndices(shapeType, index, count);
1080 	return index;
1081 }
1082 
setVertexStore(TREVertexStore * vertexStore)1083 void TREShapeGroup::setVertexStore(TREVertexStore *vertexStore)
1084 {
1085 	vertexStore->retain();
1086 	TCObject::release(m_vertexStore);
1087 	m_vertexStore = vertexStore;
1088 }
1089 
scanPoints(TCObject * scanner,TREScanPointCallback scanPointCallback,const TCFloat * matrix)1090 void TREShapeGroup::scanPoints(TCObject *scanner,
1091 							   TREScanPointCallback scanPointCallback,
1092 							   const TCFloat* matrix)
1093 {
1094 	int bit;
1095 
1096 	for (bit = 1; (TREShapeType)bit < TRESFirstStrip; bit = bit << 1)
1097 	{
1098 		scanPoints(getIndices((TREShapeType)bit), scanner, scanPointCallback,
1099 			matrix);
1100 	}
1101 	for (; (TREShapeType)bit <= TRESLast; bit = bit << 1)
1102 	{
1103 		scanStripPoints(getIndices((TREShapeType)bit),
1104 			getStripCounts((TREShapeType)bit), scanner, scanPointCallback,
1105 			matrix);
1106 	}
1107 }
1108 
scanPoints(TCULongArray * indices,TCObject * scanner,TREScanPointCallback scanPointCallback,const TCFloat * matrix)1109 void TREShapeGroup::scanPoints(TCULongArray *indices, TCObject *scanner,
1110 							   TREScanPointCallback scanPointCallback,
1111 							   const TCFloat* matrix)
1112 {
1113 	if (indices)
1114 	{
1115 		int i;
1116 		int count = indices->getCount();
1117 
1118 		for (i = 0; i < count; i++)
1119 		{
1120 			scanPoints((*indices)[i], scanner, scanPointCallback, matrix);
1121 		}
1122 	}
1123 }
1124 
scanStripPoints(TCULongArray * indices,TCULongArray * stripCounts,TCObject * scanner,TREScanPointCallback scanPointCallback,const TCFloat * matrix)1125 void TREShapeGroup::scanStripPoints(TCULongArray *indices,
1126 									TCULongArray *stripCounts,
1127 									TCObject *scanner,
1128 									TREScanPointCallback scanPointCallback,
1129 									const TCFloat* matrix)
1130 {
1131 	if (indices && stripCounts)
1132 	{
1133 		int i, j;
1134 		int numStrips = stripCounts->getCount();
1135 		int indexOffset = 0;
1136 
1137 		for (i = 0; i < numStrips; i++)
1138 		{
1139 			int stripCount = (*stripCounts)[i];
1140 			for (j = 0; j < stripCount; j++)
1141 			{
1142 				scanPoints((*indices)[j + indexOffset], scanner,
1143 					scanPointCallback, matrix);
1144 			}
1145 			indexOffset += stripCount;
1146 		}
1147 	}
1148 }
1149 
scanPoints(const TREVertex & vertex,TCObject * scanner,TREScanPointCallback scanPointCallback)1150 void TREShapeGroup::scanPoints(const TREVertex &vertex, TCObject *scanner,
1151 							   TREScanPointCallback scanPointCallback)
1152 {
1153 	TCVector point = TCVector(vertex.v[0], vertex.v[1], vertex.v[2]);
1154 	((*scanner).*scanPointCallback)(point);
1155 }
1156 
scanPoints(TCULong index,TCObject * scanner,TREScanPointCallback scanPointCallback,const TCFloat * matrix)1157 void TREShapeGroup::scanPoints(TCULong index, TCObject *scanner,
1158 							   TREScanPointCallback scanPointCallback,
1159 							   const TCFloat *matrix)
1160 {
1161 	TREVertex vertex = (*m_vertexStore->getVertices())[index];
1162 
1163 	transformVertex(vertex, matrix);
1164 	scanPoints(vertex, scanner, scanPointCallback);
1165 }
1166 
unshrinkNormals(const TCFloat * matrix,const TCFloat * unshrinkMatrix)1167 void TREShapeGroup::unshrinkNormals(const TCFloat *matrix,
1168 									const TCFloat *unshrinkMatrix)
1169 {
1170 	int bit;
1171 
1172 	// Skip lines and conditional lines, whose normals don't matter
1173 	for (bit = TRESTriangle; (TREShapeType)bit < TRESFirstStrip; bit = bit << 1)
1174 	{
1175 		unshrinkNormals(getIndices((TREShapeType)bit), matrix, unshrinkMatrix);
1176 	}
1177 	for (; (TREShapeType)bit <= TRESLast; bit = bit << 1)
1178 	{
1179 		unshrinkStripNormals(getIndices((TREShapeType)bit),
1180 			getStripCounts((TREShapeType)bit), matrix, unshrinkMatrix);
1181 	}
1182 }
1183 
unshrinkNormals(TCULongArray * indices,const TCFloat * matrix,const TCFloat * unshrinkMatrix)1184 void TREShapeGroup::unshrinkNormals(TCULongArray *indices, const TCFloat *matrix,
1185 									const TCFloat *unshrinkMatrix)
1186 {
1187 	if (indices)
1188 	{
1189 		int i;
1190 		int count = indices->getCount();
1191 
1192 		for (i = 0; i < count; i++)
1193 		{
1194 			unshrinkNormal((*indices)[i], matrix, unshrinkMatrix);
1195 		}
1196 	}
1197 }
1198 
unshrinkStripNormals(TCULongArray * indices,TCULongArray * stripCounts,const TCFloat * matrix,const TCFloat * unshrinkMatrix)1199 void TREShapeGroup::unshrinkStripNormals(TCULongArray *indices,
1200 										 TCULongArray *stripCounts,
1201 										 const TCFloat *matrix,
1202 										 const TCFloat *unshrinkMatrix)
1203 {
1204 	if (indices && stripCounts)
1205 	{
1206 		int i, j;
1207 		int numStrips = stripCounts->getCount();
1208 		int indexOffset = 0;
1209 
1210 		for (i = 0; i < numStrips; i++)
1211 		{
1212 			int stripCount = (*stripCounts)[i];
1213 			for (j = 0; j < stripCount; j++)
1214 			{
1215 				unshrinkNormal((*indices)[j + indexOffset], matrix,
1216 					unshrinkMatrix);
1217 			}
1218 			indexOffset += stripCount;
1219 		}
1220 	}
1221 }
1222 
unshrinkNormal(TCULong index,const TCFloat * matrix,const TCFloat * unshrinkMatrix)1223 void TREShapeGroup::unshrinkNormal(TCULong index, const TCFloat *matrix,
1224 								   const TCFloat *unshrinkMatrix)
1225 {
1226 	TREVertexArray *normals = m_vertexStore->getNormals();
1227 	TREVertex &normal = normals->vertexAtIndex(index);
1228 	TCVector newNormal = TCVector(normal.v[0], normal.v[1], normal.v[2]);
1229 	TCFloat adjust;
1230 
1231 	newNormal = newNormal.transformNormal(matrix);
1232 	newNormal = newNormal.transformNormal(unshrinkMatrix, false);
1233 	adjust = 1.0f / newNormal.length();
1234 	normal.v[0] *= adjust;
1235 	normal.v[1] *= adjust;
1236 	normal.v[2] *= adjust;
1237 }
1238 
invertULongArray(TCULongArray * array,int start=0,int end=-1)1239 static void invertULongArray(TCULongArray *array, int start = 0, int end = -1)
1240 {
1241 	int i;
1242 	int count = array->getCount();
1243 
1244 	if (end == -1)
1245 	{
1246 		end = count;
1247 	}
1248 	for (i = start; i < (end - start) / 2 + start; i++)
1249 	{
1250 		TCULong temp1 = (*array)[i];
1251 		TCULong temp2 = (*array)[end - i - 1 + start];
1252 
1253 		array->replaceValue(temp2, i);
1254 		array->replaceValue(temp1, end - i - 1 + start);
1255 	}
1256 }
1257 
flipNormal(int index)1258 int TREShapeGroup::flipNormal(int index)
1259 {
1260 	TREVertexArray *vertices = m_vertexStore->getVertices();
1261 	TREVertexArray *normals = m_vertexStore->getNormals();
1262 	TREVertexArray *textureCoords = m_vertexStore->getTextureCoords();
1263 	TCULongArray *colors = m_vertexStore->getColors();
1264 	TREVertex vertex = (*vertices)[index];
1265 	TREVertex normal = (*normals)[index];
1266 
1267 	normal.v[0] = -normal.v[0];
1268 	normal.v[1] = -normal.v[1];
1269 	normal.v[2] = -normal.v[2];
1270 	vertices->addVertex(vertex);
1271 	normals->addVertex(normal);
1272 	if (textureCoords)
1273 	{
1274 		TREVertex textureCoord = (*textureCoords)[index];
1275 
1276 		textureCoord.v[0] = 1.0f - textureCoord.v[0];
1277 		textureCoords->addVertex(textureCoord);
1278 	}
1279 	if (colors)
1280 	{
1281 		colors->addValue((*colors)[index]);
1282 	}
1283 	return vertices->getCount() - 1;
1284 }
1285 
invertShapes(TCULongArray * oldIndices,TCULongArray * newIndices)1286 void TREShapeGroup::invertShapes(TCULongArray *oldIndices,
1287 								 TCULongArray *newIndices)
1288 {
1289 	int i;
1290 	int indexCount = oldIndices->getCount();
1291 
1292 	for (i = indexCount - 1; i >= 0; i--)
1293 	{
1294 		int index = (*oldIndices)[i];
1295 
1296 		newIndices->addValue(flipNormal(index));
1297 	}
1298 }
1299 
invert(void)1300 void TREShapeGroup::invert(void)
1301 {
1302 	if (m_indices)
1303 	{
1304 		int i, j;
1305 		int shapeTypeCount = m_indices->getCount();
1306 		int firstStripIndex = getShapeTypeIndex(TRESFirstStrip);
1307 		int triangleStripIndex = getShapeTypeIndex(TRESTriangleStrip);
1308 		int quadStripIndex = getShapeTypeIndex(TRESQuadStrip);
1309 		int triangleFanIndex = getShapeTypeIndex(TRESTriangleFan);
1310 		int conditionalLineIndex = getShapeTypeIndex(TRESConditionalLine);
1311 
1312 		for (i = 0; i < shapeTypeCount; i++)
1313 		{
1314 			if ((m_shapesPresent & TRESConditionalLine) &&
1315 				i == conditionalLineIndex)
1316 			{
1317 				continue;
1318 			}
1319 			TCULongArray *theseIndices = (*m_indices)[i];
1320 			TCULongArray *newIndices =
1321 				new TCULongArray(theseIndices->getCount());
1322 			TCULongArray *theseStripCounts = (*m_stripCounts)[i];
1323 			int indexCount = theseIndices->getCount();
1324 
1325 			if (i < firstStripIndex)
1326 			{
1327 				invertShapes(theseIndices, newIndices);
1328 			}
1329 			else
1330 			{
1331 				if ((m_shapesPresent & TRESTriangleStrip) &&
1332 					i == triangleStripIndex)
1333 				{
1334 					int numStrips = theseStripCounts->getCount();
1335 					int indexOffset = 0;
1336 
1337 					for (j = 0; j < numStrips; j++)
1338 					{
1339 						int stripCount = (*theseStripCounts)[j];
1340 
1341 						if (stripCount % 2)
1342 						{
1343 							invertULongArray(theseIndices, indexOffset,
1344 								indexOffset + stripCount);
1345 						}
1346 						else
1347 						{
1348 							printf("Cannot invert tri strip with even number "
1349 								"of points.\n");
1350 						}
1351 						indexOffset += stripCount;
1352 					}
1353 					for (j = 0; j < indexCount; j++)
1354 					{
1355 						newIndices->addValue(flipNormal((*theseIndices)[j]));
1356 					}
1357 				}
1358 				else if ((m_shapesPresent & TRESQuadStrip) &&
1359 					i == quadStripIndex)
1360 				{
1361 					for (j = 0; j < indexCount; j += 2)
1362 					{
1363 						TCULong index1 = (*theseIndices)[j];
1364 						TCULong index2 = (*theseIndices)[j + 1];
1365 
1366 						newIndices->addValue(flipNormal(index2));
1367 						newIndices->addValue(flipNormal(index1));
1368 					}
1369 				}
1370 				else if ((m_shapesPresent & TRESTriangleFan) &&
1371 					i == triangleFanIndex)
1372 				{
1373 					int numStrips = theseStripCounts->getCount();
1374 					int indexOffset = 0;
1375 
1376 					for (j = 0; j < numStrips; j++)
1377 					{
1378 						int stripCount = (*theseStripCounts)[j];
1379 
1380 						invertULongArray(theseIndices, indexOffset + 1,
1381 							indexOffset + stripCount);
1382 						indexOffset += stripCount;
1383 					}
1384 					for (j = 0; j < indexCount; j++)
1385 					{
1386 						newIndices->addValue(flipNormal((*theseIndices)[j]));
1387 					}
1388 				}
1389 			}
1390 			m_indices->replaceObject(newIndices, i);
1391 			newIndices->release();
1392 		}
1393 	}
1394 }
1395 
unMirror(void)1396 void TREShapeGroup::unMirror(void)
1397 {
1398 	if (m_indices)
1399 	{
1400 		int i, j;
1401 		int shapeTypeCount = m_indices->getCount();
1402 		int firstStripIndex = getShapeTypeIndex(TRESFirstStrip);
1403 		int triangleStripIndex = getShapeTypeIndex(TRESTriangleStrip);
1404 		int quadStripIndex = getShapeTypeIndex(TRESQuadStrip);
1405 		int triangleFanIndex = getShapeTypeIndex(TRESTriangleFan);
1406 		int conditionalLineIndex = getShapeTypeIndex(TRESConditionalLine);
1407 
1408 		for (i = 0; i < shapeTypeCount; i++)
1409 		{
1410 			if ((m_shapesPresent & TRESConditionalLine) &&
1411 				i == conditionalLineIndex)
1412 			{
1413 				continue;
1414 			}
1415 			TCULongArray *theseIndices = (*m_indices)[i];
1416 			TCULongArray *theseStripCounts = (*m_stripCounts)[i];
1417 			int indexCount = theseIndices->getCount();
1418 
1419 			if (i < firstStripIndex)
1420 			{
1421 				invertULongArray(theseIndices);
1422 				mirrorTextureCoords(theseIndices);
1423 			}
1424 			else
1425 			{
1426 				if ((m_shapesPresent & TRESTriangleStrip) &&
1427 					i == triangleStripIndex)
1428 				{
1429 					int numStrips = theseStripCounts->getCount();
1430 					int indexOffset = 0;
1431 
1432 					for (j = 0; j < numStrips; j++)
1433 					{
1434 						int stripCount = (*theseStripCounts)[j];
1435 
1436 						if (stripCount % 2)
1437 						{
1438 							invertULongArray(theseIndices, indexOffset,
1439 								indexOffset + stripCount);
1440 						}
1441 						else
1442 						{
1443 							printf("Cannot un-mirror tri strip with even "
1444 								"number of points.\n");
1445 						}
1446 						indexOffset += stripCount;
1447 					}
1448 				}
1449 				else if ((m_shapesPresent & TRESQuadStrip) &&
1450 					i == quadStripIndex)
1451 				{
1452 					for (j = 0; j < indexCount; j += 2)
1453 					{
1454 						TCULong temp1 = (*theseIndices)[j];
1455 						TCULong temp2 = (*theseIndices)[j + 1];
1456 
1457 						theseIndices->replaceValue(temp2, j);
1458 						theseIndices->replaceValue(temp1, j + 1);
1459 					}
1460 				}
1461 				else if ((m_shapesPresent & TRESTriangleFan) &&
1462 					i == triangleFanIndex)
1463 				{
1464 					int numStrips = theseStripCounts->getCount();
1465 					int indexOffset = 0;
1466 
1467 					for (j = 0; j < numStrips; j++)
1468 					{
1469 						int stripCount = (*theseStripCounts)[j];
1470 
1471 						invertULongArray(theseIndices, indexOffset + 1,
1472 							indexOffset + stripCount);
1473 						indexOffset += stripCount;
1474 					}
1475 					mirrorTextureCoords(theseIndices);
1476 				}
1477 			}
1478 		}
1479 	}
1480 }
1481 
mirrorTextureCoords(TCULongArray * indices)1482 void TREShapeGroup::mirrorTextureCoords(TCULongArray *indices)
1483 {
1484 	TREVertexArray *textureCoords = m_vertexStore->getTextureCoords();
1485 
1486 	if (textureCoords)
1487 	{
1488 		int i;
1489 		int count = indices->getCount();
1490 
1491 		for (i = 0; i < count; i++)
1492 		{
1493 			int index = (*indices)[i];
1494 			TREVertex &textureCoord = textureCoords->vertexAtIndex(index);
1495 
1496 			textureCoord.v[0] = 1.0f - textureCoord.v[0];
1497 		}
1498 	}
1499 }
1500 
transferTriangle(TRESTransferType type,TCULong color,TCULong index0,TCULong index1,TCULong index2,const TCFloat * matrix,bool bfcInvert)1501 void TREShapeGroup::transferTriangle(
1502 	TRESTransferType type,
1503 	TCULong color,
1504 	TCULong index0,
1505 	TCULong index1,
1506 	TCULong index2,
1507 	const TCFloat *matrix,
1508 	bool bfcInvert)
1509 {
1510 	TREVertexArray *oldVertices = m_vertexStore->getVertices();
1511 	TREVertexArray *oldNormals = m_vertexStore->getNormals();
1512 	TREVertexArray *oldTextureCoords = m_vertexStore->getTextureCoords();
1513 	TREVertex vertex = (*oldVertices)[index0];
1514 	TREVertex normal = (*oldNormals)[index0];
1515 	TCVector vertices[3];
1516 	TCVector normals[3];
1517 	TCVector textureCoords[3];
1518 	bool mirrored = TCVector::determinant(matrix) < 0.0;
1519 
1520 	vertices[0] =
1521 		TCVector(vertex.v[0], vertex.v[1], vertex.v[2]).transformPoint(matrix);
1522 	normals[0] =
1523 		TCVector(normal.v[0], normal.v[1], normal.v[2]).transformNormal(matrix);
1524 	vertex = (*oldVertices)[index1];
1525 	normal = (*oldNormals)[index1];
1526 	vertices[1] =
1527 		TCVector(vertex.v[0], vertex.v[1], vertex.v[2]).transformPoint(matrix);
1528 	normals[1] =
1529 		TCVector(normal.v[0], normal.v[1], normal.v[2]).transformNormal(matrix);
1530 	vertex = (*oldVertices)[index2];
1531 	normal = (*oldNormals)[index2];
1532 	vertices[2] =
1533 		TCVector(vertex.v[0], vertex.v[1], vertex.v[2]).transformPoint(matrix);
1534 	normals[2] =
1535 		TCVector(normal.v[0], normal.v[1], normal.v[2]).transformNormal(matrix);
1536 	if (mirrored)
1537 	{
1538 		normals[0] *= -1.0f;
1539 		normals[1] *= -1.0f;
1540 		normals[2] *= -1.0f;
1541 	}
1542 	if (oldTextureCoords)
1543 	{
1544 		textureCoords[0] = TCVector((*oldTextureCoords)[index0].v);
1545 		textureCoords[1] = TCVector((*oldTextureCoords)[index1].v);
1546 		textureCoords[2] = TCVector((*oldTextureCoords)[index2].v);
1547 	}
1548 	if (bfcInvert)
1549 	{
1550 		normals[0] *= -1.0f;
1551 		normals[1] *= -1.0f;
1552 		normals[2] *= -1.0f;
1553 		std::swap(vertices[0], vertices[2]);
1554 		std::swap(normals[0], normals[2]);
1555 		std::swap(textureCoords[0], textureCoords[2]);
1556 	}
1557 	m_mainModel->addTransferTriangle(type, color, vertices, normals,
1558 		m_bfc, textureCoords, matrix);
1559 }
1560 
transferQuadStrip(TRESTransferType type,int shapeTypeIndex,TCULong color,int offset,int stripCount,const TCFloat * matrix,bool bfcInvert)1561 void TREShapeGroup::transferQuadStrip(
1562 	TRESTransferType type,
1563 	int shapeTypeIndex,
1564 	TCULong color,
1565 	int offset,
1566 	int stripCount,
1567 	const TCFloat *matrix,
1568 	bool bfcInvert)
1569 {
1570 	int i;
1571 	TCULongArray *indices = (*m_indices)[shapeTypeIndex];
1572 
1573 	for (i = offset; i < offset + stripCount - 2; i++)
1574 	{
1575 		if ((i - offset) % 2)
1576 		{
1577 			transferTriangle(type, color, (*indices)[i], (*indices)[i + 2],
1578 				(*indices)[i + 1], matrix, bfcInvert);
1579 		}
1580 		else
1581 		{
1582 			transferTriangle(type, color, (*indices)[i], (*indices)[i + 1],
1583 				(*indices)[i + 2], matrix, bfcInvert);
1584 		}
1585 	}
1586 }
1587 
transferTriangleStrip(TRESTransferType type,int shapeTypeIndex,TCULong color,int offset,int stripCount,const TCFloat * matrix,bool bfcInvert)1588 void TREShapeGroup::transferTriangleStrip(
1589 	TRESTransferType type,
1590 	int shapeTypeIndex,
1591 	TCULong color,
1592 	int offset,
1593 	int stripCount,
1594 	const TCFloat *matrix,
1595 	bool bfcInvert)
1596 {
1597 	int i;
1598 	TCULongArray *indices = (*m_indices)[shapeTypeIndex];
1599 
1600 	for (i = offset; i < offset + stripCount - 2; i++)
1601 	{
1602 		if ((i - offset) % 2)
1603 		{
1604 			transferTriangle(type, color, (*indices)[i], (*indices)[i + 2],
1605 				(*indices)[i + 1], matrix, bfcInvert);
1606 		}
1607 		else
1608 		{
1609 			transferTriangle(type, color, (*indices)[i], (*indices)[i + 1],
1610 				(*indices)[i + 2], matrix, bfcInvert);
1611 		}
1612 	}
1613 }
1614 
transferTriangleFan(TRESTransferType type,int shapeTypeIndex,TCULong color,int offset,int stripCount,const TCFloat * matrix,bool bfcInvert)1615 void TREShapeGroup::transferTriangleFan(
1616 	TRESTransferType type,
1617 	int shapeTypeIndex,
1618 	TCULong color,
1619 	int offset,
1620 	int stripCount,
1621 	const TCFloat *matrix,
1622 	bool bfcInvert)
1623 {
1624 	int i;
1625 	TCULongArray *indices = (*m_indices)[shapeTypeIndex];
1626 
1627 	for (i = offset; i < offset + stripCount - 2; i++)
1628 	{
1629 		transferTriangle(type, color, (*indices)[offset], (*indices)[i + 1],
1630 			(*indices)[i + 2], matrix, bfcInvert);
1631 	}
1632 }
1633 
isTransparent(TCULong color,bool hostFormat)1634 bool TREShapeGroup::isTransparent(TCULong color, bool hostFormat)
1635 {
1636 	TCULong transparentThreshold = 240;
1637 	if (hostFormat)
1638 	{
1639 		return (htonl(color) & 0xFF) < transparentThreshold;
1640 	}
1641 	else
1642 	{
1643 		return (color & 0xFF) < transparentThreshold;
1644 	}
1645 }
1646 
transfer(TRESTransferType type,TCULong color,const TCFloat * matrix,bool bfcInvert)1647 void TREShapeGroup::transfer(
1648 	TRESTransferType type,
1649 	TCULong color,
1650 	const TCFloat *matrix,
1651 	bool bfcInvert /*= false*/)
1652 {
1653 	if (m_indices && (type != TTTransparent || isTransparent(color, true)))
1654 	{
1655 		int bit;
1656 
1657 		for (bit = TRESFirst; (TREShapeType)bit <= TRESLast; bit = bit << 1)
1658 		{
1659 			TREShapeType shapeType = (TREShapeType)bit;
1660 			TCULongArray *transferIndices =
1661 				getTransferIndices(type, (TREShapeType)bit);
1662 
1663 			if (transferIndices != NULL && transferIndices->getCount())
1664 			{
1665 				// If we already have transfer indices, then we've
1666 				// already processed this model and recorded which indices
1667 				// to transfer.  If that is the case, we don't want to
1668 				// re-record the indices.
1669 				transferIndices = NULL;
1670 			}
1671 			if (type != TTTexmapped || isTexmappedShapeType(shapeType))
1672 			{
1673 				transfer(type, htonl(color), shapeType, getIndices(shapeType),
1674 					transferIndices, matrix, bfcInvert);
1675 			}
1676 		}
1677 	}
1678 }
1679 
shouldTransferIndex(TRESTransferType type,TREShapeType shapeType,TCULong color,int index,const TCFloat * matrix)1680 bool TREShapeGroup::shouldTransferIndex(
1681 	TRESTransferType type,
1682 	TREShapeType shapeType,
1683 	TCULong color,
1684 	int index,
1685 	const TCFloat *matrix)
1686 {
1687 	return shouldTransferIndex(type, shapeType, color, index, false, matrix);
1688 }
1689 
1690 // Note: static method.
isTexmappedShapeType(TREShapeType shapeType)1691 bool TREShapeGroup::isTexmappedShapeType(TREShapeType shapeType)
1692 {
1693 	switch (shapeType)
1694 	{
1695 	case TRESTriangle:
1696 	case TRESQuad:
1697 	case TRESTriangleStrip:
1698 	case TRESQuadStrip:
1699 	case TRESTriangleFan:
1700 		return true;
1701 	default:
1702 		return false;
1703 	}
1704 }
1705 
shouldTransferIndex(TRESTransferType type,TREShapeType shapeType,TCULong color,int index,bool colored,const TCFloat * matrix)1706 bool TREShapeGroup::shouldTransferIndex(
1707 	TRESTransferType type,
1708 	TREShapeType shapeType,
1709 	TCULong color,
1710 	int index,
1711 	bool colored,
1712 	const TCFloat *matrix)
1713 {
1714 	switch (type)
1715 	{
1716 	case TTTransparent:
1717 		return isTransparent(color, false);
1718 	case TTTexmapped:
1719 		if (isTexmappedShapeType(shapeType))
1720 		{
1721 			TREModel::TexmapInfoList::const_iterator it;
1722 			const TREModel::TexmapInfoList &texmapInfos =
1723 				m_model->getTexmapInfos();
1724 
1725 			if (m_mainModel->getModelTexmapTransferFlag())
1726 			{
1727 				return true;
1728 			}
1729 			for (it = texmapInfos.begin(); it != texmapInfos.end(); ++it)
1730 			{
1731 				const TREModel::TexmapInfo::GeomInfo &geomInfo =
1732 					m_bfc ? it->bfc : it->standard;
1733 				const TREModel::TexmapInfo::GeomSubInfo &geomSubInfo =
1734 					colored ? geomInfo.colored : geomInfo.standard;
1735 				const IntSet *shapes = NULL;
1736 
1737 				switch (shapeType)
1738 				{
1739 				case TRESTriangle:
1740 					shapes = &geomSubInfo.triangles;
1741 					break;
1742 				case TRESQuad:
1743 					shapes = &geomSubInfo.quads;
1744 					break;
1745 				case TRESTriangleStrip:
1746 					shapes = &geomSubInfo.triStrips;
1747 					break;
1748 				case TRESQuadStrip:
1749 					shapes = &geomSubInfo.quadStrips;
1750 					break;
1751 				default:
1752 					// Get rid of warning.
1753 					break;
1754 				}
1755 
1756 				if (shapes->find(index) != shapes->end())
1757 				{
1758 					// It should be impossible to get here with a strip, since
1759 					// strips can only show up as sub-files, but keep the code
1760 					// above handling strips anyway, just in case.
1761 					m_mainModel->setTransferTexmapInfo(*it, m_bfc, matrix);
1762 					return true;
1763 				}
1764 			}
1765 		}
1766 	}
1767 	return false;
1768 }
1769 
transfer(TRESTransferType type,TCULong color,TREShapeType shapeType,TCULongArray * indices,TCULongArray * transferIndices,const TCFloat * matrix,bool bfcInvert)1770 void TREShapeGroup::transfer(
1771 	TRESTransferType type,
1772 	TCULong color,
1773 	TREShapeType shapeType,
1774 	TCULongArray *indices,
1775 	TCULongArray *transferIndices,
1776 	const TCFloat *matrix,
1777 	bool bfcInvert)
1778 {
1779 	TREVertexArray *oldVertices = m_vertexStore->getVertices();
1780 	TREVertexArray *oldNormals = m_vertexStore->getNormals();
1781 
1782 	if (indices && oldVertices && oldNormals)
1783 	{
1784 		int i;
1785 		int count = indices->getCount();
1786 
1787 		if (shapeType == TRESTriangle || shapeType == TRESQuad)
1788 		{
1789 			int shapeSize = numPointsForShapeType(shapeType);
1790 
1791 			if (shapeSize > 2)
1792 			{
1793 				// Start at the end and work backward.  This makes the removal
1794 				// of fully transparent geometry more efficient later.
1795 				for (i = count - shapeSize; i >= 0; i -= shapeSize)
1796 				{
1797 					TCULong index = (*indices)[i];
1798 
1799 					if (shouldTransferIndex(type, shapeType, color, index,
1800 						matrix))
1801 					{
1802 						transferTriangle(type, color, index, (*indices)[i + 1],
1803 							(*indices)[i + 2], matrix, bfcInvert);
1804 						if (shapeSize == 4)
1805 						{
1806 							transferTriangle(type, color, index,
1807 								(*indices)[i + 2], (*indices)[i + 3], matrix,
1808 								bfcInvert);
1809 						}
1810 						recordTransfer(transferIndices, i, shapeSize);
1811 					}
1812 				}
1813 			}
1814 		}
1815 		else if (shapeType >= TRESFirstStrip && shapeType <= TRESLast)
1816 		{
1817 			int shapeTypeIndex = getShapeTypeIndex(shapeType);
1818 			TCULongArray *stripCounts = (*m_stripCounts)[shapeTypeIndex];
1819 			int numStrips = stripCounts->getCount();
1820 			int offset = count;
1821 
1822 			for (i = numStrips - 1; i >= 0; i--)
1823 			{
1824 				int stripCount = (*stripCounts)[i];
1825 
1826 				offset -= stripCount;
1827 				if (shouldTransferIndex(type, shapeType, color, offset, matrix))
1828 				{
1829 					switch (shapeType)
1830 					{
1831 					case TRESTriangleStrip:
1832 						transferTriangleStrip(type, shapeTypeIndex, color, offset,
1833 							stripCount, matrix, bfcInvert);
1834 						break;
1835 					case TRESQuadStrip:
1836 						transferQuadStrip(type, shapeTypeIndex, color, offset,
1837 							stripCount, matrix, bfcInvert);
1838 						break;
1839 					case TRESTriangleFan:
1840 						transferTriangleFan(type, shapeTypeIndex, color, offset,
1841 							stripCount, matrix, bfcInvert);
1842 						break;
1843 					default:
1844 						break;
1845 					}
1846 					recordTransfer(transferIndices, offset, stripCount);
1847 				}
1848 			}
1849 		}
1850 	}
1851 }
1852 
flatten(TREShapeGroup * srcShapes,const TCFloat * matrix,TCULong color,bool colorSet,bool skipTexmapped)1853 void TREShapeGroup::flatten(
1854 	TREShapeGroup *srcShapes,
1855 	const TCFloat *matrix,
1856 	TCULong color,
1857 	bool colorSet,
1858 	bool skipTexmapped)
1859 {
1860 	skipTexmapped = false;
1861 	TREVertexStore *srcVertexStore = NULL;
1862 
1863 	if (srcShapes && (srcVertexStore = srcShapes->getVertexStore()) != NULL &&
1864 		m_vertexStore != NULL)
1865 	{
1866 		TCULong bit;
1867 
1868 		for (bit = TRESFirst; bit <= TRESLast; bit = bit << 1)
1869 		{
1870 			TREShapeType shapeType = (TREShapeType)bit;
1871 			TCULongArray *srcIndices = srcShapes->getIndices(shapeType);
1872 
1873 			if (skipTexmapped && isTexmappedShapeType(shapeType))
1874 			{
1875 				continue;
1876 			}
1877 			if (srcIndices)
1878 			{
1879 				TREVertexArray *srcVertices = srcVertexStore->getVertices();
1880 				TREVertexArray *srcNormals = srcVertexStore->getNormals();
1881 				TREVertexArray *srcTextureCoords =
1882 					srcVertexStore->getTextureCoords();
1883 				TCULongArray *srcColors = srcVertexStore->getColors();
1884 				GLbooleanVector &srcEdgeFlags = srcVertexStore->getEdgeFlags();
1885 				TCULongArray *dstIndices = getIndices(shapeType, true);
1886 				TCULongArray *srcCPIndices = NULL;
1887 				TCULongArray *dstCPIndices = NULL;
1888 
1889 				if (shapeType == TRESConditionalLine)
1890 				{
1891 					srcCPIndices = srcShapes->getControlPointIndices();
1892 					dstCPIndices = getControlPointIndices(true);
1893 				}
1894 				if (srcVertices)
1895 				{
1896 					TREVertexArray *dstVertices = m_vertexStore->getVertices();
1897 					TREVertexArray *dstNormals = m_vertexStore->getNormals();
1898 					TREVertexArray *dstTextureCoords =
1899 						m_vertexStore->getTextureCoords();
1900 					TCULongArray *dstColors = m_vertexStore->getColors();
1901 					GLbooleanVector &dstEdgeFlags =
1902 						m_vertexStore->getEdgeFlags();
1903 
1904 					if (shapeType < TRESFirstStrip)
1905 					{
1906 						flattenShapes(dstVertices, dstNormals, dstTextureCoords,
1907 							dstColors, dstIndices, dstCPIndices, dstEdgeFlags,
1908 							srcVertices, srcNormals, srcTextureCoords,
1909 							srcColors, srcIndices, srcCPIndices, srcEdgeFlags,
1910 							matrix, color, colorSet);
1911 					}
1912 					else
1913 					{
1914 						TCULongArray *dstStripCounts = getStripCounts(shapeType,
1915 							true);
1916 						TCULongArray *srcStripCounts =
1917 							srcShapes->getStripCounts(shapeType);
1918 
1919 						flattenStrips(dstVertices, dstNormals, dstTextureCoords,
1920 							dstColors, dstIndices, dstStripCounts, srcVertices,
1921 							srcNormals, srcTextureCoords, srcColors, srcIndices,
1922 							srcStripCounts, matrix, color, colorSet);
1923 					}
1924 				}
1925 			}
1926 		}
1927 	}
1928 }
1929 
flattenShapes(TREVertexArray * dstVertices,TREVertexArray * dstNormals,TREVertexArray * dstTextureCoords,TCULongArray * dstColors,TCULongArray * dstIndices,TCULongArray * dstCPIndices,GLbooleanVector & dstEdgeFlags,TREVertexArray * srcVertices,TREVertexArray * srcNormals,TREVertexArray * srcTextureCoords,TCULongArray * srcColors,TCULongArray * srcIndices,TCULongArray * srcCPIndices,GLbooleanVector & srcEdgeFlags,const TCFloat * matrix,TCULong color,bool colorSet)1930 void TREShapeGroup::flattenShapes(TREVertexArray *dstVertices,
1931 								  TREVertexArray *dstNormals,
1932 								  TREVertexArray *dstTextureCoords,
1933 								  TCULongArray *dstColors,
1934 								  TCULongArray *dstIndices,
1935 								  TCULongArray *dstCPIndices,
1936 								  GLbooleanVector &dstEdgeFlags,
1937 								  TREVertexArray *srcVertices,
1938 								  TREVertexArray *srcNormals,
1939 								  TREVertexArray *srcTextureCoords,
1940 								  TCULongArray *srcColors,
1941 								  TCULongArray *srcIndices,
1942 								  TCULongArray *srcCPIndices,
1943 								  GLbooleanVector &srcEdgeFlags,
1944 								  const TCFloat *matrix,
1945 								  TCULong color,
1946 								  bool colorSet)
1947 {
1948 	int i;
1949 	int count = srcIndices->getCount();
1950 	int addedVertexCount = 0;
1951 
1952 	for (i = 0; i < count; i++)
1953 	{
1954 		int index = (*srcIndices)[i];
1955 		TREVertex vertex = (*srcVertices)[index];
1956 
1957 		dstIndices->addValue(dstVertices->getCount());
1958 		transformVertex(vertex, matrix);
1959 		dstVertices->addVertex(vertex);
1960 		++addedVertexCount;
1961 		if (srcNormals)
1962 		{
1963 			TREVertex normal = (*srcNormals)[index];
1964 
1965 			transformNormal(normal, matrix);
1966 			dstNormals->addVertex(normal);
1967 		}
1968 		if (srcTextureCoords)
1969 		{
1970 			dstTextureCoords->addVertex((*srcTextureCoords)[index]);
1971 		}
1972 		if (colorSet)
1973 		{
1974 			dstColors->addValue(color);
1975 		}
1976 		else if (srcColors)
1977 		{
1978 			dstColors->addValue((*srcColors)[index]);
1979 		}
1980 		if (srcCPIndices && dstCPIndices)
1981 		{
1982 			if (srcEdgeFlags.size() > 0)
1983 			{
1984 				if (dstEdgeFlags.size() > 0)
1985 				{
1986 					int j;
1987 
1988 					for (j = (int)dstEdgeFlags.size(); j <
1989 						dstVertices->getCount() - 1; j++)
1990 					{
1991 						dstEdgeFlags.push_back(GL_TRUE);
1992 					}
1993 					dstEdgeFlags.push_back(GL_TRUE);
1994 				}
1995 				index++;
1996 				// If we have control point indices, that means this is a
1997 				// conditional, and therefore we need to copy the extra edge
1998 				// flag.
1999 				dstVertices->addVertex(vertex);
2000 				++addedVertexCount;
2001 				if (srcNormals)
2002 				{
2003 					// This is a line; it doesn't have a normal.
2004 					TREVertex normal;
2005 
2006 					dstNormals->addVertex(normal);
2007 				}
2008 				if (srcTextureCoords)
2009 				{
2010 					dstTextureCoords->addVertex((*srcTextureCoords)[index]);
2011 				}
2012 				if (colorSet)
2013 				{
2014 					dstColors->addValue(color);
2015 				}
2016 				else if (srcColors)
2017 				{
2018 					dstColors->addValue((*srcColors)[index]);
2019 				}
2020 				if (dstEdgeFlags.size() > 0)
2021 				{
2022 					dstEdgeFlags.push_back(GL_FALSE);
2023 				}
2024 				else
2025 				{
2026 					debugPrintf("No dstEdgeFlags\n");
2027 				}
2028 			}
2029 			index = (*srcCPIndices)[i];
2030 			vertex = (*srcVertices)[index];
2031 			dstCPIndices->addValue(dstVertices->getCount());
2032 			transformVertex(vertex, matrix);
2033 			dstVertices->addVertex(vertex);
2034 			++addedVertexCount;
2035 			if (srcNormals)
2036 			{
2037 				dstNormals->addVertex((*srcNormals)[index]);
2038 			}
2039 			if (colorSet)
2040 			{
2041 				dstColors->addValue(color);
2042 			}
2043 			else if (srcColors)
2044 			{
2045 				dstColors->addValue((*srcColors)[index]);
2046 			}
2047 			if (dstEdgeFlags.size() > 0)
2048 			{
2049 				dstEdgeFlags.push_back(GL_FALSE);
2050 			}
2051 		}
2052 	}
2053 	if (dstTextureCoords != NULL && srcTextureCoords == NULL &&
2054 		addedVertexCount > 0)
2055 	{
2056 		dstTextureCoords->addEmptyValues(addedVertexCount);
2057 	}
2058 }
2059 
flattenStrips(TREVertexArray * dstVertices,TREVertexArray * dstNormals,TREVertexArray * dstTextureCoords,TCULongArray * dstColors,TCULongArray * dstIndices,TCULongArray * dstStripCounts,TREVertexArray * srcVertices,TREVertexArray * srcNormals,TREVertexArray * srcTextureCoords,TCULongArray * srcColors,TCULongArray * srcIndices,TCULongArray * srcStripCounts,const TCFloat * matrix,TCULong color,bool colorSet)2060 void TREShapeGroup::flattenStrips(TREVertexArray *dstVertices,
2061 								  TREVertexArray *dstNormals,
2062 								  TREVertexArray *dstTextureCoords,
2063 								  TCULongArray *dstColors,
2064 								  TCULongArray *dstIndices,
2065 								  TCULongArray *dstStripCounts,
2066 								  TREVertexArray *srcVertices,
2067 								  TREVertexArray *srcNormals,
2068 								  TREVertexArray *srcTextureCoords,
2069 								  TCULongArray *srcColors,
2070 								  TCULongArray *srcIndices,
2071 								  TCULongArray *srcStripCounts,
2072 								  const TCFloat *matrix, TCULong color,
2073 								  bool colorSet)
2074 {
2075 	int i, j;
2076 	int numStrips = srcStripCounts->getCount();
2077 	int indexOffset = 0;
2078 	int addedVertexCount = 0;
2079 
2080 	for (i = 0; i < numStrips; i++)
2081 	{
2082 		int stripCount = (*srcStripCounts)[i];
2083 
2084 		dstStripCounts->addValue(stripCount);
2085 		for (j = 0; j < stripCount; j++)
2086 		{
2087 			int index = (*srcIndices)[j + indexOffset];
2088 			TREVertex vertex = (*srcVertices)[index];
2089 
2090 			dstIndices->addValue(dstVertices->getCount());
2091 			transformVertex(vertex, matrix);
2092 			dstVertices->addVertex(vertex);
2093 			++addedVertexCount;
2094 			if (srcNormals)
2095 			{
2096 				TREVertex normal = (*srcNormals)[index];
2097 
2098 				transformNormal(normal, matrix);
2099 				dstNormals->addVertex(normal);
2100 			}
2101 			if (srcTextureCoords)
2102 			{
2103 				dstTextureCoords->addVertex((*srcTextureCoords)[index]);
2104 			}
2105 			if (colorSet)
2106 			{
2107 				dstColors->addValue(color);
2108 			}
2109 			else if (srcColors)
2110 			{
2111 				dstColors->addValue((*srcColors)[index]);
2112 			}
2113 		}
2114 		indexOffset += stripCount;
2115 	}
2116 	if (dstTextureCoords != NULL && srcTextureCoords == NULL &&
2117 		addedVertexCount > 0)
2118 	{
2119 		dstTextureCoords->addEmptyValues(addedVertexCount);
2120 	}
2121 }
2122 
transformVertex(TREVertex & vertex,const TCFloat * matrix)2123 void TREShapeGroup::transformVertex(TREVertex &vertex, const TCFloat *matrix)
2124 {
2125 	TCVector newVertex;
2126 	TCFloat x = vertex.v[0];
2127 	TCFloat y = vertex.v[1];
2128 	TCFloat z = vertex.v[2];
2129 
2130 //	x' = a*x + b*y + c*z + X
2131 //	y' = d*x + e*y + f*z + Y
2132 //	z' = g*x + h*y + i*z + Z
2133 	newVertex[0] = matrix[0]*x + matrix[4]*y + matrix[8]*z + matrix[12];
2134 	newVertex[1] = matrix[1]*x + matrix[5]*y + matrix[9]*z + matrix[13];
2135 	newVertex[2] = matrix[2]*x + matrix[6]*y + matrix[10]*z + matrix[14];
2136 	TREVertexStore::initVertex(vertex, newVertex);
2137 }
2138 
transformNormal(TREVertex & normal,const TCFloat * matrix)2139 void TREShapeGroup::transformNormal(TREVertex &normal, const TCFloat *matrix)
2140 {
2141 	TCVector newNormal;
2142 	TCFloat inverseMatrix[16];
2143 	TCFloat x = normal.v[0];
2144 	TCFloat y = normal.v[1];
2145 	TCFloat z = normal.v[2];
2146 
2147 	TCVector::invertMatrix(matrix, inverseMatrix);
2148 //	x' = a*x + b*y + c*z + X
2149 //	y' = d*x + e*y + f*z + Y
2150 //	z' = g*x + h*y + i*z + Z
2151 	newNormal[0] = inverseMatrix[0]*x + inverseMatrix[1]*y +
2152 		inverseMatrix[2]*z;
2153 	newNormal[1] = inverseMatrix[4]*x + inverseMatrix[5]*y + inverseMatrix[6]*z;
2154 	newNormal[2] = inverseMatrix[8]*x + inverseMatrix[9]*y +
2155 		inverseMatrix[10]*z;
2156 	if (newNormal.lengthSquared() > 0)
2157 	{
2158 		newNormal.normalize();
2159 	}
2160 	TREVertexStore::initVertex(normal, newNormal);
2161 }
2162 
updateConditionalsStepCount(int step)2163 void TREShapeGroup::updateConditionalsStepCount(int step)
2164 {
2165 	TCULongArray *itemArray = getIndices(TRESConditionalLine);
2166 	int count = 0;
2167 
2168 	if (itemArray)
2169 	{
2170 		count = itemArray->getCount();
2171 	}
2172 	if (m_stepCounts[TRESConditionalLine].size() < (size_t)step)
2173 	{
2174 		m_stepCounts[TRESConditionalLine][step] = count;
2175 	}
2176 	else
2177 	{
2178 		m_stepCounts[TRESConditionalLine].push_back(count);
2179 	}
2180 }
2181 
nextStep(TREShapeType shapeType)2182 void TREShapeGroup::nextStep(TREShapeType shapeType)
2183 {
2184 	TCULongArray *itemArray;
2185 	if (shapeType < TRESFirstStrip)
2186 	{
2187 		itemArray = getIndices(shapeType);
2188 	}
2189 	else
2190 	{
2191 		itemArray = getStripCounts(shapeType);
2192 	}
2193 	if (itemArray)
2194 	{
2195 		m_stepCounts[shapeType].push_back(itemArray->getCount());
2196 	}
2197 	else
2198 	{
2199 		m_stepCounts[shapeType].push_back(0);
2200 	}
2201 }
2202 
nextStep(void)2203 void TREShapeGroup::nextStep(void)
2204 {
2205 	int bit;
2206 
2207 	for (bit = TRESFirst; (TREShapeType)bit < TRESLast; bit = bit << 1)
2208 	{
2209 		nextStep((TREShapeType)bit);
2210 	}
2211 }
2212 
getIndexCount(TREShapeType shapeType)2213 int TREShapeGroup::getIndexCount(TREShapeType shapeType)
2214 {
2215 	if (!m_mainModel->onLastStep())
2216 	{
2217 		int step = m_mainModel->getStep();
2218 		IntVector &counts = m_stepCounts[shapeType];
2219 
2220 		if ((size_t)step < counts.size())
2221 		{
2222 			return counts[step];
2223 		}
2224 	}
2225 	TCULongArray *indices = getIndices(shapeType);
2226 
2227 	if (indices)
2228 	{
2229 		return indices->getCount();
2230 	}
2231 	else
2232 	{
2233 		return 0;
2234 	}
2235 }
2236 
setModel(TREModel * value)2237 void TREShapeGroup::setModel(TREModel *value)
2238 {
2239 	m_model = value;
2240 	m_mainModel = m_model->getMainModel();
2241 }
2242 
cleanupTransfer(void)2243 void TREShapeGroup::cleanupTransfer(void)
2244 {
2245 	int i, j;
2246 
2247 	if (m_transferIndices != NULL)
2248 	{
2249 		int arrayCount = m_transferIndices->getCount();
2250 
2251 		for (i = 0; i < arrayCount; i++)
2252 		{
2253 			TCULongArray *transparentIndices = (*m_transferIndices)[i];
2254 			TCULongArray *indices = (*m_indices)[i];
2255 			int indexCount = transparentIndices->getCount();
2256 
2257 			for (j = 0; j < indexCount; j++)
2258 			{
2259 				indices->removeValueAtIndex((*transparentIndices)[j]);
2260 			}
2261 		}
2262 		m_transferIndices->release();
2263 		m_transferIndices = NULL;
2264 	}
2265 }
2266 
getTransferIndices(TRESTransferType type,TREShapeType shapeType)2267 TCULongArray *TREShapeGroup::getTransferIndices(
2268 	TRESTransferType type,
2269 	TREShapeType shapeType)
2270 {
2271 	if (shouldGetTransferIndices(type))
2272 	{
2273 		TCULong index = getShapeTypeIndex(shapeType);
2274 
2275 		if (!(m_shapesPresent & shapeType))
2276 		{
2277 			return NULL;
2278 		}
2279 		if (!m_transferIndices)
2280 		{
2281 			int i;
2282 			int count = m_indices->getCount();
2283 
2284 			m_transferIndices = new TCULongArrayArray;
2285 			for (i = 0; i < count; i++)
2286 			{
2287 				TCULongArray *indices = new TCULongArray;
2288 
2289 				m_transferIndices->addObject(indices);
2290 				indices->release();
2291 			}
2292 		}
2293 		return (*m_transferIndices)[index];
2294 	}
2295 	else
2296 	{
2297 		return NULL;
2298 	}
2299 }
2300 
shouldGetTransferIndices(TRESTransferType type)2301 bool TREShapeGroup::shouldGetTransferIndices(TRESTransferType type)
2302 {
2303 	switch (type)
2304 	{
2305 	case TTTexmapped:
2306 		return !m_mainModel->getModelTexmapTransferFlag();
2307 	default:
2308 		return false;
2309 	}
2310 }
2311 
recordTransfer(TCULongArray * transferIndices,int index,int shapeSize)2312 void TREShapeGroup::recordTransfer(
2313 	TCULongArray *transferIndices,
2314 	int index,
2315 	int shapeSize)
2316 {
2317 	if (transferIndices)
2318 	{
2319 		for (int i = shapeSize - 1; i >= 0; i--)
2320 		{
2321 			transferIndices->addValue(index + i);
2322 		}
2323 	}
2324 }
2325