1 #include "TREMainModel.h"
2 #include "TREVertexStore.h"
3 #include "TRETransShapeGroup.h"
4 #include "TRETexmappedShapeGroup.h"
5 #include "TREGL.h"
6 #include "TREGLExtensions.h"
7 #include "TRESubModel.h"
8 #include <math.h>
9 #include <string.h>
10 #include <gl2ps/gl2ps.h>
11
12 #include <TCFoundation/TCDictionary.h>
13 #include <TCFoundation/TCProgressAlert.h>
14 #include <TCFoundation/TCLocalStrings.h>
15
16 #ifdef USE_CPP11
17 #include <thread>
18 #endif
19
20 #ifdef WIN32
21 #if defined(_MSC_VER) && _MSC_VER >= 1400 && defined(_DEBUG)
22 #define new DEBUG_CLIENTBLOCK
23 #endif // _DEBUG
24 #endif // WIN32
25
26 #ifdef USE_CPP11
27 typedef std::unique_lock<std::mutex> ScopedLock;
28 #else
29 #ifndef _NO_TRE_THREADS
30 #include <boost/bind.hpp>
31 //#define ANTI_DEADLOCK_HACK
32 #ifdef ANTI_DEADLOCK_HACK
33 #include <boost/thread/xtime.hpp>
34 #endif // ANTI_DEADLOCK_HACK
35 typedef boost::mutex::scoped_lock ScopedLock;
36
37 #ifdef __APPLE__
38 #include <CoreServices/CoreServices.h>
39 #endif // __APPLE__
40 #endif // !_NO_TRE_THREADS
41 #endif // !USE_CPP11
42
43 //const GLfloat POLYGON_OFFSET_FACTOR = 0.85f;
44 //const GLfloat POLYGON_OFFSET_UNITS = 0.0f;
45 const GLfloat POLYGON_OFFSET_FACTOR = 1.0f;
46 // NOTE: setting the following to a non-zero value results in "implementation-
47 // specific" behavior. In other words, "undefined". Yech.
48 const GLfloat POLYGON_OFFSET_UNITS = 0.0f;
49
50 TCImageArray *TREMainModel::sm_studTextures = NULL;
51 GLuint TREMainModel::sm_studTextureID = 0;
52 TREMainModel::TREMainModelCleanup TREMainModel::sm_mainModelCleanup;
53
~TREMainModelCleanup(void)54 TREMainModel::TREMainModelCleanup::~TREMainModelCleanup(void)
55 {
56 TCObject::release(TREMainModel::sm_studTextures);
57 TREMainModel::sm_studTextures = NULL;
58 // We can't deletet the texture from GL, since there's not likely to be an
59 // OpenGL context active at this point in the app shutdown process.
60 //if (TREMainModel::sm_studTextureID)
61 //{
62 // glDeleteTextures(1, &TREMainModel::sm_studTextureID);
63 //}
64 }
65
66 //TREMainModel::TREMainModel(const TREMainModel &other)
67 // :TREModel(other),
68 // m_loadedModels((TCDictionary *)TCObject::copy(other.m_loadedModels)),
69 // m_loadedBFCModels((TCDictionary *)TCObject::copy(other.m_loadedBFCModels)),
70 // m_vertexStore((TREVertexStore *)TCObject::copy(other.m_vertexStore)),
71 // m_studVertexStore((TREVertexStore *)TCObject::copy(
72 // other.m_studVertexStore)),
73 // m_coloredVertexStore((TREVertexStore *)TCObject::copy(
74 // other.m_coloredVertexStore)),
75 // m_coloredStudVertexStore((TREVertexStore *)TCObject::copy(
76 // other.m_coloredStudVertexStore)),
77 // m_transVertexStore((TREVertexStore *)TCObject::copy(
78 // other.m_transVertexStore)),
79 // m_color(other.m_color),
80 // m_edgeColor(other.m_edgeColor),
81 // m_maxRadiusSquared(other.m_maxRadiusSquared),
82 // m_edgeLineWidth(other.m_edgeLineWidth),
83 // m_studAnisoLevel(other.m_studAnisoLevel),
84 // m_abort(false),
85 // m_studTextureFilter(other.m_studTextureFilter),
86 // m_mainFlags(other.m_mainFlags)
87 //{
88 //#ifdef _LEAK_DEBUG
89 // strcpy(className, "TREMainModel");
90 //#endif // _LEAK_DEBUG
91 // m_mainModel = this;
92 //}
93
TREMainModel(void)94 TREMainModel::TREMainModel(void)
95 : m_alertSender(NULL)
96 , m_loadedModels(NULL)
97 , m_loadedBFCModels(NULL)
98 , m_vertexStore(new TREVertexStore)
99 , m_studVertexStore(new TREVertexStore)
100 , m_coloredVertexStore(new TREVertexStore)
101 , m_coloredStudVertexStore(new TREVertexStore)
102 , m_transVertexStore(new TREVertexStore)
103 , m_texmapVertexStore(new TREVertexStore)
104 #ifndef __INTEL_COMPILER
105 , m_color(htonl(0x999999FF))
106 , m_edgeColor(htonl(0x666658FF))
107 #endif // !__INTEL_COMPILER
108 , m_maxRadiusSquared(0.0f)
109 , m_textureOffsetFactor(5.0f)
110 , m_edgeLineWidth(1.0f)
111 , m_studAnisoLevel(1.0f)
112 , m_abort(false)
113 , m_studTextureFilter(GL_LINEAR_MIPMAP_LINEAR)
114 , m_step(-1)
115 , m_curGeomModel(NULL)
116 , m_texClampMode(GL_CLAMP)
117 , m_seamWidth(0.5f)
118 #if defined(USE_CPP11) || !defined(_NO_TRE_THREADS)
119 #ifdef USE_CPP11
120 , m_threads(NULL)
121 #else
122 , m_threadGroup(NULL)
123 #endif
124 , m_workerMutex(NULL)
125 , m_workerCondition(NULL)
126 , m_sortCondition(NULL)
127 , m_conditionalsCondition(NULL)
128 , m_exiting(false)
129 #endif // !_NO_TRE_THREADS
130 {
131 #ifdef __INTEL_COMPILER
132 m_color = htonl(0x999999FF);
133 m_edgeColor = htonl(0x666658FF);
134 #endif // __INTEL_COMPILER
135 #ifdef _LEAK_DEBUG
136 strcpy(className, "TREMainModel");
137 #endif // _LEAK_DEBUG
138 m_mainModel = this;
139 m_mainFlags.compiled = false;
140 m_mainFlags.compiling = false;
141 m_mainFlags.removingHiddenLines = false;
142 m_mainFlags.cutawayDraw = false;
143 m_mainFlags.activeLineJoins = false;
144 m_mainFlags.frameSorted = false;
145 m_mainFlags.frameSortStarted = false;
146 m_mainFlags.frameStarted = false;
147
148 m_mainFlags.compileParts = false;
149 m_mainFlags.compileAll = false;
150 m_mainFlags.edgeLines = false;
151 m_mainFlags.edgesOnly = false;
152 m_mainFlags.twoSidedLighting = false;
153 m_mainFlags.lighting = false;
154 m_mainFlags.useStrips = true;
155 m_mainFlags.disableStrips = false;
156 m_mainFlags.useTriStrips = true;
157 m_mainFlags.useTriFans = true;
158 m_mainFlags.useQuadStrips = true;
159 m_mainFlags.useFlatStrips = false;
160 m_mainFlags.bfc = false;
161 m_mainFlags.aaLines = false;
162 m_mainFlags.sortTransparent = false;
163 m_mainFlags.stipple = false;
164 m_mainFlags.wireframe = false;
165 m_mainFlags.conditionalLines = false;
166 m_mainFlags.smoothCurves = true;
167 m_mainFlags.showAllConditional = false;
168 m_mainFlags.conditionalControlPoints = false;
169 m_mainFlags.studLogo = true;
170 m_mainFlags.redBackFaces = false;
171 m_mainFlags.greenFrontFaces = false;
172 m_mainFlags.blueNeutralFaces = false;
173 m_mainFlags.lineJoins = false; // Doesn't work right
174 m_mainFlags.drawNormals = false;
175 m_mainFlags.stencilConditionals = false;
176 m_mainFlags.vertexArrayEdgeFlags = false;
177 m_mainFlags.multiThreaded = true;
178 m_mainFlags.gl2ps = false;
179 m_mainFlags.sendProgress = true;
180 m_mainFlags.modelTexmapTransfer = false;
181 m_mainFlags.flattenParts = true;
182 m_mainFlags.texturesAfterTransparent = false;
183 m_mainFlags.noDepthEdgeLines = false;
184
185 m_conditionalsDone = 0;
186 m_conditionalsStep = 0;
187 memset(m_activeConditionals, 0, sizeof(m_activeConditionals));
188 memset(m_activeColorConditionals, 0, sizeof(m_activeColorConditionals));
189 memset(m_texmappedShapes, 0, sizeof(m_texmappedShapes));
190 }
191
~TREMainModel(void)192 TREMainModel::~TREMainModel(void)
193 {
194 }
195
dealloc(void)196 void TREMainModel::dealloc(void)
197 {
198 #if defined(USE_CPP11) || !defined(_NO_TRE_THREADS)
199 #ifdef USE_CPP11
200 if (m_threads != NULL)
201 #else
202 if (m_threadGroup)
203 #endif
204 {
205 if (m_workerMutex != NULL)
206 {
207 ScopedLock lock(*m_workerMutex);
208
209 m_exiting = true;
210 m_workerCondition->notify_all();
211 lock.unlock();
212 #ifdef USE_CPP11
213 for (auto&& thread: *m_threads)
214 {
215 thread.join();
216 }
217 delete m_threads;
218 m_threads = NULL;
219 #else
220 m_threadGroup->join_all();
221 delete m_threadGroup;
222 m_threadGroup = NULL;
223 #endif
224 }
225 delete m_workerMutex;
226 m_workerMutex = NULL;
227 delete m_workerCondition;
228 m_workerCondition = NULL;
229 delete m_sortCondition;
230 m_sortCondition = NULL;
231 delete m_conditionalsCondition;
232 m_conditionalsCondition = NULL;
233 }
234 #endif // !_NO_TRE_THREADS
235 uncompile();
236 for (size_t i = 0; i < 2; i++)
237 {
238 TCObject::release(m_texmappedShapes[i]);
239 }
240 deleteGLTexmaps();
241 TCObject::release(m_loadedModels);
242 TCObject::release(m_loadedBFCModels);
243 TCObject::release(m_vertexStore);
244 TCObject::release(m_studVertexStore);
245 TCObject::release(m_coloredVertexStore);
246 TCObject::release(m_coloredStudVertexStore);
247 TCObject::release(m_transVertexStore);
248 TCObject::release(m_texmapVertexStore);
249 TREModel::dealloc();
250 }
251
copy(void) const252 TCObject *TREMainModel::copy(void) const
253 {
254 return new TREMainModel(*this);
255 }
256
getLoadedModels(bool bfc)257 TCDictionary *TREMainModel::getLoadedModels(bool bfc)
258 {
259 if (bfc)
260 {
261 if (!m_loadedBFCModels)
262 {
263 m_loadedBFCModels = new TCDictionary(0);
264 }
265 return m_loadedBFCModels;
266 }
267 else
268 {
269 if (!m_loadedModels)
270 {
271 m_loadedModels = new TCDictionary(0);
272 }
273 return m_loadedModels;
274 }
275 }
276
activateBFC(void)277 void TREMainModel::activateBFC(void)
278 {
279 if (getRedBackFacesFlag() || getGreenFrontFacesFlag())
280 {
281 bool needColorMaterial = true;
282
283 if (getRedBackFacesFlag() && getGreenFrontFacesFlag())
284 {
285 needColorMaterial = false;
286 glDisable(GL_COLOR_MATERIAL);
287 }
288 else if (getBlueNeutralFacesFlag())
289 {
290 glEnable(GL_COLOR_MATERIAL);
291 }
292 if (getRedBackFacesFlag())
293 {
294 GLfloat mRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
295
296 if (needColorMaterial)
297 {
298 glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
299 }
300 glMaterialfv(GL_BACK, GL_AMBIENT, mRed);
301 glMaterialfv(GL_BACK, GL_DIFFUSE, mRed);
302 }
303 if (getGreenFrontFacesFlag())
304 {
305 GLfloat mGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
306
307 if (needColorMaterial)
308 {
309 glColorMaterial(GL_BACK, GL_AMBIENT_AND_DIFFUSE);
310 }
311 glMaterialfv(GL_FRONT, GL_AMBIENT, mGreen);
312 glMaterialfv(GL_FRONT, GL_DIFFUSE, mGreen);
313 }
314 }
315 else
316 {
317 if (getBlueNeutralFacesFlag())
318 {
319 glEnable(GL_COLOR_MATERIAL);
320 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
321 }
322 // Note that GL_BACK is the default face to cull, and GL_CCW is the
323 // default polygon winding.
324 glEnable(GL_CULL_FACE);
325 if (getTwoSidedLightingFlag() && getLightingFlag())
326 {
327 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
328 }
329 }
330 }
331
deactivateBFC(bool transparent)332 void TREMainModel::deactivateBFC(bool transparent /*= false*/)
333 {
334 if (getBlueNeutralFacesFlag() && !transparent)
335 {
336 GLfloat mBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
337
338 glDisable(GL_COLOR_MATERIAL);
339 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mBlue);
340 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mBlue);
341 }
342 else
343 {
344 glEnable(GL_COLOR_MATERIAL);
345 if (getRedBackFacesFlag() && getGreenFrontFacesFlag())
346 {
347 // Don't do anything here.
348 }
349 else if ((getRedBackFacesFlag() || getGreenFrontFacesFlag()))
350 {
351 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
352 }
353 else
354 {
355 if (getTwoSidedLightingFlag() && getLightingFlag())
356 {
357 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
358 }
359 glDisable(GL_CULL_FACE);
360 }
361 }
362 }
363
364 /*
365 void TREMainModel::compileTransparent(void)
366 {
367 if (!m_coloredListIDs[TREMTransparent] &&
368 m_coloredShapes[TREMTransparent])
369 {
370 int listID = glGenLists(1);
371
372 glNewList(listID, GL_COMPILE);
373 ((TRETransShapeGroup *)m_coloredShapes[TREMTransparent])->
374 draw(false);
375 glEndList();
376 m_coloredListIDs[TREMTransparent] = listID;
377 }
378 }
379 */
380
getStencilConditionalsFlag(void)381 bool TREMainModel::getStencilConditionalsFlag(void)
382 {
383 // Save alpha requires the stencil buffer for another purpose; don't allow
384 // stencil conditionals when it's set.
385 return m_mainFlags.stencilConditionals != false &&
386 !getSaveAlphaFlag();
387 }
388
shouldCompileSection(TREMSection section)389 bool TREMainModel::shouldCompileSection(TREMSection section)
390 {
391 if (getStencilConditionalsFlag())
392 {
393 return section != TREMTransparent;
394 }
395 else
396 {
397 return section != TREMConditionalLines && section != TREMTransparent;
398 }
399 }
400
compile(void)401 void TREMainModel::compile(void)
402 {
403 if (!m_mainFlags.compiled)
404 {
405 int i;
406 float numSections = (float)(TREMLast - TREMFirst + 1);
407
408 // TCProgressAlert::send("TREMainModel",
409 // TCLocalStrings::get("TREMainModelCompiling"), 0.0f, &m_abort);
410 if (!m_abort)
411 {
412 m_mainFlags.compiling = true;
413 for (i = TREMFirst; i <= TREMLast && !m_abort; i++)
414 {
415 TREMSection section = (TREMSection)i;
416
417 if (shouldCompileSection(section))
418 {
419 float progress = (float)i / (numSections * 2.0f);
420
421 if (m_mainFlags.sendProgress)
422 {
423 TCProgressAlert::send("TREMainModel",
424 TCLocalStrings::get(_UC("TREMainModelCompiling")),
425 progress, &m_abort, this);
426 }
427 if (!m_abort && isSectionPresent(section, false))
428 {
429 if (isStudSection(section))
430 {
431 m_studVertexStore->activate(true);
432 }
433 else
434 {
435 m_vertexStore->activate(true);
436 }
437 if (section == TREMEdgeLines)
438 {
439 if (getLineJoinsFlag() && m_edgeLineWidth > 1.0f)
440 {
441 // pointSize(m_edgeLineWidth);
442 m_mainFlags.activeLineJoins = true;
443 // glEnable(GL_POINT_SMOOTH);
444 // glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
445 }
446 }
447 TREModel::compile(section, false);
448 m_mainFlags.activeLineJoins = false;
449 }
450 }
451 }
452 /*
453 TREModel::compile(TREMStandard, false);
454 TCProgressAlert::send("TREMainModel",
455 TCLocalStrings::get(L"TREMainModelCompiling"), 0.2f, &m_abort);
456 */
457 }
458 /*
459 if (!m_abort)
460 {
461 if (getBFCFlag())
462 {
463 TREModel::compile(TREMBFC, false);
464 }
465 TCProgressAlert::send("TREMainModel",
466 TCLocalStrings::get(L"TREMainModelCompiling"), 0.3f, &m_abort);
467 }
468 if (!m_abort)
469 {
470 TREModel::compile(TREMLines, false);
471 TCProgressAlert::send("TREMainModel",
472 TCLocalStrings::get(L"TREMainModelCompiling"), 0.35f, &m_abort);
473 }
474 if (!m_abort)
475 {
476 TREModel::compile(TREMEdgeLines, false);
477 TCProgressAlert::send("TREMainModel",
478 TCLocalStrings::get(L"TREMainModelCompiling"), 0.45f, &m_abort);
479 }
480 */
481 if (!m_abort)
482 {
483 for (i = TREMFirst; i <= TREMLast && !m_abort; i++)
484 {
485 TREMSection section = (TREMSection)i;
486
487 if (shouldCompileSection(section))
488 {
489 float progress = (float)i / (numSections * 2.0f) + 0.5f;
490
491 if (m_mainFlags.sendProgress)
492 {
493 TCProgressAlert::send("TREMainModel",
494 TCLocalStrings::get(_UC("TREMainModelCompiling")),
495 progress, &m_abort, this);
496 }
497 if (!m_abort && isSectionPresent(section, true))
498 {
499 if (isStudSection(section))
500 {
501 m_coloredStudVertexStore->activate(true);
502 }
503 else
504 {
505 m_coloredVertexStore->activate(true);
506 }
507 TREModel::compile(section, true);
508 }
509 }
510 }
511 /*
512 TREModel::compile(TREMStandard, true);
513 TCProgressAlert::send("TREMainModel",
514 TCLocalStrings::get(L"TREMainModelCompiling"), 0.55f, &m_abort);
515 */
516 }
517 /*
518 if (!m_abort)
519 {
520 if (getBFCFlag())
521 {
522 TREModel::compile(TREMBFC, true);
523 }
524 TCProgressAlert::send("TREMainModel",
525 TCLocalStrings::get(L"TREMainModelCompiling"), 0.65f, &m_abort);
526 }
527 if (!m_abort)
528 {
529 TREModel::compile(TREMBFC, true);
530 TCProgressAlert::send("TREMainModel",
531 TCLocalStrings::get(L"TREMainModelCompiling"), 0.7f, &m_abort);
532 }
533 if (!m_abort)
534 {
535 TREModel::compile(TREMEdgeLines, true);
536 TCProgressAlert::send("TREMainModel",
537 TCLocalStrings::get(L"TREMainModelCompiling"), 0.8f, &m_abort);
538 }
539 if (!m_abort)
540 {
541 if (m_transVertexStore)
542 {
543 m_transVertexStore->activate(true);
544 }
545 if (!getSortTransparentFlag())
546 {
547 TREModel::compile(TREMTransparent, true);
548 }
549 TCProgressAlert::send("TREMainModel",
550 TCLocalStrings::get(L"TREMainModelCompiling"), 0.9f, &m_abort);
551 }
552 */
553 if (!m_abort)
554 {
555 m_mainFlags.compiled = true;
556 m_mainFlags.compiling = false;
557 if (m_mainFlags.sendProgress)
558 {
559 TCProgressAlert::send("TREMainModel",
560 TCLocalStrings::get(_UC("TREMainModelCompiling")), 1.0f,
561 &m_abort, this);
562 }
563 // TCProgressAlert::send("LDrawModelViewer", "Done.", 2.0f);
564 }
565 TREVertexStore::deactivateActiveVertexStore();
566 }
567 }
568
recompile(void)569 void TREMainModel::recompile(void)
570 {
571 if (m_mainFlags.compiled)
572 {
573 uncompile();
574 m_mainFlags.compiled = false;
575 }
576 compile();
577 }
578
579 /*
580 void checkNormals(TREVertexStore *vertexStore)
581 {
582 if (vertexStore)
583 {
584 TREVertexArray *normals = vertexStore->getNormals();
585
586 if (normals)
587 {
588 int i;
589 int count = normals->getCount();
590
591 for (i = 0; i < count; i++)
592 {
593 TCVector normal = (*normals)[i].v;
594
595 if (!fEq(normal.lengthSquared(), 1.0))
596 {
597 MessageBox(NULL, "Bad Normal", "LDView", MB_OK);
598 }
599 }
600 }
601 }
602 }
603 */
604
passOnePrep(void)605 void TREMainModel::passOnePrep(void)
606 {
607 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_STENCIL_BUFFER_BIT);
608 // First pass: draw just the color of all the transparent polygons
609 // that are just in front of the background. Don't draw anywhere
610 // that has already been drawn to. This makes sure that subsequent
611 // color blend operations don't include the background color. Also
612 // set the stencil to 1 for every pixel we update the alpha on.
613 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
614 glEnable(GL_STENCIL_TEST);
615 glStencilFunc(GL_EQUAL, 0, 0xFFFFFFFF);
616 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
617 glStencilMask(0xFFFFFFFF);
618 disable(GL_BLEND);
619 }
620
passTwoPrep(void)621 void TREMainModel::passTwoPrep(void)
622 {
623 // Second pass: update just the alpha channel on all transparent
624 // polygons that have the background visible through them (which
625 // is all the ones we set the stencil to 1 in on pass 1 above).
626 // Note that depth testing is disabled, and the blend function
627 // is set to allow the alpha channel to build up as transparent
628 // polygons overlap.
629 glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
630 glDisable(GL_DEPTH_TEST);
631 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
632 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
633 }
634
passThreePrep(void)635 void TREMainModel::passThreePrep(void)
636 {
637 // Third pass (actual drawing is outside this if statement):
638 // Now draw the color component of all the transparent polygons
639 // except for the ones drawn in step 1. (Depth test is set to
640 // GL_LESS, so that those don't ge redrawn.) Other than that
641 // depth test setting, everything is configure the same as for
642 // standard one-pass transparency.
643 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
644 glDisable(GL_STENCIL_TEST);
645 glEnable(GL_DEPTH_TEST);
646 glDepthFunc(GL_LESS);
647 }
648
getNumBackgroundTasks(void)649 int TREMainModel::getNumBackgroundTasks(void)
650 {
651 int numTasks = 0;
652
653 if (backgroundSortNeeded())
654 {
655 numTasks++;
656 }
657 if (backgroundConditionalsNeeded())
658 {
659 numTasks += 32;
660 }
661 return numTasks;
662 }
663
getNumWorkerThreads(void)664 int TREMainModel::getNumWorkerThreads(void)
665 {
666 #if defined(USE_CPP11) || !defined(_NO_TRE_THREADS)
667 if (getMultiThreadedFlag())
668 {
669 #ifdef USE_CPP11
670 int numProcessors = std::thread::hardware_concurrency();
671 #else // USE_CPP11
672 int numProcessors = 1;
673
674 #if defined(WIN32)
675 DWORD_PTR processAffinityMask;
676 DWORD_PTR systemAffinityMask;
677
678 if (GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask,
679 &systemAffinityMask))
680 {
681 numProcessors = 0;
682
683 while (processAffinityMask)
684 {
685 if (processAffinityMask & 0x01)
686 {
687 numProcessors++;
688 }
689 processAffinityMask >>= 1;
690 }
691 }
692 #elif defined(__APPLE__)
693 numProcessors = (int)MPProcessorsScheduled();
694 #elif defined(_QT)
695 int result = -1;
696 #ifdef _SC_NPROCESSORS_CONF
697 result = (int)sysconf(_SC_NPROCESSORS_CONF);
698 if (result > 0)
699 {
700 numProcessors = result;
701 }
702 #endif // _SC_NPROCESSORS_CONF
703 #ifdef _SC_NPROCESSORS_ONLN
704 result = (int)sysconf(_SC_NPROCESSORS_ONLN);
705 if (result > 0)
706 {
707 numProcessors = result;
708 }
709 #endif // _SC_NPROCESSORS_ONLN
710 #endif // _QT
711 #endif // !USE_CPP11
712 if (numProcessors > 1)
713 {
714 return std::min(numProcessors - 1, getNumBackgroundTasks());
715 }
716 }
717 #endif // USE_CPP11 || !_NO_TRE_THREADS
718 return 0;
719 }
720
backgroundSortNeeded(void)721 bool TREMainModel::backgroundSortNeeded(void)
722 {
723 TRETransShapeGroup* transShapeGroup =
724 (TRETransShapeGroup*)m_coloredShapes[TREMTransparent];
725
726 return (transShapeGroup && getSortTransparentFlag() &&
727 !getCutawayDrawFlag());
728 }
729
backgroundConditionalsNeeded(void)730 bool TREMainModel::backgroundConditionalsNeeded(void)
731 {
732 return getFlattenConditionalsFlag() && getConditionalLinesFlag();
733 }
734
doingBackgroundConditionals(void)735 bool TREMainModel::doingBackgroundConditionals(void)
736 {
737 return backgroundConditionalsNeeded() && getMultiThreadedFlag() &&
738 getNumBackgroundTasks() > 0 && getNumWorkerThreads() > 0;
739 }
740
backgroundConditionals(TREShapeGroup * shapes,int step)741 TCULongArray *TREMainModel::backgroundConditionals(
742 TREShapeGroup *shapes,
743 int step)
744 {
745 if (shapes)
746 {
747 TCULongArray *indices = shapes->getIndices(TRESConditionalLine);
748
749 if (indices)
750 {
751 int subCount = shapes->getIndexCount(TRESConditionalLine) / 2;
752 int stepSize = subCount / 32 * 2;
753 int stepCount = stepSize;
754
755 if (step == 31)
756 {
757 stepCount += (subCount % 32) * 2;
758 }
759 return shapes->getActiveConditionalIndices(indices,
760 TCVector::getIdentityMatrix(), stepSize * step, stepCount);
761 }
762 }
763 return NULL;
764 }
765
backgroundConditionals(int step)766 void TREMainModel::backgroundConditionals(int step)
767 {
768 m_activeConditionals[step] =
769 backgroundConditionals(m_shapes[TREMConditionalLines], step);
770 m_activeColorConditionals[step] =
771 backgroundConditionals(m_coloredShapes[TREMConditionalLines], step);
772 }
773
774 #if defined(USE_CPP11) || !defined(_NO_TRE_THREADS)
775
776 template <class _ScopedLock>
nextConditionalsStep(_ScopedLock & lock)777 void TREMainModel::nextConditionalsStep(_ScopedLock &lock)
778 {
779 // lock is always locked here.
780 int step = m_conditionalsStep;
781
782 ++m_conditionalsStep;
783 lock.unlock();
784 backgroundConditionals(step);
785 lock.lock();
786 m_conditionalsDone |= 1 << step;
787 }
788
789 template <class _ScopedLock>
workerThreadDoWork(_ScopedLock & lock)790 bool TREMainModel::workerThreadDoWork(_ScopedLock &lock)
791 {
792 // lock is always locked here.
793 if (!m_mainFlags.frameStarted)
794 {
795 return false;
796 }
797 if (backgroundConditionalsNeeded() && (m_conditionalsStep < 32))
798 {
799 nextConditionalsStep(lock);
800 if (m_conditionalsDone == 0xFFFFFFFF)
801 {
802 m_conditionalsCondition->notify_all();
803 }
804 return true;
805 }
806 if (!m_mainFlags.frameSortStarted && backgroundSortNeeded())
807 {
808 TRETransShapeGroup* transShapeGroup =
809 (TRETransShapeGroup*)m_coloredShapes[TREMTransparent];
810
811 m_mainFlags.frameSortStarted = true;
812 lock.unlock();
813 transShapeGroup->backgroundSort();
814 lock.lock();
815 m_mainFlags.frameSorted = true;
816 m_sortCondition->notify_all();
817 return true;
818 }
819 return false;
820 }
821
workerThreadProc(void)822 void TREMainModel::workerThreadProc(void)
823 {
824 ScopedLock lock(*m_workerMutex);
825
826 if (!m_mainFlags.frameStarted)
827 {
828 m_workerCondition->wait(lock);
829 }
830 while (1)
831 {
832 if (m_exiting)
833 {
834 break;
835 }
836 if (!workerThreadDoWork(lock))
837 {
838 if (!m_exiting)
839 {
840 #ifdef ANTI_DEADLOCK_HACK
841 #ifdef USE_CPP11
842 m_workerCondition->wait_for(lock, std::chrono::milliseconds(100));
843 #else
844 boost::xtime xt;
845
846 boost::xtime_get(&xt, boost::TIME_UTC);
847 // 100,000,000 nsec == 100 msec
848 xt.nsec += 100 * 1000000;
849 // HACK: If any deadlocks are encountered during testing,
850 // ANTI_DEADLOCK_HACK can be defined, and hopefully they'll go
851 // away.
852 m_workerCondition->timed_wait(lock, xt);
853 #endif
854 #else // ANTI_DEADLOCK_HACK
855 m_workerCondition->wait(lock);
856 #endif // ANTI_DEADLOCK_HACK
857 }
858 }
859 }
860 }
861 #endif // USE_CPP11 || !_NO_TRE_THREADS
862
launchWorkerThreads()863 void TREMainModel::launchWorkerThreads()
864 {
865 #if defined(USE_CPP11) || !defined(_NO_TRE_THREADS)
866 #ifdef USE_CPP11
867 if (m_threads == NULL)
868 #else
869 if (m_threadGroup == NULL)
870 #endif
871 {
872 int workerThreadCount = getNumWorkerThreads();
873 #ifdef USE_CPP11
874 m_threads = new std::vector<std::thread>;
875 #endif
876
877 if (workerThreadCount > 0)
878 {
879 #ifdef USE_CPP11
880 m_mainFlags.frameStarted = false;
881 m_workerMutex = new std::mutex;
882 m_workerCondition = new std::condition_variable;
883 m_sortCondition = new std::condition_variable;
884 m_conditionalsCondition = new std::condition_variable;
885 #else
886 m_threadGroup = new boost::thread_group;
887 m_workerMutex = new boost::mutex;
888 m_workerCondition = new boost::condition;
889 m_sortCondition = new boost::condition;
890 m_conditionalsCondition = new boost::condition;
891 #endif
892 for (int i = 0; i < workerThreadCount; i++)
893 {
894 #ifdef USE_CPP11
895 m_threads->emplace_back(&TREMainModel::workerThreadProc, this);
896 #else
897 m_threadGroup->create_thread(
898 boost::bind(&TREMainModel::workerThreadProc, this));
899 #endif
900 }
901 }
902 }
903 #endif // USE_CPP11 || !_NO_TRE_THREADS
904 }
905
triggerWorkerThreads(void)906 void TREMainModel::triggerWorkerThreads(void)
907 {
908 #if defined(USE_CPP11) || !defined(_NO_TRE_THREADS)
909 if (m_workerMutex)
910 {
911 ScopedLock lock(*m_workerMutex);
912 m_mainFlags.frameSorted = false;
913 m_mainFlags.frameSortStarted = false;
914 m_mainFlags.frameStarted = true;
915 m_conditionalsDone = 0;
916 m_conditionalsStep = 0;
917 m_workerCondition->notify_all();
918 memset(m_activeConditionals, 0, sizeof(m_activeConditionals));
919 memset(m_activeColorConditionals, 0, sizeof(m_activeColorConditionals));
920 }
921 #endif // USE_CPP11 || !_NO_TRE_THREADS
922 }
923
hasWorkerThreads(void)924 bool TREMainModel::hasWorkerThreads(void)
925 {
926 #if defined(USE_CPP11) || !defined(_NO_TRE_THREADS)
927 if (m_workerMutex)
928 {
929 ScopedLock lock(*m_workerMutex);
930 #ifdef USE_CPP11
931 return m_threads != NULL;
932 #else
933 return m_threadGroup != NULL;
934 #endif
935 }
936 #endif // USE_CPP11 || !_NO_TRE_THREADS
937 return false;
938 }
939
waitForSort(void)940 void TREMainModel::waitForSort(void)
941 {
942 #if defined(USE_CPP11) || !defined(_NO_TRE_THREADS)
943 if (m_workerMutex)
944 {
945 ScopedLock lock(*m_workerMutex);
946 if (!m_mainFlags.frameSorted)
947 {
948 m_sortCondition->wait(lock);
949 }
950 }
951 #endif // USE_CPP11 || !_NO_TRE_THREADS
952 }
953
954 #if !defined(USE_CPP11) && defined(_NO_TRE_THREADS)
waitForConditionals(int)955 void TREMainModel::waitForConditionals(int /*step*/)
956 #else // !USE_CPP11 && _NO_TRE_THREADS
957 void TREMainModel::waitForConditionals(int step)
958 #endif // USE_CPP11 || !_NO_TRE_THREADS
959 {
960 #if defined(USE_CPP11) || !defined(_NO_TRE_THREADS)
961 if (m_workerMutex)
962 {
963 ScopedLock lock(*m_workerMutex);
964
965 while ((m_conditionalsDone & (1 << step)) == 0)
966 {
967 if (m_conditionalsStep < 32)
968 {
969 nextConditionalsStep(lock);
970 }
971 else
972 {
973 m_conditionalsCondition->wait(lock);
974 }
975 }
976 }
977 #endif // USE_CPP11 || !_NO_TRE_THREADS
978 }
979
draw(void)980 void TREMainModel::draw(void)
981 {
982 GLfloat normalSpecular[4];
983 bool multiPass = false;
984
985 treGlGetFloatv(GL_MODELVIEW_MATRIX, m_currentModelViewMatrix);
986 treGlGetFloatv(GL_PROJECTION_MATRIX, m_currentProjectionMatrix);
987 if (getSaveAlphaFlag() && (!getStippleFlag() || getAALinesFlag()))
988 {
989 GLint stencilBits;
990
991 multiPass = true;
992 glGetIntegerv(GL_STENCIL_BITS, &stencilBits);
993 glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT |
994 GL_STENCIL_BUFFER_BIT);
995 glEnable(GL_STENCIL_TEST);
996 glStencilFunc(GL_ALWAYS, 2, 0xFFFFFFFF);
997 glStencilMask(0xFFFFFFFF);
998 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
999 }
1000 glGetLightfv(GL_LIGHT0, GL_SPECULAR, normalSpecular);
1001 if (m_mainFlags.compileParts || m_mainFlags.compileAll)
1002 {
1003 compile();
1004 }
1005 launchWorkerThreads();
1006 triggerWorkerThreads();
1007 if ((getEdgeLinesFlag() && !getWireframeFlag() && getPolygonOffsetFlag()) ||
1008 !m_mainTexmapInfos.empty())
1009 {
1010 glPolygonOffset(getPolygonOffsetFactor(TPOPMain), POLYGON_OFFSET_UNITS);
1011 enable(GL_POLYGON_OFFSET_FILL);
1012 }
1013 else
1014 {
1015 disable(GL_POLYGON_OFFSET_FILL);
1016 }
1017 if (getWireframeFlag())
1018 {
1019 enableLineSmooth();
1020 }
1021 if (getEdgesOnlyFlag())
1022 {
1023 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1024 }
1025 if (!getEdgesOnlyFlag() || !getWireframeFlag())
1026 {
1027 drawSolid();
1028 }
1029 if (getEdgesOnlyFlag())
1030 {
1031 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1032 }
1033 // Next, disable lighting and draw lines. First draw default colored lines,
1034 // which probably don't exist, since color number 16 doesn't often get used
1035 // for lines.
1036 if (getAALinesFlag() && !getWireframeFlag() &&
1037 m_coloredShapes[TREMTransparent] != NULL)
1038 {
1039 // First, draw all the lines without smoothing, but with depth
1040 // writing enabled so that they won't be covered by textures or
1041 // faded by transparent geometry.
1042 drawLines(-2);
1043 }
1044 if (getSaveAlphaFlag() && !getEdgesOnlyFlag())
1045 {
1046 passOnePrep();
1047 drawLines(1);
1048 passTwoPrep();
1049 drawLines(2);
1050 passThreePrep();
1051 drawLines(3);
1052 glPopAttrib();
1053 }
1054 else
1055 {
1056 drawLines();
1057 }
1058 if (getAALinesFlag() && getWireframeFlag())
1059 {
1060 // We use glPushAttrib() when we enable line smoothing.
1061 glPopAttrib();
1062 }
1063 if (!getEdgesOnlyFlag())
1064 {
1065 drawTexmapped(false);
1066 if (!getTexturesAfterTransparentFlag())
1067 {
1068 // There is a trade-off. If textures are drawn before transparent
1069 // geometry, then everything looks great as long as the textures don't
1070 // contain alpha values that are semi-transparent. However, if a
1071 // texture attached to a transparent part includes semi-transparent
1072 // portions, those portions don't get blended with the underlying part,
1073 // which looks wrong.
1074 // If textures are drawn after transparent geometry, semi-transparent
1075 // portions look fine, but the textures show up in front of any
1076 // transparent geometry that is in front of them.
1077 drawTexmapped(true);
1078 }
1079 }
1080 if (!getEdgesOnlyFlag() && !getRemovingHiddenLines())
1081 {
1082 if (getSaveAlphaFlag() && !getStippleFlag())
1083 {
1084 passOnePrep();
1085 drawTransparent(1);
1086 passTwoPrep();
1087 drawTransparent(2);
1088 passThreePrep();
1089 drawTransparent(3);
1090 glPopAttrib();
1091 }
1092 else
1093 {
1094 drawTransparent();
1095 }
1096 }
1097 if (getTexturesAfterTransparentFlag())
1098 {
1099 drawTexmapped(true);
1100 }
1101 if (multiPass)
1102 {
1103 glPopAttrib();
1104 }
1105 if (backgroundConditionalsNeeded())
1106 {
1107 for (int i = 0; i < 32; i++)
1108 {
1109 TCObject::release(m_activeConditionals[i]);
1110 TCObject::release(m_activeColorConditionals[i]);
1111 }
1112 }
1113 m_mainFlags.frameStarted = false;
1114 // checkNormals(m_vertexStore);
1115 // checkNormals(m_coloredVertexStore);
1116 }
1117
enable(GLenum cap)1118 void TREMainModel::enable(GLenum cap)
1119 {
1120 if (getGl2psFlag())
1121 {
1122 GLint mode = GL2PS_BLEND;
1123
1124 if (cap == GL_POLYGON_OFFSET_FILL)
1125 {
1126 mode = GL2PS_POLYGON_OFFSET_FILL;
1127 }
1128 gl2psEnable(mode);
1129 }
1130 glEnable(cap);
1131 }
1132
disable(GLenum cap)1133 void TREMainModel::disable(GLenum cap)
1134 {
1135 if (getGl2psFlag())
1136 {
1137 GLint mode = GL2PS_BLEND;
1138
1139 if (cap == GL_POLYGON_OFFSET_FILL)
1140 {
1141 mode = GL2PS_POLYGON_OFFSET_FILL;
1142 }
1143 gl2psDisable(mode);
1144 }
1145 glDisable(cap);
1146 }
1147
blendFunc(GLenum sfactor,GLenum dfactor)1148 void TREMainModel::blendFunc(GLenum sfactor, GLenum dfactor)
1149 {
1150 if (getGl2psFlag())
1151 {
1152 gl2psBlendFunc(sfactor, dfactor);
1153 }
1154 glBlendFunc(sfactor, dfactor);
1155 }
1156
lineWidth(GLfloat width)1157 void TREMainModel::lineWidth(GLfloat width)
1158 {
1159 if (getGl2psFlag())
1160 {
1161 gl2psLineWidth(width);
1162 }
1163 glLineWidth(width);
1164 }
1165
pointSize(GLfloat size)1166 void TREMainModel::pointSize(GLfloat size)
1167 {
1168 if (getGl2psFlag())
1169 {
1170 gl2psPointSize(size);
1171 }
1172 glPointSize(size);
1173 }
1174
enableLineSmooth(int pass)1175 void TREMainModel::enableLineSmooth(int pass /*= -1*/)
1176 {
1177 if (getAALinesFlag())
1178 {
1179 glPushAttrib(GL_ENABLE_BIT);
1180 glEnable(GL_LINE_SMOOTH);
1181 if (pass != 1)
1182 {
1183 enable(GL_BLEND);
1184 if (pass == 2)
1185 {
1186 blendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE_MINUS_SRC_ALPHA);
1187 }
1188 else
1189 {
1190 blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1191 }
1192 }
1193 }
1194 }
1195
drawSolid(void)1196 void TREMainModel::drawSolid(void)
1197 {
1198 bool subModelsOnly = false;
1199
1200 deactivateBFC();
1201 if (TREShapeGroup::isTransparent(m_color, true))
1202 {
1203 subModelsOnly = true;
1204 }
1205 // I admit, this is a mess. But I'm not sure how to make it less of a mess.
1206 // The various things do need to be drawn separately, and they have to get
1207 // drawn in a specific order.
1208 //
1209 // First, draw all opaque triangles and quads that are color number 16 (the
1210 // default color inherited from above. Note that the actual drawing color
1211 // will generally be changed before each part, since you don't usually use
1212 // color number 16 when you use a part in your model.
1213
1214 glColor4ubv((GLubyte*)&m_color);
1215 m_vertexStore->activate(m_mainFlags.compileAll || m_mainFlags.compileParts);
1216 TREModel::draw(TREMStandard, false, subModelsOnly);
1217 if (getStudLogoFlag())
1218 {
1219 glEnable(GL_TEXTURE_2D);
1220 bindStudTexture();
1221 configureStudTexture();
1222 m_studVertexStore->activate(m_mainFlags.compileAll ||
1223 m_mainFlags.compileParts);
1224 TREModel::draw(TREMStud, false, subModelsOnly);
1225 glDisable(GL_TEXTURE_2D);
1226 }
1227 if (getBFCFlag())
1228 {
1229 activateBFC();
1230 m_vertexStore->activate(m_mainFlags.compileAll ||
1231 m_mainFlags.compileParts);
1232 TREModel::draw(TREMBFC, false, subModelsOnly);
1233 if (getStudLogoFlag())
1234 {
1235 glEnable(GL_TEXTURE_2D);
1236 m_studVertexStore->activate(m_mainFlags.compileAll ||
1237 m_mainFlags.compileParts);
1238 TREModel::draw(TREMStudBFC, false, subModelsOnly);
1239 glDisable(GL_TEXTURE_2D);
1240 }
1241 deactivateBFC();
1242 }
1243 // Next draw all opaque triangles and quads that were specified with a color
1244 // number other than 16. Note that the colored vertex store includes color
1245 // information for every vertex.
1246 m_coloredVertexStore->activate(m_mainFlags.compileAll ||
1247 m_mainFlags.compileParts);
1248 drawColored(TREMStandard);
1249 if (getStudLogoFlag())
1250 {
1251 glEnable(GL_TEXTURE_2D);
1252 m_coloredStudVertexStore->activate(m_mainFlags.compileAll ||
1253 m_mainFlags.compileParts);
1254 drawColored(TREMStud);
1255 glDisable(GL_TEXTURE_2D);
1256 }
1257 if (getBFCFlag())
1258 {
1259 activateBFC();
1260 m_coloredVertexStore->activate(m_mainFlags.compileAll ||
1261 m_mainFlags.compileParts);
1262 drawColored(TREMBFC);
1263 if (getStudLogoFlag())
1264 {
1265 glEnable(GL_TEXTURE_2D);
1266 m_coloredStudVertexStore->activate(m_mainFlags.compileAll ||
1267 m_mainFlags.compileParts);
1268 drawColored(TREMStudBFC);
1269 glDisable(GL_TEXTURE_2D);
1270 }
1271 deactivateBFC();
1272 }
1273 TREVertexStore::deactivateActiveVertexStore();
1274 }
1275
drawTexmappedInternal(bool texture,bool colorMaterialOff,bool transparent)1276 void TREMainModel::drawTexmappedInternal(
1277 bool texture,
1278 bool colorMaterialOff,
1279 bool transparent)
1280 {
1281 for (TexmapInfoList::const_iterator it = m_mainTexmapInfos.begin();
1282 it != m_mainTexmapInfos.end(); it ++)
1283 {
1284 size_t i = 0;
1285 const IntSet *shapeSet = NULL;
1286
1287 if (texture)
1288 {
1289 activateTexmap(*it);
1290 }
1291 if (transparent)
1292 {
1293 shapeSet = &it->transparent.colored.triangles;
1294 deactivateBFC(true);
1295 i = 2;
1296 }
1297 else if (it->bfc.colored.triangles.size() > 0)
1298 {
1299 shapeSet = &it->bfc.colored.triangles;
1300 // TODO Texmaps: BFC
1301 activateBFC();
1302 i = 1;
1303 }
1304 else if (it->standard.colored.triangles.size() > 0)
1305 {
1306 shapeSet = &it->standard.colored.triangles;
1307 // TODO Texmaps: BFC
1308 deactivateBFC(false);
1309 }
1310 if (colorMaterialOff)
1311 {
1312 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1313 glDisable(GL_COLOR_MATERIAL);
1314 }
1315 if (m_texmappedShapes[i] == NULL)
1316 {
1317 continue;
1318 }
1319 if (shapeSet != NULL && shapeSet->size() > 0)
1320 {
1321 IntSet::const_iterator itShape;
1322
1323 for (itShape = shapeSet->begin(); itShape != shapeSet->end();
1324 ++itShape, ++itShape, ++itShape)
1325 {
1326 m_texmappedShapes[i]->drawShapeType(TRESTriangle, *itShape,
1327 3);
1328 }
1329 }
1330 }
1331 }
1332
drawTexmapped(bool transparent)1333 void TREMainModel::drawTexmapped(bool transparent)
1334 {
1335 if (!m_mainTexmapInfos.empty())
1336 {
1337 if (transparent)
1338 {
1339 // It is important that the textures on transparent geometry are
1340 // drawn at the same Z value as the transparent geometry.
1341 if (getEdgeLinesFlag() && !getWireframeFlag() && getPolygonOffsetFlag())
1342 {
1343 // Push textures on transparent geometry back the same amount
1344 // as the geometry itself.
1345 glPolygonOffset(getPolygonOffsetFactor(TPOPTransparent),
1346 POLYGON_OFFSET_UNITS);
1347 enable(GL_POLYGON_OFFSET_FILL);
1348 }
1349 else
1350 {
1351 // Don't offset on transparent geometry, because the original
1352 // transparent geometry wasn't offset.
1353 disable(GL_POLYGON_OFFSET_FILL);
1354 }
1355 }
1356 else
1357 {
1358 // Push textures on opaque geometry back by an amount that is less
1359 // than the amount the original opaque geometry was pushed back by,
1360 // so that when they draw they will be closer than the geometry
1361 // they're drawing over. Even pushing the other geometry back by a
1362 // lot, textures can disappear when FOV is very low (like 0.1), but
1363 // pushing them too far introduces really bad artifacts.
1364 glPolygonOffset(getPolygonOffsetFactor(TPOPTexmaps),
1365 POLYGON_OFFSET_UNITS);
1366 enable(GL_POLYGON_OFFSET_FILL);
1367 }
1368 m_texmapVertexStore->activate(false);
1369 glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
1370 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
1371 glEnable(GL_BLEND);
1372 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1373 glDepthFunc(GL_LEQUAL);
1374 configTexmaps();
1375 drawTexmappedInternal(true, true, transparent);
1376 disableTexmaps();
1377 glPopAttrib();
1378 m_texmapVertexStore->deactivate();
1379 }
1380 }
1381
drawLines(int pass)1382 void TREMainModel::drawLines(int pass /*= -1*/)
1383 {
1384 if (getLightingFlag())
1385 {
1386 glDisable(GL_LIGHTING);
1387 }
1388 if (getAALinesFlag() && !getWireframeFlag() && pass != -2)
1389 {
1390 // Note that if we're in wireframe mode, smoothing is already enabled.
1391 enableLineSmooth(pass);
1392 if (m_coloredShapes[TREMTransparent] != NULL)
1393 {
1394 // Smooth lines produce odd effects on the edge of transparent surfaces
1395 // when depth writing is enabled, so disable.
1396 glDepthMask(GL_FALSE);
1397 }
1398 }
1399 glColor4ubv((GLubyte*)&m_color);
1400 m_vertexStore->activate(m_mainFlags.compileAll || m_mainFlags.compileParts);
1401 TREModel::draw(TREMLines);
1402 // Next, switch to the default edge color, and draw the edge lines. By
1403 // definition, edge lines in the original files use the default edge color.
1404 // However, if parts are flattened, they can contain sub-models of a
1405 // different color, which can lead to non-default colored edge lines.
1406 glColor4ubv((GLubyte*)&m_edgeColor);
1407 lineWidth(m_edgeLineWidth);
1408 if (getLineJoinsFlag() && m_edgeLineWidth > 1.0f)
1409 {
1410 pointSize(m_edgeLineWidth);
1411 m_mainFlags.activeLineJoins = true;
1412 glEnable(GL_POINT_SMOOTH);
1413 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
1414 }
1415 if (getEdgeLinesFlag())
1416 {
1417 if (getNoDepthEdgeLinesFlag())
1418 {
1419 glPushAttrib(GL_DEPTH_BUFFER_BIT);
1420 glDisable(GL_DEPTH_TEST);
1421 }
1422 TREModel::draw(TREMEdgeLines);
1423 if (getNoDepthEdgeLinesFlag())
1424 {
1425 glPopAttrib();
1426 }
1427 }
1428 if (!getStencilConditionalsFlag())
1429 {
1430 m_vertexStore->deactivate();
1431 m_vertexStore->activate(false);
1432 }
1433 if (getConditionalLinesFlag())
1434 {
1435 TREModel::draw(TREMConditionalLines);
1436 }
1437 if (getLineJoinsFlag() && m_edgeLineWidth > 1.0f)
1438 {
1439 pointSize(1.0f);
1440 m_mainFlags.activeLineJoins = false;
1441 }
1442 // Next, draw the specific colored lines. As with the specific colored
1443 // triangles and quads, every point in the vertex store specifies a color.
1444 m_coloredVertexStore->activate(m_mainFlags.compileAll ||
1445 m_mainFlags.compileParts);
1446 drawColored(TREMLines);
1447 if (getEdgeLinesFlag())
1448 {
1449 if (getNoDepthEdgeLinesFlag())
1450 {
1451 glPushAttrib(GL_DEPTH_BUFFER_BIT);
1452 glDisable(GL_DEPTH_TEST);
1453 }
1454 // Next draw the specific colored edge lines. Note that if it weren't for
1455 // the fact that edge lines can be turned off, these could simply be added
1456 // to the colored lines list.
1457 drawColored(TREMEdgeLines);
1458 if (getNoDepthEdgeLinesFlag())
1459 {
1460 glPopAttrib();
1461 }
1462 }
1463 if (!getStencilConditionalsFlag())
1464 {
1465 m_coloredVertexStore->deactivate();
1466 m_coloredVertexStore->activate(false);
1467 }
1468 if (getConditionalLinesFlag())
1469 {
1470 drawColored(TREMConditionalLines);
1471 }
1472 if (getAALinesFlag() && !getWireframeFlag())
1473 {
1474 // Note that if we're in wireframe mode, smoothing was enabled
1475 // elsewhere, and will therefore be disabled eleswhere.
1476 glDepthMask(GL_TRUE);
1477 // We use glPushAttrib() when we enable line smoothing.
1478 glPopAttrib();
1479 }
1480 if (getLightingFlag())
1481 {
1482 glEnable(GL_LIGHTING);
1483 }
1484 m_vertexStore->deactivate();
1485 m_coloredVertexStore->deactivate();
1486 }
1487
modelNamed(const char * name,bool bfc)1488 TREModel *TREMainModel::modelNamed(const char *name, bool bfc)
1489 {
1490 return (TREMainModel *)getLoadedModels(bfc)->objectForKey(name);
1491 }
1492
registerModel(TREModel * model,bool bfc)1493 void TREMainModel::registerModel(TREModel *model, bool bfc)
1494 {
1495 getLoadedModels(bfc)->setObjectForKey(model, model->getName());
1496 }
1497
setColor(TCULong color,TCULong edgeColor)1498 void TREMainModel::setColor(TCULong color, TCULong edgeColor)
1499 {
1500 m_color = htonl(color);
1501 m_edgeColor = htonl(edgeColor);
1502 }
1503
getColor(void)1504 TCULong TREMainModel::getColor(void)
1505 {
1506 return htonl(m_color);
1507 }
1508
getEdgeColor(void)1509 TCULong TREMainModel::getEdgeColor(void)
1510 {
1511 return htonl(m_edgeColor);
1512 }
1513
setLightingFlag(bool value)1514 void TREMainModel::setLightingFlag(bool value)
1515 {
1516 m_mainFlags.lighting = value;
1517 m_vertexStore->setLightingFlag(value);
1518 m_studVertexStore->setLightingFlag(value);
1519 m_coloredVertexStore->setLightingFlag(value);
1520 m_coloredStudVertexStore->setLightingFlag(value);
1521 m_transVertexStore->setLightingFlag(value);
1522 m_texmapVertexStore->setLightingFlag(value);
1523 }
1524
setTwoSidedLightingFlag(bool value)1525 void TREMainModel::setTwoSidedLightingFlag(bool value)
1526 {
1527 m_mainFlags.twoSidedLighting = value;
1528 m_vertexStore->setTwoSidedLightingFlag(value);
1529 m_studVertexStore->setTwoSidedLightingFlag(value);
1530 m_coloredVertexStore->setTwoSidedLightingFlag(value);
1531 m_coloredStudVertexStore->setTwoSidedLightingFlag(value);
1532 m_transVertexStore->setTwoSidedLightingFlag(value);
1533 m_texmapVertexStore->setTwoSidedLightingFlag(value);
1534 }
1535
setShowAllConditionalFlag(bool value)1536 void TREMainModel::setShowAllConditionalFlag(bool value)
1537 {
1538 m_mainFlags.showAllConditional = value;
1539 m_vertexStore->setShowAllConditionalFlag(value);
1540 m_studVertexStore->setShowAllConditionalFlag(value);
1541 m_coloredVertexStore->setShowAllConditionalFlag(value);
1542 m_coloredStudVertexStore->setShowAllConditionalFlag(value);
1543 m_transVertexStore->setShowAllConditionalFlag(value);
1544 m_texmapVertexStore->setShowAllConditionalFlag(value);
1545 }
1546
setConditionalControlPointsFlag(bool value)1547 void TREMainModel::setConditionalControlPointsFlag(bool value)
1548 {
1549 m_mainFlags.conditionalControlPoints = value;
1550 m_vertexStore->setConditionalControlPointsFlag(value);
1551 m_studVertexStore->setConditionalControlPointsFlag(value);
1552 m_coloredVertexStore->setConditionalControlPointsFlag(value);
1553 m_coloredStudVertexStore->setConditionalControlPointsFlag(value);
1554 m_transVertexStore->setConditionalControlPointsFlag(value);
1555 m_texmapVertexStore->setConditionalControlPointsFlag(value);
1556 }
1557
getMaxRadiusSquared(const TCVector & center)1558 TCFloat TREMainModel::getMaxRadiusSquared(const TCVector ¢er)
1559 {
1560 if (!m_maxRadiusSquared)
1561 {
1562 m_center = center;
1563 scanPoints(this,
1564 (TREScanPointCallback)&TREMainModel::scanMaxRadiusSquaredPoint,
1565 TCVector::getIdentityMatrix());
1566 }
1567 return m_maxRadiusSquared;
1568 }
1569
scanMaxRadiusSquaredPoint(const TCVector & point)1570 void TREMainModel::scanMaxRadiusSquaredPoint(const TCVector &point)
1571 {
1572 TCFloat rSquared = (point - m_center).lengthSquared();
1573
1574 if (rSquared > m_maxRadiusSquared)
1575 {
1576 m_maxRadiusSquared = rSquared;
1577 }
1578 }
1579
1580 // By asking for the maximum radius squared, and then returning the square root
1581 // of that, we only have to do one square root for the whole radius calculation.
1582 // Otherwise, we would have to do one for every point.
getMaxRadius(const TCVector & center)1583 TCFloat TREMainModel::getMaxRadius(const TCVector ¢er)
1584 {
1585 return (TCFloat)sqrt(getMaxRadiusSquared(center));
1586 }
1587
postProcess(void)1588 bool TREMainModel::postProcess(void)
1589 {
1590 int i;
1591 float numSections = (float)(TREMTransparent - TREMStandard);
1592
1593 if (m_mainFlags.sendProgress)
1594 {
1595 TCProgressAlert::send("TREMainModel",
1596 TCLocalStrings::get(_UC("TREMainModelProcessing")), 0.0f, &m_abort,
1597 this);
1598 }
1599 if (m_abort)
1600 {
1601 return false;
1602 }
1603 transferTransparent();
1604 // Note: I DON'T want to check if the transparent section is present.
1605 // That's why I'm using < below, instead of <=.
1606 for (i = TREMFirst; i < TREMTransparent && !m_abort; i++)
1607 {
1608 float progress = (float)i / numSections * 0.8f + 0.2f;
1609
1610 if (m_mainFlags.sendProgress)
1611 {
1612 TCProgressAlert::send("TREMainModel",
1613 TCLocalStrings::get(_UC("TREMainModelProcessing")), progress,
1614 &m_abort, this);
1615 }
1616 if (!m_abort)
1617 {
1618 checkSectionPresent((TREMSection)i);
1619 checkSectionPresent((TREMSection)i, true);
1620 }
1621 }
1622 if (m_abort)
1623 {
1624 return false;
1625 }
1626 if (m_mainFlags.sendProgress)
1627 {
1628 TCProgressAlert::send("TREMainModel",
1629 TCLocalStrings::get(_UC("TREMainModelProcessing")), 1.0f, &m_abort,
1630 this);
1631 }
1632 if (m_abort)
1633 {
1634 return false;
1635 }
1636
1637 bindTexmaps();
1638 if (getCompilePartsFlag() || getCompileAllFlag())
1639 {
1640 compile();
1641 }
1642
1643 return !m_abort;
1644 }
1645
transferTexmapped(void)1646 void TREMainModel::transferTexmapped(void)
1647 {
1648 SectionList sectionList;
1649
1650 sectionList.push_back(TREMStandard);
1651 sectionList.push_back(TREMStud);
1652 if (getBFCFlag())
1653 {
1654 sectionList.push_back(TREMBFC);
1655 sectionList.push_back(TREMStudBFC);
1656 }
1657 transferTexmapped(sectionList);
1658 for (size_t i = 0; i < 3; i++)
1659 {
1660 for (size_t j = 1; j < m_texmappedStepCounts[i].size(); j++)
1661 {
1662 m_texmappedStepCounts[i][j] += m_texmappedStepCounts[i][j - 1];
1663 }
1664 if (m_texmappedShapes[i])
1665 {
1666 m_texmappedShapes[i]->setStepCounts(m_texmappedStepCounts[i]);
1667 }
1668 }
1669 }
1670
1671 // We have to remove all the transparent objects from the whole tree after we've
1672 // completely built the tree. Before it is completely built, we don't know
1673 // which items are transparent. The actual removal is complicated.
1674 //
1675 // First, any geometry that has a specific color specified (and thus is in a
1676 // TREColoredShapeGroup at the point this method is called) is simply removed
1677 // from its parent model completely, and then added to the transparent triangle
1678 // list (after being transformed into its coordinate system). Strips, fans,
1679 // and quads are all split into triangles.
1680 //
1681 // Next, any "default color" geometry that will in the end by transparent will
1682 // be transferred to the triangle list (with coordinate transformation and
1683 // strip/quad splitting). When the non-transparent portions are drawn, they
1684 // will completely skip default colored geomtry when the default color is
1685 // transparent.
transferTransparent(void)1686 void TREMainModel::transferTransparent(void)
1687 {
1688 SectionList sectionList;
1689
1690 sectionList.push_back(TREMStandard);
1691 sectionList.push_back(TREMStud);
1692 if (getBFCFlag())
1693 {
1694 sectionList.push_back(TREMBFC);
1695 sectionList.push_back(TREMStudBFC);
1696 }
1697 transferPrep();
1698 transferTransparent(sectionList);
1699 for (size_t i = 1; i < m_transStepCounts.size(); i++)
1700 {
1701 m_transStepCounts[i] += m_transStepCounts[i - 1];
1702 }
1703 TRETransShapeGroup *transShapes =
1704 (TRETransShapeGroup *)m_coloredShapes[TREMTransparent];
1705
1706 if (transShapes)
1707 {
1708 transShapes->setStepCounts(m_transStepCounts);
1709 }
1710 }
1711
transferTexmapped(const SectionList & sectionList)1712 void TREMainModel::transferTexmapped(const SectionList §ionList)
1713 {
1714 const TCFloat *matrix = TCVector::getIdentityMatrix();
1715 SectionList::const_iterator it;
1716
1717 for (it = sectionList.begin(); it != sectionList.end(); ++it)
1718 {
1719 TREShapeGroup *shapeGroup = m_shapes[*it];
1720 TREColoredShapeGroup *coloredShapeGroup = m_coloredShapes[*it];
1721
1722 if (shapeGroup)
1723 {
1724 shapeGroup->transfer(TREShapeGroup::TTTexmapped, m_color, matrix);
1725 }
1726 if (coloredShapeGroup)
1727 {
1728 coloredShapeGroup->transferColored(TREShapeGroup::TTTexmapped,
1729 matrix);
1730 }
1731 transferPrep();
1732 transferSubModels(TREShapeGroup::TTTexmapped, m_color, *it, matrix);
1733 //transferPrep();
1734 //transferColoredSubModels(TREShapeGroup::TTTexmapped, *it, matrix);
1735 }
1736 //if (m_subModels != NULL)
1737 //{
1738 // int i;
1739 // int count = m_subModels->getCount();
1740
1741 // for (i = 0; i < count; i++)
1742 // {
1743 // updateModelTransferStep(i);
1744 // for (SectionList::const_iterator it = sectionList.begin();
1745 // it != sectionList.end(); ++it)
1746 // {
1747 // TRESubModel *subModel = (*m_subModels)[i];
1748
1749 // subModel->transfer(TREShapeGroup::TTTexmapped, m_color, *it,
1750 // matrix);
1751 // subModel->transferColored(TREShapeGroup::TTTexmapped, *it,
1752 // matrix);
1753 // }
1754 // }
1755 //}
1756 for (it = sectionList.begin(); it != sectionList.end(); ++it)
1757 {
1758 TREModel::cleanupTransfer(TREShapeGroup::TTTexmapped, *it);
1759 }
1760 }
1761
transferTransparent(const SectionList & sectionList)1762 void TREMainModel::transferTransparent(const SectionList §ionList)
1763 {
1764 const TCFloat *matrix = TCVector::getIdentityMatrix();
1765 SectionList::const_iterator it;
1766
1767 for (it = sectionList.begin(); it != sectionList.end(); ++it)
1768 {
1769 TREShapeGroup *shapeGroup = m_shapes[*it];
1770 TREColoredShapeGroup *coloredShapeGroup = m_coloredShapes[*it];
1771
1772 if (shapeGroup)
1773 {
1774 shapeGroup->transfer(TREShapeGroup::TTTransparent, m_color, matrix);
1775 }
1776 if (coloredShapeGroup)
1777 {
1778 coloredShapeGroup->transferColored(TREShapeGroup::TTTransparent,
1779 matrix);
1780 }
1781 }
1782 if (m_subModels)
1783 {
1784 int i;
1785 int count = m_subModels->getCount();
1786
1787 for (i = 0; i < count; i++)
1788 {
1789 updateModelTransferStep(i);
1790 for (it = sectionList.begin(); it != sectionList.end(); ++it)
1791 {
1792 TRESubModel *subModel = (*m_subModels)[i];
1793
1794 subModel->transfer(TREShapeGroup::TTTransparent, m_color, *it,
1795 matrix);
1796 subModel->transferColored(TREShapeGroup::TTTransparent, *it,
1797 matrix);
1798 }
1799 }
1800 }
1801 for (it = sectionList.begin(); it != sectionList.end(); ++it)
1802 {
1803 TREModel::cleanupTransfer(TREShapeGroup::TTTransparent, *it);
1804 }
1805 }
1806
addTransferTriangle(TREShapeGroup::TRESTransferType type,TCULong color,const TCVector vertices[],const TCVector normals[],bool bfc,const TCVector * textureCoords,const TCFloat * matrix)1807 void TREMainModel::addTransferTriangle(
1808 TREShapeGroup::TRESTransferType type,
1809 TCULong color,
1810 const TCVector vertices[],
1811 const TCVector normals[],
1812 bool bfc,
1813 const TCVector *textureCoords,
1814 const TCFloat *matrix)
1815 {
1816 if (type == TREShapeGroup::TTTransparent)
1817 {
1818 if (!m_coloredShapes[TREMTransparent])
1819 {
1820 m_coloredShapes[TREMTransparent] = new TRETransShapeGroup;
1821 m_coloredShapes[TREMTransparent]->setModel(this);
1822 m_coloredShapes[TREMTransparent]->setVertexStore(m_transVertexStore);
1823 }
1824 if (getStudLogoFlag() && getStudTextures())
1825 {
1826 if (textureCoords)
1827 {
1828 m_coloredShapes[TREMTransparent]->addTriangle(color, vertices,
1829 normals, textureCoords);
1830 }
1831 else
1832 {
1833 static TCVector zeroTextureCoords[3] =
1834 {
1835 TCVector(0.0, 0.0, 0.0),
1836 TCVector(0.0, 0.0, 0.0),
1837 TCVector(0.0, 0.0, 0.0)
1838 };
1839
1840 m_coloredShapes[TREMTransparent]->addTriangle(color, vertices,
1841 normals, zeroTextureCoords);
1842 }
1843 }
1844 else
1845 {
1846 m_coloredShapes[TREMTransparent]->addTriangle(color, vertices, normals);
1847 }
1848 if (m_transStepCounts.size() <= (size_t)m_transferStep)
1849 {
1850 m_transStepCounts.resize(m_transferStep + 1);
1851 }
1852 m_transStepCounts[m_transferStep] += 3;
1853 }
1854 else // type == TREShapeGroup::TTTexmapped
1855 {
1856 int shapeIndex;
1857 bool mirror = bfc && TCVector::determinant(matrix) < 0.0f;
1858 TexmapInfo& texmapInfo = m_mainTexmapInfos.back();
1859 TREModel::TexmapInfo::GeomInfo *geomInfo = bfc ? &texmapInfo.bfc :
1860 &texmapInfo.standard;
1861 TCVector finalTextureCoords[3];
1862
1863 if (TREShapeGroup::isTransparent(color, false))
1864 {
1865 shapeIndex = 2;
1866 geomInfo = &m_mainTexmapInfos.back().transparent;
1867 }
1868 else
1869 {
1870 shapeIndex = bfc ? 1 : 0;
1871 }
1872 texmapInfo.calcTextureCoords(vertices, finalTextureCoords);
1873 if (m_texmappedShapes[shapeIndex] == NULL)
1874 {
1875 m_texmappedShapes[shapeIndex] = new TRETexmappedShapeGroup;
1876 m_texmappedShapes[shapeIndex]->setModel(this);
1877 m_texmappedShapes[shapeIndex]->setVertexStore(m_texmapVertexStore);
1878 }
1879 if (mirror)
1880 {
1881 TCVector mirroredVertices[3];
1882 TCVector *mirroredNormals = NULL;
1883 int i;
1884
1885 for (i = 0; i < 3; i++)
1886 {
1887 mirroredVertices[2 - i] = vertices[i];
1888 }
1889 if (normals != NULL)
1890 {
1891 mirroredNormals = new TCVector[3];
1892
1893 for (i = 0; i < 3; i++)
1894 {
1895 mirroredNormals[2 - i] = -normals[i];
1896 }
1897 }
1898 std::swap(finalTextureCoords[0], finalTextureCoords[2]);
1899 m_texmappedShapes[shapeIndex]->addTriangle(0xFFFFFFFF,
1900 mirroredVertices, mirroredNormals, finalTextureCoords);
1901 delete[] mirroredNormals;
1902 }
1903 else
1904 {
1905 m_texmappedShapes[shapeIndex]->addTriangle(0xFFFFFFFF, vertices,
1906 normals, finalTextureCoords);
1907 }
1908 int indexCount =
1909 m_texmappedShapes[shapeIndex]->getIndexCount(TRESTriangle);
1910 if (mirror)
1911 {
1912 for (int i = 2; i >= 0; i--)
1913 {
1914 geomInfo->colored.triangles.insert(indexCount - 3 + i);
1915 }
1916 }
1917 else
1918 {
1919 for (int i = 0; i < 3; i++)
1920 {
1921 geomInfo->colored.triangles.insert(indexCount - 3 + i);
1922 }
1923 }
1924 if (m_texmappedStepCounts[shapeIndex].size() <= (size_t)m_transferStep)
1925 {
1926 m_texmappedStepCounts[shapeIndex].resize(m_transferStep + 1);
1927 }
1928 m_texmappedStepCounts[shapeIndex][m_transferStep] += 3;
1929 }
1930 }
1931
onLastStep(void)1932 bool TREMainModel::onLastStep(void)
1933 {
1934 return m_step == -1 || m_step == m_numSteps - 1;
1935 }
1936
getPolygonOffsetFactor(TREPolygonOffsetPurpose purpose)1937 GLfloat TREMainModel::getPolygonOffsetFactor(TREPolygonOffsetPurpose purpose)
1938 {
1939 if (getEdgeLinesFlag())
1940 {
1941 float multiplier = getPolygonOffsetFlag() ? 1.0f : 0.0f;
1942 switch (purpose)
1943 {
1944 case TPOPMain:
1945 if (m_coloredShapes[TREMTransparent] != NULL)
1946 {
1947 // If there is transparent geometry, we want the main
1948 // geometry to be pushed away slightly more than the
1949 // transparent geometry.
1950 multiplier += 0.5;
1951 }
1952 if (!m_mainTexmapInfos.empty())
1953 {
1954 // If there are texmaps, we need the main geometry to be
1955 // pushed away enough to allow the texmaps to display
1956 // correctly.
1957 multiplier += m_textureOffsetFactor;
1958 }
1959 return POLYGON_OFFSET_FACTOR * multiplier;
1960 case TPOPTransparent:
1961 return POLYGON_OFFSET_FACTOR;
1962 case TPOPTexmaps:
1963 if (m_coloredShapes[TREMTransparent] != NULL)
1964 {
1965 // If there is transparent geometry, we want the texmapped
1966 // geometry to be pushed away slightly more than the
1967 // transparent geometry.
1968 multiplier += 0.5;
1969 }
1970 return POLYGON_OFFSET_FACTOR * multiplier;
1971 default:
1972 return 0.0;
1973 }
1974 }
1975 else
1976 {
1977 switch (purpose)
1978 {
1979 case TPOPMain:
1980 return POLYGON_OFFSET_FACTOR;
1981 case TPOPTransparent:
1982 return -POLYGON_OFFSET_FACTOR;
1983 case TPOPTexmaps:
1984 return -POLYGON_OFFSET_FACTOR * m_textureOffsetFactor;
1985 default:
1986 return 0.0;
1987 }
1988 }
1989 }
1990
drawTransparent(int pass)1991 void TREMainModel::drawTransparent(int pass /*= -1*/)
1992 {
1993 if (m_coloredShapes[TREMTransparent])
1994 {
1995 GLfloat specular[] = {0.75f, 0.75f, 0.75f, 1.0f};
1996 GLfloat oldSpecular[4];
1997 GLfloat oldShininess;
1998
1999 deactivateBFC(true);
2000 if (getStudLogoFlag())
2001 {
2002 glEnable(GL_TEXTURE_2D);
2003 bindStudTexture();
2004 // Don't allow mip-mapping for transparent textures; it might cause
2005 // artifacts.
2006 configureStudTexture(false);
2007 }
2008 glGetMaterialfv(GL_FRONT, GL_SHININESS, &oldShininess);
2009 glGetMaterialfv(GL_FRONT, GL_SPECULAR, oldSpecular);
2010 m_transVertexStore->activate(!m_mainFlags.sortTransparent);
2011 if (getStippleFlag())
2012 {
2013 glEnable(GL_POLYGON_STIPPLE);
2014 }
2015 else if (!getCutawayDrawFlag())
2016 {
2017 if (pass != 1)
2018 {
2019 enable(GL_BLEND);
2020 if (pass == 2)
2021 {
2022 blendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE_MINUS_SRC_ALPHA);
2023 }
2024 else
2025 {
2026 blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2027 }
2028 glDepthMask(GL_FALSE);
2029 }
2030 }
2031 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128.0f);
2032 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
2033 if (!getWireframeFlag() && getPolygonOffsetFlag())
2034 {
2035 if (getEdgeLinesFlag())
2036 {
2037 disable(GL_POLYGON_OFFSET_FILL);
2038 // glPolygonOffset(0.0f, 0.0f);
2039 }
2040 else
2041 {
2042 glPolygonOffset(getPolygonOffsetFactor(TPOPTransparent),
2043 POLYGON_OFFSET_UNITS);
2044 enable(GL_POLYGON_OFFSET_FILL);
2045 }
2046 }
2047 if (onLastStep() && m_coloredListIDs[TREMTransparent])
2048 {
2049 glCallList(m_coloredListIDs[TREMTransparent]);
2050 }
2051 else
2052 {
2053 ((TRETransShapeGroup *)m_coloredShapes[TREMTransparent])->
2054 draw(getSortTransparentFlag() && !getCutawayDrawFlag() &&
2055 pass < 2);
2056 }
2057 if (getStudLogoFlag())
2058 {
2059 glDisable(GL_TEXTURE_2D);
2060 }
2061 disable(GL_POLYGON_OFFSET_FILL);
2062 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, oldSpecular);
2063 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, oldShininess);
2064 if (getStippleFlag())
2065 {
2066 glDisable(GL_POLYGON_STIPPLE);
2067 }
2068 else if (!getCutawayDrawFlag())
2069 {
2070 disable(GL_BLEND);
2071 glDepthMask(GL_TRUE);
2072 }
2073 m_transVertexStore->deactivate();
2074 }
2075 }
2076
shouldLoadConditionalLines(void)2077 bool TREMainModel::shouldLoadConditionalLines(void)
2078 {
2079 return (m_mainFlags.edgeLines && m_mainFlags.conditionalLines) ||
2080 m_mainFlags.smoothCurves;
2081 }
2082
configTextureFilters(void)2083 void TREMainModel::configTextureFilters(void)
2084 {
2085 if (m_studTextureFilter == GL_NEAREST_MIPMAP_NEAREST ||
2086 m_studTextureFilter == GL_NEAREST_MIPMAP_LINEAR ||
2087 m_studTextureFilter == GL_NEAREST)
2088 {
2089 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2090 }
2091 else
2092 {
2093 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2094 }
2095 if (m_studTextureFilter == GL_LINEAR_MIPMAP_LINEAR)
2096 {
2097 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2098 m_studTextureFilter);
2099 }
2100 else
2101 {
2102 if (m_studTextureFilter == GL_NEAREST)
2103 {
2104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2105 GL_NEAREST);
2106 }
2107 else
2108 {
2109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2110 GL_LINEAR);
2111 }
2112 //glTexImage2D(GL_TEXTURE_2D, 0, format, info.image->getWidth(),
2113 // info.image->getHeight(), 0, format, GL_UNSIGNED_BYTE,
2114 // info.image->getImageData());
2115 }
2116 if (m_studTextureFilter == GL_LINEAR_MIPMAP_LINEAR &&
2117 TREGLExtensions::haveAnisoExtension())
2118 {
2119 GLfloat aniso = 1.0f;
2120
2121 if (m_studTextureFilter == GL_LINEAR_MIPMAP_LINEAR)
2122 {
2123 aniso = m_studAnisoLevel;
2124 }
2125 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
2126 aniso);
2127 }
2128 }
2129
configTexmaps(void)2130 void TREMainModel::configTexmaps(void)
2131 {
2132 if (m_texmapImages.size() > 0)
2133 {
2134 for (TexmapImageInfoMap::iterator it = m_texmapImages.begin();
2135 it != m_texmapImages.end(); ++it)
2136 {
2137 TexmapImageInfo &info = it->second;
2138 GLint textureMode = GL_MODULATE;
2139
2140 if (!getLightingFlag())
2141 {
2142 textureMode = GL_REPLACE;
2143 }
2144 glBindTexture(GL_TEXTURE_2D, info.textureID);
2145 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, textureMode);
2146 configTextureFilters();
2147 }
2148 }
2149 }
2150
bindTexmaps(void)2151 void TREMainModel::bindTexmaps(void)
2152 {
2153 if (m_texmapImages.size() > 0)
2154 {
2155 std::vector<GLuint> textureIDs;
2156 size_t i = 0;
2157
2158 if (TREGLExtensions::haveClampToBorderExtension())
2159 {
2160 m_texClampMode = GL_CLAMP_TO_BORDER;
2161 }
2162 textureIDs.resize(m_texmapImages.size());
2163 glGenTextures((GLsizei)m_texmapImages.size(), &textureIDs[0]);
2164 for (TexmapImageInfoMap::iterator it = m_texmapImages.begin();
2165 it != m_texmapImages.end(); ++it)
2166 {
2167 TexmapImageInfo &info = it->second;
2168 if (info.image == NULL)
2169 {
2170 continue;
2171 }
2172
2173 info.textureID = textureIDs[i++];
2174 if (info.image->getDataFormat() == TCRgb8)
2175 {
2176 // Source image is RGB; we need to convert to RGBA. We can't just
2177 // send the RGB data to OpenGL because that causes it to use black
2178 // for all pixels outside the border of the texture instead of
2179 // transparent.
2180 TCImage *rgbaImage = new TCImage;
2181 int width = info.image->getWidth();
2182 int height = info.image->getHeight();
2183 TCByte *src = info.image->getImageData();
2184 TCByte *dst = NULL;
2185 int srcPadding = info.image->getRowSize() - width * 3;
2186
2187 // Note: no need to set the line alignment to 4, because each pixel
2188 // is 4 bytes, so we're already guaranteed to have that alignment.
2189 rgbaImage->setDataFormat(TCRgba8);
2190 rgbaImage->setSize(width, height);
2191 rgbaImage->allocateImageData();
2192 dst = rgbaImage->getImageData();
2193 for (int row = 0; row < height; row++)
2194 {
2195 for (int col = 0; col < width; col++)
2196 {
2197 for (int component = 0; component < 3; component++)
2198 {
2199 *dst++ = *src++;
2200 }
2201 *dst++ = 255; // Fully opaque.
2202 }
2203 src += srcPadding;
2204 }
2205 info.image->release();
2206 info.image = rgbaImage;
2207 }
2208 glBindTexture(GL_TEXTURE_2D, info.textureID);
2209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_texClampMode);
2210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_texClampMode);
2211 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2212 configTextureFilters();
2213 #ifdef __clang__
2214 #pragma clang diagnostic push
2215 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2216 #endif
2217 gluBuild2DMipmaps(GL_TEXTURE_2D, 4, info.image->getWidth(),
2218 info.image->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
2219 info.image->getImageData());
2220 #ifdef __clang__
2221 #pragma clang diagnostic pop
2222 #endif
2223 }
2224 }
2225 }
2226
bindStudTexture(void)2227 void TREMainModel::bindStudTexture(void)
2228 {
2229 if (!sm_studTextureID && sm_studTextures)
2230 {
2231 int i;
2232 int count = sm_studTextures->getCount();
2233
2234 glGenTextures(1, (GLuint*)&sm_studTextureID);
2235 glBindTexture(GL_TEXTURE_2D, sm_studTextureID);
2236 for (i = 0; i < count; i++)
2237 {
2238 TCImage *texture = (*sm_studTextures)[i];
2239
2240 if (texture)
2241 {
2242 int textureSize = texture->getWidth();
2243
2244 glTexImage2D(GL_TEXTURE_2D, i, 4, textureSize, textureSize, 0,
2245 GL_RGBA, GL_UNSIGNED_BYTE, texture->getImageData());
2246 }
2247 }
2248 }
2249 if (sm_studTextureID)
2250 {
2251 glBindTexture(GL_TEXTURE_2D, sm_studTextureID);
2252 }
2253 }
2254
configureStudTexture(bool allowMipMap)2255 void TREMainModel::configureStudTexture(bool allowMipMap)
2256 {
2257 if (sm_studTextureID)
2258 {
2259 glBindTexture(GL_TEXTURE_2D, sm_studTextureID);
2260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_texClampMode);
2261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_texClampMode);
2262 // Note: if the card doesn't support the following extension, it will
2263 // just silently fail, and nothing bad will have happened. If it is
2264 // supported, it makes textures a bit sharper, with a higher possibility
2265 // of moire.
2266 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, -0.5f);
2267 while (glGetError() != GL_NO_ERROR)
2268 {
2269 // Don't do anything; just loop until error flag(s) is/are clear.
2270 }
2271 if (m_studTextureFilter == GL_NEAREST_MIPMAP_NEAREST ||
2272 m_studTextureFilter == GL_NEAREST_MIPMAP_LINEAR ||
2273 m_studTextureFilter == GL_NEAREST)
2274 {
2275 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2276 }
2277 else
2278 {
2279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2280 }
2281 if (allowMipMap)
2282 {
2283 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2284 m_studTextureFilter);
2285 }
2286 else
2287 {
2288 if (m_studTextureFilter == GL_NEAREST)
2289 {
2290 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2291 GL_NEAREST);
2292 }
2293 else
2294 {
2295 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2296 GL_LINEAR);
2297 }
2298 }
2299 if (TREGLExtensions::haveAnisoExtension())
2300 {
2301 GLfloat aniso = 1.0f;
2302
2303 if (m_studTextureFilter == GL_LINEAR_MIPMAP_LINEAR)
2304 {
2305 aniso = m_studAnisoLevel;
2306 }
2307 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
2308 aniso);
2309 }
2310 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
2311 }
2312 }
2313
2314 // NOTE: static function
loadStudTexture(const char * filename)2315 void TREMainModel::loadStudTexture(const char *filename)
2316 {
2317 if (!sm_studTextures)
2318 {
2319 TCImage *mainImage = new TCImage;
2320
2321 mainImage->setFlipped(true);
2322 mainImage->setLineAlignment(4);
2323 if (mainImage->loadFile(filename))
2324 {
2325 loadStudMipTextures(mainImage);
2326 }
2327 mainImage->release();
2328 }
2329 }
2330
2331 // NOTE: static function
loadStudMipTextures(TCImage * mainImage)2332 void TREMainModel::loadStudMipTextures(TCImage *mainImage)
2333 {
2334 int i;
2335 int yPosition = 0;
2336 int thisSize = mainImage->getWidth();
2337 int imageHeight = mainImage->getHeight();
2338
2339 TCObject::release(sm_studTextures);
2340 sm_studTextures = new TCImageArray(8);
2341 for (i = 0; thisSize > 0 && yPosition + thisSize <= imageHeight; i++)
2342 {
2343 TCImage *texture = mainImage->createSubImage(0, yPosition,
2344 thisSize, thisSize);
2345 sm_studTextures->addObject(texture);
2346 texture->release();
2347 yPosition += thisSize;
2348 thisSize /= 2;
2349 }
2350 }
2351
2352 // NOTE: static function
setStudTextureData(TCByte * data,long length)2353 void TREMainModel::setStudTextureData(TCByte *data, long length)
2354 {
2355 if (!sm_studTextures)
2356 {
2357 TCImage *mainImage = new TCImage;
2358
2359 mainImage->setFlipped(true);
2360 mainImage->setLineAlignment(4);
2361 if (mainImage->loadData(data, length))
2362 {
2363 loadStudMipTextures(mainImage);
2364 }
2365 mainImage->release();
2366 }
2367 }
2368
2369 // NOTE: static function
setRawStudTextureData(TCByte * data,long length)2370 void TREMainModel::setRawStudTextureData(TCByte *data, long length)
2371 {
2372 if (!sm_studTextures)
2373 {
2374 TCImage *mainImage = new TCImage;
2375 int rowSize;
2376
2377 mainImage->setFlipped(true);
2378 mainImage->setLineAlignment(4);
2379 mainImage->setDataFormat(TCRgba8);
2380 mainImage->setSize(128, 255);
2381 mainImage->allocateImageData();
2382 rowSize = mainImage->getRowSize();
2383 if (length == rowSize * 255)
2384 {
2385 TCByte *imageData = mainImage->getImageData();
2386 int i;
2387
2388 for (i = 0; i < 255; i++)
2389 {
2390 memcpy(imageData + rowSize * (254 - i), data + rowSize * i,
2391 rowSize);
2392 }
2393 loadStudMipTextures(mainImage);
2394 }
2395 mainImage->release();
2396 }
2397 }
2398
openGlWillEnd(void)2399 void TREMainModel::openGlWillEnd(void)
2400 {
2401 uncompile();
2402 m_vertexStore->openGlWillEnd();
2403 m_studVertexStore->openGlWillEnd();
2404 m_coloredVertexStore->openGlWillEnd();
2405 m_coloredStudVertexStore->openGlWillEnd();
2406 m_transVertexStore->openGlWillEnd();
2407 if (sm_studTextureID)
2408 {
2409 glDeleteTextures(1, &TREMainModel::sm_studTextureID);
2410 sm_studTextureID = 0;
2411 }
2412 deleteGLTexmaps();
2413 }
2414
deleteGLTexmaps(void)2415 void TREMainModel::deleteGLTexmaps(void)
2416 {
2417 std::vector<GLuint> textureIDs;
2418
2419 textureIDs.reserve(m_texmapImages.size());
2420 for (TexmapImageInfoMap::iterator it = m_texmapImages.begin();
2421 it != m_texmapImages.end(); ++it)
2422 {
2423 TexmapImageInfo &info = it->second;
2424
2425 if (info.textureID != 0)
2426 {
2427 textureIDs.push_back(info.textureID);
2428 info.textureID = 0;
2429 }
2430 }
2431 if (textureIDs.size() > 0)
2432 {
2433 glDeleteTextures((GLsizei)textureIDs.size(), &textureIDs[0]);
2434 }
2435 }
2436
finish(void)2437 void TREMainModel::finish(void)
2438 {
2439 // transferTexmapped() has to happen before finishParts does any part
2440 // flattening. And it has to happen after shrinkParts().
2441 if (m_seamWidth != 0.0 && !isPart())
2442 {
2443 shrinkParts();
2444 }
2445 transferTexmapped();
2446 //flattenNonUniform();
2447 finishParts();
2448 findLights();
2449 flattenConditionals();
2450 if (m_stepCounts.size() > 0)
2451 {
2452 if (m_subModels->getCount() > m_stepCounts.back())
2453 {
2454 m_numSteps = (int)m_stepCounts.size() + 1;
2455 }
2456 else
2457 {
2458 m_numSteps = (int)m_stepCounts.size();
2459 }
2460 }
2461 else
2462 {
2463 m_numSteps = 1;
2464 }
2465 if (getSmoothCurvesFlag())
2466 {
2467 // We are smoothing curves; check to see if we have any texmapped
2468 // triangles.
2469 TRETrianglesMap triangles[2];
2470 int i;
2471
2472 for (i = 0; i < 2; i++)
2473 {
2474 if (m_texmappedShapes[i] != NULL &&
2475 m_texmappedShapes[i]->getIndexCount(TRESTriangle) > 0)
2476 {
2477 populateTrianglesMap(m_texmappedShapes[i], triangles[i]);
2478 }
2479 }
2480 transferSmoothNormals(triangles);
2481 }
2482 }
2483
transferSmoothNormals(const TRETrianglesMap & triangles,TREVertexStore * vertexStore,TCULongArray * indices,TREVertexStore * dstVertexStore,TCULongArray * dstIndices,int i0,int i1,int i2,const TCFloat * matrix)2484 bool TREMainModel::transferSmoothNormals(
2485 const TRETrianglesMap &triangles,
2486 TREVertexStore *vertexStore,
2487 TCULongArray *indices,
2488 TREVertexStore *dstVertexStore,
2489 TCULongArray *dstIndices,
2490 int i0,
2491 int i1,
2492 int i2,
2493 const TCFloat *matrix)
2494 {
2495 int triIndices[3] = { i0, i1, i2 };
2496 TRETrianglesMap::const_iterator itMap = triangles.end();
2497 int i;
2498 TREVertex triangleVerts[3];
2499 TREVertexArray *vertices = vertexStore->getVertices();
2500 TREVertexArray *normals = vertexStore->getNormals();
2501 TREVertexArray *dstNormals = dstVertexStore->getNormals();
2502
2503 for (i = 0; i < 3; i++)
2504 {
2505 triangleVerts[i] = (*vertices)[(*indices)[triIndices[i]]];
2506 TCVector vec(
2507 TCVector(triangleVerts[i].v).transformPoint(matrix));
2508 memcpy(triangleVerts[i].v, &vec[0],
2509 sizeof(triangleVerts[i].v));
2510 if (i == 0)
2511 {
2512 itMap = triangles.find(triangleVerts[0]);
2513 if (itMap == triangles.end())
2514 {
2515 break;
2516 }
2517 }
2518 }
2519 if (itMap != triangles.end())
2520 {
2521 const TRETriangleList &triList = itMap->second;
2522 TRETriangleList::const_iterator itList;
2523
2524 for (itList = triList.begin(); itList != triList.end();
2525 ++itList)
2526 {
2527 const TRETriangle &triangle = *itList;
2528 bool match1 = true;
2529 bool match2 = false;
2530
2531 for (i = 0; i < 3; i++)
2532 {
2533 if (!triangle.points[i]->approxEquals(triangleVerts[i],
2534 1e-5f))
2535 {
2536 match1 = false;
2537 break;
2538 }
2539 }
2540 if (!match1)
2541 {
2542 match2 = true;
2543 for (i = 0; i < 3; i++)
2544 {
2545 if (!triangle.points[2 - i]->approxEquals(triangleVerts[i],
2546 1e-5f))
2547 {
2548 match2 = false;
2549 break;
2550 }
2551 }
2552 }
2553 if (match1 || match2)
2554 {
2555 // This is our texmapped triangle.
2556 for (i = 0; i < 3; i++)
2557 {
2558 int dstNormalIndex;
2559 TREVertex normal = (*normals)[(*indices)[triIndices[i]]];
2560 TCVector normalVec(
2561 TCVector(normal.v).transformNormal(matrix));
2562 if (match1)
2563 {
2564 dstNormalIndex = (*dstIndices)[triangle.index + i];
2565 }
2566 else
2567 {
2568 dstNormalIndex = (*dstIndices)[triangle.index + 2 - i];
2569 }
2570 TREVertex &dstNormal = (*dstNormals)[dstNormalIndex];
2571 TCVector dstNormalVec(dstNormal.v);
2572 if (TRESmoother::shouldFlipNormal(normalVec, dstNormalVec))
2573 {
2574 normalVec *= -1.0f;
2575 }
2576 memcpy(dstNormal.v, &normalVec[0], sizeof(dstNormal.v));
2577 }
2578 return true;
2579 }
2580 }
2581 }
2582 return false;
2583 }
2584
transferSmoothNormals(const TRETrianglesMap & triangles,TREShapeGroup * shapeGroup,TREShapeType shapeType,int shapeSize,const TCFloat * matrix)2585 void TREMainModel::transferSmoothNormals(
2586 const TRETrianglesMap &triangles,
2587 TREShapeGroup *shapeGroup,
2588 TREShapeType shapeType,
2589 int shapeSize,
2590 const TCFloat *matrix)
2591 {
2592 int dstIndex = shapeGroup->getBfc() ? 1 : 0;
2593 TREShapeGroup *dstShapeGroup = m_texmappedShapes[dstIndex];
2594
2595 if (dstShapeGroup != NULL)
2596 {
2597 TREVertexStore *dstVertexStore = dstShapeGroup->getVertexStore();
2598 TCULongArray *indices = shapeGroup->getIndices(shapeType);
2599 TCULongArray *dstIndices = dstShapeGroup->getIndices(TRESTriangle);
2600 int count = shapeGroup->getIndexCount(shapeType);
2601 TREVertexStore *vertexStore = shapeGroup->getVertexStore();
2602
2603 if (count > 0 && indices != NULL && vertexStore != NULL &&
2604 dstVertexStore != NULL)
2605 {
2606 for (int i = count - shapeSize; i >= 0; i -= shapeSize)
2607 {
2608 bool found = transferSmoothNormals(triangles, vertexStore,
2609 indices, dstVertexStore, dstIndices, i, i + 1, i + 2, matrix);
2610 if (shapeSize == 4)
2611 {
2612 transferSmoothNormals(triangles, vertexStore, indices,
2613 dstVertexStore, dstIndices, i, i + 2, i + 3, matrix);
2614 }
2615 if (!found && shapeSize == 4)
2616 {
2617 transferSmoothNormals(triangles, vertexStore,
2618 indices, dstVertexStore, dstIndices, i + 3, i + 2, i + 1, matrix);
2619 if (shapeSize == 4)
2620 {
2621 transferSmoothNormals(triangles, vertexStore, indices,
2622 dstVertexStore, dstIndices, i + 3, i + 1, i + 0, matrix);
2623 }
2624 }
2625 }
2626 }
2627 }
2628 }
2629
transferSmoothNormals(const TRETrianglesMap & triangles,TREShapeGroup * shapeGroup,const TCFloat * matrix)2630 void TREMainModel::transferSmoothNormals(
2631 const TRETrianglesMap &triangles,
2632 TREShapeGroup *shapeGroup,
2633 const TCFloat *matrix)
2634 {
2635 if (shapeGroup != NULL)
2636 {
2637 transferSmoothNormals(triangles, shapeGroup, TRESTriangle, 3, matrix);
2638 transferSmoothNormals(triangles, shapeGroup, TRESQuad, 4, matrix);
2639 }
2640 }
2641
transferSmoothNormals(const TRETrianglesMap triangles[],TREModel * model,const TCFloat * matrix)2642 void TREMainModel::transferSmoothNormals(
2643 const TRETrianglesMap triangles[],
2644 TREModel *model,
2645 const TCFloat *matrix)
2646 {
2647 if (model != NULL)
2648 {
2649 int subModelCount = model->getSubModelCount();
2650 TRESubModelArray *subModels = model->getSubModels();
2651
2652 transferSmoothNormals(triangles[0], model->getShape(TREMStandard), matrix);
2653 transferSmoothNormals(triangles[1], model->getShape(TREMBFC), matrix);
2654 transferSmoothNormals(triangles[0], model->getColoredShape(TREMStandard), matrix);
2655 transferSmoothNormals(triangles[1], model->getColoredShape(TREMBFC), matrix);
2656 for (int i = 0; i < subModelCount; i++)
2657 {
2658 TRESubModel *subModel = (*subModels)[i];
2659 TCFloat newMatrix[16];
2660
2661 TCVector::multMatrix(matrix, subModel->getMatrix(), newMatrix);
2662 transferSmoothNormals(triangles, subModel->getModel(), newMatrix);
2663 }
2664 }
2665 }
2666
transferSmoothNormals(const TRETrianglesMap triangles[])2667 void TREMainModel::transferSmoothNormals(const TRETrianglesMap triangles[])
2668 {
2669 TCFloat matrix[16];
2670
2671 TCVector::initIdentityMatrix(matrix);
2672 transferSmoothNormals(triangles, this, matrix);
2673 }
2674
populateTrianglesMap(TRETexmappedShapeGroup * shapeGroup,TRETrianglesMap & triangles)2675 void TREMainModel::populateTrianglesMap(
2676 TRETexmappedShapeGroup *shapeGroup,
2677 TRETrianglesMap &triangles)
2678 {
2679 TCULongArray *indices = shapeGroup->getIndices(TRESTriangle);
2680 TREVertexStore *vertexStore = shapeGroup->getVertexStore();
2681
2682 if (indices != NULL && vertexStore != NULL)
2683 {
2684 TREVertexArray *vertices = vertexStore->getVertices();
2685
2686 if (vertices != NULL)
2687 {
2688 int count = shapeGroup->getIndexCount(TRESTriangle);
2689 TRETriangle triangle;
2690 int i, j;
2691
2692 memset(&triangle, 0, sizeof(triangle));
2693 for (i = 0; i < count; i += 3)
2694 {
2695 triangle.index = i;
2696 for (j = 0; j < 3; j++)
2697 {
2698 triangle.points[j] = &(*vertices)[(*indices)[i + j]];
2699 }
2700 for (j = 0; j < 3; j++)
2701 {
2702 triangles[*triangle.points[j]].push_back(triangle);
2703 }
2704 }
2705 }
2706 }
2707 }
2708
addLight(const TCVector & location,TCULong color)2709 void TREMainModel::addLight(const TCVector &location, TCULong color)
2710 {
2711 m_lightLocations.push_back(location);
2712 m_lightColors.push_back(color);
2713 }
2714
flattenConditionals(void)2715 void TREMainModel::flattenConditionals(void)
2716 {
2717 if (doingBackgroundConditionals())
2718 {
2719 setup(TREMConditionalLines);
2720 m_shapes[TREMConditionalLines]->getVertexStore()->setup();
2721 setupColored(TREMConditionalLines);
2722 m_coloredShapes[TREMConditionalLines]->getVertexStore()->setupColored();
2723 transferPrep();
2724 TREModel::flattenConditionals(TCVector::getIdentityMatrix(), 0, false);
2725 removeConditionals();
2726 }
2727 }
2728
transferPrep(void)2729 void TREMainModel::transferPrep(void)
2730 {
2731 m_transferStep = 0;
2732 }
2733
updateModelTransferStep(int subModelIndex,bool isConditionals)2734 void TREMainModel::updateModelTransferStep(
2735 int subModelIndex,
2736 bool isConditionals /*= false*/)
2737 {
2738 if (m_stepCounts.size() > (size_t)m_transferStep)
2739 {
2740 if (m_stepCounts[m_transferStep] <= subModelIndex)
2741 {
2742 if (isConditionals)
2743 {
2744 TREShapeGroup *coloredShapeGroup =
2745 m_coloredShapes[TREMConditionalLines];
2746 if (coloredShapeGroup != NULL)
2747 {
2748 coloredShapeGroup->updateConditionalsStepCount(
2749 m_transferStep);
2750 }
2751 }
2752 m_transferStep++;
2753 }
2754 }
2755 }
2756
setStep(int value)2757 void TREMainModel::setStep(int value)
2758 {
2759 m_step = value;
2760 TRETransShapeGroup *transShapes =
2761 (TRETransShapeGroup *)m_coloredShapes[TREMTransparent];
2762
2763 if (transShapes)
2764 {
2765 transShapes->stepChanged();
2766 }
2767 }
2768
startTexture(int type,const std::string & filename,TCImage * image,const TCVector * points,const TCFloat * extra)2769 void TREMainModel::startTexture(
2770 int type,
2771 const std::string &filename,
2772 TCImage *image,
2773 const TCVector *points,
2774 const TCFloat *extra)
2775 {
2776 getCurGeomModel()->startTexture(type, filename, image, points, extra);
2777 TREModel::startTexture(type, filename, image, points, extra);
2778 }
2779
getCurGeomModel(void)2780 TREModel *TREMainModel::getCurGeomModel(void)
2781 {
2782 if (m_curGeomModel == NULL)
2783 {
2784 m_curGeomModel = new TREModel;
2785
2786 m_curGeomModel->setMainModel(this);
2787 m_curGeomModel->setName("TREMainModel GeomModel");
2788 addSubModel(TCVector::getIdentityMatrix(), m_curGeomModel, false);
2789 m_curGeomModel->release();
2790 }
2791 return m_curGeomModel;
2792 }
2793
nextStep(void)2794 void TREMainModel::nextStep(void)
2795 {
2796 if (m_subModels == NULL || (m_stepCounts.size() > 0 &&
2797 m_subModels->getCount() == m_stepCounts.back()) ||
2798 (m_stepCounts.size() == 0 && m_subModels->getCount() == 0))
2799 {
2800 // Empty step; ignore.
2801 return;
2802 }
2803 m_curStepIndex++;
2804 for (int i = 0; i <= TREMLast; i++)
2805 {
2806 if (m_shapes[i])
2807 {
2808 m_shapes[i]->nextStep();
2809 }
2810 if (m_coloredShapes[i])
2811 {
2812 m_coloredShapes[i]->nextStep();
2813 }
2814 }
2815 if (m_subModels)
2816 {
2817 m_stepCounts.push_back(m_subModels->getCount());
2818 }
2819 else
2820 {
2821 m_stepCounts.push_back(0);
2822 }
2823 m_curGeomModel = NULL;
2824 }
2825
addLine(TCULong color,const TCVector * vertices)2826 void TREMainModel::addLine(TCULong color, const TCVector *vertices)
2827 {
2828 getCurGeomModel()->addLine(color, vertices);
2829 }
2830
addLine(const TCVector * vertices)2831 void TREMainModel::addLine(const TCVector *vertices)
2832 {
2833 getCurGeomModel()->addLine(vertices);
2834 }
2835
addEdgeLine(const TCVector * vertices,TCULong color)2836 void TREMainModel::addEdgeLine(const TCVector *vertices, TCULong color)
2837 {
2838 getCurGeomModel()->addEdgeLine(vertices, color);
2839 }
2840
addTriangle(TCULong color,const TCVector * vertices)2841 void TREMainModel::addTriangle(TCULong color, const TCVector *vertices)
2842 {
2843 getCurGeomModel()->addTriangle(color, vertices);
2844 }
2845
addTriangle(TCULong color,const TCVector * vertices,const TCVector * normals)2846 void TREMainModel::addTriangle(
2847 TCULong color,
2848 const TCVector *vertices,
2849 const TCVector *normals)
2850 {
2851 getCurGeomModel()->addTriangle(color, vertices, normals);
2852 }
2853
addTriangle(const TCVector * vertices)2854 void TREMainModel::addTriangle(const TCVector *vertices)
2855 {
2856 getCurGeomModel()->addTriangle(vertices);
2857 }
2858
addTriangle(const TCVector * vertices,const TCVector * normals)2859 void TREMainModel::addTriangle(
2860 const TCVector *vertices,
2861 const TCVector *normals)
2862 {
2863 getCurGeomModel()->addTriangle(vertices, normals);
2864 }
2865
addBFCTriangle(TCULong color,const TCVector * vertices)2866 void TREMainModel::addBFCTriangle(TCULong color, const TCVector *vertices)
2867 {
2868 getCurGeomModel()->addBFCTriangle(color, vertices);
2869 }
2870
addBFCTriangle(TCULong color,const TCVector * vertices,const TCVector * normals)2871 void TREMainModel::addBFCTriangle(
2872 TCULong color,
2873 const TCVector *vertices,
2874 const TCVector *normals)
2875 {
2876 getCurGeomModel()->addBFCTriangle(color, vertices, normals);
2877 }
2878
addBFCTriangle(const TCVector * vertices)2879 void TREMainModel::addBFCTriangle(const TCVector *vertices)
2880 {
2881 getCurGeomModel()->addBFCTriangle(vertices);
2882 }
2883
addBFCTriangle(const TCVector * vertices,const TCVector * normals)2884 void TREMainModel::addBFCTriangle(
2885 const TCVector *vertices,
2886 const TCVector *normals)
2887 {
2888 getCurGeomModel()->addBFCTriangle(vertices, normals);
2889 }
2890
addQuad(TCULong color,const TCVector * vertices)2891 void TREMainModel::addQuad(TCULong color, const TCVector *vertices)
2892 {
2893 getCurGeomModel()->addQuad(color, vertices);
2894 }
2895
addQuad(const TCVector * vertices)2896 void TREMainModel::addQuad(const TCVector *vertices)
2897 {
2898 getCurGeomModel()->addQuad(vertices);
2899 }
2900
addBFCQuad(TCULong color,const TCVector * vertices)2901 void TREMainModel::addBFCQuad(TCULong color, const TCVector *vertices)
2902 {
2903 getCurGeomModel()->addBFCQuad(color, vertices);
2904 }
2905
addBFCQuad(const TCVector * vertices)2906 void TREMainModel::addBFCQuad(const TCVector *vertices)
2907 {
2908 getCurGeomModel()->addBFCQuad(vertices);
2909 }
2910
addConditionalLine(const TCVector * vertices,const TCVector * controlPoints,TCULong color)2911 void TREMainModel::addConditionalLine(
2912 const TCVector *vertices,
2913 const TCVector *controlPoints,
2914 TCULong color)
2915 {
2916 getCurGeomModel()->addConditionalLine(vertices, controlPoints, color);
2917 }
2918
addTriangleStrip(const TCVector * vertices,const TCVector * normals,int count,bool flat)2919 void TREMainModel::addTriangleStrip(
2920 const TCVector *vertices,
2921 const TCVector *normals,
2922 int count,
2923 bool flat)
2924 {
2925 getCurGeomModel()->addTriangleStrip(vertices, normals, count, flat);
2926 }
2927
addTriangleStrip(TREShapeGroup * shapeGroup,const TCVector * vertices,const TCVector * normals,int count,bool flat)2928 void TREMainModel::addTriangleStrip(
2929 TREShapeGroup *shapeGroup,
2930 const TCVector *vertices,
2931 const TCVector *normals,
2932 int count,
2933 bool flat)
2934 {
2935 getCurGeomModel()->addTriangleStrip(shapeGroup, vertices, normals, count,
2936 flat);
2937 }
2938
addBFCTriangleStrip(const TCVector * vertices,const TCVector * normals,int count,bool flat)2939 void TREMainModel::addBFCTriangleStrip(
2940 const TCVector *vertices,
2941 const TCVector *normals,
2942 int count,
2943 bool flat)
2944 {
2945 getCurGeomModel()->addBFCTriangleStrip(vertices, normals, count, flat);
2946 }
2947
addTriangleFan(const TCVector * vertices,const TCVector * normals,const TCVector * textureCoords,int count,bool flat)2948 void TREMainModel::addTriangleFan(
2949 const TCVector *vertices,
2950 const TCVector *normals,
2951 const TCVector *textureCoords,
2952 int count,
2953 bool flat)
2954 {
2955 getCurGeomModel()->addTriangleFan(vertices, normals, textureCoords, count,
2956 flat);
2957 }
2958
addTriangleFan(TREShapeGroup * shapeGroup,const TCVector * vertices,const TCVector * normals,const TCVector * textureCoords,int count,bool flat)2959 void TREMainModel::addTriangleFan(
2960 TREShapeGroup *shapeGroup,
2961 const TCVector *vertices,
2962 const TCVector *normals,
2963 const TCVector *textureCoords,
2964 int count,
2965 bool flat)
2966 {
2967 getCurGeomModel()->addTriangleFan(shapeGroup, vertices, normals,
2968 textureCoords, count, flat);
2969 }
2970
addTriangleFan(TCULong color,const TCVector * vertices,const TCVector * normals,int count,bool flat)2971 void TREMainModel::addTriangleFan(
2972 TCULong color,
2973 const TCVector *vertices,
2974 const TCVector *normals,
2975 int count,
2976 bool flat)
2977 {
2978 getCurGeomModel()->addTriangleFan(color, vertices, normals, count, flat);
2979 }
2980
addTriangleFan(TREColoredShapeGroup * shapeGroup,TCULong color,const TCVector * vertices,const TCVector * normals,int count,bool flat)2981 void TREMainModel::addTriangleFan(
2982 TREColoredShapeGroup *shapeGroup,
2983 TCULong color,
2984 const TCVector *vertices,
2985 const TCVector *normals,
2986 int count,
2987 bool flat)
2988 {
2989 getCurGeomModel()->addTriangleFan(shapeGroup, color, vertices, normals,
2990 count, flat);
2991 }
2992
addBFCTriangleFan(const TCVector * vertices,const TCVector * normals,const TCVector * textureCoords,int count,bool flat)2993 void TREMainModel::addBFCTriangleFan(
2994 const TCVector *vertices,
2995 const TCVector *normals,
2996 const TCVector *textureCoords,
2997 int count,
2998 bool flat)
2999 {
3000 getCurGeomModel()->addBFCTriangleFan(vertices, normals, textureCoords,
3001 count, flat);
3002 }
3003
addBFCTriangleFan(TCULong color,const TCVector * vertices,const TCVector * normals,int count,bool flat)3004 void TREMainModel::addBFCTriangleFan(
3005 TCULong color,
3006 const TCVector *vertices,
3007 const TCVector *normals,
3008 int count,
3009 bool flat)
3010 {
3011 getCurGeomModel()->addBFCTriangleFan(color, vertices, normals, count, flat);
3012 }
3013
addQuadStrip(const TCVector * vertices,const TCVector * normals,int count,bool flat)3014 void TREMainModel::addQuadStrip(
3015 const TCVector *vertices,
3016 const TCVector *normals,
3017 int count,
3018 bool flat)
3019 {
3020 getCurGeomModel()->addQuadStrip(vertices, normals, count, flat);
3021 }
3022
addQuadStrip(TREShapeGroup * shapeGroup,const TCVector * vertices,const TCVector * normals,int count,bool flat)3023 void TREMainModel::addQuadStrip(
3024 TREShapeGroup *shapeGroup,
3025 const TCVector *vertices,
3026 const TCVector *normals,
3027 int count,
3028 bool flat)
3029 {
3030 getCurGeomModel()->addQuadStrip(shapeGroup, vertices, normals, count, flat);
3031 }
3032
addQuadStrip(TCULong color,const TCVector * vertices,const TCVector * normals,int count,bool flat)3033 void TREMainModel::addQuadStrip(
3034 TCULong color,
3035 const TCVector *vertices,
3036 const TCVector *normals,
3037 int count,
3038 bool flat)
3039 {
3040 getCurGeomModel()->addQuadStrip(color, vertices, normals, count, flat);
3041 }
3042
addQuadStrip(TREColoredShapeGroup * shapeGroup,TCULong color,const TCVector * vertices,const TCVector * normals,int count,bool flat)3043 void TREMainModel::addQuadStrip(
3044 TREColoredShapeGroup *shapeGroup,
3045 TCULong color,
3046 const TCVector *vertices,
3047 const TCVector *normals,
3048 int count,
3049 bool flat)
3050 {
3051 getCurGeomModel()->addQuadStrip(shapeGroup, color, vertices, normals, count,
3052 flat);
3053 }
3054
addBFCQuadStrip(const TCVector * vertices,const TCVector * normals,int count,bool flat)3055 void TREMainModel::addBFCQuadStrip(
3056 const TCVector *vertices,
3057 const TCVector *normals,
3058 int count,
3059 bool flat)
3060 {
3061 getCurGeomModel()->addBFCQuadStrip(vertices, normals, count, flat);
3062 }
3063
addBFCQuadStrip(TCULong color,const TCVector * vertices,const TCVector * normals,int count,bool flat)3064 void TREMainModel::addBFCQuadStrip(
3065 TCULong color,
3066 const TCVector *vertices,
3067 const TCVector *normals,
3068 int count,
3069 bool flat)
3070 {
3071 getCurGeomModel()->addBFCQuadStrip(color, vertices, normals, count, flat);
3072 }
3073
startTexture(const std::string & filename,TCImage * image)3074 void TREMainModel::startTexture(const std::string &filename, TCImage *image)
3075 {
3076 loadTexture(filename, image);
3077 m_activeTextures.push_front(filename);
3078 }
3079
endTexture(void)3080 bool TREMainModel::endTexture(void)
3081 {
3082 if (m_activeTextures.empty())
3083 {
3084 return false;
3085 }
3086 m_activeTextures.pop_front();
3087 return true;
3088 }
3089
loadTexture(const std::string & filename,TCImage * image)3090 void TREMainModel::loadTexture(const std::string &filename, TCImage *image)
3091 {
3092 if (m_texmapImages.find(filename) == m_texmapImages.end())
3093 {
3094 m_texmapImages[filename] = TexmapImageInfo(filename, image);
3095 }
3096 }
3097
getActiveTextureFilename(void) const3098 const std::string *TREMainModel::getActiveTextureFilename(void) const
3099 {
3100 if (m_activeTextures.size() > 0)
3101 {
3102 return &m_activeTextures.front();
3103 }
3104 else
3105 {
3106 return NULL;
3107 }
3108 }
3109
getTexmapTextureID(const std::string & filename) const3110 GLuint TREMainModel::getTexmapTextureID(const std::string &filename) const
3111 {
3112 TexmapImageInfoMap::const_iterator it = m_texmapImages.find(filename);
3113
3114 if (it != m_texmapImages.end())
3115 {
3116 return it->second.textureID;
3117 }
3118 else
3119 {
3120 return 0;
3121 }
3122 }
3123
getTexmapImage(const std::string & filename) const3124 const TCImage *TREMainModel::getTexmapImage(const std::string &filename) const
3125 {
3126 TexmapImageInfoMap::const_iterator it = m_texmapImages.find(filename);
3127
3128 if (it != m_texmapImages.end())
3129 {
3130 return it->second.image;
3131 }
3132 else
3133 {
3134 return NULL;
3135 }
3136 }
3137
setTransferTexmapInfo(const TexmapInfo & texmapInfo,bool,const TCFloat * matrix)3138 void TREMainModel::setTransferTexmapInfo(
3139 const TexmapInfo &texmapInfo,
3140 bool /*bfc*/,
3141 const TCFloat *matrix)
3142 {
3143 TexmapInfo transferTexmapInfo = texmapInfo;
3144 transferTexmapInfo.transform(matrix);
3145 if (m_mainTexmapInfos.empty() ||
3146 !m_mainTexmapInfos.back().texmapEquals(transferTexmapInfo))
3147 {
3148 m_mainTexmapInfos.push_back(transferTexmapInfo);
3149 //TREModel::TexmapInfo::GeomInfo *geomInfo =
3150 // bfc ? &m_mainTexmapInfos.back().bfc :
3151 // &m_mainTexmapInfos.back().standard;
3152 //int bfcIndex = bfc ? 1 : 0;
3153
3154 //if (m_texmappedShapes[bfcIndex] != NULL)
3155 //{
3156 // geomInfo->colored.triangleOffset =
3157 // m_texmappedShapes[bfcIndex]->getIndexCount(TRESTriangle) / 3;
3158 //}
3159 }
3160 }
3161