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 &center)
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 &center)
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 &sectionList)
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 &sectionList)
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