1 /*
2     Copyright (c) 2008-2009 NetAllied Systems GmbH
3 
4     This file is part of COLLADASaxFrameworkLoader.
5 
6     Licensed under the MIT Open Source License,
7     for details please see LICENSE file or the website
8     http://www.opensource.org/licenses/mit-license.php
9 */
10 
11 #include "COLLADASaxFWLStableHeaders.h"
12 #include "COLLADASaxFWLMeshLoader.h"
13 #include "COLLADASaxFWLGeometryMaterialIdInfo.h"
14 #include "COLLADASaxFWLLoader.h"
15 #include "COLLADASaxFWLFileLoader.h"
16 
17 #include "COLLADAFWTriangles.h"
18 #include "COLLADAFWLines.h"
19 #include "COLLADAFWTristrips.h"
20 #include "COLLADAFWTrifans.h"
21 #include "COLLADAFWPolygons.h"
22 #include "COLLADAFWPolylist.h"
23 #include "COLLADAFWLinestrips.h"
24 #include "COLLADAFWIWriter.h"
25 
26 #include <fstream>
27 
28 
29 namespace COLLADASaxFWL
30 {
31 
MeshLoader(IFilePartLoader * callingFilePartLoader,const String & geometryId,const String & geometryName)32 	MeshLoader::MeshLoader( IFilePartLoader* callingFilePartLoader, const String& geometryId, const String& geometryName )
33 		: SourceArrayLoader (callingFilePartLoader )
34 		, mMeshUniqueId(createUniqueIdFromId((ParserChar*)geometryId.c_str(), COLLADAFW::Geometry::ID()))
35 		, mMesh ( new COLLADAFW::Mesh(mMeshUniqueId) )
36 		, mMaterialIdInfo(getMeshMaterialIdInfo())
37 		, mCurrentMeshPrimitive(0)
38         , mInVertices ( false )
39         , mCurrentVertexInput(0)
40 		, mMeshPrimitiveInputs(mVerticesInputs)
41 		, mCurrentMeshPrimitiveInput(0)
42         , mCurrentOffset (0)
43         , mCurrentMaxOffset(0)
44         , mCurrentVertexCount(0)
45         , mCurrentLastPrimitiveVertexCount(0)
46         , mCurrentPhHasEmptyP(true)
47         , mCurrentExpectedVertexCount(0)
48         , mCurrentFaceOrLineCount(0)
49 		, mPositionsOffset (0)
50 		, mPositionsIndexOffset(0)
51 		, mUsePositions ( true )
52 		, mNormalsOffset (0)
53 		, mNormalsIndexOffset(0)
54 		, mUseNormals ( false )
55         , mUseTangents ( false )
56         , mUseBinormals ( false )
57         , mColorList (0)
58         , mTexCoordList (0)
59 		, mCurrentPrimitiveType(NONE)
60 		, mPOrPhElementCountOfCurrentPrimitive(0)
61         , mInMesh (true)
62 	{
63         if ( !geometryName.empty() )
64             mMesh->setName ( geometryName );
65         else if ( !geometryId.empty() )
66             mMesh->setName ( geometryId );
67 
68         if ( !geometryId.empty() )
69             mMesh->setOriginalId ( geometryId );
70 	}
71 
72     //------------------------------
getUniqueId()73     const COLLADAFW::UniqueId& MeshLoader::getUniqueId ()
74     {
75         switch ( mCurrentPrimitiveType )
76         {
77         case TRIANGLES:
78         case LINES:
79         case TRISTRIPS:
80         case TRIFANS:
81         case POLYGONS:
82         case POLYGONS_HOLE:
83 		case POLYLIST:
84 		case LINESTRIPS:
85             return mCurrentMeshPrimitive->getUniqueId (); break;
86         default:
87             if ( mMesh ) return mMesh->getUniqueId (); break;
88         }
89 
90         return COLLADAFW::UniqueId::INVALID;
91     }
92 
93     //------------------------------
getVertexInputBySemantic(const InputSemantic::Semantic & semantic) const94     const InputUnshared* MeshLoader::getVertexInputBySemantic ( const InputSemantic::Semantic& semantic ) const
95     {
96         // Search the vertex input elements for the semantic element.
97         return getVertices().getInputBySemantic ( semantic );
98     }
99 
100     //------------------------------
getSourceByInputSemanticFromVertices(const InputSemantic::Semantic & semantic) const101     const SourceBase* MeshLoader::getSourceByInputSemanticFromVertices ( const InputSemantic::Semantic& semantic ) const
102     {
103         // Check if the input element with the semantic is a vertex element.
104         const InputUnshared* positionsInput = getVertexInputBySemantic ( semantic );
105         if ( positionsInput == 0 ) return 0;
106 
107         // Get the source element with the uri of the input element.
108         COLLADABU::URI positionsInputSource = positionsInput->getSource ();
109         String sourceId = positionsInputSource.getFragment ();
110 
111         return getSourceById ( sourceId );
112     }
113 
114     //------------------------------
getPositionsSource() const115     const SourceBase* MeshLoader::getPositionsSource () const
116     {
117         return getSourceByInputSemanticFromVertices ( InputSemantic::POSITION );
118     }
119 
120 
121     //------------------------------
loadSourceElements(const MeshPrimitiveInputList & polyBaseElement)122     void MeshLoader::loadSourceElements ( const MeshPrimitiveInputList& polyBaseElement )
123     {
124         const InputSharedArray& inputArray = polyBaseElement.getInputArray ();
125         size_t numInputElements = inputArray.getCount ();
126         for ( size_t n=0; n<numInputElements; ++n )
127         {
128             // Get the input element and read the semantic.
129             InputShared* input = inputArray [n];
130 
131             // Load the source element of the current input element into the framework mesh.
132             loadSourceElement ( *input );
133         }
134     }
135 
136     //------------------------------
loadSourceElement(const InputShared & input)137     bool MeshLoader::loadSourceElement ( const InputShared& input )
138     {
139         bool retValue = false;
140 
141         // Get the semantic of the current input element.
142         InputSemantic::Semantic semantic = input.getSemantic ();
143         switch ( semantic )
144         {
145         case InputSemantic::POSITION:
146             retValue = loadPositionsSourceElement ( input );
147             break;
148         case InputSemantic::NORMAL:
149             retValue = loadNormalsSourceElement ( input );
150             break;
151         case InputSemantic::COLOR:
152             retValue = loadColorsSourceElement ( input );
153             break;
154         case InputSemantic::UV:
155         case InputSemantic::TEXCOORD:
156             retValue = loadTexCoordsSourceElement ( input );
157             break;
158         case InputSemantic::TEXTANGENT:
159             retValue = loadTexTangentSourceElement( input );
160             break;
161         case InputSemantic::TEXBINORMAL:
162             retValue = loadTexBinormalSourceElement( input );
163             break;
164         default:
165             // Not implemented source
166 //            std::cerr << "Source with semantic " << semantic << "not implemented!" << std::endl;
167             retValue = false;
168         }
169 
170         return retValue;
171     }
172 
173 	//------------------------------
loadPositionsSourceElement(const InputShared & input)174     bool MeshLoader::loadPositionsSourceElement ( const InputShared& input )
175     {
176         // Get the semantic of the current input element.
177         InputSemantic::Semantic semantic = input.getSemantic ();
178         if ( semantic != InputSemantic::POSITION )
179         {
180             std::cerr << "The current input element is not a POSITION element!" << std::endl;
181             return false;
182         }
183 
184         // Get the source element with the uri of the input element.
185         COLLADABU::URI inputUrl = input.getSource ();
186         String sourceId = inputUrl.getFragment ();
187         SourceBase* sourceBase = getSourceById ( sourceId );
188         if ( sourceBase == 0 ) return false;
189 
190         // Check if the source element is already loaded.
191         if ( sourceBase->isLoadedInputElement ( semantic ) ) return false;
192 
193         // Get the source input array
194         const SourceBase::DataType& dataType = sourceBase->getDataType ();
195         switch ( dataType )
196         {
197         case SourceBase::DATA_TYPE_FLOAT:
198             {
199                 // Get the values array from the source
200                 FloatSource* source = ( FloatSource* ) sourceBase;
201                 FloatArrayElement& arrayElement = source->getArrayElement ();
202                 COLLADAFW::ArrayPrimitiveType<float>& valuesArray = arrayElement.getValues ();
203 
204                 // TODO
205                 /* unsigned long long stride = source->getStride (); */ /* UNUSED */
206 
207                 // Check if there are already some values in the positions list.
208                 // If so, we have to store the last index to increment the following indexes.
209                 COLLADAFW::MeshVertexData& positions = mMesh->getPositions ();
210                 const size_t initialIndex = positions.getValuesCount ();
211                 sourceBase->setInitialIndex ( initialIndex );
212 
213                 // Push the new positions into the list of positions.
214                 positions.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT );
215                 if ( initialIndex != 0 )
216 				{
217 					positions.appendValues ( valuesArray );
218 				}
219                 else
220 				{
221 					positions.setData ( valuesArray.getData (), valuesArray.getCount () );
222 					valuesArray.yieldOwnerShip();
223 				}
224 
225                 // Set the source base as loaded element.
226                 sourceBase->addLoadedInputElement ( semantic );
227 
228                 break;
229             }
230         case SourceBase::DATA_TYPE_DOUBLE:
231             {
232                 // Get the values array from the source
233                 DoubleSource* source = ( DoubleSource* ) sourceBase;
234                 DoubleArrayElement& arrayElement = source->getArrayElement ();
235                 COLLADAFW::ArrayPrimitiveType<double>& valuesArray = arrayElement.getValues ();
236 
237                 // Check if there are already some values in the positions list.
238                 // If so, we have to store the last index to increment the following indexes.
239                 COLLADAFW::MeshVertexData& positions = mMesh->getPositions ();
240                 const size_t initialIndex = positions.getValuesCount ();
241                 sourceBase->setInitialIndex ( initialIndex );
242 
243                 // Push the new positions into the list of positions.
244                 positions.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE );
245                 if ( initialIndex != 0 )
246 				{
247 					positions.appendValues ( valuesArray );
248 				}
249                 else
250 				{
251 					positions.setData ( valuesArray.getData (), valuesArray.getCount () );
252 					valuesArray.yieldOwnerShip();
253 				}
254 
255                 // Set the source base as loaded element.
256                 sourceBase->addLoadedInputElement ( semantic );
257 
258                 break;
259             }
260         default:
261             std::cerr << "Position source has an other datatype as float or double! " << dataType << std::endl;
262             return false;
263         }
264 
265         return true;
266     }
267 
268 	//------------------------------
loadNormalsSourceElement(const InputShared & input)269     bool MeshLoader::loadNormalsSourceElement ( const InputShared& input )
270     {
271         // Get the semantic of the current input element.
272         InputSemantic::Semantic semantic = input.getSemantic ();
273         if ( semantic != InputSemantic::NORMAL )
274         {
275             std::cerr << "The current input element is not a NORMAL element!" << std::endl;
276             return false;
277         }
278 
279         // Get the source element with the uri of the input element.
280         COLLADABU::URI inputUrl = input.getSource ();
281         String sourceId = inputUrl.getFragment ();
282         SourceBase* sourceBase = getSourceById ( sourceId );
283         if ( sourceBase == 0 ) return false;
284 
285         // Check if the source element is already loaded.
286         if ( sourceBase->isLoadedInputElement ( semantic ) ) return false;
287 
288         // Get the source input array
289         const SourceBase::DataType& dataType = sourceBase->getDataType ();
290         switch ( dataType )
291         {
292         case SourceBase::DATA_TYPE_FLOAT:
293             {
294                 // Get the values array from the source
295                 FloatSource* source = ( FloatSource* ) sourceBase;
296                 FloatArrayElement& arrayElement = source->getArrayElement ();
297                 COLLADAFW::ArrayPrimitiveType<float>& valuesArray = arrayElement.getValues ();
298 
299                 // Check if there are already some values in the positions list.
300                 // If so, we have to store the last index to increment the following indexes.
301                 COLLADAFW::MeshVertexData& normals = mMesh->getNormals ();
302                 const size_t initialIndex = normals.getValuesCount ();
303                 sourceBase->setInitialIndex ( initialIndex );
304 
305                 // Push the new positions into the list of positions.
306                 normals.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT );
307                 if ( initialIndex != 0 )
308 				{
309 					normals.appendValues ( valuesArray );
310 				}
311                 else
312 				{
313 					normals.setData ( valuesArray.getData (), valuesArray.getCount () );
314 					valuesArray.yieldOwnerShip();
315 				}
316 
317                 // Set the source base as loaded element.
318                 sourceBase->addLoadedInputElement ( semantic );
319 
320                 break;
321             }
322         case SourceBase::DATA_TYPE_DOUBLE:
323             {
324                 // Get the values array from the source
325                 DoubleSource* source = ( DoubleSource* ) sourceBase;
326                 DoubleArrayElement& arrayElement = source->getArrayElement ();
327                 COLLADAFW::ArrayPrimitiveType<double>& valuesArray = arrayElement.getValues ();
328 
329                 // Check if there are already some values in the positions list.
330                 // If so, we have to store the last index to increment the following indexes.
331                 COLLADAFW::MeshVertexData& normals = mMesh->getNormals ();
332                 const size_t initialIndex = normals.getValuesCount ();
333                 sourceBase->setInitialIndex ( initialIndex );
334 
335                 // Push the new positions into the list of positions.
336                 normals.setType ( COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE );
337                 if ( initialIndex != 0 )
338 				{
339 					normals.appendValues ( valuesArray );
340 				}
341                 else
342 				{
343 					normals.setData ( valuesArray.getData (), valuesArray.getCount () );
344 					valuesArray.yieldOwnerShip();
345 				}
346 
347                 // Set the source base as loaded element.
348                 sourceBase->addLoadedInputElement ( semantic );
349 
350                 break;
351             }
352         default:
353             std::cerr << "Normals source has an other datatype as float or double! " << dataType << std::endl;
354             return false;
355         }
356 
357         return true;
358     }
359     //------------------------------
loadColorsSourceElement(const InputShared & input)360     bool MeshLoader::loadColorsSourceElement ( const InputShared& input )
361     {
362         bool retValue = true;
363 
364         // Get the semantic of the current input element.
365         InputSemantic::Semantic semantic = input.getSemantic ();
366         if ( semantic != InputSemantic::COLOR )
367         {
368             std::cerr << "The current input element is not a COLOR element!" << std::endl;
369             return false;
370         }
371 
372         // Get the source element with the uri of the input element.
373         COLLADABU::URI inputUrl = input.getSource ();
374         String sourceId = inputUrl.getFragment ();
375         SourceBase* sourceBase = getSourceById ( sourceId );
376         if ( sourceBase == 0 ) return false;
377 
378         // Check if the source element is already loaded.
379         if ( sourceBase->isLoadedInputElement ( semantic ) ) return false;
380 
381         // Get the stride of the uv coordinates.
382         // This is the dimension of the uv coordinates.
383         // In depend on the dimension, we store the coordinates in the mesh.
384         unsigned long long stride = sourceBase->getStride ();
385         if ( stride < 3 || stride > 4 )
386         {
387             std::cerr << "The color source " <<  input.getSource().getURIString ()
388                 << " has a wrong dimension of " << stride
389                 << ". Dimensions between 3 (RGB) and 4 (RGBA) are allowed. " << std::endl;
390             retValue = false;
391         }
392         else
393         {
394             COLLADAFW::MeshVertexData& colors = mMesh->getColors ();
395             retValue = appendVertexValues ( sourceBase, colors );
396         }
397 
398         // Set the source base as loaded element.
399         sourceBase->addLoadedInputElement ( semantic );
400 
401         return retValue;
402     }
403 
loadTexTangentSourceElement(const InputShared & input)404     bool MeshLoader::loadTexTangentSourceElement( const InputShared& input )
405     {
406         bool retValue = true;
407 
408         // Get the semantic of the current input element.
409         InputSemantic::Semantic semantic = input.getSemantic ();
410         if ( semantic != InputSemantic::TEXTANGENT )
411         {
412             std::cerr << "The current input element is not a TEXTANGENT element!" << std::endl;
413             return false;
414         }
415 
416         // Get the source element with the uri of the input element.
417         COLLADABU::URI inputUrl = input.getSource ();
418         String sourceId = inputUrl.getFragment ();
419         SourceBase* sourceBase = getSourceById ( sourceId );
420         if ( sourceBase == 0 ) return false;
421 
422         // Check if the source element is already loaded.
423         if ( sourceBase->isLoadedInputElement ( semantic ) ) return false;
424 
425         // Get the stride of the uv coordinates.
426         // This is the dimension of the uv coordinates.
427         // In depend on the dimension, we store the coordinates in the mesh.
428         unsigned long long stride = sourceBase->getStride ();
429         if ( stride !=  3 )
430         {
431             std::cerr << "The tangent source " <<  input.getSource().getURIString ()
432                 << " has a wrong dimension of " << stride
433                 << ". Dimensions must be 3." << std::endl;
434             retValue = false;
435         }
436         else
437         {
438             COLLADAFW::MeshVertexData& colors = mMesh->getTangents ();
439             retValue = appendVertexValues ( sourceBase, colors );
440         }
441 
442         // Set the source base as loaded element.
443         sourceBase->addLoadedInputElement ( semantic );
444 
445         return retValue;
446     }
447 
loadTexBinormalSourceElement(const InputShared & input)448     bool MeshLoader::loadTexBinormalSourceElement ( const InputShared& input )
449     {
450         bool retValue = true;
451 
452         // Get the semantic of the current input element.
453         InputSemantic::Semantic semantic = input.getSemantic ();
454         if ( semantic != InputSemantic::TEXBINORMAL )
455         {
456             std::cerr << "The current input element is not a TEXBINORMAL element!" << std::endl;
457             return false;
458         }
459 
460         // Get the source element with the uri of the input element.
461         COLLADABU::URI inputUrl = input.getSource ();
462         String sourceId = inputUrl.getFragment ();
463         SourceBase* sourceBase = getSourceById ( sourceId );
464         if ( sourceBase == 0 ) return false;
465 
466         // Check if the source element is already loaded.
467         if ( sourceBase->isLoadedInputElement ( semantic ) ) return false;
468 
469         // Get the stride of the uv coordinates.
470         // This is the dimension of the uv coordinates.
471         // In depend on the dimension, we store the coordinates in the mesh.
472         unsigned long long stride = sourceBase->getStride ();
473         if ( stride !=  3 )
474         {
475             std::cerr << "The binormal source " <<  input.getSource().getURIString ()
476                 << " has a wrong dimension of " << stride
477                 << ". Dimensions must be 3." << std::endl;
478             retValue = false;
479         }
480         else
481         {
482             COLLADAFW::MeshVertexData& colors = mMesh->getBinormals ();
483             retValue = appendVertexValues ( sourceBase, colors );
484         }
485 
486         // Set the source base as loaded element.
487         sourceBase->addLoadedInputElement ( semantic );
488 
489         return retValue;
490     }
491 
492     //------------------------------
appendVertexValues(SourceBase * sourceBase,COLLADAFW::MeshVertexData & vertexData)493     bool MeshLoader::appendVertexValues (
494         SourceBase* sourceBase,
495         COLLADAFW::MeshVertexData &vertexData )
496     {
497         bool retValue = true;
498 
499         // Check if there are already some values in the positions list.
500         // If so, we have to store the last index to increment the following indexes.
501         const size_t initialIndex = vertexData.getValuesCount ();
502         sourceBase->setInitialIndex ( initialIndex );
503 
504         // Get the source input array
505         const SourceBase::DataType& dataType = sourceBase->getDataType ();
506         switch ( dataType )
507         {
508         case SourceBase::DATA_TYPE_FLOAT:
509             {
510                 // Get the values array from the source
511                 FloatSource* source = ( FloatSource* ) sourceBase;
512                 FloatArrayElement& arrayElement = source->getArrayElement ();
513                 COLLADAFW::ArrayPrimitiveType<float>& valuesArray = arrayElement.getValues ();
514 
515                 // Push the values with the infos into the list.
516                 vertexData.appendValues ( valuesArray, source->getId (), (size_t) source->getStride () );
517 
518                 break;
519             }
520         case SourceBase::DATA_TYPE_DOUBLE:
521             {
522                 // Get the values array from the source
523                 DoubleSource* source = ( DoubleSource* ) sourceBase;
524                 DoubleArrayElement& arrayElement = source->getArrayElement ();
525                 COLLADAFW::ArrayPrimitiveType<double>& valuesArray = arrayElement.getValues ();
526 
527                 // Push the values with the infos into the list.
528                 vertexData.appendValues ( valuesArray, source->getId (), (size_t) source->getStride () );
529 
530                 break;
531             }
532         default:
533             std::cerr << "Source has an other datatype as float or double! " << dataType << std::endl;
534             retValue = false;
535         }
536 
537         return retValue;
538     }
539 
540     //------------------------------
loadTexCoordsSourceElement(const InputShared & input)541     bool MeshLoader::loadTexCoordsSourceElement ( const InputShared& input )
542     {
543         bool retValue = true;
544 
545         // Get the semantic of the current input element.
546         InputSemantic::Semantic semantic = input.getSemantic ();
547         if ( semantic != InputSemantic::UV && semantic != InputSemantic::TEXCOORD )
548         {
549             std::cerr << "The current input element is not a UV / TEXCOORD element!" << std::endl;
550             return false;
551         }
552 
553         // Get the source element with the uri of the input element.
554         COLLADABU::URI inputUrl = input.getSource ();
555         String sourceId = inputUrl.getFragment ();
556         SourceBase* sourceBase = getSourceById ( sourceId );
557         if ( sourceBase == 0 ) return false;
558 
559         // Check if the source element is already loaded.
560         if ( sourceBase->isLoadedInputElement ( semantic ) ) return false;
561 
562         // Get the stride of the uv coordinates.
563         // This is the dimension of the uv coordinates.
564         // In depend on the dimension, we store the coordinates in the mesh.
565         unsigned long long stride = sourceBase->getStride ();
566         if ( stride < 2 || stride > 4 )
567         {
568             std::cerr << "The uv source " <<  input.getSource().getURIString ()
569                 << " has a wrong dimension of " << stride
570                 << ". Dimensions between 2 and 4 are allowed. " << std::endl;
571             retValue = false;
572         }
573         else
574         {
575             COLLADAFW::MeshVertexData& uvCoords = mMesh->getUVCoords ();
576             retValue = appendVertexValues ( sourceBase, uvCoords );
577         }
578 
579         // Set the source base as loaded element.
580         sourceBase->addLoadedInputElement ( semantic );
581 
582         return retValue;
583     }
584 
585     //------------------------------
writePrimitiveIndices(const unsigned long long * data,size_t length)586 	bool MeshLoader::writePrimitiveIndices ( const unsigned long long* data, size_t length )
587 	{
588 		// check, if we are parsing an unsupported primitive type
589 		if ( !mCurrentMeshPrimitive )
590 			return true;
591 
592 		// Write the index values in the index lists.
593 		for ( size_t i=0; i<length; ++i )
594 		{
595 			// Get the current index value.
596 			unsigned int index = (unsigned int)data [i];
597 
598 			// Write the indices
599 			if ( mUsePositions && (mCurrentOffset == mPositionsOffset) )
600 			{
601 				COLLADAFW::UIntValuesArray& positionIndices = mCurrentMeshPrimitive->getPositionIndices();
602 				positionIndices.append ( index + mPositionsIndexOffset );
603 			}
604 
605 			if ( mUseNormals && (mCurrentOffset == mNormalsOffset) )
606 			{
607 				COLLADAFW::UIntValuesArray& normalIndices = mCurrentMeshPrimitive->getNormalIndices();
608 				normalIndices.append ( index + mNormalsIndexOffset );
609 			}
610 
611             if ( mUseTangents && (mCurrentOffset == mTangentsOffset) )
612             {
613                 COLLADAFW::UIntValuesArray& tangentIndices = mCurrentMeshPrimitive->getTangentIndices();
614                 tangentIndices.append ( index + mTangentsIndexOffset );
615             }
616 
617             if ( mUseBinormals && (mCurrentOffset == mBinormalsOffset) )
618             {
619                 COLLADAFW::UIntValuesArray& binormalIndices = mCurrentMeshPrimitive->getBinormalIndices();
620                 binormalIndices.append ( index + mBinormalsIndexOffset );
621             }
622 
623 
624             // Look if the current offset is a texcoord offset.
625             size_t numTexCoordinates = mTexCoordList.size();
626             for ( size_t j=0; j<numTexCoordinates; ++j )
627             {
628                 PrimitiveInput& texCoord = mTexCoordList[j];
629                 if ( mCurrentOffset == texCoord.mOffset )
630                 {
631                     COLLADAFW::ArrayPrimitiveType<COLLADAFW::IndexList*>& texCoordIndicesArray =
632                         mCurrentMeshPrimitive->getUVCoordIndicesArray();
633 
634                     // Resize the array if necessary
635                     if ( texCoordIndicesArray.getCount () != numTexCoordinates )
636                     {
637                         // Be careful: no constructor is called!
638                         texCoordIndicesArray.reallocMemory ( numTexCoordinates );
639                         for ( size_t k=0; k<numTexCoordinates; ++k )
640                         {
641                             COLLADAFW::IndexList* texCoordIndices = new COLLADAFW::IndexList ();
642                             PrimitiveInput& tex = mTexCoordList [k];
643                             texCoordIndices->setSetIndex ( tex.mSetIndex );
644                             texCoordIndices->setName ( tex.mName );
645                             texCoordIndices->setStride ( tex.mStride );
646                             texCoordIndices->setInitialIndex ( tex.mInitialIndex );
647 
648                             texCoordIndicesArray.append( texCoordIndices );
649                         }
650                     }
651 
652                     // Write the values.
653                     COLLADAFW::IndexList* texCoordIndices = mCurrentMeshPrimitive->getUVCoordIndices ( j );
654                     texCoordIndices->getIndices().append ( index + (unsigned int)texCoord.mInitialIndex );
655                 }
656             }
657 
658             // Look if the current offset is a texcoord offset.
659             size_t numColors = mColorList.size ();
660             for ( size_t j=0; j<numColors; ++j )
661             {
662                 PrimitiveInput& color = mColorList [j];
663                 if ( mCurrentOffset == color.mOffset )
664                 {
665                     COLLADAFW::ArrayPrimitiveType<COLLADAFW::IndexList*>& colorIndicesArray =
666                         mCurrentMeshPrimitive->getColorIndicesArray ();
667 
668                     // Resize the array if necessary
669                     if ( colorIndicesArray.getCount () != numColors )
670                     {
671                         // Be careful: no constructor is called!
672                         colorIndicesArray.reallocMemory ( numColors );
673                         for ( size_t k=0; k<numColors; ++k )
674                         {
675                             COLLADAFW::IndexList* colorIndices = new COLLADAFW::IndexList ();
676                             PrimitiveInput& col = mColorList [k];
677                             colorIndices->setSetIndex ( col.mSetIndex );
678                             colorIndices->setName ( col.mName );
679                             colorIndices->setStride ( col.mStride );
680                             colorIndices->setInitialIndex ( col.mInitialIndex );
681 
682                             colorIndicesArray.append ( colorIndices );
683                         }
684                     }
685 
686                     // Write the values.
687                     COLLADAFW::IndexList* colorIndices = mCurrentMeshPrimitive->getColorIndices ( j );
688                     colorIndices->getIndices().append ( index + (unsigned int)color.mInitialIndex );
689                 }
690             }
691 
692 			// Reset the offset if we went through all offset values
693 			if ( mCurrentOffset == mCurrentMaxOffset )
694 			{
695 				// Reset the current offset value
696 				mCurrentOffset = 0;
697 				++mCurrentVertexCount;
698 			}
699 			else
700 			{
701 				// Increment the current offset value
702 				++mCurrentOffset;
703 			}
704 		}
705 		return true;
706 	}
707 
708 
709 	//------------------------------
initializeOffsets()710 	bool MeshLoader::initializeOffsets()
711 	{
712         bool has_errors = false;
713         // Reset the members
714         mCurrentOffset = 0;
715         mPositionsOffset = 0;
716         mPositionsIndexOffset = 0;
717         mUsePositions = true;
718         mNormalsOffset = 0;
719         mNormalsIndexOffset = 0;
720         mUseNormals = false;
721         mUseTangents = false;
722         mUseBinormals = false;
723         mTexCoordList.clear ();
724         mColorList.clear ();
725 
726 		// We need the maximum offset value of the input elements to calculate the
727 		// number of indices for each index list.
728 		mCurrentMaxOffset = (size_t)mMeshPrimitiveInputs.getInputArrayMaxOffset ();
729 
730 		// The offset values of the input elements.
731         has_errors |= initializePositionsOffset();
732         initializeNormalsOffset();
733         has_errors |= initializeColorsOffset();
734         has_errors |= initializeTexCoordsOffset();
735         initializeTangentsOffset();
736         initializeBinormalsOffset();
737         return has_errors;
738 	}
739 
740     //------------------------------
initializePositionsOffset()741     bool MeshLoader::initializePositionsOffset ()
742     {
743         bool has_errors = false;
744         const InputShared* positionInput = mMeshPrimitiveInputs.getPositionInput ();
745         COLLADABU_ASSERT ( positionInput != 0 );
746         if (positionInput == 0) {
747             has_errors |= handleFWLError(SaxFWLError::ERROR_DATA_NOT_VALID, "No positions, can't import!", IError::SEVERITY_CRITICAL);
748         }
749         else {
750             // Get the offset value, the initial index values and alloc the memory.
751             mPositionsOffset = positionInput->getOffset();
752         }
753 
754         COLLADABU::URI inputUrl = positionInput->getSource ();
755         String sourceId = inputUrl.getFragment ();
756         const SourceBase* sourceBase = getSourceById ( sourceId );
757         COLLADABU_ASSERT ( sourceBase != 0 );
758         if ( sourceBase == 0 )
759             has_errors |= handleFWLError(SaxFWLError::ERROR_DATA_NOT_VALID, "Positions sourceBase is null.", IError::SEVERITY_CRITICAL);
760         else {
761             // only stride 3 makes sense for normals
762             unsigned long long stride = sourceBase->getStride();
763             if (stride != 3)
764                 has_errors |= handleFWLError(SaxFWLError::ERROR_DATA_NOT_VALID, "Positios stride is not three.", IError::SEVERITY_CRITICAL);
765 
766             mPositionsIndexOffset = (unsigned int)sourceBase->getInitialIndex();
767         }
768         return has_errors;
769     }
770 
771     //------------------------------
initializeNormalsOffset()772     void MeshLoader::initializeNormalsOffset ()
773     {
774         // Check for using normals
775         const InputShared* normalInput = mMeshPrimitiveInputs.getNormalInput ();
776         if ( normalInput != 0 )
777         {
778             // Get the offset value, the initial index values and alloc the memory.
779             mNormalsOffset = normalInput->getOffset ();
780             const SourceBase* sourceBase = getSourceById ( normalInput->getSource ().getFragment () );
781             if ( !sourceBase )
782             {
783                 mNormalsIndexOffset = 0;
784                 mUseNormals = false;
785             }
786             else
787             {
788                 // only stride 3 makes sense for normals
789                 unsigned long long stride = sourceBase->getStride();
790                 if ( stride == 3 )
791                 {
792                     mNormalsIndexOffset = (unsigned int)(sourceBase->getInitialIndex() / stride);
793                     mUseNormals = true;
794                 }
795                 else
796                 {
797                     mNormalsIndexOffset = 0;
798                     mUseNormals = false;
799                 }
800             }
801         }
802         else
803         {
804             mNormalsIndexOffset = 0;
805             mUseNormals = false;
806         }
807     }
808 
809     //------------------------------
initializeTangentsOffset()810     void MeshLoader::initializeTangentsOffset ()
811     {
812         // Check for using normals
813         const InputShared* tangentInput = mMeshPrimitiveInputs.getTangentInput ();
814         if ( tangentInput != 0 )
815         {
816             // Get the offset value, the initial index values and alloc the memory.
817             mTangentsOffset = tangentInput->getOffset ();
818             const SourceBase* sourceBase = getSourceById ( tangentInput->getSource ().getFragment () );
819             if ( !sourceBase )
820             {
821                 mTangentsIndexOffset = 0;
822                 mUseTangents = false;
823             }
824             else
825             {
826                 // only stride 3 makes sense for normals
827                 unsigned long long stride = sourceBase->getStride();
828                 if ( stride == 3 )
829                 {
830                     mTangentsIndexOffset = (unsigned int)(sourceBase->getInitialIndex() / stride);
831                     mUseTangents = true;
832                 }
833                 else
834                 {
835                     mTangentsIndexOffset = 0;
836                     mUseTangents = false;
837                 }
838             }
839         }
840         else
841         {
842             mTangentsIndexOffset = 0;
843             mUseTangents = false;
844         }
845     }
846 
847 
848     //------------------------------
initializeBinormalsOffset()849     void MeshLoader::initializeBinormalsOffset ()
850     {
851         // Check for using normals
852         const InputShared* binormalInput = mMeshPrimitiveInputs.getBinormalInput ();
853         if ( binormalInput != 0 )
854         {
855             // Get the offset value, the initial index values and alloc the memory.
856             mBinormalsOffset = binormalInput->getOffset ();
857             const SourceBase* sourceBase = getSourceById ( binormalInput->getSource ().getFragment () );
858             if ( !sourceBase )
859             {
860                 mBinormalsIndexOffset = 0;
861                 mUseBinormals = false;
862             }
863             else
864             {
865                 // only stride 3 makes sense for normals
866                 unsigned long long stride = sourceBase->getStride();
867                 if ( stride == 3 )
868                 {
869                     mBinormalsIndexOffset = (unsigned int)(sourceBase->getInitialIndex() / stride);
870                     mUseBinormals = true;
871                 }
872                 else
873                 {
874                     mBinormalsIndexOffset = 0;
875                     mUseBinormals = false;
876                 }
877             }
878         }
879         else
880         {
881             mBinormalsIndexOffset = 0;
882             mUseBinormals = false;
883         }
884     }
885 
886     //------------------------------
initializeColorsOffset()887     bool MeshLoader::initializeColorsOffset ()
888     {
889         // Check for using colors
890         const InputSharedArray& inputArray = mMeshPrimitiveInputs.getInputArray ();
891         size_t numInputs = inputArray.getCount ();
892 
893         for ( size_t i=0; i<numInputs; ++i )
894         {
895             const InputShared* input = inputArray [i];
896             if ( input->getSemantic () == InputSemantic::COLOR )
897             {
898                 // TODO Id management!
899                 String sourceId = input->getSource ().getFragment ();
900                 SourceBase* sourceBase = getSourceById ( sourceId );
901                 if ( sourceBase == 0 )
902                 {
903                     return handleFWLError ( SaxFWLError::ERROR_DATA_NOT_VALID, "SourceBase of tex coords with semantic TEXCOORD not valid!" );
904                 }
905 
906                 // only stride 1, 2, 3 or 4 makes sense for uv coords
907                 size_t stride = ( size_t ) sourceBase->getStride();
908                 COLLADABU_ASSERT ( (stride >= 1) || (stride <= 4) );
909 
910                 size_t intitialIndex = sourceBase->getInitialIndex ();
911                 size_t indexOffset = intitialIndex / stride;
912 
913                 PrimitiveInput color;
914                 color.mOffset = ( size_t ) input->getOffset ();
915                 color.mInitialIndex = indexOffset;
916                 color.mStride = stride;
917                 color.mSetIndex = ( size_t ) input->getSet ();
918                 color.mName = sourceId;
919 
920                 mColorList.push_back ( color );
921             }
922         }
923 		return false;
924     }
925 
926     //------------------------------
initializeTexCoordsOffset()927     bool MeshLoader::initializeTexCoordsOffset ()
928     {
929         // Check for using tex coordinates
930         const InputSharedArray& inputArray = mMeshPrimitiveInputs.getInputArray ();
931         size_t numInputs = inputArray.getCount ();
932 
933         for ( size_t i=0; i<numInputs; ++i )
934         {
935             const InputShared* input = inputArray [i];
936             if ( input->getSemantic () == InputSemantic::TEXCOORD )
937             {
938                 // TODO Id management!
939                 String sourceId = input->getSource ().getFragment ();
940                 SourceBase* sourceBase = getSourceById ( sourceId );
941                 if ( sourceBase == 0 )
942                 {
943                     return handleFWLError ( SaxFWLError::ERROR_DATA_NOT_VALID, "SourceBase of tex coords with semantic TEXCOORD not valid!" );
944                 }
945 
946                 // only stride 1, 2, 3 or 4 makes sense for uv coords
947                 size_t stride = ( size_t ) sourceBase->getStride();
948                 COLLADABU_ASSERT ( (stride >= 1) || (stride <= 4) );
949 
950                 size_t intitialIndex = sourceBase->getInitialIndex ();
951                 size_t indexOffset = intitialIndex / stride;
952 
953                 PrimitiveInput texCoord;
954                 texCoord.mOffset = ( size_t ) input->getOffset ();
955                 texCoord.mInitialIndex = indexOffset;
956                 texCoord.mStride = stride;
957                 texCoord.mSetIndex = ( size_t ) input->getSet ();
958                 texCoord.mName = sourceId;
959 
960                 mTexCoordList.push_back ( texCoord );
961             }
962         }
963 		return false;
964     }
965 
966 
967 	//------------------------------
initCurrentValues()968 	void MeshLoader::initCurrentValues()
969 	{
970 		mCurrentVertexCount = 0;
971 		mCurrentLastPrimitiveVertexCount = 0;
972 		mCurrentExpectedVertexCount = 0;
973 		mCurrentMeshPrimitive = 0;
974 		mCurrentFaceOrLineCount = 0;
975 		mCurrentPhHasEmptyP = true;
976 		mPOrPhElementCountOfCurrentPrimitive = 0;
977 	}
978 
979 	//------------------------------
end__mesh()980 	bool MeshLoader::end__mesh()
981 	{
982         mInMesh = false;
983 
984 		// The mesh will be written by the GeometyLoader. Therefore nothing to with the mesh here
985 		finish();
986 		return true;
987 	}
988 
989 	//------------------------------
begin__source(const source__AttributeData & attributes)990 	bool MeshLoader::begin__source( const source__AttributeData& attributes )
991 	{
992 		return beginSource(attributes);
993 	}
994 
995 	//------------------------------
end__source()996 	bool MeshLoader::end__source(  )
997 	{
998 		return endSource();
999 	}
1000 
1001 	//------------------------------
begin__vertices(const vertices__AttributeData & attributeData)1002 	bool MeshLoader::begin__vertices( const vertices__AttributeData& attributeData )
1003 	{
1004         mInVertices = true;
1005 
1006 		if ( attributeData.id )
1007 			mVerticesInputs.setId( attributeData.id );
1008 		if ( attributeData.name )
1009 			mVerticesInputs.setName( attributeData.name );
1010 		return true;
1011 	}
1012 
1013 	//------------------------------
end__vertices()1014 	bool MeshLoader::end__vertices()
1015 	{
1016         mInVertices = false;
1017 
1018 		return true;
1019 	}
1020 
1021 	//------------------------------
begin__input____InputLocal(const input____InputLocal__AttributeData & attributeData)1022 	bool MeshLoader::begin__input____InputLocal( const input____InputLocal__AttributeData& attributeData )
1023 	{
1024 		mCurrentVertexInput = new InputUnshared(attributeData.semantic, attributeData.source);
1025 		return true;
1026 	}
1027 
1028 	//------------------------------
end__input____InputLocal()1029 	bool MeshLoader::end__input____InputLocal()
1030 	{
1031 		mVerticesInputs.getInputArray().append(mCurrentVertexInput);
1032 		mCurrentVertexInput = 0;
1033 		return true;
1034 	}
1035 
1036 	//------------------------------
begin__triangles(const triangles__AttributeData & attributeData)1037 	bool MeshLoader::begin__triangles( const triangles__AttributeData& attributeData )
1038 	{
1039 		mCurrentPrimitiveType = TRIANGLES;
1040 		mCurrentMeshPrimitive = new COLLADAFW::Triangles(createUniqueId(COLLADAFW::Triangles::ID()));
1041 		if ( (size_t)attributeData.count > 0)
1042 		{
1043 			mCurrentMeshPrimitive->getPositionIndices().reallocMemory((size_t)attributeData.count);
1044 			if ( mUseNormals )
1045 			{
1046 				mCurrentMeshPrimitive->getNormalIndices().reallocMemory((size_t)attributeData.count);
1047 			}
1048 
1049             if ( mUseTangents )
1050             {
1051                 mCurrentMeshPrimitive->getTangentIndices().reallocMemory((size_t)attributeData.count);
1052             }
1053 
1054             if ( mUseBinormals )
1055             {
1056                 mCurrentMeshPrimitive->getBinormalIndices().reallocMemory((size_t)attributeData.count);
1057             }
1058 
1059 			// TODO pre-alloc memory for uv indices
1060 		}
1061 		if ( attributeData.material )
1062 		{
1063 			mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId(attributeData.material));
1064 			mCurrentMeshPrimitive->setMaterial(attributeData.material);
1065 		}
1066 		return true;
1067 	}
1068 
1069 	//------------------------------
end__triangles()1070 	bool MeshLoader::end__triangles()
1071 	{
1072 		size_t trianglesCount = mCurrentVertexCount/3;
1073 		// check if the triangles really contains triangles. If not, we will discard it
1074 		if ( trianglesCount > 0 )
1075 		{
1076 			mCurrentMeshPrimitive->setFaceCount(trianglesCount);
1077 			mMesh->appendPrimitive(mCurrentMeshPrimitive);
1078 		}
1079 		else
1080 		{
1081 			delete mCurrentMeshPrimitive;
1082 		}
1083 		initCurrentValues();
1084 		mMeshPrimitiveInputs.clearInputs();
1085 		mCurrentPrimitiveType = NONE;
1086 		return true;
1087 	}
1088 
1089 
1090 	//------------------------------
begin__input____InputLocalOffset(const input____InputLocalOffset__AttributeData & attributeData)1091 	bool MeshLoader::begin__input____InputLocalOffset( const input____InputLocalOffset__AttributeData& attributeData )
1092 	{
1093 		return beginInput(attributeData);
1094 	}
1095 
1096 	//------------------------------
end__input____InputLocalOffset()1097 	bool MeshLoader::end__input____InputLocalOffset()
1098 	{
1099 		return true;
1100 	}
1101 
1102 	//------------------------------
beginInput(const input____InputLocalOffset__AttributeData & attributeData)1103 	bool MeshLoader::beginInput( const input____InputLocalOffset__AttributeData& attributeData )
1104 	{
1105 		bool setPresent = (attributeData.present_attributes & input____InputLocalOffset__AttributeData::ATTRIBUTE_SET_PRESENT) == input____InputLocalOffset__AttributeData::ATTRIBUTE_SET_PRESENT;
1106 		mMeshPrimitiveInputs.appendInputElement(new InputShared(attributeData.semantic,
1107 			attributeData.source,
1108 			attributeData.offset,
1109 			setPresent ? attributeData.set : 0));
1110 		return true;
1111 	}
1112 
1113 	//------------------------------
begin__polylist(const polylist__AttributeData & attributeData)1114 	bool MeshLoader::begin__polylist( const polylist__AttributeData& attributeData )
1115 	{
1116 		mCurrentPrimitiveType = POLYLIST;
1117         COLLADAFW::Polylist* polylist = new COLLADAFW::Polylist(createUniqueId(COLLADAFW::Polylist::ID()));
1118 		polylist->getGroupedVerticesVertexCountArray().allocMemory((size_t)attributeData.count);
1119 		mCurrentMeshPrimitive = polylist;
1120 		if ( attributeData.material )
1121 		{
1122 			mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId( attributeData.material ));
1123 			mCurrentMeshPrimitive->setMaterial(attributeData.material);
1124 
1125 		}
1126 		return true;
1127 	}
1128 
1129 	//------------------------------
end__polylist()1130 	bool MeshLoader::end__polylist()
1131 	{
1132 		// check if there are enough vertices as expected by the vcount and that there exist at least
1133 		// one polygon. If not, we will discard it
1134 		if ( mCurrentVertexCount >= mCurrentExpectedVertexCount && mCurrentVertexCount > 0 )
1135 		{
1136 			COLLADAFW::Polylist* polylist = (COLLADAFW::Polylist*) mCurrentMeshPrimitive;
1137 			COLLADAFW::Polylist::VertexCountArray& vertexCountArray = polylist->getGroupedVerticesVertexCountArray();
1138 
1139 			mCurrentMeshPrimitive->setFaceCount(vertexCountArray.getCount());
1140 			mMesh->appendPrimitive(mCurrentMeshPrimitive);
1141 		}
1142 		else
1143 		{
1144 			delete mCurrentMeshPrimitive;
1145 		}
1146 		initCurrentValues();
1147 		mMeshPrimitiveInputs.clearInputs();
1148 		mCurrentPrimitiveType = NONE;
1149 		return true;
1150 	}
1151 
1152 	//------------------------------
begin__lines(const lines__AttributeData & attributeData)1153 	bool MeshLoader::begin__lines( const lines__AttributeData& attributeData )
1154 	{
1155         mCurrentPrimitiveType = LINES;
1156         if ( attributeData.material )
1157             mCurrentMeshMaterial = attributeData.material;
1158         mCurrentCOLLADAPrimitiveCount = (size_t)attributeData.count;
1159         return true;
1160 	}
1161 
1162 	//------------------------------
end__lines()1163 	bool MeshLoader::end__lines()
1164 	{
1165         mMeshPrimitiveInputs.clearInputs();
1166         mCurrentPrimitiveType = NONE;
1167         return true;
1168 // 		initCurrentValues();
1169 // 		return true;
1170 	}
1171 
1172 	//------------------------------
begin__linestrips(const linestrips__AttributeData & attributeData)1173 	bool MeshLoader::begin__linestrips( const linestrips__AttributeData& attributeData )
1174 	{
1175 		COLLADAFW::Linestrips* lineStrips = new COLLADAFW::Linestrips(createUniqueId(COLLADAFW::Linestrips::ID()));
1176 		// The actual size might be bigger, but its a lower bound
1177 		lineStrips->getGroupedVerticesVertexCountArray().allocMemory((size_t)attributeData.count);
1178 		mCurrentMeshPrimitive = lineStrips;
1179 		mCurrentPrimitiveType = LINESTRIPS;
1180 		if ( attributeData.material )
1181 		{
1182 			mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId( attributeData.material ));
1183 			mCurrentMeshPrimitive->setMaterial(attributeData.material);
1184 		}
1185 		return true;
1186 	}
1187 
1188 	//------------------------------
end__linestrips()1189 	bool MeshLoader::end__linestrips()
1190 	{
1191 		mCurrentPrimitiveType = LINESTRIPS;
1192 		// check if there is at least one linestrip. If not, we will discard it.
1193 		if ( mCurrentFaceOrLineCount > 0 )
1194 		{
1195 			mCurrentMeshPrimitive->setFaceCount(mCurrentFaceOrLineCount);
1196 			mMesh->appendPrimitive(mCurrentMeshPrimitive);
1197 		}
1198 		else
1199 		{
1200 			delete mCurrentMeshPrimitive;
1201 		}
1202 		initCurrentValues();
1203 		mMeshPrimitiveInputs.clearInputs();
1204 		mCurrentPrimitiveType = NONE;
1205 		return true;
1206 	}
1207 
1208 	//------------------------------
begin__vcount()1209 	bool MeshLoader::begin__vcount()
1210 	{
1211 //		initializeOffsets();
1212 		return true;
1213 	}
1214 
1215 	//------------------------------
end__vcount()1216 	bool MeshLoader::end__vcount()
1217 	{
1218 		return true;
1219 	}
1220 
1221 	//------------------------------
data__vcount(const unsigned long long * data,size_t length)1222 	bool MeshLoader::data__vcount( const unsigned long long* data, size_t length )
1223 	{
1224 		COLLADAFW::Polygons* polygons = (COLLADAFW::Polygons*) mCurrentMeshPrimitive;
1225 		COLLADAFW::Polygons::VertexCountArray& vertexCountArray = polygons->getGroupedVerticesVertexCountArray();
1226 		size_t count = vertexCountArray.getCount();
1227 		vertexCountArray.reallocMemory( count + length);
1228 		for ( size_t i = 0; i < length; ++i)
1229 		{
1230 			unsigned long long vcount = data[i];
1231 			vertexCountArray.append((unsigned int)vcount);
1232 			mCurrentExpectedVertexCount += (size_t)vcount;
1233 		}
1234 		return true;
1235 	}
1236 
1237 	//------------------------------
begin__polygons(const polygons__AttributeData & attributeData)1238 	bool MeshLoader::begin__polygons( const polygons__AttributeData& attributeData )
1239 	{
1240 		mCurrentPrimitiveType = POLYGONS;
1241 		COLLADAFW::Polygons* polygons = new COLLADAFW::Polygons(createUniqueId(COLLADAFW::Polygons::ID()));
1242 		// The actual size might be bigger, but its a lower bound
1243 		polygons->getGroupedVerticesVertexCountArray().allocMemory((size_t)attributeData.count);
1244 		mCurrentMeshPrimitive = polygons;
1245 		if ( attributeData.material )
1246 		{
1247 			mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId( attributeData.material ));
1248 			mCurrentMeshPrimitive->setMaterial(attributeData.material);
1249 		}
1250 		return true;
1251 	}
1252 
1253 	//------------------------------
end__polygons()1254 	bool MeshLoader::end__polygons()
1255 	{
1256 		// check if there is at least one polygon. If not, we will discard it.
1257 		if ( mCurrentFaceOrLineCount > 0 )
1258 		{
1259 			mCurrentMeshPrimitive->setFaceCount(mCurrentFaceOrLineCount);
1260 			mMesh->appendPrimitive(mCurrentMeshPrimitive);
1261 		}
1262 		else
1263 		{
1264 			delete mCurrentMeshPrimitive;
1265 		}
1266 		initCurrentValues();
1267 		mMeshPrimitiveInputs.clearInputs();
1268 		mCurrentPrimitiveType = NONE;
1269 		return true;
1270 	}
1271 
1272 	//------------------------------
begin__ph()1273 	bool MeshLoader::begin__ph()
1274 	{
1275 		mCurrentPhHasEmptyP = true;
1276 		mCurrentPrimitiveType = POLYGONS_HOLE;
1277 		return true;
1278 	}
1279 
1280 	//------------------------------
end__ph()1281 	bool MeshLoader::end__ph()
1282 	{
1283 		mCurrentPrimitiveType = POLYGONS;
1284 		mPOrPhElementCountOfCurrentPrimitive++;
1285 		return true;
1286 	}
1287 
1288 	//------------------------------
begin__h()1289 	bool MeshLoader::begin__h()
1290 	{
1291 		return true;
1292 	}
1293 
1294 	//------------------------------
end__h()1295 	bool MeshLoader::end__h()
1296 	{
1297 		int currentFaceVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount;
1298 		if ( currentFaceVertexCount > 0 )
1299 		{
1300 			COLLADAFW::Polygons* polygons = (COLLADAFW::Polygons*) mCurrentMeshPrimitive;
1301 			COLLADAFW::Polygons::VertexCountArray& vertexCountArray = polygons->getGroupedVerticesVertexCountArray();
1302 			vertexCountArray.append(-currentFaceVertexCount);
1303 			mCurrentLastPrimitiveVertexCount = mCurrentVertexCount;
1304 		}
1305 		return true;
1306 	}
1307 
1308 	//------------------------------
data__h(const uint64 * data,size_t length)1309 	bool MeshLoader::data__h( const uint64* data, size_t length )
1310 	{
1311 		// If the p element of the parent ph is empty, we don't need to read the h element
1312 		if ( mCurrentPhHasEmptyP )
1313 			return true;
1314 		return writePrimitiveIndices(data, length);
1315 	}
1316 
1317 	//------------------------------
begin__tristrips(const tristrips__AttributeData & attributeData)1318 	bool MeshLoader::begin__tristrips( const tristrips__AttributeData& attributeData )
1319 	{
1320 		COLLADAFW::Tristrips* tristrips = new COLLADAFW::Tristrips(createUniqueId(COLLADAFW::Tristrips::ID()));
1321 		// The actual size might be bigger, but its a lower bound
1322 		tristrips->getGroupedVerticesVertexCountArray().allocMemory((size_t)attributeData.count);
1323 		mCurrentMeshPrimitive = tristrips;
1324 		mCurrentPrimitiveType = TRISTRIPS;
1325 		if ( attributeData.material )
1326 		{
1327 			mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId( attributeData.material ));
1328 			mCurrentMeshPrimitive->setMaterial(attributeData.material);
1329 		}
1330 		return true;
1331 	}
1332 
1333 	//------------------------------
end__tristrips()1334 	bool MeshLoader::end__tristrips()
1335 	{
1336 		mCurrentPrimitiveType = TRISTRIPS;
1337 		// check if there is at least one tristrip. If not, we will discard it.
1338 		if ( mCurrentFaceOrLineCount > 0 )
1339 		{
1340 			mCurrentMeshPrimitive->setFaceCount(mCurrentFaceOrLineCount);
1341 			mMesh->appendPrimitive(mCurrentMeshPrimitive);
1342 		}
1343 		else
1344 		{
1345 			delete mCurrentMeshPrimitive;
1346 		}
1347 		initCurrentValues();
1348 		mMeshPrimitiveInputs.clearInputs();
1349 		mCurrentPrimitiveType = NONE;
1350 		return true;
1351 	}
1352 
1353 	//------------------------------
begin__trifans(const trifans__AttributeData & attributeData)1354 	bool MeshLoader::begin__trifans( const trifans__AttributeData& attributeData )
1355 	{
1356 		mCurrentPrimitiveType = TRIFANS;
1357 		COLLADAFW::Trifans* trifans = new COLLADAFW::Trifans(createUniqueId(COLLADAFW::Trifans::ID()));
1358 		// The actual size might be bigger, but its a lower bound
1359 		trifans->getGroupedVerticesVertexCountArray().allocMemory((size_t)attributeData.count);
1360 		mCurrentMeshPrimitive = trifans;
1361 		if ( attributeData.material )
1362 		{
1363 			mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId( attributeData.material ));
1364 			mCurrentMeshPrimitive->setMaterial(attributeData.material);
1365 		}
1366 		return true;
1367 	}
1368 
1369 	//------------------------------
end__trifans()1370 	bool MeshLoader::end__trifans()
1371 	{
1372 		// check if there is at least one trifan. If not, we will discard it.
1373 		if ( mCurrentFaceOrLineCount > 0 )
1374 		{
1375 			mCurrentMeshPrimitive->setFaceCount(mCurrentFaceOrLineCount);
1376 			mMesh->appendPrimitive(mCurrentMeshPrimitive);
1377 		}
1378 		else
1379 		{
1380 			delete mCurrentMeshPrimitive;
1381 		}
1382 		initCurrentValues();
1383 		mMeshPrimitiveInputs.clearInputs();
1384 		mCurrentPrimitiveType = NONE;
1385 		return true;
1386 	}
1387 
1388 	//------------------------------
begin__p()1389 	bool MeshLoader::begin__p()
1390 	{
1391 		switch ( mCurrentPrimitiveType )
1392 		{
1393 		case TRIANGLES:
1394 			{
1395 				loadSourceElements(mMeshPrimitiveInputs);
1396 				if (initializeOffsets())
1397 					return false; // abort
1398 			}
1399 			break;
1400         case LINES:
1401             {
1402                 loadSourceElements(mMeshPrimitiveInputs);
1403 				if (initializeOffsets())
1404 					return false; // abort
1405                 mCurrentMeshPrimitive = new COLLADAFW::Lines(createUniqueId(COLLADAFW::Lines::ID()));
1406                 if ( mCurrentCOLLADAPrimitiveCount > 0)
1407                 {
1408                     mCurrentMeshPrimitive->getPositionIndices().reallocMemory(mCurrentCOLLADAPrimitiveCount);
1409                     if ( mUseNormals )
1410                     {
1411                         mCurrentMeshPrimitive->getNormalIndices().reallocMemory(mCurrentCOLLADAPrimitiveCount);
1412                     }
1413                     // TODO pre-alloc memory for uv indices
1414                 }
1415                 mCurrentMeshPrimitive->setMaterialId(mMaterialIdInfo.getMaterialId(mCurrentMeshMaterial));
1416 				mCurrentMeshPrimitive->setMaterial(mCurrentMeshMaterial);
1417             }
1418             break;
1419 		case TRIFANS:
1420 			{
1421 				if ( mPOrPhElementCountOfCurrentPrimitive == 0)
1422 				{
1423 					loadSourceElements(mMeshPrimitiveInputs);
1424 					if (initializeOffsets())
1425 						return false; // abort
1426 				}
1427 				int currentTrifanVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount;
1428 				if ( currentTrifanVertexCount > 0 )
1429 				{
1430 					COLLADAFW::Trifans* trifans = (COLLADAFW::Trifans*) mCurrentMeshPrimitive;
1431 					if ( currentTrifanVertexCount >= 3 )
1432 					{
1433 						COLLADAFW::Trifans::VertexCountArray& vertexCountArray = trifans->getGroupedVerticesVertexCountArray();
1434 						vertexCountArray.append(currentTrifanVertexCount);
1435 						trifans->setTrifanCount(trifans->getTrifanCount() + 1);
1436 						mCurrentFaceOrLineCount += (currentTrifanVertexCount - 2);
1437 					}
1438 					else
1439 					{
1440 						trifans->getPositionIndices().erase(currentTrifanVertexCount);
1441 						trifans->getNormalIndices().erase(currentTrifanVertexCount);
1442 
1443 						const COLLADAFW::IndexListArray& colorIndicesArray = trifans->getColorIndicesArray ();
1444 						for ( size_t i=0; i<colorIndicesArray.getCount (); ++i )
1445 							trifans->getColorIndices(i)->getIndices ().erase(currentTrifanVertexCount);
1446 
1447 						const COLLADAFW::IndexListArray& uvCoordIndicesArray = trifans->getUVCoordIndicesArray ();
1448 						for ( size_t i=0; i<uvCoordIndicesArray.getCount (); ++i )
1449 							trifans->getUVCoordIndices(i)->getIndices ().erase(currentTrifanVertexCount);
1450 					}
1451 					mCurrentLastPrimitiveVertexCount = mCurrentVertexCount;
1452 				}
1453 			}
1454 			break;
1455 		case TRISTRIPS:
1456 		case POLYLIST:
1457 		case POLYGONS:
1458         case POLYGONS_HOLE:
1459 		case LINESTRIPS:
1460 			{
1461 				if ( mPOrPhElementCountOfCurrentPrimitive == 0)
1462 				{
1463 					loadSourceElements(mMeshPrimitiveInputs);
1464 					if (initializeOffsets())
1465 						return false; // abort
1466 				}
1467 			}
1468 			break;
1469         case NONE:
1470             return false;
1471 		}
1472 		return true;
1473 	}
1474 
1475 	//------------------------------
end__p()1476 	bool MeshLoader::end__p()
1477 	{
1478 		mPOrPhElementCountOfCurrentPrimitive++;
1479 		switch ( mCurrentPrimitiveType )
1480 		{
1481 		case TRIANGLES:
1482 			{
1483 
1484 			}
1485 			break;
1486         case LINES:
1487             {
1488                 size_t linesCount = mCurrentVertexCount/2;
1489                 // check if the lines really contains lines. If not, we will discard it
1490                 if ( linesCount > 0 )
1491                 {
1492                     mCurrentMeshPrimitive->setFaceCount(linesCount);
1493                     mMesh->appendPrimitive(mCurrentMeshPrimitive);
1494                 }
1495                 else
1496                 {
1497                     delete mCurrentMeshPrimitive;
1498                 }
1499                 initCurrentValues();
1500             }
1501             break;
1502         case TRIFANS:
1503 			{
1504 				int currentTrifanVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount;
1505 				if ( currentTrifanVertexCount > 0 )
1506 				{
1507 					COLLADAFW::Trifans* trifans = (COLLADAFW::Trifans*) mCurrentMeshPrimitive;
1508 					if ( currentTrifanVertexCount >= 3 )
1509 					{
1510 						COLLADAFW::Trifans::VertexCountArray& vertexCountArray = trifans->getGroupedVerticesVertexCountArray();
1511 						vertexCountArray.append(currentTrifanVertexCount);
1512 						trifans->setTrifanCount(trifans->getTrifanCount() + 1);
1513 						mCurrentFaceOrLineCount += (currentTrifanVertexCount - 2);
1514 					}
1515 					else
1516 					{
1517 						trifans->getPositionIndices().erase(currentTrifanVertexCount);
1518 						trifans->getNormalIndices().erase(currentTrifanVertexCount);
1519 
1520 						const COLLADAFW::IndexListArray& colorIndicesArray = trifans->getColorIndicesArray ();
1521 						for ( size_t i=0; i<colorIndicesArray.getCount (); ++i )
1522 							trifans->getColorIndices(i)->getIndices ().erase(currentTrifanVertexCount);
1523 
1524 						const COLLADAFW::IndexListArray& uvCoordIndicesArray = trifans->getUVCoordIndicesArray ();
1525 						for ( size_t i=0; i<uvCoordIndicesArray.getCount (); ++i )
1526 							trifans->getUVCoordIndices(i)->getIndices ().erase(currentTrifanVertexCount);
1527 					}
1528 					mCurrentLastPrimitiveVertexCount = mCurrentVertexCount;
1529 				}
1530 			}
1531 			break;
1532 		case TRISTRIPS:
1533 			{
1534 				int currentTristripVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount;
1535 				if ( currentTristripVertexCount > 0 )
1536 				{
1537 					COLLADAFW::Tristrips* tristrips = (COLLADAFW::Tristrips*) mCurrentMeshPrimitive;
1538 					if ( currentTristripVertexCount >= 3 )
1539 					{
1540 						COLLADAFW::Tristrips::VertexCountArray& vertexCountArray = tristrips->getGroupedVerticesVertexCountArray();
1541 						vertexCountArray.append(currentTristripVertexCount);
1542 						tristrips->setTristripCount(tristrips->getTristripCount() + 1);
1543 						mCurrentFaceOrLineCount += (currentTristripVertexCount - 2);
1544 					}
1545 					else
1546 					{
1547 						tristrips->getPositionIndices().erase(currentTristripVertexCount);
1548 						tristrips->getNormalIndices().erase(currentTristripVertexCount);
1549 
1550 						const COLLADAFW::IndexListArray& colorIndicesArray = tristrips->getColorIndicesArray ();
1551 						for ( size_t i=0; i<colorIndicesArray.getCount (); ++i )
1552 							tristrips->getColorIndices(i)->getIndices().erase(currentTristripVertexCount);
1553 
1554 						const COLLADAFW::IndexListArray& uvCoordIndicesArray = tristrips->getUVCoordIndicesArray ();
1555 						for ( size_t i=0; i<uvCoordIndicesArray.getCount (); ++i )
1556 							tristrips->getUVCoordIndices(i)->getIndices ().erase(currentTristripVertexCount);
1557 					}
1558 					mCurrentLastPrimitiveVertexCount = mCurrentVertexCount;
1559 				}
1560 			}
1561 			break;
1562 		case LINESTRIPS:
1563 			{
1564 				int currentLinestripVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount;
1565 				if ( currentLinestripVertexCount > 0 )
1566 				{
1567 					COLLADAFW::Linestrips* linestrips = (COLLADAFW::Linestrips*) mCurrentMeshPrimitive;
1568 					if ( currentLinestripVertexCount >= 2 )
1569 					{
1570 						COLLADAFW::Tristrips::VertexCountArray& vertexCountArray = linestrips->getGroupedVerticesVertexCountArray();
1571 						vertexCountArray.append(currentLinestripVertexCount);
1572 						linestrips->setLinestripCount(linestrips->getLinestripCount() + 1);
1573 						mCurrentFaceOrLineCount += (currentLinestripVertexCount - 1);
1574 					}
1575 					else
1576 					{
1577 						linestrips->getPositionIndices().erase(currentLinestripVertexCount);
1578 						linestrips->getNormalIndices().erase(currentLinestripVertexCount);
1579 
1580 						const COLLADAFW::IndexListArray& colorIndicesArray = linestrips->getColorIndicesArray ();
1581 						for ( size_t i=0; i<colorIndicesArray.getCount (); ++i )
1582 							linestrips->getColorIndices(i)->getIndices().erase(currentLinestripVertexCount);
1583 
1584 						const COLLADAFW::IndexListArray& uvCoordIndicesArray = linestrips->getUVCoordIndicesArray ();
1585 						for ( size_t i=0; i<uvCoordIndicesArray.getCount (); ++i )
1586 							linestrips->getUVCoordIndices(i)->getIndices ().erase(currentLinestripVertexCount);
1587 					}
1588 					mCurrentLastPrimitiveVertexCount = mCurrentVertexCount;
1589 				}
1590 			}
1591 			break;
1592 		case POLYLIST:
1593 			{
1594 
1595 			}
1596 			break;
1597 		case POLYGONS:
1598 			{
1599 				int currentFaceVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount;
1600 				if ( currentFaceVertexCount > 0 )
1601 				{
1602 					COLLADAFW::Polygons* polygons = (COLLADAFW::Polygons*) mCurrentMeshPrimitive;
1603 					COLLADAFW::Polygons::VertexCountArray& vertexCountArray = polygons->getGroupedVerticesVertexCountArray();
1604 					vertexCountArray.append(currentFaceVertexCount);
1605 					mCurrentLastPrimitiveVertexCount = mCurrentVertexCount;
1606 					mCurrentFaceOrLineCount++;
1607 				}
1608 			}
1609 			break;
1610 		case POLYGONS_HOLE:
1611 			{
1612 				int currentPolygonVertexCount = (int)mCurrentVertexCount - (int)mCurrentLastPrimitiveVertexCount;
1613 				if ( currentPolygonVertexCount > 0 )
1614 				{
1615 					COLLADAFW::Polygons* polygons = (COLLADAFW::Polygons*) mCurrentMeshPrimitive;
1616 					COLLADAFW::Polygons::VertexCountArray& vertexCountArray = polygons->getGroupedVerticesVertexCountArray();
1617 					vertexCountArray.append(currentPolygonVertexCount);
1618 					mCurrentLastPrimitiveVertexCount = mCurrentVertexCount;
1619 					mCurrentFaceOrLineCount++;
1620 					mCurrentPhHasEmptyP = false;
1621 				}
1622 				else
1623 				{
1624 					mCurrentPhHasEmptyP = true;
1625 				}
1626 			}
1627 			break;
1628         case NONE:
1629             return false;
1630 		}
1631 		return true;
1632 	}
1633 
1634 	//------------------------------
data__p(const unsigned long long * data,size_t length)1635 	bool MeshLoader::data__p( const unsigned long long* data, size_t length )
1636 	{
1637 		return writePrimitiveIndices(data, length);
1638 	}
1639 
1640 
1641 } // namespace COLLADASaxFWL
1642