1 #include "LDModelParser.h"
2 #include "LDrawModelViewer.h"
3 #include "LDObiInfo.h"
4 
5 #include <string.h>
6 
7 #include <LDLoader/LDLMainModel.h>
8 #include <LDLoader/LDLShapeLine.h>
9 #include <LDLoader/LDLModelLine.h>
10 #include <LDLoader/LDLCommentLine.h>
11 #include <LDLoader/LDLConditionalLineLine.h>
12 #include <LDLoader/LDLPalette.h>
13 #include <TRE/TREMainModel.h>
14 #include <TRE/TRESubModel.h>
15 #include <TCFoundation/mystring.h>
16 #include <TCFoundation/TCMacros.h>
17 #include <TCFoundation/TCVector.h>
18 #include <TCFoundation/TCProgressAlert.h>
19 #include <TCFoundation/TCLocalStrings.h>
20 #include <ctype.h>
21 
22 #ifdef WIN32
23 #if defined(_MSC_VER) && _MSC_VER >= 1400 && defined(_DEBUG)
24 #define new DEBUG_CLIENTBLOCK
25 #endif // _DEBUG
26 #endif // WIN32
27 
28 static const int LO_NUM_SEGMENTS = 8;
29 
30 
LDModelParser(LDrawModelViewer * modelViewer)31 LDModelParser::LDModelParser(LDrawModelViewer *modelViewer)
32 	:m_modelViewer(modelViewer),
33 	m_topLDLModel(NULL),
34 	m_mainTREModel(NULL),
35 	m_seamWidth(0.0f),
36 	m_obiInfo(NULL),
37 	m_obiUniqueId(0),
38 	m_abort(false)
39 {
40 	TCByte defaultR, defaultG, defaultB;
41 	bool defaultTrans;
42 	int defaultColorNumber;
43 
44 	// Initialize all flags to false.
45 	memset(&m_flags, 0, sizeof(m_flags));
46 	m_flags.flattenParts = true;	// Supporting false here could take a lot
47 									// of work.
48 	m_flags.seams = false;
49 	m_flags.defaultColorSet = false;
50 	m_flags.defaultColorNumberSet = false;
51 	setCurveQuality(m_modelViewer->getCurveQuality());
52 	setNoLightGeomFlag(m_modelViewer->getNoLightGeom());
53 	setPrimitiveSubstitutionFlag(
54 		m_modelViewer->getAllowPrimitiveSubstitution());
55 	setSeamWidth(m_modelViewer->getSeamWidth());
56 	m_modelViewer->getDefaultRGB(defaultR, defaultG, defaultB, defaultTrans);
57 	setDefaultRGB(defaultR, defaultG, defaultB, defaultTrans);
58 	defaultColorNumber = m_modelViewer->getDefaultColorNumber();
59 	if (defaultColorNumber == -1)
60 	{
61 		TCByte r, g, b;
62 		bool transparent;
63 
64 		modelViewer->getDefaultRGB(r, g, b, transparent);
65 		LDLModel *mainModel = modelViewer->getMainModel();
66 
67 		if (mainModel)
68 		{
69 			LDLPalette *palette = mainModel->getMainModel()->getPalette();
70 
71 			setDefaultColorNumber(palette->getColorNumberForRGB(r, g, b,
72 				transparent));
73 		}
74 	}
75 	else
76 	{
77 		setDefaultColorNumber(defaultColorNumber);
78 	}
79 	m_flags.boundingBoxesOnly = m_modelViewer->getBoundingBoxesOnly();
80 	m_flags.obi = m_modelViewer->getObi();
81 	m_flags.newTexmap = false;
82 	m_flags.texmapNext = false;
83 	m_flags.texmapStarted = false;
84 }
85 
~LDModelParser(void)86 LDModelParser::~LDModelParser(void)
87 {
88 }
89 
dealloc(void)90 void LDModelParser::dealloc(void)
91 {
92 	TCObject::release(m_topLDLModel);
93 	TCObject::release(m_mainTREModel);
94 	LDLPrimitiveCheck::dealloc();
95 }
96 
shouldLoadConditionalLines(void)97 bool LDModelParser::shouldLoadConditionalLines(void)
98 {
99 	return (getEdgeLinesFlag() && getConditionalLinesFlag()) ||
100 		getSmoothCurvesFlag();
101 }
102 
shouldLoadEdgeLines(void)103 bool LDModelParser::shouldLoadEdgeLines(void)
104 {
105 	return getEdgeLinesFlag() || getSmoothCurvesFlag();
106 }
107 
108 
109 //void LDModelParser::finishPart(TREModel *treModel, TRESubModel *subModel)
110 //{
111 //	if (getFlattenPartsFlag())
112 //	{
113 //		treModel->flatten();
114 //	}
115 //	if (getSmoothCurvesFlag())
116 //	{
117 //		treModel->smooth();
118 //	}
119 //	if (subModel)
120 //	{
121 //		if (getSeamsFlag() && !treModel->getNoShrinkFlag())
122 //		{
123 //			subModel->shrink(m_seamWidth);
124 //		}
125 //	}
126 //}
127 
setDefaultRGB(TCByte r,TCByte g,TCByte b,bool transparent)128 void LDModelParser::setDefaultRGB(TCByte r, TCByte g, TCByte b,
129 								  bool transparent)
130 {
131 	m_defaultR = r;
132 	m_defaultG = g;
133 	m_defaultB = b;
134 	m_flags.defaultTrans = transparent;
135 	setDefaultColorSetFlag(true);
136 }
137 
setDefaultColorNumber(int colorNumber)138 void LDModelParser::setDefaultColorNumber(int colorNumber)
139 {
140 	m_defaultColorNumber = colorNumber;
141 	setDefaultColorNumberSetFlag(true);
142 }
143 
getDefaultColorNumber(void)144 int LDModelParser::getDefaultColorNumber(void)
145 {
146 	LDLPalette *palette = m_topLDLModel->getMainModel()->getPalette();
147 	if (getDefaultColorNumberSetFlag())
148 	{
149 		return m_defaultColorNumber;
150 	}
151 	else if (getDefaultColorSetFlag())
152 	{
153 		return palette->getColorNumberForRGB(m_defaultR, m_defaultG,
154 			m_defaultB, m_flags.defaultTrans);
155 	}
156 	return 7;
157 }
158 
parseMainModel(LDLModel * mainLDLModel)159 bool LDModelParser::parseMainModel(LDLModel *mainLDLModel)
160 {
161 	int colorNumber = 7;
162 	int edgeColorNumber;
163 
164 	m_topLDLModel = (LDLModel *)mainLDLModel->retain();
165 	m_mainTREModel = new TREMainModel;
166 	if (m_alertSender != NULL)
167 	{
168 		m_mainTREModel->setAlertSender(m_alertSender);
169 	}
170 	else
171 	{
172 		m_mainTREModel->setSendProgressFlag(false);
173 	}
174 	m_mainTREModel->setMultiThreadedFlag(getMultiThreadedFlag());
175 	m_mainTREModel->setUseStripsFlag(getUseStripsFlag());
176 	m_mainTREModel->setPartFlag(mainLDLModel->isPart());
177 	m_mainTREModel->setEdgeLinesFlag(getEdgeLinesFlag());
178 	m_mainTREModel->setEdgesOnlyFlag(getEdgesOnlyFlag());
179 	m_mainTREModel->setLightingFlag(getLightingFlag());
180 	m_mainTREModel->setTwoSidedLightingFlag(getTwoSidedLightingFlag());
181 	m_mainTREModel->setBFCFlag(getBFCFlag());
182 	m_mainTREModel->setRedBackFacesFlag(getRedBackFacesFlag());
183 	m_mainTREModel->setGreenFrontFacesFlag(getGreenFrontFacesFlag());
184 	m_mainTREModel->setBlueNeutralFacesFlag(getBlueNeutralFacesFlag());
185 	m_mainTREModel->setGl2psFlag(m_modelViewer->getGl2ps());
186 	switch (m_modelViewer->getMemoryUsage())
187 	{
188 	case 0:
189 		m_mainTREModel->setCompilePartsFlag(false);
190 		m_mainTREModel->setCompileAllFlag(false);
191 		m_mainTREModel->setFlattenConditionalsFlag(false);
192 		break;
193 	case 1:
194 		m_mainTREModel->setCompilePartsFlag(true);
195 		m_mainTREModel->setCompileAllFlag(false);
196 		m_mainTREModel->setFlattenConditionalsFlag(false);
197 		break;
198 	case 2:
199 		m_mainTREModel->setCompilePartsFlag(true);
200 		m_mainTREModel->setCompileAllFlag(true);
201 		m_mainTREModel->setFlattenConditionalsFlag(true);
202 		break;
203 	}
204 	m_mainTREModel->setPolygonOffsetFlag(getPolygonOffsetFlag());
205 	m_mainTREModel->setEdgeLineWidth(
206 		m_modelViewer->getScaledHighlightLineWidth());
207 	m_mainTREModel->setStudAnisoLevel(m_modelViewer->getAnisoLevel());
208 	m_mainTREModel->setAALinesFlag(getAALinesFlag());
209 	m_mainTREModel->setSortTransparentFlag(getSortTransparentFlag());
210 	m_mainTREModel->setStippleFlag(getStippleFlag());
211 	m_mainTREModel->setWireframeFlag(getWireframeFlag());
212 	m_mainTREModel->setConditionalLinesFlag(getConditionalLinesFlag());
213 	m_mainTREModel->setSmoothCurvesFlag(getSmoothCurvesFlag());
214 	m_mainTREModel->setShowAllConditionalFlag(getShowAllConditionalFlag());
215 	m_mainTREModel->setConditionalControlPointsFlag(
216 		getConditionalControlPointsFlag());
217 	m_mainTREModel->setStudLogoFlag(getStudLogoFlag());
218 	m_mainTREModel->setStudTextureFilter(m_modelViewer->getTextureFilterType());
219 	m_mainTREModel->setFlattenPartsFlag(getFlattenPartsFlag());
220 	m_mainTREModel->setSeamWidth(getSeamWidth());
221 	colorNumber = getDefaultColorNumber();
222 	edgeColorNumber = mainLDLModel->getEdgeColorNumber(colorNumber);
223 	m_mainTREModel->setColor(mainLDLModel->getPackedRGBA(colorNumber),
224 		mainLDLModel->getPackedRGBA(edgeColorNumber));
225 	m_obiTokens.clear();
226 	if (parseModel(m_topLDLModel, m_mainTREModel, getBFCFlag(),
227 		m_defaultColorNumber, false))
228 	{
229 		if (m_mainTREModel->isPart() || getFileIsPartFlag())
230 		{
231 			m_mainTREModel->setPartFlag(true);
232 			//finishPart(m_mainTREModel);
233 		}
234 		m_mainTREModel->finish();
235 		if (m_topLDLModel->getName())
236 		{
237 			m_mainTREModel->setName(m_topLDLModel->getName());
238 		}
239 		else
240 		{
241 			char *name = filenameFromPath(m_topLDLModel->getFilename());
242 
243 			m_mainTREModel->setName(name);
244 			delete[] name;
245 		}
246 		if (m_alertSender != NULL)
247 		{
248 			TCProgressAlert::send("LDModelParser",
249 				TCLocalStrings::get(_UC("ParsingStatus")), 1.0f, &m_abort,
250 				this);
251 		}
252 		if (m_abort)
253 		{
254 			return false;
255 		}
256 		else
257 		{
258 			return m_mainTREModel->postProcess();
259 		}
260 	}
261 	else
262 	{
263 		return false;
264 	}
265 }
266 
getFileIsPartFlag(void) const267 bool LDModelParser::getFileIsPartFlag(void) const
268 {
269 	return m_modelViewer->getFileIsPart();
270 }
271 
getEdgeLinesFlag(void) const272 bool LDModelParser::getEdgeLinesFlag(void) const
273 {
274 	return m_modelViewer->getShowsHighlightLines();
275 }
276 
getEdgesOnlyFlag(void) const277 bool LDModelParser::getEdgesOnlyFlag(void) const
278 {
279 	return m_modelViewer->getEdgesOnly();
280 }
281 
getLightingFlag(void) const282 bool LDModelParser::getLightingFlag(void) const
283 {
284 	return m_modelViewer->getUseLighting();
285 }
286 
getTwoSidedLightingFlag(void) const287 bool LDModelParser::getTwoSidedLightingFlag(void) const
288 {
289 	return m_modelViewer->forceOneLight();
290 }
291 
getBFCFlag(void) const292 bool LDModelParser::getBFCFlag(void) const
293 {
294 	return m_modelViewer->getBfc();
295 }
296 
getAALinesFlag(void) const297 bool LDModelParser::getAALinesFlag(void) const
298 {
299 	return m_modelViewer->getLineSmoothing();
300 }
301 
getSortTransparentFlag(void) const302 bool LDModelParser::getSortTransparentFlag(void) const
303 {
304 	return m_modelViewer->getSortTransparent();
305 }
306 
getStippleFlag(void) const307 bool LDModelParser::getStippleFlag(void) const
308 {
309 	return m_modelViewer->getUseStipple();
310 }
311 
getWireframeFlag(void) const312 bool LDModelParser::getWireframeFlag(void) const
313 {
314 	return m_modelViewer->getDrawWireframe();
315 }
316 
getConditionalLinesFlag(void) const317 bool LDModelParser::getConditionalLinesFlag(void) const
318 {
319 	return m_modelViewer->getDrawConditionalHighlights();
320 }
321 
getSmoothCurvesFlag(void) const322 bool LDModelParser::getSmoothCurvesFlag(void) const
323 {
324 	return m_modelViewer->getPerformSmoothing();
325 }
326 
getShowAllConditionalFlag(void) const327 bool LDModelParser::getShowAllConditionalFlag(void) const
328 {
329 	return m_modelViewer->getShowAllConditionalLines();
330 }
331 
getConditionalControlPointsFlag(void) const332 bool LDModelParser::getConditionalControlPointsFlag(void) const
333 {
334 	return m_modelViewer->getShowConditionalControlPoints();
335 }
336 
getPolygonOffsetFlag(void) const337 bool LDModelParser::getPolygonOffsetFlag(void) const
338 {
339 	return m_modelViewer->getUsePolygonOffset();
340 }
341 
getStudLogoFlag(void) const342 bool LDModelParser::getStudLogoFlag(void) const
343 {
344 	return m_modelViewer->getTextureStuds();
345 }
346 
getRedBackFacesFlag(void) const347 bool LDModelParser::getRedBackFacesFlag(void) const
348 {
349 	return m_modelViewer->getRedBackFaces();
350 }
351 
getGreenFrontFacesFlag(void) const352 bool LDModelParser::getGreenFrontFacesFlag(void) const
353 {
354 	return m_modelViewer->getGreenFrontFaces();
355 }
356 
getBlueNeutralFacesFlag(void) const357 bool LDModelParser::getBlueNeutralFacesFlag(void) const
358 {
359 	return m_modelViewer->getBlueNeutralFaces();
360 }
361 
getMultiThreadedFlag(void) const362 bool LDModelParser::getMultiThreadedFlag(void) const
363 {
364 	return m_modelViewer->getMultiThreaded();
365 }
366 
getUseStripsFlag(void) const367 bool LDModelParser::getUseStripsFlag(void) const
368 {
369 	return m_modelViewer->getUseStrips();
370 }
371 
addSubModel(LDLModelLine * modelLine,TREModel * treParentModel,TREModel * treModel,bool invert,int activeColorNumber)372 bool LDModelParser::addSubModel(
373 	LDLModelLine *modelLine,
374 	TREModel *treParentModel,
375 	TREModel *treModel,
376 	bool invert,
377 	int activeColorNumber)
378 {
379 	int colorNumber = actualColorNumber(modelLine, activeColorNumber);
380 	TRESubModel *treSubModel = NULL;
381 
382 	if (colorNumber == 16 || colorNumber == 24)
383 	{
384 		treSubModel = treParentModel->addSubModel(modelLine->getMatrix(),
385 			treModel, invert);
386 	}
387 	else
388 	{
389 		LDLModel *parentModel = modelLine->getParentModel();
390 		TCULong edgeColorNumber = parentModel->getEdgeColorNumber(colorNumber);
391 
392 		treSubModel = treParentModel->addSubModel(
393 			parentModel->getPackedRGBA(colorNumber),
394 			parentModel->getPackedRGBA(edgeColorNumber),
395 			modelLine->getMatrix(), treModel, invert);
396 		treSubModel->setNonUniformFlag(modelLine->getNonUniformFlag());
397 		if (parentModel->hasSpecular(colorNumber))
398 		{
399 			GLfloat specular[4];
400 
401 			parentModel->getSpecular(colorNumber, specular);
402 			treSubModel->setSpecular(specular);
403 		}
404 		if (parentModel->hasShininess(colorNumber))
405 		{
406 			GLfloat shininess;
407 
408 			parentModel->getShininess(colorNumber, shininess);
409 			treSubModel->setShininess(shininess);
410 		}
411 	}
412 	if (treModel->isPart() && !treParentModel->isPart())
413 	{
414 		//finishPart(treModel, treSubModel);
415 		if (strcasecmp(treModel->getName(), "light.dat") == 0)
416 		{
417 			treSubModel->setLightFlag(true);
418 		}
419 	}
420 	if (TCVector::determinant(treSubModel->getMatrix()) < 0.0f)
421 	{
422 		// Generate an inverted version of the child model, because this
423 		// reference to it involves a mirror.
424 		treModel->getUnMirroredModel();
425 	}
426 	return true;
427 }
428 
addBoundingQuad(TREModel * model,const TCVector * minMax,int face)429 void LDModelParser::addBoundingQuad(
430 	TREModel *model,
431 	const TCVector *minMax,
432 	int face)
433 {
434 	TCVector quad[4];
435 	int faceIndices[][4][3] =
436 	{
437 		{
438 			{ 0, 0, 0 },
439 			{ 0, 1, 0 },
440 			{ 1, 1, 0 },
441 			{ 1, 0, 0 }
442 		},
443 		{
444 			{ 1, 1, 1 },
445 			{ 0, 1, 1 },
446 			{ 0, 0, 1 },
447 			{ 1, 0, 1 }
448 		},
449 		{
450 			{ 0, 0, 0 },
451 			{ 0, 0, 1 },
452 			{ 0, 1, 1 },
453 			{ 0, 1, 0 }
454 		},
455 		{
456 			{ 1, 1, 1 },
457 			{ 1, 0, 1 },
458 			{ 1, 0, 0 },
459 			{ 1, 1, 0 }
460 		},
461 		{
462 			{ 0, 0, 0 },
463 			{ 1, 0, 0 },
464 			{ 1, 0, 1 },
465 			{ 0, 0, 1 }
466 		},
467 		{
468 			{ 1, 1, 1 },
469 			{ 1, 1, 0 },
470 			{ 0, 1, 0 },
471 			{ 0, 1, 1 }
472 		},
473 	};
474 	for (int q = 0; q < 4; q++)
475 	{
476 		for (int i = 0; i < 3; i++)
477 		{
478 			quad[q][i] = minMax[faceIndices[face][q][i]][i];
479 		}
480 	}
481 	if (getBFCFlag())
482 	{
483 		model->addBFCQuad(quad);
484 	}
485 	else
486 	{
487 		model->addQuad(quad);
488 	}
489 }
490 
getActiveColorNumber(LDLModelLine * modelLine,int activeColorNumber)491 int LDModelParser::getActiveColorNumber(
492 	LDLModelLine *modelLine,
493 	int activeColorNumber)
494 {
495 	if (modelLine)
496 	{
497 		int modelLineColorNumber = modelLine->getColorNumber();
498 
499 		if (modelLineColorNumber != 16)
500 		{
501 			if (modelLineColorNumber == 24)
502 			{
503 				LDLModel *ldlModel = modelLine->getModel();
504 
505 				if (ldlModel)
506 				{
507 					return ldlModel->getEdgeColorNumber(activeColorNumber);
508 				}
509 			}
510 			else
511 			{
512 				return modelLineColorNumber;
513 			}
514 		}
515 	}
516 	return activeColorNumber;
517 }
518 
modelNameKey(LDLModel * model,int activeColorNumber)519 std::string LDModelParser::modelNameKey(LDLModel *model, int activeColorNumber)
520 {
521 	const char *name = model->getName();
522 
523 	if (model->colorNumberIsTransparent(activeColorNumber))
524 	{
525 		std::string nameKey;
526 
527 		m_obiInfo->end();
528 		nameKey = "Trans:";
529 		nameKey += name;
530 		return nameKey;
531 	}
532 	else if (m_obiTokens.size() > 0 ||
533 		(m_obiInfo != NULL && m_obiInfo->isActive()))
534 	{
535 		std::string nameKey;
536 		char num[32];
537 
538 		sprintf(num, "%X:", m_obiUniqueId++);
539 		nameKey = num;
540 		nameKey += name;
541 		return nameKey;
542 	}
543 	else
544 	{
545 		return name;
546 	}
547 }
548 
parseModel(LDLModelLine * modelLine,TREModel * treModel,bool bfc,int activeColorNumber,bool parentIsPart)549 bool LDModelParser::parseModel(
550 	LDLModelLine *modelLine,
551 	TREModel *treModel,
552 	bool bfc,
553 	int activeColorNumber,
554     bool parentIsPart)
555 {
556 	LDLModel *ldlModel = modelLine->getModel();
557 	bool invert = modelLine->getBFCInvert();
558 
559 	if (bfc)
560 	{
561 		bfc = modelLine->getBFCOn();
562 	}
563 	activeColorNumber = getActiveColorNumber(modelLine, activeColorNumber);
564     if (ldlModel->colorNumberIsTransparent(activeColorNumber))
565     {
566         bfc = false;
567     }
568 	if (ldlModel)
569 	{
570 		TREModel *model = NULL;
571 		std::string nameKey = modelNameKey(ldlModel, activeColorNumber);
572 
573 		model = m_mainTREModel->modelNamed(nameKey.c_str(), bfc);
574 		if (model)
575 		{
576 			return addSubModel(modelLine, treModel, model, bfc && invert,
577 				activeColorNumber);
578 		}
579 		else
580 		{
581 			model = new TREModel;
582 			model->setMainModel(treModel->getMainModel());
583 			model->setName(nameKey.c_str());
584 			model->setPartFlag(ldlModel->isPart());
585 			model->setNoShrinkFlag(ldlModel->getNoShrinkFlag());
586 			if (m_flags.boundingBoxesOnly && ldlModel->isPart())
587 			{
588 				TCVector minMax[2];
589 
590 				m_mainTREModel->registerModel(model, bfc);
591 				model->release();
592 				ldlModel->getBoundingBox(minMax[0], minMax[1]);
593 				for (int i = 0; i < 6; i++)
594 				{
595 					addBoundingQuad(model, minMax, i);
596 				}
597 				return addSubModel(modelLine, treModel, model, bfc && invert,
598 					activeColorNumber);
599 			}
600 			else if (parseModel(ldlModel, model, bfc, activeColorNumber,
601             	parentIsPart))
602 			{
603 				m_mainTREModel->registerModel(model, bfc);
604 				model->release();
605 				return addSubModel(modelLine, treModel, model, bfc && invert,
606 					activeColorNumber);
607 			}
608 			else
609 			{
610 				model->release();
611 				return false;
612 			}
613 		}
614 	}
615 	else
616 	{
617 		return false;
618 	}
619 }
620 
substituteStud(int numSegments)621 bool LDModelParser::substituteStud(int numSegments)
622 {
623 	TCULong edgeColor = 0;
624 
625 	if (m_flags.obi &&
626 		!m_topLDLModel->colorNumberIsTransparent(m_currentColorNumber) &&
627 		m_obiTokens.find("obi_stud_cancel") == m_obiTokens.end())
628 	{
629 		LDLPalette *palette = m_topLDLModel->getMainModel()->getPalette();
630 		int colorNumber = 0;
631 
632 		if (palette)
633 		{
634 			colorNumber = palette->getColorNumberForName("OBI_BLACK");
635 		}
636 		edgeColor = m_topLDLModel->getPackedRGBA(colorNumber);
637 	}
638 	m_currentTREModel->addCylinder(TCVector(0.0f, -4.0f, 0.0f), 6.0f, 4.0f,
639 		numSegments, numSegments, getBFCFlag(), edgeColor, edgeColor);
640 	m_currentTREModel->addStudDisc(TCVector(0.0f, -4.0f, 0.0f), 6.0f,
641 		numSegments, numSegments, getBFCFlag());
642 	if (shouldLoadEdgeLines())
643 	{
644 		if (getIsHighlightModel())
645 		{
646 			edgeColor = m_topLDLModel->getPackedRGBA(getDefaultColorNumber());
647 		}
648 		m_currentTREModel->addCircularEdge(TCVector(0.0f, -4.0f, 0.0f), 6.0f,
649 			numSegments, -1, edgeColor);
650 		m_currentTREModel->addCircularEdge(TCVector(0.0f, 0.0f, 0.0f), 6.0f,
651 			numSegments, -1, edgeColor);
652 	}
653 	return true;
654 }
655 
substituteStud(void)656 bool LDModelParser::substituteStud(void)
657 {
658 	return substituteStud(getNumCircleSegments());
659 }
660 
substituteStu2(void)661 bool LDModelParser::substituteStu2(void)
662 {
663 	return substituteStud(LO_NUM_SEGMENTS);
664 }
665 
substituteStu22(bool isA,bool bfc)666 bool LDModelParser::substituteStu22(bool isA, bool bfc)
667 {
668 	int numSegments = LO_NUM_SEGMENTS;
669 
670 	m_currentTREModel->addCylinder(TCVector(0.0f, 0.0f, 0.0f), 4.0f, -4.0f, numSegments,
671 		numSegments, bfc);
672 	m_currentTREModel->addCylinder(TCVector(0.0f, -4.0f, 0.0f), 6.0f, 4.0f, numSegments,
673 		numSegments, bfc);
674 	m_currentTREModel->addOpenCone(TCVector(0.0f, -4.0f, 0.0f), 4.0f, 6.0f, 0.0f,
675 		numSegments, numSegments, bfc);
676 	if (shouldLoadEdgeLines())
677 	{
678 		TCULong edgeColor = 0;
679 		if (getIsHighlightModel())
680 		{
681 			edgeColor = m_topLDLModel->getPackedRGBA(getDefaultColorNumber());
682 		}
683 		m_currentTREModel->addCircularEdge(TCVector(0.0f, -4.0f, 0.0f), 4.0f,
684 			numSegments, -1, edgeColor);
685 		m_currentTREModel->addCircularEdge(TCVector(0.0f, -4.0f, 0.0f), 6.0f,
686 			numSegments, -1, edgeColor);
687 		if (!isA)
688 		{
689 			m_currentTREModel->addCircularEdge(TCVector(0.0f, 0.0f, 0.0f), 4.0f,
690 				numSegments, -1, edgeColor);
691 			m_currentTREModel->addCircularEdge(TCVector(0.0f, 0.0f, 0.0f), 6.0f,
692 				numSegments, -1, edgeColor);
693 		}
694 	}
695 	return true;
696 }
697 
substituteStu23(bool isA,bool bfc)698 bool LDModelParser::substituteStu23(bool isA, bool bfc)
699 {
700 	int numSegments = LO_NUM_SEGMENTS;
701 
702 	m_currentTREModel->addCylinder(TCVector(0.0f, -4.0f, 0.0f), 4.0f, 4.0f, numSegments,
703 		numSegments, bfc);
704 	m_currentTREModel->addDisc(TCVector(0.0f, -4.0f, 0.0f), 4.0f, numSegments,
705 		numSegments, bfc);
706 	if (shouldLoadEdgeLines())
707 	{
708 		TCULong edgeColor = 0;
709 		if (getIsHighlightModel())
710 		{
711 			edgeColor = m_topLDLModel->getPackedRGBA(getDefaultColorNumber());
712 		}
713 		m_currentTREModel->addCircularEdge(TCVector(0.0f, -4.0f, 0.0f), 4.0f,
714 			numSegments, -1, edgeColor);
715 		if (!isA)
716 		{
717 			m_currentTREModel->addCircularEdge(TCVector(0.0f, 0.0f, 0.0f), 4.0f,
718 				numSegments, -1, edgeColor);
719 		}
720 	}
721 	return true;
722 }
723 
substituteStu24(bool isA,bool bfc)724 bool LDModelParser::substituteStu24(bool isA, bool bfc)
725 {
726 	int numSegments = LO_NUM_SEGMENTS;
727 
728 	m_currentTREModel->addCylinder(TCVector(0.0f, 0.0f, 0.0f), 6.0f, -4.0f, numSegments,
729 		numSegments, bfc);
730 	m_currentTREModel->addCylinder(TCVector(0.0f, -4.0f, 0.0f), 8.0f, 4.0f, numSegments,
731 		numSegments, bfc);
732 	m_currentTREModel->addOpenCone(TCVector(0.0f, -4.0f, 0.0f), 6.0f, 8.0f, 0.0f,
733 		numSegments, numSegments, bfc);
734 	if (shouldLoadEdgeLines())
735 	{
736 		TCULong edgeColor = 0;
737 		if (getIsHighlightModel())
738 		{
739 			edgeColor = m_topLDLModel->getPackedRGBA(getDefaultColorNumber());
740 		}
741 		m_currentTREModel->addCircularEdge(TCVector(0.0f, -4.0f, 0.0f), 6.0f,
742 			numSegments, -1, edgeColor);
743 		m_currentTREModel->addCircularEdge(TCVector(0.0f, -4.0f, 0.0f), 8.0f,
744 			numSegments, -1, edgeColor);
745 		if (!isA)
746 		{
747 			m_currentTREModel->addCircularEdge(TCVector(0.0f, 0.0f, 0.0f), 6.0f,
748 				numSegments, -1, edgeColor);
749 			m_currentTREModel->addCircularEdge(TCVector(0.0f, 0.0f, 0.0f), 8.0f,
750 				numSegments, -1, edgeColor);
751 		}
752 	}
753 	return true;
754 }
755 
substituteTorusQ(TCFloat fraction,int size,bool bfc,bool isMixed,bool is48)756 bool LDModelParser::substituteTorusQ(TCFloat fraction, int size, bool bfc,
757 									 bool isMixed, bool is48)
758 {
759 	int numSegments;
760 	int numMinorSegments;
761 
762 	numSegments = getNumCircleSegments(fraction, is48);
763 	numMinorSegments = getNumCircleSegments(0.0, is48 && !isMixed);
764 	m_currentTREModel->addTorusIO(true, TCVector(0.0f, 0.0f, 0.0f), 1.0f,
765 		getTorusFraction(size), numSegments,
766 		getUsedCircleSegments(numSegments, fraction), numMinorSegments, bfc);
767 	m_currentTREModel->addTorusIO(false, TCVector(0.0f, 0.0f, 0.0f), 1.0f,
768 		getTorusFraction(size), numSegments,
769 		getUsedCircleSegments(numSegments, fraction), numMinorSegments, bfc);
770 	m_currentTREModel->addTorusIO(true, TCVector(0.0f, 0.0f, 0.0f), 1.0f,
771 		-getTorusFraction(size), numSegments,
772 		getUsedCircleSegments(numSegments, fraction), numMinorSegments, bfc);
773 	m_currentTREModel->addTorusIO(false, TCVector(0.0f, 0.0f, 0.0f), 1.0f,
774 		-getTorusFraction(size), numSegments,
775 		getUsedCircleSegments(numSegments, fraction), numMinorSegments, bfc);
776 	return true;
777 }
778 
substituteTorusIO(bool inner,TCFloat fraction,int size,bool bfc,bool isMixed,bool is48)779 bool LDModelParser::substituteTorusIO(bool inner, TCFloat fraction, int size,
780 									  bool bfc, bool isMixed, bool is48)
781 {
782 	int numSegments;
783 	int numMinorSegments;
784 	//int size;
785 	//const char *modelName = m_currentTREModel->getName();
786 	//TCFloat fraction;
787 	//int offset = 0;
788 
789 	//if (is48)
790 	//{
791 	//	offset = 3;
792 	//}
793 	//sscanf(modelName + 1 + offset, "%d", &numSegments);
794 	//sscanf(modelName + 4 + offset, "%d", &size);
795 	//fraction = (TCFloat)numSegments / 16.0f;
796 	numSegments = getNumCircleSegments(fraction, is48);
797 	numMinorSegments = getNumCircleSegments(0.0, is48 && !isMixed);
798 	m_currentTREModel->addTorusIO(inner, TCVector(0.0f, 0.0f, 0.0f), 1.0f,
799 		getTorusFraction(size), numSegments,
800 		getUsedCircleSegments(numSegments, fraction), numMinorSegments, bfc);
801 	return true;
802 }
803 
substituteEighthSphere(bool bfc,bool is48)804 bool LDModelParser::substituteEighthSphere(bool bfc,
805 										   bool is48)
806 {
807 	int numSegments = getNumCircleSegments(1.0, is48);
808 
809 	m_currentTREModel->addEighthSphere(TCVector(0.0f, 0.0f, 0.0f), 1.0f, numSegments,
810 		bfc);
811 	return true;
812 }
813 
substituteCylinder(TCFloat fraction,bool bfc,bool is48)814 bool LDModelParser::substituteCylinder(TCFloat fraction,
815 									   bool bfc, bool is48)
816 {
817 	int numSegments = getNumCircleSegments(fraction, is48);
818 
819 	m_currentTREModel->addCylinder(TCVector(0.0f, 0.0f, 0.0f), 1.0f, 1.0f, numSegments,
820 		getUsedCircleSegments(numSegments, fraction), bfc);
821 	return true;
822 }
823 
substituteSlopedCylinder(TCFloat fraction,bool bfc,bool is48)824 bool LDModelParser::substituteSlopedCylinder(TCFloat fraction,
825 											 bool bfc, bool is48)
826 {
827 	int numSegments = getNumCircleSegments(fraction, is48);
828 
829 	m_currentTREModel->addSlopedCylinder(TCVector(0.0f, 0.0f, 0.0f), 1.0f, 1.0f,
830 		numSegments, getUsedCircleSegments(numSegments, fraction), bfc);
831 	return true;
832 }
833 
substituteSlopedCylinder2(TCFloat fraction,bool bfc,bool is48)834 bool LDModelParser::substituteSlopedCylinder2(TCFloat fraction, bool bfc,
835 											  bool is48)
836 {
837 	int numSegments = getNumCircleSegments(fraction, is48);
838 
839 	m_currentTREModel->addSlopedCylinder2(TCVector(0.0f, 0.0f, 0.0f), 1.0f, 1.0f,
840 		numSegments, getUsedCircleSegments(numSegments, fraction), bfc);
841 	return true;
842 }
843 
substituteChrd(TCFloat fraction,bool bfc,bool is48)844 bool LDModelParser::substituteChrd(TCFloat fraction, bool bfc,
845 								   bool is48)
846 {
847 	int numSegments = getNumCircleSegments(fraction, is48);
848 
849 	m_currentTREModel->addChrd(TCVector(0.0f, 0.0f, 0.0f), 1.0f, numSegments,
850 		getUsedCircleSegments(numSegments, fraction), bfc);
851 	return true;
852 }
853 
substituteDisc(TCFloat fraction,bool bfc,bool is48)854 bool LDModelParser::substituteDisc(TCFloat fraction, bool bfc,
855 								   bool is48)
856 {
857 	int numSegments = getNumCircleSegments(fraction, is48);
858 
859 	m_currentTREModel->addDisc(TCVector(0.0f, 0.0f, 0.0f), 1.0f, numSegments,
860 		getUsedCircleSegments(numSegments, fraction), bfc);
861 	return true;
862 }
863 
substituteNotDisc(TCFloat fraction,bool bfc,bool is48)864 bool LDModelParser::substituteNotDisc(TCFloat fraction,
865 									  bool bfc, bool is48)
866 {
867 	int numSegments = getNumCircleSegments(fraction, is48);
868 
869 	m_currentTREModel->addNotDisc(TCVector(0.0f, 0.0f, 0.0f), 1.0f, numSegments,
870 		getUsedCircleSegments(numSegments, fraction), bfc);
871 	return true;
872 }
873 
substituteTangent(TCFloat fraction,bool bfc,bool is48)874 bool LDModelParser::substituteTangent(TCFloat fraction,
875 									  bool bfc, bool is48)
876 {
877 	int numSegments = getNumCircleSegments(fraction, is48);
878 
879 	while (numSegments % 16 != 0)
880 	{
881 		numSegments += LO_NUM_SEGMENTS;
882 	}
883 	m_currentTREModel->addTangent(TCVector(0.0f, 0.0f, 0.0f), 1.0f, numSegments,
884 		getUsedCircleSegments(numSegments, fraction), bfc);
885 	return true;
886 }
887 
substituteCircularEdge(TCFloat fraction,bool is48)888 bool LDModelParser::substituteCircularEdge(TCFloat fraction,
889 										   bool is48)
890 {
891 	if (shouldLoadEdgeLines())
892 	{
893 		TCULong edgeColor = 0;
894 		if (getIsHighlightModel())
895 		{
896 			edgeColor = m_topLDLModel->getPackedRGBA(getDefaultColorNumber());
897 		}
898 		int numSegments = getNumCircleSegments(fraction, is48);
899 
900 		m_currentTREModel->addCircularEdge(TCVector(0.0f, 0.0f, 0.0f), 1.0f, numSegments,
901 			getUsedCircleSegments(numSegments, fraction), edgeColor);
902 	}
903 	return true;
904 }
905 
substituteCone(TCFloat fraction,int size,bool bfc,bool is48)906 bool LDModelParser::substituteCone(TCFloat fraction, int size,
907 								   bool bfc, bool is48)
908 {
909 	int numSegments = getNumCircleSegments(fraction, is48);
910 
911 	m_currentTREModel->addOpenCone(TCVector(0.0f, 0.0f, 0.0f), (TCFloat)size + 1.0f,
912 		(TCFloat)size, 1.0f, numSegments,
913 		getUsedCircleSegments(numSegments, fraction), bfc);
914 	return true;
915 }
916 
substituteRing(TCFloat fraction,int size,bool bfc,bool is48,bool)917 bool LDModelParser::substituteRing(TCFloat fraction, int size,
918 								   bool bfc, bool is48, bool /*isOld*/)
919 {
920 	int numSegments = getNumCircleSegments(fraction, is48);
921 
922 	m_currentTREModel->addRing(TCVector(0.0f, 0.0f, 0.0f), (TCFloat)size,
923 		(TCFloat)size + 1.0f, numSegments,
924 		getUsedCircleSegments(numSegments, fraction), bfc);
925 	return true;
926 }
927 
performPrimitiveSubstitution2(LDLModel * ldlModel,TREModel * treModel,int activeColorNumber,bool bfc)928 bool LDModelParser::performPrimitiveSubstitution2(
929 	LDLModel *ldlModel,
930 	TREModel *treModel,
931 	int activeColorNumber,
932 	bool bfc)
933 {
934 	m_currentTREModel = treModel;
935 	m_currentColorNumber = activeColorNumber;
936 	return LDLPrimitiveCheck::performPrimitiveSubstitution(ldlModel, bfc);
937 }
938 
actionLineIsActive(LDLActionLine * actionLine)939 bool LDModelParser::actionLineIsActive(LDLActionLine *actionLine)
940 {
941 	if (getTexmapsFlag())
942 	{
943 		// If texmaps are enabled, we need to skip the fallback geometry.
944 		return !actionLine->isTexmapFallback();
945 	}
946 	else
947 	{
948 		// If texmaps are disabled, we need to skip the texmap geometry.
949 		return actionLine->getTexmapFilename().size() == 0;
950 	}
951 }
952 
parseModel(LDLModel * ldlModel,TREModel * treModel,bool bfc,int activeColorNumber,bool parentIsPart)953 bool LDModelParser::parseModel(
954 	LDLModel *ldlModel,
955 	TREModel *treModel,
956 	bool bfc,
957 	int activeColorNumber,
958     bool parentIsPart)
959 {
960 	BFCState newState = ldlModel->getBFCState();
961 	LDObiInfo obiInfo;
962 	LDObiInfo *origObiInfo = m_obiInfo;
963 
964 	if (m_obiInfo != NULL && m_obiInfo->isActive() &&
965 		!ldlModel->colorNumberIsTransparent(activeColorNumber))
966 	{
967 		obiInfo.start(m_obiInfo->getColor(), m_obiInfo->getEdgeColor(), true);
968 	}
969 	m_obiInfo = &obiInfo;
970     if (newState == BFCForcedOnState && parentIsPart)
971     {
972         newState = BFCOnState;
973     }
974 	bfc = ((bfc && (newState == BFCOnState)) || newState == BFCForcedOnState)
975 		&& getBFCFlag() && !ldlModel->colorNumberIsTransparent(activeColorNumber);
976 	if (ldlModel && !performPrimitiveSubstitution2(ldlModel, treModel,
977 		activeColorNumber, bfc))
978 	{
979 		LDLFileLineArray *fileLines = ldlModel->getFileLines();
980 
981 		if (fileLines)
982 		{
983 			int i;
984 			int count = ldlModel->getActiveLineCount();
985 			StringSet obiOrigTokens = m_obiTokens;
986 
987 			for (i = 0; i < count && !m_abort; i++)
988 			{
989 				LDLFileLine *fileLine = (*fileLines)[i];
990 
991 				if (fileLine->isValid())
992 				{
993 					if (fileLine->isActionLine() &&
994 						actionLineIsActive((LDLActionLine *)fileLine))
995 					{
996 						if (m_flags.newTexmap)
997 						{
998 							treModel->startTexture(fileLine->getTexmapType(),
999 								fileLine->getTexmapFilename(),
1000 								fileLine->getTexmapImage(),
1001 								fileLine->getTexmapPoints(),
1002 								fileLine->getTexmapExtra());
1003 							m_flags.newTexmap = false;
1004 							m_flags.texmapStarted = true;
1005 						}
1006 						//if (m_flags.obi)
1007 						//{
1008 						//	((LDLActionLine *)fileLine)->setObiOverrideActive(
1009 						//		!ldlModel->colorNumberIsTransparent(
1010 						//		activeColorNumber));
1011 						//}
1012 						switch (fileLine->getLineType())
1013 						{
1014 						case LDLLineTypeModel:
1015 							parseModel((LDLModelLine *)fileLine, treModel, bfc,
1016 								activeColorNumber, ldlModel->isPart());
1017 							break;
1018 						case LDLLineTypeLine:
1019 							parseLine((LDLShapeLine *)fileLine, treModel,
1020 								activeColorNumber);
1021 							break;
1022 						case LDLLineTypeTriangle:
1023 							parseTriangle((LDLShapeLine *)fileLine, treModel,
1024 								bfc, false, activeColorNumber);
1025 							break;
1026 						case LDLLineTypeQuad:
1027 							parseQuad((LDLShapeLine *)fileLine, treModel, bfc,
1028 								false, activeColorNumber);
1029 							break;
1030 						case LDLLineTypeConditionalLine:
1031 							parseConditionalLine(
1032 								(LDLConditionalLineLine *)fileLine, treModel,
1033 								activeColorNumber);
1034 							break;
1035 						default:
1036 							break;
1037 						}
1038 						m_obiInfo->actionHappened();
1039 						if (m_flags.texmapNext)
1040 						{
1041 							treModel->endTexture();
1042 						}
1043 					}
1044 					else if (fileLine->getLineType() == LDLLineTypeComment)
1045 					{
1046 						parseCommentLine((LDLCommentLine *)fileLine, treModel);
1047 					}
1048 				}
1049 				if (ldlModel == m_topLDLModel && m_alertSender != NULL)
1050 				{
1051 					TCProgressAlert::send("LDLModelParser",
1052 						TCLocalStrings::get(_UC("ParsingStatus")),
1053 						(float)(i + 1) / (float)(count + 1), &m_abort, this);
1054 				}
1055 			}
1056 			m_obiTokens = obiOrigTokens;
1057 		}
1058 	}
1059 	m_obiInfo = origObiInfo;
1060 	return !m_abort;
1061 }
1062 
1063 // Note: static method
unsetToken(StringSet & tokens,const char * token)1064 bool LDModelParser::unsetToken(StringSet &tokens, const char *token)
1065 {
1066 	StringSet::iterator it = tokens.find(token);
1067 
1068 	if (it != tokens.end())
1069 	{
1070 		tokens.erase(it);
1071 		return true;
1072 	}
1073 	return false;
1074 }
1075 
parseCommentLine(LDLCommentLine * commentLine,TREModel * treModel)1076 void LDModelParser::parseCommentLine(
1077 	LDLCommentLine *commentLine,
1078 	TREModel *treModel)
1079 {
1080 	if (commentLine->isStepMeta())
1081 	{
1082 		treModel->nextStep();
1083 	}
1084 	else if (commentLine->isOBIMeta())
1085 	{
1086 		if (m_flags.obi)
1087 		{
1088 			// 0 !OBI SET <token>
1089 			// 0 !OBI UNSET <token>
1090 			// 0 !OBI NEXT <color> [IFSET <token>|IFNSET <token>]
1091 			// 0 !OBI START <color> [IFSET <token>|IFNSET <token>]
1092 			// 0 !OBI END
1093 			switch (commentLine->getOBICommand())
1094 			{
1095 			case LDLCommentLine::OBICSet:
1096 				if (commentLine->hasOBIToken())
1097 				{
1098 					std::string token = commentLine->getOBIToken();
1099 
1100 					convertStringToLower(&token[0]);
1101 					m_obiTokens.insert(token);
1102 				}
1103 				break;
1104 			case LDLCommentLine::OBICUnset:
1105 				if (commentLine->hasOBIToken())
1106 				{
1107 					std::string token = commentLine->getOBIToken();
1108 
1109 					convertStringToLower(&token[0]);
1110 					unsetToken(m_obiTokens, token.c_str());
1111 				}
1112 				break;
1113 			case LDLCommentLine::OBICNext:
1114 			case LDLCommentLine::OBICStart:
1115 				m_obiInfo->start(commentLine, m_obiTokens);
1116 				break;
1117 			case LDLCommentLine::OBICEnd:
1118 				m_obiInfo->end();
1119 				break;
1120 			default:
1121 				// Gets rid of warning.
1122 				break;
1123 			}
1124 		}
1125 	}
1126 	else if (commentLine->isTexmapMeta() && getTexmapsFlag() &&
1127 		commentLine->isValid())
1128 	{
1129 		bool isStart = commentLine->containsTexmapCommand("START");
1130 		bool isNext = commentLine->containsTexmapCommand("NEXT");
1131 
1132 		if (isStart || isNext)
1133 		{
1134 			// Note: the data has already been copied out of this command and
1135 			// into the associated action lines.  We just want to know that we
1136 			// got here so we can activate the new texmap.
1137 			m_flags.newTexmap = true;
1138 			m_flags.texmapNext = isNext;
1139 		}
1140 		else if (commentLine->containsTexmapCommand("END"))
1141 		{
1142 			if (m_flags.texmapStarted)
1143 			{
1144 				treModel->endTexture();
1145 				m_flags.texmapStarted = false;
1146 			}
1147 			else
1148 			{
1149 				// If the texmap didn't contain any geometry we need to clear
1150 				// the newTexmap flag. Ideally we should also warn, but that's
1151 				// not critical.
1152 				m_flags.newTexmap = false;
1153 			}
1154 		}
1155 	}
1156 }
1157 
parseLine(LDLShapeLine * shapeLine,TREModel * treModel,int activeColorNumber)1158 void LDModelParser::parseLine(
1159 	LDLShapeLine *shapeLine,
1160 	TREModel *treModel,
1161 	int activeColorNumber)
1162 {
1163 	int colorNumber = actualColorNumber(shapeLine, activeColorNumber);
1164 	//TCULong colorNumber = shapeLine->getColorNumber();
1165 
1166 	if (colorNumber == 16)
1167 	{
1168 		if (!getEdgesOnlyFlag())
1169 		{
1170 			treModel->addLine(shapeLine->getPoints());
1171 		}
1172 	}
1173 	else if (colorNumber == 24)
1174 	{
1175 		if (shouldLoadEdgeLines())
1176 		{
1177 			TCULong edgeColor = 0;
1178 			if (getIsHighlightModel())
1179 			{
1180 				edgeColor = m_topLDLModel->getPackedRGBA(getDefaultColorNumber());
1181 			}
1182 			treModel->addEdgeLine(shapeLine->getPoints(), edgeColor);
1183 		}
1184 	}
1185 	else if (!getEdgesOnlyFlag())
1186 	{
1187 		treModel->addLine(shapeLine->getParentModel()->
1188 			getPackedRGBA(colorNumber), shapeLine->getPoints());
1189 	}
1190 }
1191 
parseConditionalLine(LDLConditionalLineLine * conditionalLine,TREModel * treModel,int activeColorNumber)1192 void LDModelParser::parseConditionalLine(
1193 	LDLConditionalLineLine
1194 	*conditionalLine,
1195 	TREModel *treModel,
1196 	int activeColorNumber)
1197 {
1198 	if (shouldLoadConditionalLines())
1199 	{
1200 		int colorNumber = actualColorNumber(conditionalLine, activeColorNumber);
1201 		TCULong color = 0;
1202 
1203 		if (colorNumber != 24)
1204 		{
1205 			color = conditionalLine->getParentModel()->getPackedRGBA(
1206 				colorNumber);
1207 		}
1208 		treModel->addConditionalLine(conditionalLine->getPoints(),
1209 			conditionalLine->getControlPoints(), color);
1210 	}
1211 }
1212 
shouldFlipWinding(bool invert,bool windingCCW)1213 bool LDModelParser::shouldFlipWinding(bool invert, bool windingCCW)
1214 {
1215 	return (invert && windingCCW) || (!invert && !windingCCW);
1216 }
1217 
parseTriangle(LDLShapeLine * shapeLine,TREModel * treModel,bool bfc,bool invert,int activeColorNumber)1218 void LDModelParser::parseTriangle(
1219 	LDLShapeLine *shapeLine,
1220 	TREModel *treModel,
1221 	bool bfc,
1222 	bool invert,
1223 	int activeColorNumber)
1224 {
1225 	int colorNumber = actualColorNumber(shapeLine, activeColorNumber);
1226 	//TCULong colorNumber = shapeLine->getColorNumber();
1227 
1228 	if (bfc)
1229 	{
1230 		bfc = shapeLine->getBFCOn();
1231 	}
1232 	if (colorNumber == 16)
1233 	{
1234 		if (bfc)
1235 		{
1236 			if (shouldFlipWinding(invert, shapeLine->getBFCWindingCCW()))
1237 			{
1238 				TCVector points[3];
1239 
1240 				points[0] = shapeLine->getPoints()[2];
1241 				points[1] = shapeLine->getPoints()[1];
1242 				points[2] = shapeLine->getPoints()[0];
1243 				treModel->addBFCTriangle(points);
1244 			}
1245 			else
1246 			{
1247 				treModel->addBFCTriangle(shapeLine->getPoints());
1248 			}
1249 		}
1250 		else
1251 		{
1252 			treModel->addTriangle(shapeLine->getPoints());
1253 		}
1254 	}
1255 	else
1256 	{
1257 		if (bfc)
1258 		{
1259 			if (shouldFlipWinding(invert, shapeLine->getBFCWindingCCW()))
1260 			{
1261 				TCVector points[3];
1262 
1263 				points[0] = shapeLine->getPoints()[2];
1264 				points[1] = shapeLine->getPoints()[1];
1265 				points[2] = shapeLine->getPoints()[0];
1266 				treModel->addBFCTriangle(shapeLine->getParentModel()->
1267 					getPackedRGBA(colorNumber), points);
1268 			}
1269 			else
1270 			{
1271 				treModel->addBFCTriangle(shapeLine->getParentModel()->
1272 					getPackedRGBA(colorNumber), shapeLine->getPoints());
1273 			}
1274 		}
1275 		else
1276 		{
1277 			treModel->addTriangle(shapeLine->getParentModel()->
1278 				getPackedRGBA(colorNumber), shapeLine->getPoints());
1279 		}
1280 	}
1281 }
1282 
actualColorNumber(LDLActionLine * actionLine,int activeColorNumber)1283 int LDModelParser::actualColorNumber(
1284 	LDLActionLine *actionLine,
1285 	int activeColorNumber)
1286 {
1287 	int colorNumber = actionLine->getColorNumber();
1288 	LDLModel *model = actionLine->getParentModel();
1289 
1290 	if (model && !model->colorNumberIsTransparent(activeColorNumber))
1291 	{
1292 		TCULong color;
1293 
1294 		switch (colorNumber)
1295 		{
1296 		case 16:
1297 			color = m_obiInfo->getColor();
1298 			break;
1299 		case 24:
1300 			color = m_obiInfo->getEdgeColor();
1301 			break;
1302 		default:
1303 			color = 0;
1304 			break;
1305 		}
1306 		if (color != 0)
1307 		{
1308 			return LDLPalette::colorNumberForPackedRGBA(color);
1309 		}
1310 	}
1311 	return colorNumber;
1312 }
1313 
parseQuad(LDLShapeLine * shapeLine,TREModel * treModel,bool bfc,bool invert,int activeColorNumber)1314 void LDModelParser::parseQuad(
1315 	LDLShapeLine *shapeLine,
1316 	TREModel *treModel,
1317 	bool bfc,
1318 	bool invert,
1319 	int activeColorNumber)
1320 {
1321 	int colorNumber = actualColorNumber(shapeLine, activeColorNumber);
1322 
1323 	if (bfc)
1324 	{
1325 		bfc = shapeLine->getBFCOn();
1326 	}
1327 	if (colorNumber == 16)
1328 	{
1329 		if (bfc)
1330 		{
1331 			if (shouldFlipWinding(invert, shapeLine->getBFCWindingCCW()))
1332 			{
1333 				TCVector points[4];
1334 
1335 				points[0] = shapeLine->getPoints()[3];
1336 				points[1] = shapeLine->getPoints()[2];
1337 				points[2] = shapeLine->getPoints()[1];
1338 				points[3] = shapeLine->getPoints()[0];
1339 				treModel->addBFCQuad(points);
1340 			}
1341 			else
1342 			{
1343 				treModel->addBFCQuad(shapeLine->getPoints());
1344 			}
1345 		}
1346 		else
1347 		{
1348 			treModel->addQuad(shapeLine->getPoints());
1349 		}
1350 	}
1351 	else
1352 	{
1353 		if (bfc)
1354 		{
1355 			if (shouldFlipWinding(invert, shapeLine->getBFCWindingCCW()))
1356 			{
1357 				TCVector points[4];
1358 
1359 				points[0] = shapeLine->getPoints()[3];
1360 				points[1] = shapeLine->getPoints()[2];
1361 				points[2] = shapeLine->getPoints()[1];
1362 				points[3] = shapeLine->getPoints()[0];
1363 				treModel->addBFCQuad(shapeLine->getParentModel()->
1364 					getPackedRGBA(colorNumber), points);
1365 			}
1366 			else
1367 			{
1368 				treModel->addBFCQuad(shapeLine->getParentModel()->
1369 					getPackedRGBA(colorNumber), shapeLine->getPoints());
1370 			}
1371 		}
1372 		else
1373 		{
1374 			treModel->addQuad(shapeLine->getParentModel()->
1375 				getPackedRGBA(colorNumber), shapeLine->getPoints());
1376 		}
1377 	}
1378 }
1379 
setSeamWidth(TCFloat seamWidth)1380 void LDModelParser::setSeamWidth(TCFloat seamWidth)
1381 {
1382 	m_seamWidth = seamWidth;
1383 	if (m_seamWidth)
1384 	{
1385 		setSeamsFlag(true);
1386 	}
1387 	else
1388 	{
1389 		setSeamsFlag(false);
1390 	}
1391 }
1392 
getSeamWidth(void)1393 TCFloat LDModelParser::getSeamWidth(void)
1394 {
1395 	if (getSeamsFlag())
1396 	{
1397 		return m_seamWidth;
1398 	}
1399 	else
1400 	{
1401 		return 0.0f;
1402 	}
1403 }
1404 
1405