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