1 /*
2 Copyright (c) 2008-2009 NetAllied Systems GmbH
3 
4 This file is part of COLLADAMax.
5 
6 Portions of the code are:
7 Copyright (c) 2005-2007 Feeling Software Inc.
8 Copyright (c) 2005-2007 Sony Computer Entertainment America
9 
10 Based on the 3dsMax COLLADASW Tools:
11 Copyright (c) 2005-2006 Autodesk Media Entertainment
12 
13 Licensed under the MIT Open Source License,
14 for details please see LICENSE file or the website
15 http://www.opensource.org/licenses/mit-license.php
16 */
17 
18 #include "COLLADAMaxStableHeaders.h"
19 #include "COLLADAMaxGeometryImporter.h"
20 
21 #include "COLLADAFWTypes.h"
22 #include "COLLADAFWGeometry.h"
23 #include "COLLADAFWMesh.h"
24 #include "COLLADAFWTriangles.h"
25 #include "COLLADAFWTristrips.h"
26 #include "COLLADAFWTrifans.h"
27 #include "COLLADAFWPolygons.h"
28 #include "COLLADAFWPolylist.h"
29 #include "COLLADAFWUniqueId.h"
30 
31 
32 namespace COLLADAMax
33 {
34 
35 
isSupportedMeshPrimitive(const COLLADAFW::MeshPrimitive * meshPrimitive)36 	bool isSupportedMeshPrimitive(const COLLADAFW::MeshPrimitive* meshPrimitive)
37 	{
38 		COLLADAFW::MeshPrimitive::PrimitiveType type = meshPrimitive->getPrimitiveType();
39 		return    (type == COLLADAFW::MeshPrimitive::TRIANGLES)
40 			|| (type == COLLADAFW::MeshPrimitive::TRIANGLE_FANS)
41 			|| (type == COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS)
42 			|| (type == COLLADAFW::MeshPrimitive::POLYGONS)
43 			|| (type == COLLADAFW::MeshPrimitive::POLYLIST);
44 	}
45 
GeometryImporter(DocumentImporter * documentImporter,const COLLADAFW::Geometry * geometry)46 	GeometryImporter::GeometryImporter( DocumentImporter* documentImporter, const COLLADAFW::Geometry* geometry )
47 		:	ImporterBase(documentImporter)
48 		, mGeometry(geometry)
49 		, mTotalTrianglesCount(0)
50 		, mLargestMapChannel(0)
51 		, mHasVertexColor(false)
52 	{
53 
54 	}
55 
56     //------------------------------
~GeometryImporter()57 	GeometryImporter::~GeometryImporter()
58 	{
59 	}
60 
61 	//------------------------------
import()62 	bool GeometryImporter::import()
63 	{
64 		if ( mGeometry->getType() == COLLADAFW::Geometry::GEO_TYPE_MESH )
65 		{
66 			importMesh();
67 		}
68 		return true;
69 	}
70 
71 	//------------------------------
importMesh()72 	bool GeometryImporter::importMesh( )
73 	{
74 		COLLADAFW::Mesh* mesh = (COLLADAFW::Mesh*) mGeometry;
75 
76 		bool success = true;
77 		mTotalTrianglesCount = mesh->getTrianglesTriangleCount() + mesh->getTristripsTriangleCount() + mesh->getTrifansTriangleCount();
78 
79 		if ( mesh->getPolygonsPolygonCount() > 0 || mesh->getPolylistPolygonCount() > 0 )
80 		{
81 			success = importPolygonMesh();
82 		}
83 		else if ( mTotalTrianglesCount > 0 )
84 		{
85 			success = importTriangleMesh();
86 		}
87 
88 		if ( mHasVertexColor && success)
89 		{
90 			addVertexColorObjects( mGeometry->getUniqueId() );
91 		}
92 
93 
94 		return success;
95 	}
96 
97 	//------------------------------
importTriangleMesh()98 	bool GeometryImporter::importTriangleMesh( )
99 	{
100 
101 		COLLADAFW::Mesh* mesh = (COLLADAFW::Mesh*) mGeometry;
102 
103 		TriObject* triangleObject = CreateNewTriObject();
104 
105 		Mesh& triangleMesh = triangleObject->GetMesh();
106 
107 
108 		if ( !importTriangleMeshPositions(triangleObject) )
109 			return false;
110 
111 		if ( !importTriangleMeshNormals(triangleObject) )
112 			return false;
113 
114 		if ( !importTriangleMeshUVCoords(triangleObject) )
115 			return false;
116 
117 		triangleMesh.InvalidateGeomCache();
118 		triangleMesh.InvalidateTopologyCache();
119 
120 		handleObjectReferences(mesh, triangleObject);
121 
122 		return true;
123 	}
124 
125 
126 	//------------------------------
importTriangleMeshPositions(TriObject * triangleObject)127 	bool GeometryImporter::importTriangleMeshPositions( TriObject* triangleObject )
128 	{
129 		COLLADAFW::Mesh* mesh = (COLLADAFW::Mesh*) mGeometry;
130 
131 		Mesh& triangleMesh = triangleObject->GetMesh();
132 
133 		const COLLADAFW::MeshVertexData& meshPositions = mesh->getPositions();
134 
135 		int positionsCount = (int)meshPositions.getValuesCount() / 3;
136 
137 		triangleMesh.setNumVerts(positionsCount);
138 
139 		if ( meshPositions.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE )
140 		{
141 			const COLLADAFW::DoubleArray* positionsArray = meshPositions.getDoubleValues();
142 			for ( int i = 0; i < positionsCount; ++i)
143 			{
144 				triangleMesh.setVert(i, convertSpaceUnit((float)(*positionsArray)[3*i]),
145 					                    convertSpaceUnit((float)(*positionsArray)[3*i + 1]),
146 										convertSpaceUnit((float)(*positionsArray)[3*i + 2]));
147 			}
148 		}
149 		else
150 		{
151 			const COLLADAFW::FloatArray* positionsArray = meshPositions.getFloatValues();
152 			for ( int i = 0; i < positionsCount; ++i)
153 			{
154 				triangleMesh.setVert(i, convertSpaceUnit((*positionsArray)[3*i]),
155 					                    convertSpaceUnit((*positionsArray)[3*i + 1]),
156 										convertSpaceUnit((*positionsArray)[3*i + 2]));
157 			}
158 		}
159 
160 		triangleMesh.setNumFaces((int)mTotalTrianglesCount);
161 		COLLADAFW::MeshPrimitiveArray& meshPrimitiveArray =  mesh->getMeshPrimitives();
162 		size_t faceIndex = 0;
163 		DocumentImporter::FWMaterialIdMaxMtlIdMap& fWMaterialIdMaxMtlIdMap = getMaterialIdMapByGeometryUniqueId(mGeometry->getUniqueId());
164 		createFWMaterialIdMaxMtlIdMap( meshPrimitiveArray, fWMaterialIdMaxMtlIdMap);
165 		for ( size_t i = 0, count = meshPrimitiveArray.getCount(); i < count; ++i)
166 		{
167 			const COLLADAFW::MeshPrimitive* meshPrimitive = meshPrimitiveArray[i];
168 			if ( ! meshPrimitive )
169 				continue;
170 			// We use the frame work material id as max material id
171 			MtlID maxMaterialId = (MtlID)meshPrimitive->getMaterialId();
172 			switch (meshPrimitive->getPrimitiveType())
173 			{
174 			case COLLADAFW::MeshPrimitive::TRIANGLES:
175 				{
176 					const COLLADAFW::Triangles* triangles = (const COLLADAFW::Triangles*) meshPrimitive;
177 					const COLLADAFW::UIntValuesArray& positionIndices =  triangles->getPositionIndices();
178 					for ( size_t j = 0, count = positionIndices.getCount() ; j < count; j+=3 )
179 					{
180 						Face& face = triangleMesh.faces[faceIndex];
181 //						face.setMatID(fWMaterialIdMaxMtlIdMap[meshPrimitive->getMaterialId()]);
182 						if ( maxMaterialId != 0 )
183 							face.setMatID(maxMaterialId);
184 						face.setEdgeVisFlags(1, 1, 1);
185 						face.setVerts(positionIndices[j], positionIndices[j + 1], positionIndices[j + 2]);
186 						++faceIndex;
187 					}
188 					break;
189 				}
190 			case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
191 				{
192 					const COLLADAFW::Tristrips* tristrips = (const COLLADAFW::Tristrips*) meshPrimitive;
193 					const COLLADAFW::UIntValuesArray& positionIndices =  tristrips->getPositionIndices();
194 					const COLLADAFW::UIntValuesArray& faceVertexCountArray = tristrips->getGroupedVerticesVertexCountArray();
195 					size_t nextTristripStartIndex = 0;
196 					for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
197 					{
198 						unsigned int faceVertexCount = faceVertexCountArray[k];
199 						bool switchOrientation = false;
200 						for ( size_t j = nextTristripStartIndex + 2, lastVertex = nextTristripStartIndex +  faceVertexCount; j < lastVertex; ++j )
201 						{
202 							Face& face = triangleMesh.faces[faceIndex];
203 //   						face.setMatID(fWMaterialIdMaxMtlIdMap[meshPrimitive->getMaterialId()]);
204 							face.setEdgeVisFlags(1, 1, 1);
205 							if ( maxMaterialId != 0 )
206 								face.setMatID(maxMaterialId);
207 							if ( switchOrientation )
208 							{
209 								face.setVerts(positionIndices[j - 1], positionIndices[j - 2], positionIndices[j]);
210 								switchOrientation = false;
211 							}
212 							else
213 							{
214 								face.setVerts(positionIndices[j - 2], positionIndices[j - 1], positionIndices[j]);
215 								switchOrientation = true;
216 							}
217 							++faceIndex;
218 						}
219 						nextTristripStartIndex += faceVertexCount;
220 					}
221 					break;
222 				}
223 			case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
224 				{
225 					const COLLADAFW::Trifans* trifans = (const COLLADAFW::Trifans*) meshPrimitive;
226 					const COLLADAFW::UIntValuesArray& positionIndices =  trifans->getPositionIndices();
227 					const COLLADAFW::UIntValuesArray& faceVertexCountArray = trifans->getGroupedVerticesVertexCountArray();
228 					size_t nextTrifanStartIndex = 0;
229 					for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
230 					{
231 						unsigned int faceVertexCount = faceVertexCountArray[k];
232 						unsigned int commonVertexIndex = positionIndices[nextTrifanStartIndex];
233 						for ( size_t j = nextTrifanStartIndex + 2, lastVertex = nextTrifanStartIndex +  faceVertexCount; j < lastVertex; ++j )
234 						{
235 							Face& face = triangleMesh.faces[faceIndex];
236 //   						face.setMatID(fWMaterialIdMaxMtlIdMap[meshPrimitive->getMaterialId()]);
237 							if ( maxMaterialId != 0 )
238 								face.setMatID(maxMaterialId);
239 							face.setEdgeVisFlags(1, 1, 1);
240 							face.setVerts(commonVertexIndex, positionIndices[j - 1], positionIndices[j]);
241 							++faceIndex;
242 						}
243 						nextTrifanStartIndex += faceVertexCount;
244 					}
245 					break;
246 				}
247 			default:
248 				continue;
249 			}
250 
251 
252 		}
253 		return true;
254 	}
255 
256 	//------------------------------
importTriangleMeshNormals(TriObject * triangleObject)257 	bool GeometryImporter::importTriangleMeshNormals( TriObject* triangleObject )
258 	{
259 		COLLADAFW::Mesh* mesh = (COLLADAFW::Mesh*) mGeometry;
260 
261 		if ( !mesh->hasNormals() )
262 			return true;
263 
264 		Mesh& triangleMesh = triangleObject->GetMesh();
265 
266 		triangleMesh.SpecifyNormals();
267 		MeshNormalSpec* normalsSpecifier = triangleMesh.GetSpecifiedNormals();
268 
269 		normalsSpecifier->ClearNormals();
270 		size_t numFaces = triangleMesh.getNumFaces();
271 		normalsSpecifier->SetNumFaces((int)numFaces);
272 
273 		// fill in the normals
274 		const COLLADAFW::MeshVertexData& meshNormals = mesh->getNormals();
275 		int normalCount = (int)meshNormals.getValuesCount()/3;
276 
277 		normalsSpecifier->SetNumNormals(normalCount);
278 
279 		if ( meshNormals.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE )
280 		{
281 			const COLLADAFW::DoubleArray* normalsArray = meshNormals.getDoubleValues();
282 			for ( int i = 0; i < normalCount; ++i)
283 			{
284 				Point3 normal((*normalsArray)[i*3], (*normalsArray)[i*3 + 1], (*normalsArray)[i*3 + 2]);
285 				normalsSpecifier->Normal(i) = normal.Normalize();
286 				normalsSpecifier->SetNormalExplicit(i, true);
287 			}
288 		}
289 		else
290 		{
291 			const COLLADAFW::FloatArray* normalsArray = meshNormals.getFloatValues();
292 			for ( int i = 0; i < normalCount; ++i)
293 			{
294 				Point3 normal((*normalsArray)[i*3], (*normalsArray)[i*3 + 1], (*normalsArray)[i*3 + 2]);
295 				normalsSpecifier->Normal(i) = normal.Normalize();
296 				normalsSpecifier->SetNormalExplicit(i, true);
297 			}
298 		}
299 
300 		//assign normals to faces (triangles)
301 		const COLLADAFW::MeshPrimitiveArray& meshPrimitives = mesh->getMeshPrimitives();
302 		size_t faceIndex = 0;
303 		for ( size_t i = 0, count = meshPrimitives.getCount(); i < count; ++i )
304 		{
305 			const COLLADAFW::MeshPrimitive* meshPrimitive = meshPrimitives[i];
306 			size_t trianglesCount = meshPrimitive->getFaceCount();
307 
308 			const COLLADAFW::UIntValuesArray& normalIndices = meshPrimitive->getNormalIndices();
309 			if (isSupportedMeshPrimitive(meshPrimitive))
310 			{
311 				if ( skipMeshData( meshPrimitive, normalIndices, faceIndex ) )
312 				{
313 					continue;
314 				}
315 			}
316 			else
317 			{
318 				continue;
319 			}
320 
321 			switch (meshPrimitive->getPrimitiveType())
322 			{
323 			case COLLADAFW::MeshPrimitive::TRIANGLES:
324 				{
325 					for ( size_t j = 0; j < trianglesCount; ++j)
326 					{
327 						MeshNormalFace& normalFace = normalsSpecifier->Face((int) faceIndex);
328 						normalFace.SpecifyAll();
329 						normalFace.SetNormalID(0, normalIndices[3*j]);
330 						normalFace.SetNormalID(1, normalIndices[3*j + 1]);
331 						normalFace.SetNormalID(2, normalIndices[3*j + 2]);
332 						++faceIndex;
333 					}
334 					break;
335 				}
336 			case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
337 				{
338 					const COLLADAFW::Tristrips* tristrips = (const COLLADAFW::Tristrips*) meshPrimitive;
339 					assert(tristrips);
340 					const COLLADAFW::UIntValuesArray& faceVertexCountArray = tristrips->getGroupedVerticesVertexCountArray();
341 					size_t nextTristripStartIndex = 0;
342 					for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
343 					{
344 						unsigned int faceVertexCount = faceVertexCountArray[k];
345 						bool switchOrientation = false;
346 						for ( size_t j = nextTristripStartIndex + 2, lastVertex = nextTristripStartIndex +  faceVertexCount; j < lastVertex; ++j )
347 						{
348 							MeshNormalFace& normalFace = normalsSpecifier->Face((int) faceIndex);
349 							normalFace.SpecifyAll();
350 							if ( switchOrientation )
351 							{
352 								normalFace.SetNormalID(0, normalIndices[j - 1]);
353 								normalFace.SetNormalID(1, normalIndices[j - 2]);
354 								normalFace.SetNormalID(2, normalIndices[j]);
355 								switchOrientation = false;
356 							}
357 							else
358 							{
359 								normalFace.SetNormalID(0, normalIndices[j - 2]);
360 								normalFace.SetNormalID(1, normalIndices[j - 1]);
361 								normalFace.SetNormalID(2, normalIndices[j]);
362 								switchOrientation = true;
363 							}
364 							++faceIndex;
365 						}
366 						nextTristripStartIndex += faceVertexCount;
367 					}
368 					break;
369 				}
370 			case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
371 				{
372 					const COLLADAFW::Trifans* trifans = (const COLLADAFW::Trifans*) meshPrimitive;
373 					assert(trifans);
374 					const COLLADAFW::UIntValuesArray& faceVertexCountArray = trifans->getGroupedVerticesVertexCountArray();
375 					size_t nextTrifanStartIndex = 0;
376 					for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
377 					{
378 						unsigned int faceVertexCount = faceVertexCountArray[k];
379 						unsigned int commonVertexIndex = normalIndices[nextTrifanStartIndex];
380 						for ( size_t j = nextTrifanStartIndex + 2, lastVertex = nextTrifanStartIndex +  faceVertexCount; j < lastVertex; ++j )
381 						{
382 							MeshNormalFace& normalFace = normalsSpecifier->Face((int) faceIndex);
383 							normalFace.SpecifyAll();
384 							normalFace.SetNormalID(0, commonVertexIndex);
385 							normalFace.SetNormalID(1, normalIndices[j - 1]);
386 							normalFace.SetNormalID(2, normalIndices[j]);
387 							++faceIndex;
388 						}
389 						nextTrifanStartIndex += faceVertexCount;
390 					}
391 					break;
392 				}
393 			default:
394 				continue;
395 			}
396 		}
397 
398 		// TODO uncomment
399 //		normalsSpecifier->CheckNormals();
400 
401 		return true;
402 	}
403 
404 	//------------------------------
405 	template<class NumberArray>
setTriangleMeshUVVertices(const NumberArray & uvArray,MeshMap & meshMap,size_t stride,size_t startPosition,size_t vertsCount)406 	void GeometryImporter::setTriangleMeshUVVertices(const NumberArray& uvArray, MeshMap& meshMap, size_t stride, size_t startPosition, size_t vertsCount)
407 	{
408 		size_t uvIndex = startPosition;
409 
410 		switch ( stride )
411 		{
412 		case 1:
413 			{
414 				for ( size_t i = 0; i < vertsCount; ++i)
415 				{
416 					UVVert& textureVertex = meshMap.tv[i];
417 					textureVertex.x = (float)uvArray[uvIndex++];
418 				}
419 				break;
420 			}
421 		case 2:
422 			{
423 				for ( size_t i = 0; i < vertsCount; ++i)
424 				{
425 					UVVert& textureVertex = meshMap.tv[i];
426 					textureVertex.x = (float)uvArray[uvIndex++];
427 					textureVertex.y = (float)uvArray[uvIndex++];
428 				}
429 				break;
430 			}
431 		case 3:
432 			{
433 				for ( size_t i = 0; i < vertsCount; ++i)
434 				{
435 					UVVert& textureVertex = meshMap.tv[i];
436 					float x = (float)uvArray[uvIndex++];
437 					float y = (float)uvArray[uvIndex++];
438 					float z = (float)uvArray[uvIndex++];
439 					textureVertex.Set(x, y, z);
440 				}
441 				break;
442 			}
443 		case 4:
444 			{
445 				for ( size_t i = 0; i < vertsCount; ++i)
446 				{
447 					UVVert& textureVertex = meshMap.tv[i];
448 					float x = (float)uvArray[uvIndex++];
449 					float y = (float)uvArray[uvIndex++];
450 					float z = (float)uvArray[uvIndex++];
451 					textureVertex.Set(x, y, z);
452 					uvIndex++;
453 				}
454 				break;
455 			}
456 		default:
457 			assert(false);
458 		}
459 
460 	}
461 
462 
463 
464 	//------------------------------
fillTriangleMeshMapPerSet(const COLLADAFW::MeshVertexData & uvCoordinates,const COLLADAFW::MeshVertexData::InputInfosArray & inputInfos,size_t sourceIndex,MeshMap & meshMap)465 	void GeometryImporter::fillTriangleMeshMapPerSet( const COLLADAFW::MeshVertexData& uvCoordinates,
466 		const COLLADAFW::MeshVertexData::InputInfosArray& inputInfos,
467 		size_t sourceIndex,
468 		MeshMap& meshMap)
469 	{
470 		const COLLADAFW::MeshVertexData::InputInfos* inputInfo = inputInfos[ sourceIndex ];
471 
472 		size_t stride = inputInfo->mStride;
473 		size_t vertsCount = inputInfo->mLength / stride;
474 
475 		// calculate first index position
476 		size_t startPosition = 0;
477 		for ( size_t i = 0; i < sourceIndex; ++i)
478 		{
479 			const COLLADAFW::MeshVertexData::InputInfos* inputInfo = inputInfos[ sourceIndex ];
480 			startPosition += inputInfo->mLength;
481 		}
482 
483 		meshMap.setNumVerts((int)vertsCount);
484 
485 		if ( uvCoordinates.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE )
486 		{
487 			const COLLADAFW::DoubleArray& uvArray = *uvCoordinates.getDoubleValues();
488 			setTriangleMeshUVVertices(uvArray, meshMap, stride, startPosition, vertsCount);
489 		}
490 		else
491 		{
492 			const COLLADAFW::FloatArray& uvArray = *uvCoordinates.getFloatValues();
493 			setTriangleMeshUVVertices(uvArray, meshMap, stride, startPosition, vertsCount);
494 		}
495 
496 	}
497 
498 
499 
500 	//------------------------------
setTriangleMeshUVVerticesPerPrimitiveAndChannel(const COLLADAFW::MeshPrimitive * meshPrimitive,MeshMap & meshMap,const COLLADAFW::UIntValuesArray & uvIndices,unsigned int initialIndex,size_t & currentFaceIndex)501 	void GeometryImporter::setTriangleMeshUVVerticesPerPrimitiveAndChannel( const COLLADAFW::MeshPrimitive* meshPrimitive,
502 		MeshMap& meshMap,
503 		const COLLADAFW::UIntValuesArray& uvIndices,
504 		unsigned int initialIndex,
505 		size_t& currentFaceIndex)
506 	{
507 	switch (meshPrimitive->getPrimitiveType())
508 		{
509 		case COLLADAFW::MeshPrimitive::TRIANGLES:
510 			{
511 				for ( size_t j = 0, count = uvIndices.getCount() ; j < count; j+=3 )
512 				{
513 					TVFace& face = meshMap.tf[currentFaceIndex];
514 					face.setTVerts( uvIndices[j] - initialIndex, uvIndices[j + 1] - initialIndex, uvIndices[j + 2] - initialIndex);
515 					++currentFaceIndex;
516 				}
517 				break;
518 			}
519 		case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
520 			{
521 				const COLLADAFW::Tristrips* tristrips = (const COLLADAFW::Tristrips*) meshPrimitive;
522 				const COLLADAFW::UIntValuesArray& faceVertexCountArray = tristrips->getGroupedVerticesVertexCountArray();
523 				size_t nextTristripStartIndex = 0;
524 				for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
525 				{
526 					unsigned int faceVertexCount = faceVertexCountArray[k];
527 					bool switchOrientation = false;
528 					for ( size_t j = nextTristripStartIndex + 2, lastVertex = nextTristripStartIndex +  faceVertexCount; j < lastVertex; ++j )
529 					{
530 						TVFace& face = meshMap.tf[currentFaceIndex];
531 						if ( switchOrientation )
532 						{
533 							face.setTVerts( uvIndices[j - 1]  - initialIndex, uvIndices[j - 2] - initialIndex, uvIndices[j] - initialIndex);
534 							switchOrientation = false;
535 						}
536 						else
537 						{
538 							face.setTVerts( uvIndices[j - 2] - initialIndex, uvIndices[j - 1] - initialIndex, uvIndices[j] - initialIndex);
539 							switchOrientation = true;
540 						}
541 						++currentFaceIndex;
542 					}
543 					nextTristripStartIndex += faceVertexCount;
544 				}
545 				break;
546 			}
547 		case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
548 			{
549 				const COLLADAFW::Trifans* trifans = (const COLLADAFW::Trifans*) meshPrimitive;
550 				const COLLADAFW::UIntValuesArray& faceVertexCountArray = trifans->getGroupedVerticesVertexCountArray();
551 				size_t nextTrifanStartIndex = 0;
552 				for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
553 				{
554 					unsigned int faceVertexCount = faceVertexCountArray[k];
555 					unsigned int commonVertexIndex = uvIndices[nextTrifanStartIndex] - initialIndex;
556 					for ( size_t j = nextTrifanStartIndex + 2, lastVertex = nextTrifanStartIndex +  faceVertexCount; j < lastVertex; ++j )
557 					{
558 						TVFace& face = meshMap.tf[currentFaceIndex];
559 						face.setTVerts( commonVertexIndex, uvIndices[j - 1] - initialIndex, uvIndices[j] - initialIndex);
560 						++currentFaceIndex;
561 					}
562 					nextTrifanStartIndex += faceVertexCount;
563 				}
564 				break;
565 			}
566 		default:
567 			return;
568 		}
569 	}
570 
571 
572 	//------------------------------
getTriangleMeshPrimitiveTriangleCount(const COLLADAFW::MeshPrimitive * meshPrimitive)573 	size_t getTriangleMeshPrimitiveTriangleCount( const COLLADAFW::MeshPrimitive* meshPrimitive)
574 	{
575 		const COLLADAFW::UIntValuesArray& faceVertexCountArray = meshPrimitive->getPositionIndices();
576 
577 		switch (meshPrimitive->getPrimitiveType())
578 		{
579 		case COLLADAFW::MeshPrimitive::TRIANGLES:
580 			{
581 				return meshPrimitive->getPositionIndices().getCount()/3;
582 			}
583 		case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
584 			{
585 				const COLLADAFW::Tristrips* tristrips = (const COLLADAFW::Tristrips*) meshPrimitive;
586 				const COLLADAFW::UIntValuesArray& faceVertexCountArray = tristrips->getGroupedVerticesVertexCountArray();
587 				size_t triangleCount = 0;
588 				for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
589 				{
590 					unsigned int faceVertexCount = faceVertexCountArray[k];
591 					triangleCount += (faceVertexCount > 2) ? (faceVertexCount - 2) : 0;
592 				}
593 				return triangleCount;
594 			}
595 		case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
596 			{
597 				const COLLADAFW::Trifans* trifans = (const COLLADAFW::Trifans*) meshPrimitive;
598 				const COLLADAFW::UIntValuesArray& faceVertexCountArray = trifans->getGroupedVerticesVertexCountArray();
599 				size_t triangleCount = 0;
600 				for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
601 				{
602 					unsigned int faceVertexCount = faceVertexCountArray[k];
603 					triangleCount += (faceVertexCount > 2) ? (faceVertexCount - 2) : 0;
604 				}
605 				return triangleCount;
606 			}
607 		default:
608 			return 0;
609 		}
610 	}
611 
612 	//------------------------------
importTriangleMeshUVCoords(TriObject * triangleObject)613 	bool GeometryImporter::importTriangleMeshUVCoords( TriObject* triangleObject )
614 	{
615 		COLLADAFW::Mesh* mesh = (COLLADAFW::Mesh*) mGeometry;
616 
617 		createSetSourcePairMapChannelMap();
618 
619 		Mesh& triangleMesh = triangleObject->GetMesh();
620 
621 		triangleMesh.setNumMaps( mLargestMapChannel + 1 );
622 
623 		int facesCount = (int)mTotalTrianglesCount;
624 
625 		// reset all texture indices of all used maps
626 		for ( int i = 0; i <= mLargestMapChannel; ++i )
627 		{
628 			MeshMap& meshMap = triangleMesh.Map(i);
629 			meshMap.setNumFaces( facesCount );
630 			memset( meshMap.tf, 0, sizeof(TVFace) * facesCount);
631 		}
632 
633 		const COLLADAFW::MeshVertexData& uvCoordinates = mesh->getUVCoords();
634 		const COLLADAFW::MeshVertexData& vertexColors = mesh->getColors();
635 		const COLLADAFW::MeshVertexData::InputInfosArray& uvInputInfos = uvCoordinates.getInputInfosArray();
636 		const COLLADAFW::MeshVertexData::InputInfosArray& vertexColorInputInfos = vertexColors.getInputInfosArray();
637 
638 		SetSourcePairMapChannelMap::const_iterator it = mSetSourcePairMapChannelMap.begin();
639 		for ( ; it != mSetSourcePairMapChannelMap.end(); ++it )
640 		{
641 			const SetSourcePair& setSourcePair = it->first;
642 			const size_t& sourceIndex = setSourcePair.second;
643 			// check that the channel is a texture channel and not a color channel
644 			long setIndex = setSourcePair.first;
645 			int mapChannel = it->second;
646 			triangleMesh.setMapSupport(mapChannel, true);
647 
648 			assert( (mapChannel != 0) || ( setIndex < 0) );
649 			MeshMap& meshMap = triangleMesh.Map(mapChannel);
650 			if ( setIndex >= 0 )
651 			{
652 				fillTriangleMeshMapPerSet( uvCoordinates, uvInputInfos, sourceIndex, meshMap);
653 			}
654 			else if ( mapChannel == 0 )
655 			{
656 				fillTriangleMeshMapPerSet( vertexColors, vertexColorInputInfos, sourceIndex, meshMap);
657 			}
658 		}
659 
660 
661 		COLLADAFW::MeshPrimitiveArray& meshPrimitiveArray =  mesh->getMeshPrimitives();
662 		size_t faceIndex = 0;
663 		for ( size_t i = 0, count = meshPrimitiveArray.getCount(); i < count; ++i)
664 		{
665 			const COLLADAFW::MeshPrimitive* meshPrimitive = meshPrimitiveArray[i];
666 			if ( ! meshPrimitive )
667 				continue;
668 
669 			if (isSupportedMeshPrimitive(meshPrimitive))
670 			{
671 				size_t currentFaceIndex = faceIndex;
672 
673 				//uv
674 				const COLLADAFW::IndexListArray& uvIndexArray = meshPrimitive->getUVCoordIndicesArray();
675 				for ( size_t j = 0, count = uvIndexArray.getCount(); j < count; ++j)
676 				{
677 					const COLLADAFW::IndexList& uvIndexList = *uvIndexArray[j];
678 					size_t sourceIndex = mUVInitialIndexSourceIndexMap[uvIndexList.getInitialIndex()];
679 					size_t setIndex = uvIndexList.getSetIndex();
680 					SetSourcePair setSourcePair( (long)setIndex, sourceIndex);
681 					int mapChannel = mSetSourcePairMapChannelMap[ setSourcePair ];
682 
683 					unsigned int initialIndex = (unsigned int)uvIndexList.getInitialIndex();
684 
685 					const COLLADAFW::UIntValuesArray& uvIndices =  uvIndexList.getIndices();
686 
687 					MeshMap& meshMap = triangleMesh.Map(mapChannel);
688 
689 					currentFaceIndex = faceIndex;
690 
691 					setTriangleMeshUVVerticesPerPrimitiveAndChannel( meshPrimitive, meshMap, uvIndices, initialIndex, currentFaceIndex);
692 				}
693 
694 				// vertex color color
695 				const COLLADAFW::IndexListArray& colorIndexArray = meshPrimitive->getColorIndicesArray();
696 				for ( size_t j = 0, count = colorIndexArray.getCount(); j < count; ++j)
697 				{
698 					const COLLADAFW::IndexList& colorIndexList = *colorIndexArray[j];
699 					size_t sourceIndex = mColorInitialIndexSourceIndexMap[colorIndexList.getInitialIndex()];
700 					size_t setIndex = colorIndexList.getSetIndex();
701 					SetSourcePair setSourcePair( -(long)(setIndex + 1), sourceIndex);
702 					int mapChannel = mSetSourcePairMapChannelMap[ setSourcePair ];
703 					if ( mapChannel != 0)
704 						continue;
705 
706 					unsigned int initialIndex = (unsigned int)colorIndexList.getInitialIndex();
707 
708 					const COLLADAFW::UIntValuesArray& colorIndices =  colorIndexList.getIndices();
709 
710 					MeshMap& meshMap = triangleMesh.Map(mapChannel);
711 
712 					currentFaceIndex = faceIndex;
713 
714 					setTriangleMeshUVVerticesPerPrimitiveAndChannel( meshPrimitive, meshMap, colorIndices, initialIndex, currentFaceIndex);
715 					mHasVertexColor = true;
716 				}
717 
718 				if ( faceIndex == currentFaceIndex )
719 				{
720 					// setTriangleMeshUVVerticesPerPrimitiveAndChannel was never called. we need to count triangle here
721 					faceIndex += getTriangleMeshPrimitiveTriangleCount(meshPrimitive);
722 				}
723 				else
724 				{
725 					// currentFaceIndex was properly set by the last setTriangleMeshUVVerticesPerPrimitiveAndChannel call
726 					faceIndex = currentFaceIndex;
727 				}
728 			}
729 
730 		}
731 		return true;
732 	}
733 
734 
735 	//------------------------------
importPolygonMesh()736 	bool GeometryImporter::importPolygonMesh( )
737 	{
738 
739 		COLLADAFW::Mesh* mesh = (COLLADAFW::Mesh*) mGeometry;
740 
741 		PolyObject* polygonObject = CreateEditablePolyObject();
742 		MNMesh& polygonMesh = polygonObject->GetMesh();
743 
744 
745 		if ( !importPolygonMeshPositions(polygonObject) )
746 			return false;
747 
748 		if ( !importPolygonMeshNormals(polygonObject) )
749 			return false;
750 
751 		if ( !importPolygonMeshUVCoords(polygonObject) )
752 			return false;
753 
754 
755 		polygonMesh.InvalidateGeomCache();
756 
757 		handleObjectReferences(mesh, polygonObject);
758 
759 		return true;
760 	}
761 
762 	//------------------------------
importPolygonMeshPositions(PolyObject * polygonObject)763 	bool GeometryImporter::importPolygonMeshPositions( PolyObject* polygonObject )
764 	{
765 		COLLADAFW::Mesh* mesh = (COLLADAFW::Mesh*) mGeometry;
766 
767 		MNMesh& polgonMesh = polygonObject->GetMesh();
768 
769 		const COLLADAFW::MeshVertexData& meshPositions = mesh->getPositions();
770 
771 		int positionsCount = (int)meshPositions.getValuesCount() / 3;
772 
773 		polgonMesh.setNumVerts(positionsCount);
774 
775 		if ( meshPositions.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE )
776 		{
777 			const COLLADAFW::DoubleArray* positionsArray = meshPositions.getDoubleValues();
778 			for ( int i = 0; i < positionsCount; ++i)
779 			{
780 				MNVert* vertex = polgonMesh.V(i);
781 				vertex->p = Point3( convertSpaceUnit((float)(*positionsArray)[3*i]),
782 					                convertSpaceUnit((float)(*positionsArray)[3*i + 1]),
783 									convertSpaceUnit((float)(*positionsArray)[3*i + 2]));
784 			}
785 		}
786 		else
787 		{
788 			const COLLADAFW::FloatArray* positionsArray = meshPositions.getFloatValues();
789 			for ( int i = 0; i < positionsCount; ++i)
790 			{
791 				MNVert* vertex = polgonMesh.V(i);
792 				vertex->p = Point3( convertSpaceUnit((*positionsArray)[3*i]),
793 					                convertSpaceUnit((*positionsArray)[3*i + 1]),
794 									convertSpaceUnit((*positionsArray)[3*i + 2]));
795 			}
796 		}
797 
798 		size_t polygonsCount = mTotalTrianglesCount + mesh->getPolygonsPolygonCount() + mesh->getPolylistPolygonCount();
799 		polgonMesh.setNumFaces((int)polygonsCount);
800 		COLLADAFW::MeshPrimitiveArray& meshPrimitiveArray =  mesh->getMeshPrimitives();
801 		size_t faceIndex = 0;
802 		for ( size_t i = 0, count = meshPrimitiveArray.getCount(); i < count; ++i)
803 		{
804 			const COLLADAFW::MeshPrimitive* meshPrimitive = meshPrimitiveArray[i];
805 			if ( ! meshPrimitive )
806 				continue;
807 			MtlID maxMaterialId = (MtlID)meshPrimitive->getMaterialId();
808 			switch ( meshPrimitive->getPrimitiveType() )
809 			{
810 			case COLLADAFW::MeshPrimitive::TRIANGLES:
811 				{
812 					const COLLADAFW::Triangles* triangles = (const COLLADAFW::Triangles*) meshPrimitive;
813 					const COLLADAFW::UIntValuesArray& positionIndices =  triangles->getPositionIndices();
814 					for ( size_t j = 0, count = positionIndices.getCount() ; j < count; j+=3 )
815 					{
816 						MNFace* face = polgonMesh.F((int)faceIndex);
817 						face->MakePoly(3, (int*) (&positionIndices[j]));
818 						if ( maxMaterialId != 0 )
819 							face->material = maxMaterialId;
820 
821 						++faceIndex;
822 					}
823 					break;
824 				}
825 			case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
826 				{
827 					const COLLADAFW::Tristrips* tristrips = (const COLLADAFW::Tristrips*) meshPrimitive;
828 					const COLLADAFW::UIntValuesArray& positionIndices =  tristrips->getPositionIndices();
829 					const COLLADAFW::UIntValuesArray& faceVertexCountArray = tristrips->getGroupedVerticesVertexCountArray();
830 					size_t nextTristripStartIndex = 0;
831 					for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
832 					{
833 						unsigned int faceVertexCount = faceVertexCountArray[k];
834 						bool switchOrientation = false;
835 						for ( size_t j = nextTristripStartIndex + 2, lastVertex = nextTristripStartIndex +  faceVertexCount; j < lastVertex; ++j )
836 						{
837 							MNFace* face = polgonMesh.F((int)faceIndex);
838 							if ( switchOrientation )
839 							{
840 								int indices[3];
841 								indices[0] = (int)positionIndices[j - 1];
842 								indices[1] = (int)positionIndices[j - 2];
843 								indices[2] = (int)positionIndices[j ];
844 								face->MakePoly(3, indices);
845 								if ( maxMaterialId != 0 )
846 									face->material = maxMaterialId;
847 								switchOrientation = false;
848 							}
849 							else
850 							{
851 								face->MakePoly(3, (int*) (&positionIndices[j - 2]));
852 								if ( maxMaterialId != 0 )
853 									face->material = maxMaterialId;
854 								switchOrientation = true;
855 							}
856 
857 							++faceIndex;
858 						}
859 						nextTristripStartIndex += faceVertexCount;
860 					}
861 					break;
862 				}
863 			case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
864 				{
865 					const COLLADAFW::Trifans* trifans = (const COLLADAFW::Trifans*) meshPrimitive;
866 					const COLLADAFW::UIntValuesArray& positionIndices =  trifans->getPositionIndices();
867 					const COLLADAFW::UIntValuesArray& faceVertexCountArray = trifans->getGroupedVerticesVertexCountArray();
868 					size_t nextTrifanStartIndex = 0;
869 					for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
870 					{
871 						unsigned int faceVertexCount = faceVertexCountArray[k];
872 						int trianglePositionsIndices[3];
873 						//the first vertex is the same for all fans
874 						trianglePositionsIndices[0] = (int)positionIndices[nextTrifanStartIndex];
875 						for ( size_t j = nextTrifanStartIndex + 2, lastVertex = nextTrifanStartIndex +  faceVertexCount; j < lastVertex; ++j )
876 						{
877 							trianglePositionsIndices[1] = (int)positionIndices[j - 1];
878 							trianglePositionsIndices[2] = (int)positionIndices[j];
879 							MNFace* face = polgonMesh.F((int)faceIndex);
880 							face->MakePoly(3, trianglePositionsIndices);
881 							if ( maxMaterialId != 0 )
882 								face->material = maxMaterialId;
883 
884 							++faceIndex;
885 						}
886 						nextTrifanStartIndex += faceVertexCount;
887 					}
888 					break;
889 				}
890 			case COLLADAFW::MeshPrimitive::POLYGONS:
891 				{
892 					const COLLADAFW::Polygons* polygons = (const COLLADAFW::Polygons*) meshPrimitive;
893 					const COLLADAFW::UIntValuesArray& positionIndices =  polygons->getPositionIndices();
894 					const COLLADAFW::IntValuesArray& faceVertexCountArray = polygons->getGroupedVerticesVertexCountArray();
895 					size_t currentIndex = 0;
896 					for ( size_t j = 0, count = faceVertexCountArray.getCount() ; j < count; ++j )
897 					{
898 						int faceVertexCount = faceVertexCountArray[j];
899 						// TODO for now, we ignore holes in polygons
900 						if ( faceVertexCount <= 0 )
901 							continue;
902 						MNFace* face = polgonMesh.F((int)faceIndex);
903 						face->MakePoly(faceVertexCount, (int*) (&positionIndices[currentIndex]));
904 						if ( maxMaterialId != 0 )
905 							face->material = maxMaterialId;
906 						currentIndex += faceVertexCount;
907 						++faceIndex;
908 					}
909 					break;
910 				}
911 			case COLLADAFW::MeshPrimitive::POLYLIST:
912 				{
913 					const COLLADAFW::Polylist* polylist = (const COLLADAFW::Polylist*) meshPrimitive;
914 					const COLLADAFW::UIntValuesArray& positionIndices =  polylist->getPositionIndices();
915 					const COLLADAFW::IntValuesArray& faceVertexCountArray = polylist->getGroupedVerticesVertexCountArray();
916 					size_t currentIndex = 0;
917 					for ( size_t j = 0, count = faceVertexCountArray.getCount() ; j < count; ++j )
918 					{
919 						int faceVertexCount = faceVertexCountArray[j];
920 						// polylist does not support holes!
921 						if ( faceVertexCount <= 0 )
922 							continue;
923 						MNFace* face = polgonMesh.F((int)faceIndex);
924 						face->MakePoly(faceVertexCount, (int*) (&positionIndices[currentIndex]));
925 						if ( maxMaterialId != 0 )
926 							face->material = maxMaterialId;
927 						currentIndex += faceVertexCount;
928 						++faceIndex;
929 					}
930 					break;
931 				}
932 			}
933 
934 		}
935 		return true;
936 	}
937 
938 	//------------------------------
importPolygonMeshNormals(PolyObject * polygonObject)939 	bool GeometryImporter::importPolygonMeshNormals( PolyObject* polygonObject )
940 	{
941 		COLLADAFW::Mesh* mesh = (COLLADAFW::Mesh*) mGeometry;
942 
943 		if ( !mesh->hasNormals() )
944 			return true;
945 
946 		MNMesh& polygonMesh = polygonObject->GetMesh();
947 
948 		polygonMesh.SpecifyNormals();
949 		MNNormalSpec* normalsSpecifier = polygonMesh.GetSpecifiedNormals();
950 
951 		normalsSpecifier->ClearNormals();
952 		size_t numFaces = polygonMesh.FNum();
953 		normalsSpecifier->SetNumFaces((int)numFaces);
954 
955 		// fill in the normals
956 		const COLLADAFW::MeshVertexData& meshNormals = mesh->getNormals();
957 		int normalCount = (int)meshNormals.getValuesCount()/3;
958 
959 		normalsSpecifier->SetNumNormals(normalCount);
960 
961 		if ( meshNormals.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE )
962 		{
963 			const COLLADAFW::DoubleArray* normalsArray = meshNormals.getDoubleValues();
964 			for ( int i = 0; i < normalCount; ++i)
965 			{
966 				Point3 normal((*normalsArray)[i*3], (*normalsArray)[i*3 + 1], (*normalsArray)[i*3 + 2]);
967 				normalsSpecifier->Normal(i) = normal.Normalize();
968 				normalsSpecifier->SetNormalExplicit(i, true);
969 			}
970 		}
971 		else
972 		{
973 			const COLLADAFW::FloatArray* normalsArray = meshNormals.getFloatValues();
974 			for ( int i = 0; i < normalCount; ++i)
975 			{
976 				Point3 normal((*normalsArray)[i*3], (*normalsArray)[i*3 + 1], (*normalsArray)[i*3 + 2]);
977 				normalsSpecifier->Normal(i) = normal.Normalize();
978 				normalsSpecifier->SetNormalExplicit(i, true);
979 			}
980 		}
981 
982 		//assign normals to faces (polygons)
983 		const COLLADAFW::MeshPrimitiveArray& meshPrimitives = mesh->getMeshPrimitives();
984 		size_t faceIndex = 0;
985 		for ( size_t i = 0, count = meshPrimitives.getCount(); i < count; ++i )
986 		{
987 			const COLLADAFW::MeshPrimitive* meshPrimitive = meshPrimitives[i];
988 			const COLLADAFW::UIntValuesArray& normalIndices = meshPrimitive->getNormalIndices();
989 
990 
991 			if (isSupportedMeshPrimitive(meshPrimitive))
992 			{
993 				if ( skipMeshData( meshPrimitive, normalIndices, faceIndex ) )
994 				{
995 					continue;
996 				}
997 			}
998 			else
999 			{
1000 				continue;
1001 			}
1002 
1003 			switch ( meshPrimitive->getPrimitiveType() )
1004 			{
1005 			case COLLADAFW::MeshPrimitive::TRIANGLES:
1006 				{
1007 					size_t faceCount = meshPrimitive->getFaceCount();
1008 					for ( size_t j = 0; j < faceCount; ++j)
1009 					{
1010 						MNNormalFace& normalFace = normalsSpecifier->Face((int) faceIndex);
1011 						normalFace.SetDegree(3);
1012 						normalFace.SpecifyAll();
1013 						normalFace.SetNormalID(0, normalIndices[3*j]);
1014 						normalFace.SetNormalID(1, normalIndices[3*j + 1]);
1015 						normalFace.SetNormalID(2, normalIndices[3*j + 2]);
1016 						++faceIndex;
1017 					}
1018 				}
1019 				break;
1020 			case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
1021 				{
1022 					const COLLADAFW::Tristrips* tristrips = (const COLLADAFW::Tristrips*) meshPrimitive;
1023 					const COLLADAFW::UIntValuesArray& faceVertexCountArray = tristrips->getGroupedVerticesVertexCountArray();
1024 					size_t nextTristripStartIndex = 0;
1025 					for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
1026 					{
1027 						unsigned int faceVertexCount = faceVertexCountArray[k];
1028 						bool switchOrientation = false;
1029 						for ( size_t j = nextTristripStartIndex + 2, lastVertex = nextTristripStartIndex +  faceVertexCount; j < lastVertex; ++j )
1030 						{
1031 							MNNormalFace& normalFace = normalsSpecifier->Face((int) faceIndex);
1032 							normalFace.SetDegree(3);
1033 							normalFace.SpecifyAll();
1034 							if ( switchOrientation )
1035 							{
1036 								normalFace.SetNormalID(0, normalIndices[j - 1]);
1037 								normalFace.SetNormalID(1, normalIndices[j - 2]);
1038 								normalFace.SetNormalID(2, normalIndices[j]);
1039 								switchOrientation = false;
1040 							}
1041 							else
1042 							{
1043 								normalFace.SetNormalID(0, normalIndices[j - 2]);
1044 								normalFace.SetNormalID(1, normalIndices[j - 1]);
1045 								normalFace.SetNormalID(2, normalIndices[j]);
1046 								switchOrientation = true;
1047 							}
1048 							++faceIndex;
1049 						}
1050 						nextTristripStartIndex += faceVertexCount;
1051 					}
1052 					break;
1053 				}
1054 			case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
1055 				{
1056 					const COLLADAFW::Trifans* trifans = (const COLLADAFW::Trifans*) meshPrimitive;
1057 					const COLLADAFW::UIntValuesArray& faceVertexCountArray = trifans->getGroupedVerticesVertexCountArray();
1058 					size_t nextTrifanStartIndex = 0;
1059 					for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
1060 					{
1061 						unsigned int faceVertexCount = faceVertexCountArray[k];
1062 						unsigned int commonVertexIndex = normalIndices[nextTrifanStartIndex];
1063 						for ( size_t j = nextTrifanStartIndex + 2, lastVertex = nextTrifanStartIndex +  faceVertexCount; j < lastVertex; ++j )
1064 						{
1065 							MNNormalFace& normalFace = normalsSpecifier->Face((int) faceIndex);
1066 							normalFace.SetDegree(3);
1067 							normalFace.SpecifyAll();
1068 							normalFace.SetNormalID(0, commonVertexIndex);
1069 							normalFace.SetNormalID(1, normalIndices[j - 1]);
1070 							normalFace.SetNormalID(2, normalIndices[j]);
1071 							++faceIndex;
1072 						}
1073 						nextTrifanStartIndex += faceVertexCount;
1074 					}
1075 					break;
1076 				}
1077 			case COLLADAFW::MeshPrimitive::POLYGONS:
1078 				{
1079 					COLLADAFW::Polygons* polygons = (COLLADAFW::Polygons*) meshPrimitive;
1080 
1081 					COLLADAFW::IntValuesArray& faceVertexCountArray = polygons->getGroupedVerticesVertexCountArray();
1082 					size_t currentIndex = 0;
1083 					for ( size_t j = 0, count = faceVertexCountArray.getCount(); j < count; ++j)
1084 					{
1085 						int faceVertexCount = faceVertexCountArray[j];
1086 
1087 						// TODO for now, we ignore holes in polygons
1088 						if ( faceVertexCount <= 0 )
1089 							continue;
1090 
1091 						MNNormalFace& normalFace = normalsSpecifier->Face((int) faceIndex);
1092 						normalFace.SetDegree((int)faceVertexCount);
1093 						normalFace.SpecifyAll();
1094 						for ( int k = 0; k < faceVertexCount; ++k)
1095 						{
1096 							normalFace.SetNormalID(k, normalIndices[currentIndex + k]);
1097 						}
1098 						currentIndex += faceVertexCount;
1099 						++faceIndex;
1100 					}
1101 				}
1102 				break;
1103 			case COLLADAFW::MeshPrimitive::POLYLIST:
1104 				{
1105 					COLLADAFW::Polylist* polylist = (COLLADAFW::Polylist*) meshPrimitive;
1106 
1107 					COLLADAFW::IntValuesArray& faceVertexCountArray = polylist->getGroupedVerticesVertexCountArray();
1108 					size_t currentIndex = 0;
1109 					for ( size_t j = 0, count = faceVertexCountArray.getCount(); j < count; ++j)
1110 					{
1111 						int faceVertexCount = faceVertexCountArray[j];
1112 
1113 						// polylist does not support holes!
1114 						if ( faceVertexCount <= 0 )
1115 							continue;
1116 
1117 						MNNormalFace& normalFace = normalsSpecifier->Face((int) faceIndex);
1118 						normalFace.SetDegree((int)faceVertexCount);
1119 						normalFace.SpecifyAll();
1120 						for ( int k = 0; k < faceVertexCount; ++k)
1121 						{
1122 							normalFace.SetNormalID(k, normalIndices[currentIndex + k]);
1123 						}
1124 						currentIndex += faceVertexCount;
1125 						++faceIndex;
1126 					}
1127 				}
1128 				break;
1129 			default:
1130 				continue;
1131 			}
1132 
1133 		}
1134 
1135 		normalsSpecifier->CheckNormals();
1136 
1137 		return true;
1138 	}
1139 
1140 	//------------------------------
1141 	template<class NumberArray>
setPolygonMeshUVVertices(const NumberArray & uvArray,MNMap * meshMap,size_t stride,size_t startPosition,size_t vertsCount)1142 	void GeometryImporter::setPolygonMeshUVVertices( const NumberArray& uvArray, MNMap* meshMap, size_t stride, size_t startPosition, size_t vertsCount )
1143 	{
1144 		size_t uvIndex = startPosition;
1145 
1146 		switch ( stride )
1147 		{
1148 		case 1:
1149 			{
1150 				for ( size_t i = 0; i < vertsCount; ++i)
1151 				{
1152 					UVVert& textureVertex = meshMap->v[i];
1153 					textureVertex.x = (float)uvArray[uvIndex++];
1154 				}
1155 				break;
1156 			}
1157 		case 2:
1158 			{
1159 				for ( size_t i = 0; i < vertsCount; ++i)
1160 				{
1161 					UVVert& textureVertex = meshMap->v[i];
1162 					textureVertex.x = (float)uvArray[uvIndex++];
1163 					textureVertex.y = (float)uvArray[uvIndex++];
1164 				}
1165 				break;
1166 			}
1167 		case 3:
1168 			{
1169 				for ( size_t i = 0; i < vertsCount; ++i)
1170 				{
1171 					UVVert& textureVertex = meshMap->v[i];
1172 					float x = (float)uvArray[uvIndex++];
1173 					float y = (float)uvArray[uvIndex++];
1174 					float z = (float)uvArray[uvIndex++];
1175 					textureVertex.Set(x, y, z);
1176 				}
1177 				break;
1178 			}
1179 		case 4:
1180 			{
1181 				for ( size_t i = 0; i < vertsCount; ++i)
1182 				{
1183 					UVVert& textureVertex = meshMap->v[i];
1184 					float x = (float)uvArray[uvIndex++];
1185 					float y = (float)uvArray[uvIndex++];
1186 					float z = (float)uvArray[uvIndex++];
1187 					textureVertex.Set(x, y, z);
1188 					uvIndex++;
1189 				}
1190 				break;
1191 			}
1192 		default:
1193 			assert(false);
1194 		}
1195 
1196 	}
1197 
1198 	//------------------------------
setPolygonMeshUVVerticesPerPrimitiveAndChannel(const COLLADAFW::MeshPrimitive * meshPrimitive,MNMap * meshMap,const COLLADAFW::UIntValuesArray & uvIndices,unsigned int initialIndex,size_t & currentFaceIndex)1199 	void GeometryImporter::setPolygonMeshUVVerticesPerPrimitiveAndChannel( const COLLADAFW::MeshPrimitive* meshPrimitive,
1200 														 MNMap* meshMap,
1201 														 const COLLADAFW::UIntValuesArray& uvIndices,
1202 														 unsigned int initialIndex,
1203 														 size_t& currentFaceIndex)
1204 	{
1205 
1206 		if ( skipMeshData( meshPrimitive, uvIndices, currentFaceIndex ) )
1207 		{
1208 			return;
1209 		}
1210 
1211 		int indices[3];
1212 		switch (meshPrimitive->getPrimitiveType())
1213 		{
1214 		case COLLADAFW::MeshPrimitive::TRIANGLES:
1215 			{
1216 				for ( size_t j = 0, count = uvIndices.getCount() ; j < count; j+=3 )
1217 				{
1218 					MNMapFace* face = meshMap->F((int)currentFaceIndex);
1219 					indices[0] = (int)(uvIndices[j] - initialIndex);
1220 					indices[1] = (int)(uvIndices[j+1] - initialIndex);
1221 					indices[2] = (int)(uvIndices[j+2] - initialIndex);
1222 					face->MakePoly( 3, indices );
1223 					++currentFaceIndex;
1224 				}
1225 				break;
1226 			}
1227 		case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
1228 			{
1229 				const COLLADAFW::Tristrips* tristrips = (const COLLADAFW::Tristrips*) meshPrimitive;
1230 				const COLLADAFW::UIntValuesArray& faceVertexCountArray = tristrips->getGroupedVerticesVertexCountArray();
1231 				size_t nextTristripStartIndex = 0;
1232 				int indices[3];
1233 				for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
1234 				{
1235 					unsigned int faceVertexCount = faceVertexCountArray[k];
1236 					bool switchOrientation = false;
1237 					for ( size_t j = nextTristripStartIndex + 2, lastVertex = nextTristripStartIndex +  faceVertexCount; j < lastVertex; ++j )
1238 					{
1239 						MNMapFace* face = meshMap->F((int)currentFaceIndex);
1240 						if ( switchOrientation )
1241 						{
1242 							indices[0] = (int)(uvIndices[j - 1]  - initialIndex);
1243 							indices[1] = (int)(uvIndices[j - 2] - initialIndex);
1244 							indices[2] = (int)(uvIndices[j] - initialIndex);
1245 							face->MakePoly( 3, indices );
1246 							switchOrientation = false;
1247 						}
1248 						else
1249 						{
1250 							indices[0] = (int)(uvIndices[j - 2] - initialIndex);
1251 							indices[1] = (int)(uvIndices[j - 1] - initialIndex);
1252 							indices[2] = (int)(uvIndices[j] - initialIndex);
1253 							face->MakePoly( 3, indices );
1254 							switchOrientation = true;
1255 						}
1256 						++currentFaceIndex;
1257 					}
1258 					nextTristripStartIndex += faceVertexCount;
1259 				}
1260 				break;
1261 			}
1262 		case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
1263 			{
1264 				const COLLADAFW::Trifans* trifans = (const COLLADAFW::Trifans*) meshPrimitive;
1265 				const COLLADAFW::UIntValuesArray& faceVertexCountArray = trifans->getGroupedVerticesVertexCountArray();
1266 				size_t nextTrifanStartIndex = 0;
1267 				int indices[3];
1268 				for ( size_t k = 0, count = faceVertexCountArray.getCount(); k < count; ++k)
1269 				{
1270 					unsigned int faceVertexCount = faceVertexCountArray[k];
1271 					unsigned int commonVertexIndex = uvIndices[nextTrifanStartIndex] - initialIndex;
1272 					indices[0] = (int)(commonVertexIndex);
1273 					for ( size_t j = nextTrifanStartIndex + 2, lastVertex = nextTrifanStartIndex +  faceVertexCount; j < lastVertex; ++j )
1274 					{
1275 						MNMapFace* face = meshMap->F((int)currentFaceIndex);
1276 						indices[1] = (int)(uvIndices[j - 1] - initialIndex);
1277 						indices[2] = (int)(uvIndices[j] - initialIndex);
1278 						face->MakePoly( 3, indices );
1279 						++currentFaceIndex;
1280 					}
1281 					nextTrifanStartIndex += faceVertexCount;
1282 				}
1283 				break;
1284 			}
1285 		case COLLADAFW::MeshPrimitive::POLYGONS:
1286 			{
1287 				const COLLADAFW::Polygons* polygons = (const COLLADAFW::Polygons*) meshPrimitive;
1288 				const COLLADAFW::IntValuesArray& faceVertexCountArray = polygons->getGroupedVerticesVertexCountArray();
1289 				size_t currentIndex = 0;
1290 				for ( size_t j = 0, count = faceVertexCountArray.getCount() ; j < count; ++j )
1291 				{
1292 					int faceVertexCount = faceVertexCountArray[j];
1293 					// TODO for now, we ignore holes in polygons
1294 					if ( faceVertexCount <= 0 )
1295 						continue;
1296 					MNMapFace* face = meshMap->F((int)currentFaceIndex);
1297 					int* indices = new int[faceVertexCount];
1298 					for ( int j = 0; j < faceVertexCount; ++j)
1299 					{
1300 						indices[j] = uvIndices[ currentIndex + j ] - initialIndex;
1301 					}
1302 
1303 					face->MakePoly(faceVertexCount, indices);
1304 					currentIndex += faceVertexCount;
1305 					++currentFaceIndex;
1306 					delete[] indices;
1307 				}
1308 				break;
1309 			}
1310 		case COLLADAFW::MeshPrimitive::POLYLIST:
1311 			{
1312 				const COLLADAFW::Polylist* polylist = (const COLLADAFW::Polylist*) meshPrimitive;
1313 				const COLLADAFW::IntValuesArray& faceVertexCountArray = polylist->getGroupedVerticesVertexCountArray();
1314 				size_t currentIndex = 0;
1315 				for ( size_t j = 0, count = faceVertexCountArray.getCount() ; j < count; ++j )
1316 				{
1317 					int faceVertexCount = faceVertexCountArray[j];
1318 					// polylist does not support holes!
1319 					if ( faceVertexCount <= 0 )
1320 						continue;
1321 					MNMapFace* face = meshMap->F((int)currentFaceIndex);
1322 					int* indices = new int[faceVertexCount];
1323 					for ( int j = 0; j < faceVertexCount; ++j)
1324 					{
1325 						indices[j] = uvIndices[ currentIndex + j ] - initialIndex;
1326 					}
1327 
1328 					face->MakePoly(faceVertexCount, indices);
1329 					currentIndex += faceVertexCount;
1330 					++currentFaceIndex;
1331 					delete[] indices;
1332 				}
1333 				break;
1334 			}
1335 		default:
1336 			return;
1337 		}
1338 	}
1339 
1340 	//------------------------------
getPolygonMeshPrimitiveFaceCount(const COLLADAFW::MeshPrimitive * meshPrimitive)1341 	size_t getPolygonMeshPrimitiveFaceCount( const COLLADAFW::MeshPrimitive* meshPrimitive)
1342 	{
1343 
1344 		switch (meshPrimitive->getPrimitiveType())
1345 		{
1346 		case COLLADAFW::MeshPrimitive::TRIANGLES:
1347 		case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
1348 		case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
1349 				return getTriangleMeshPrimitiveTriangleCount( meshPrimitive );
1350 		case COLLADAFW::MeshPrimitive::POLYGONS:
1351 			{
1352 				const COLLADAFW::Polygons* polygons = (const COLLADAFW::Polygons*) meshPrimitive;
1353 				const COLLADAFW::IntValuesArray& faceVertexCountArray = polygons->getGroupedVerticesVertexCountArray();
1354 				size_t faceCount = 0;
1355 				for ( size_t j = 0, count = faceVertexCountArray.getCount() ; j < count; ++j )
1356 				{
1357 					int faceVertexCount = faceVertexCountArray[j];
1358 					// TODO for now, we ignore holes in polygons
1359 					if ( faceVertexCount > 0 )
1360 					{
1361 						faceCount++;
1362 					}
1363 				}
1364 				return faceCount;
1365 			}
1366 		case COLLADAFW::MeshPrimitive::POLYLIST:
1367 			{
1368 				const COLLADAFW::Polylist* polylist = (const COLLADAFW::Polylist*) meshPrimitive;
1369 				const COLLADAFW::IntValuesArray& faceVertexCountArray = polylist->getGroupedVerticesVertexCountArray();
1370 				size_t faceCount = 0;
1371 				for ( size_t j = 0, count = faceVertexCountArray.getCount() ; j < count; ++j )
1372 				{
1373 					int faceVertexCount = faceVertexCountArray[j];
1374 					// polylist does not support holes
1375 					if ( faceVertexCount > 0 )
1376 						faceCount++;
1377 				}
1378 				return faceCount;
1379 			}
1380 		default:
1381 			return 0;
1382 		}
1383 	}
1384 
1385 
1386 	//------------------------------
fillPolygonMeshMapPerSet(const COLLADAFW::MeshVertexData & uvCoordinates,const COLLADAFW::MeshVertexData::InputInfosArray & inputInfos,size_t sourceIndex,MNMap * meshMap)1387 	void GeometryImporter::fillPolygonMeshMapPerSet( const COLLADAFW::MeshVertexData& uvCoordinates,
1388 		                                        const COLLADAFW::MeshVertexData::InputInfosArray& inputInfos,
1389 		                                        size_t sourceIndex,
1390 			                                    MNMap* meshMap)
1391 	{
1392 		const COLLADAFW::MeshVertexData::InputInfos* inputInfo = inputInfos[ sourceIndex ];
1393 
1394 		size_t stride = inputInfo->mStride;
1395 		size_t vertsCount = inputInfo->mLength / stride;
1396 
1397 		// calculate first index position
1398 		size_t startPosition = 0;
1399 		for ( size_t i = 0; i < sourceIndex; ++i)
1400 		{
1401 			const COLLADAFW::MeshVertexData::InputInfos* inputInfo = inputInfos[ i ];
1402 			startPosition += inputInfo->mLength;
1403 		}
1404 
1405 		meshMap->setNumVerts((int)vertsCount);
1406 
1407 
1408 		if ( uvCoordinates.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE )
1409 		{
1410 			const COLLADAFW::DoubleArray& uvArray = *uvCoordinates.getDoubleValues();
1411 			setPolygonMeshUVVertices(uvArray, meshMap, stride, startPosition, vertsCount);
1412 		}
1413 		else
1414 		{
1415 			const COLLADAFW::FloatArray& uvArray = *uvCoordinates.getFloatValues();
1416 			setPolygonMeshUVVertices(uvArray, meshMap, stride, startPosition, vertsCount);
1417 		}
1418 
1419 	}
1420 
1421 
1422 	//------------------------------
importPolygonMeshUVCoords(PolyObject * polygonObject)1423 	bool GeometryImporter::importPolygonMeshUVCoords( PolyObject* polygonObject )
1424 	{
1425 		COLLADAFW::Mesh* mesh = (COLLADAFW::Mesh*) mGeometry;
1426 
1427 		createSetSourcePairMapChannelMap();
1428 
1429 		MNMesh& polygonMesh = polygonObject->GetMesh();
1430 
1431 		polygonMesh.SetMapNum( mLargestMapChannel + 1 );
1432 
1433 		int facesCount = polygonMesh.FNum();;
1434 
1435 		// reset all texture indices of all used maps
1436 		for ( int i = 0; i <= mLargestMapChannel; ++i )
1437 		{
1438 			// enable / initialize the Map
1439 			polygonMesh.InitMap(i);
1440 //			MNMap& meshMap = polygonMesh.M(i);
1441 //			meshMap.setNumFaces( facesCount );
1442 //			memset( meshMap.tf, 0, sizeof(TVFace) * facesCount);
1443 		}
1444 
1445 		const COLLADAFW::MeshVertexData& uvCoordinates = mesh->getUVCoords();
1446 		const COLLADAFW::MeshVertexData& vertexColors = mesh->getColors();
1447 		const COLLADAFW::MeshVertexData::InputInfosArray& uvInputInfos = uvCoordinates.getInputInfosArray();
1448 		const COLLADAFW::MeshVertexData::InputInfosArray& vertexColorInputInfos = vertexColors.getInputInfosArray();
1449 
1450 
1451 		SetSourcePairMapChannelMap::const_iterator it = mSetSourcePairMapChannelMap.begin();
1452 		bool hasColorChannel = false;
1453 		for ( ; it != mSetSourcePairMapChannelMap.end(); ++it )
1454 		{
1455 			const SetSourcePair& setSourcePair = it->first;
1456 			const size_t& sourceIndex = setSourcePair.second;
1457 			// check that the channel is a texture channel and not a color channel
1458 			long setIndex = setSourcePair.first;
1459 			int mapChannel = it->second;
1460 			MNMap* meshMap = polygonMesh.M(mapChannel);
1461 
1462 			assert( (mapChannel != 0) || ( setIndex < 0) );
1463 			if ( setIndex >= 0 )
1464 			{
1465 				fillPolygonMeshMapPerSet( uvCoordinates, uvInputInfos, sourceIndex, meshMap);
1466 			}
1467 			else if ( !hasColorChannel )
1468 			{
1469 				fillPolygonMeshMapPerSet( vertexColors, vertexColorInputInfos, sourceIndex, meshMap);
1470 				hasColorChannel = true;
1471 			}
1472 
1473 		}
1474 
1475 
1476 		COLLADAFW::MeshPrimitiveArray& meshPrimitiveArray =  mesh->getMeshPrimitives();
1477 		size_t faceIndex = 0;
1478 		for ( size_t i = 0, count = meshPrimitiveArray.getCount(); i < count; ++i)
1479 		{
1480 			const COLLADAFW::MeshPrimitive* meshPrimitive = meshPrimitiveArray[i];
1481 			if ( ! meshPrimitive )
1482 				continue;
1483 
1484 			if (isSupportedMeshPrimitive(meshPrimitive))
1485 			{
1486 				size_t currentFaceIndex = faceIndex;
1487 
1488 				const COLLADAFW::IndexListArray& uvIndexArray = meshPrimitive->getUVCoordIndicesArray();
1489 				for ( size_t j = 0, count = uvIndexArray.getCount(); j < count; ++j)
1490 				{
1491 					const COLLADAFW::IndexList& uvIndexList = *uvIndexArray[j];
1492 					size_t sourceIndex = mUVInitialIndexSourceIndexMap[uvIndexList.getInitialIndex()];
1493 					size_t setIndex = uvIndexList.getSetIndex();
1494 					SetSourcePair setSourcePair( (long)setIndex, sourceIndex);
1495 					int mapChannel = mSetSourcePairMapChannelMap[ setSourcePair ];
1496 
1497 					unsigned int initialIndex = (unsigned int)uvIndexList.getInitialIndex();
1498 
1499 					const COLLADAFW::UIntValuesArray& uvIndices =  uvIndexList.getIndices();
1500 
1501 					MNMap* meshMap = polygonMesh.M(mapChannel);
1502 
1503 					currentFaceIndex = faceIndex;
1504 
1505 					setPolygonMeshUVVerticesPerPrimitiveAndChannel( meshPrimitive, meshMap, uvIndices, initialIndex, currentFaceIndex);
1506 
1507 
1508 				}
1509 
1510 				// vertex color color
1511 				const COLLADAFW::IndexListArray& colorIndexArray = meshPrimitive->getColorIndicesArray();
1512 				for ( size_t j = 0, count = colorIndexArray.getCount(); j < count; ++j)
1513 				{
1514 					const COLLADAFW::IndexList& colorIndexList = *colorIndexArray[j];
1515 					size_t sourceIndex = mColorInitialIndexSourceIndexMap[colorIndexList.getInitialIndex()];
1516 					size_t setIndex = colorIndexList.getSetIndex();
1517 					SetSourcePair setSourcePair( -(long)(setIndex + 1), sourceIndex);
1518 					int mapChannel = mSetSourcePairMapChannelMap[ setSourcePair ];
1519 					if ( mapChannel != 0)
1520 						continue;
1521 
1522 					unsigned int initialIndex = (unsigned int)colorIndexList.getInitialIndex();
1523 
1524 					const COLLADAFW::UIntValuesArray& colorIndices =  colorIndexList.getIndices();
1525 
1526 					MNMap* meshMap = polygonMesh.M(mapChannel);
1527 
1528 					currentFaceIndex = faceIndex;
1529 
1530 					setPolygonMeshUVVerticesPerPrimitiveAndChannel( meshPrimitive, meshMap, colorIndices, initialIndex, currentFaceIndex);
1531 					polygonMesh.SetDisplayVertexColors(0);
1532 					mHasVertexColor = true;
1533 				}
1534 
1535 				if ( faceIndex == currentFaceIndex )
1536 				{
1537 					// setTriangleMeshUVVerticesPerPrimitiveAndChannel was never called. we need to count triangle here
1538 					faceIndex += getPolygonMeshPrimitiveFaceCount(meshPrimitive);
1539 				}
1540 				else
1541 				{
1542 					// currentFaceIndex was properly set by the last setTriangleMeshUVVerticesPerPrimitiveAndChannel call
1543 					faceIndex = currentFaceIndex;
1544 				}
1545 			}
1546 		}
1547 		return true;
1548 	}
1549 
1550 
1551 	//------------------------------
createFWMaterialIdMaxMtlIdMap(const COLLADAFW::MeshPrimitiveArray & primitiveArray,DocumentImporter::FWMaterialIdMaxMtlIdMap & materialMap)1552 	void GeometryImporter::createFWMaterialIdMaxMtlIdMap( const COLLADAFW::MeshPrimitiveArray& primitiveArray, DocumentImporter::FWMaterialIdMaxMtlIdMap& materialMap )
1553 	{
1554 		MtlID nextMaxMaterialId = 1;
1555 		for ( size_t i = 0, count = primitiveArray.getCount(); i < count; ++i )
1556 		{
1557 			const COLLADAFW::MeshPrimitive* primitive = primitiveArray[i];
1558 
1559 			if (isSupportedMeshPrimitive(primitive))
1560 			{
1561 				COLLADAFW::MaterialId fWMaterialId = primitive->getMaterialId();
1562 				if ( materialMap.count(fWMaterialId) == 0 )
1563 				{
1564 					materialMap[fWMaterialId] = nextMaxMaterialId++;
1565 				}
1566 			}
1567 		}
1568 	}
1569 
1570 	//------------------------------
createSetSourcePairMapChannelMap()1571 	void GeometryImporter::createSetSourcePairMapChannelMap()
1572 	{
1573 		if ( mGeometry->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH )
1574 			return;
1575 
1576 		bool usedMapChannels[MAX_MESHMAPS + NUM_HIDDENMAPS];
1577 		memset(usedMapChannels, false, sizeof(bool) * (MAX_MESHMAPS + NUM_HIDDENMAPS));
1578 
1579 		COLLADAFW::Mesh* mesh = (COLLADAFW::Mesh*) mGeometry;
1580 
1581 		const COLLADAFW::MeshVertexData& colors = mesh->getColors();
1582 		const COLLADAFW::MeshVertexData::InputInfosArray& colorInputInfos = colors.getInputInfosArray();
1583 		size_t colorInitialIndex = 0;
1584 		for ( size_t i = 0, count = colorInputInfos.getCount(); i < count; ++i)
1585 		{
1586 			const COLLADAFW::MeshVertexData::InputInfos* inputInfo = colorInputInfos[i];
1587 			size_t& sourceIndex = i;
1588 			mColorInitialIndexSourceIndexMap.insert(std::make_pair(colorInitialIndex, sourceIndex));
1589 			mColorSourceIndexInitialIndexMap.insert(std::make_pair(sourceIndex, colorInitialIndex));
1590 			colorInitialIndex += (inputInfo->mLength / inputInfo->mStride);
1591 		}
1592 
1593 		const COLLADAFW::MeshVertexData& uvCoords = mesh->getUVCoords();
1594 		const COLLADAFW::MeshVertexData::InputInfosArray& uVInputInfos = uvCoords.getInputInfosArray();
1595 		size_t uVInitialIndex = 0;
1596 		for ( size_t i = 0, count = uVInputInfos.getCount(); i < count; ++i)
1597 		{
1598 			size_t& sourceIndex = i;
1599 			const COLLADAFW::MeshVertexData::InputInfos* inputInfo = uVInputInfos[sourceIndex];
1600 			mUVInitialIndexSourceIndexMap.insert(std::make_pair(uVInitialIndex, sourceIndex));
1601 			mUVSourceIndexInitialIndexMap.insert(std::make_pair(sourceIndex, uVInitialIndex));
1602 			uVInitialIndex += (inputInfo->mLength / inputInfo->mStride);
1603 		}
1604 
1605 
1606 		const COLLADAFW::MeshPrimitiveArray& meshPrimitives = mesh->getMeshPrimitives();
1607 
1608 		// first try
1609 		for ( size_t i = 0, count = meshPrimitives.getCount(); i < count; ++i )
1610 		{
1611 			const COLLADAFW::MeshPrimitive* meshPrimitive = meshPrimitives[i];
1612 
1613 			if (isSupportedMeshPrimitive(meshPrimitive))
1614 			{
1615 				const COLLADAFW::IndexListArray& uvIndices = meshPrimitive->getUVCoordIndicesArray();
1616 				const COLLADAFW::IndexListArray& colorIndices = meshPrimitive->getColorIndicesArray();
1617 
1618 				assignMapChannels<true, true>( colorIndices, mColorInitialIndexSourceIndexMap, usedMapChannels);
1619 				assignMapChannels<false, true>( uvIndices, mUVInitialIndexSourceIndexMap, usedMapChannels);
1620 			}
1621 		}
1622 
1623 		// second try
1624 		for ( size_t i = 0, count = meshPrimitives.getCount(); i < count; ++i )
1625 		{
1626 			const COLLADAFW::MeshPrimitive* meshPrimitive = meshPrimitives[i];
1627 			if (isSupportedMeshPrimitive(meshPrimitive))
1628 			{
1629 				const COLLADAFW::IndexListArray& uvIndices = meshPrimitive->getUVCoordIndicesArray();
1630 				const COLLADAFW::IndexListArray& colorIndices = meshPrimitive->getColorIndicesArray();
1631 
1632 				if ( !assignMapChannels<true, false>( colorIndices, mColorInitialIndexSourceIndexMap, usedMapChannels) )
1633 				{
1634 					break;
1635 				}
1636 				if ( !assignMapChannels<false, false>( uvIndices, mUVInitialIndexSourceIndexMap, usedMapChannels) )
1637 				{
1638 					break;
1639 				}
1640 			}
1641 		}
1642 
1643 		// fill the setMapChannelMap for this geometry
1644 		DocumentImporter::SetMapChannelMap& setMapChannelMap = getSetMapChannelByGeometryUniqueId( mGeometry->getUniqueId() );
1645 		SetSourcePairMapChannelMap::const_iterator it = mSetSourcePairMapChannelMap.begin();
1646 		for ( ; it != mSetSourcePairMapChannelMap.end(); ++it )
1647 		{
1648 			const SetSourcePair& setSourcePair = it->first;
1649 			long setIndex = setSourcePair.first;
1650 			if ( setIndex >= 0)
1651 			{
1652 				setMapChannelMap[setIndex] = it->second;
1653 			}
1654 		}
1655 	}
1656 
1657 	template<bool isColorChannel, bool isFirstTry>
assignMapChannels(const COLLADAFW::IndexListArray & indices,const InitialIndexSourceIndexMap & initialIndexSourceIndexMap,bool usedMapChannels[MAX_MESHMAPS+NUM_HIDDENMAPS])1658 	bool GeometryImporter::assignMapChannels( const COLLADAFW::IndexListArray& indices,
1659 		                                      const InitialIndexSourceIndexMap& initialIndexSourceIndexMap,
1660 											  bool usedMapChannels[MAX_MESHMAPS + NUM_HIDDENMAPS])
1661 	{
1662 		for ( size_t j = 0, count = indices.getCount(); j < count; ++j)
1663 		{
1664 			const COLLADAFW::IndexList* indexList = indices[j];
1665 			size_t setIndex = indexList->getSetIndex();
1666 			size_t initialIndex = indexList->getInitialIndex();
1667 			InitialIndexSourceIndexMap::const_iterator sourecIndexIt = initialIndexSourceIndexMap.find(initialIndex);
1668 			assert(sourecIndexIt != initialIndexSourceIndexMap.end());
1669 			size_t sourceIndex = sourecIndexIt->second;
1670 			SetSourcePair setSourcePair( isColorChannel ? -(long)(setIndex+1) : (long)setIndex, sourceIndex);
1671 			SetSourcePairMapChannelMap::const_iterator it = mSetSourcePairMapChannelMap.find( setSourcePair );
1672 
1673 			// check if we have already assigned a map channel to this color set/ source combination
1674 			if ( it != mSetSourcePairMapChannelMap.end() )
1675 				continue;
1676 
1677 			// assign a map channel
1678 			int favoredMapChannel = isColorChannel ? ((setIndex == 1) ? 0 : (int)setIndex) : ((setIndex == 0) ? 1 : (int)setIndex);
1679 
1680 			if ( isFirstTry )
1681 			{
1682 				if ( favoredMapChannel <= MAX_MESHMAPS)
1683 				{
1684 					if ( !usedMapChannels[favoredMapChannel + NUM_HIDDENMAPS])
1685 					{
1686 						mSetSourcePairMapChannelMap.insert( std::make_pair(setSourcePair, favoredMapChannel));
1687 
1688 						if ( favoredMapChannel > mLargestMapChannel )
1689 							mLargestMapChannel = favoredMapChannel;
1690 
1691 						usedMapChannels[favoredMapChannel + NUM_HIDDENMAPS] = true;
1692 					}
1693 				}
1694 			}
1695 			else
1696 			{
1697 				// assign a map channel
1698 				int mapChannelIndex = 1;
1699 
1700 				// Use the next unused map channel
1701 				while ( true )
1702 				{
1703 					if ( mapChannelIndex > MAX_MESHMAPS)
1704 						return false;
1705 
1706 					if ( !usedMapChannels[mapChannelIndex + NUM_HIDDENMAPS] )
1707 					{
1708 						mSetSourcePairMapChannelMap.insert( std::make_pair(setSourcePair, mapChannelIndex));
1709 
1710 						if ( mapChannelIndex > mLargestMapChannel )
1711 							mLargestMapChannel = mapChannelIndex;
1712 
1713 						usedMapChannels[mapChannelIndex + NUM_HIDDENMAPS] = true;
1714 						break;
1715 					}
1716 
1717 					++mapChannelIndex;
1718 				}
1719 			}
1720 		}
1721 		return true;
1722 	}
1723 
skipMeshData(const COLLADAFW::MeshPrimitive * meshPrimitive,const COLLADAFW::UIntValuesArray & dataIndices,size_t & faceIndex)1724 	bool GeometryImporter::skipMeshData( const COLLADAFW::MeshPrimitive* meshPrimitive,
1725 										 const COLLADAFW::UIntValuesArray& dataIndices,
1726 										 size_t& faceIndex)
1727 	{
1728 		const COLLADAFW::UIntValuesArray& positionIndices = meshPrimitive->getPositionIndices();
1729 
1730 		size_t positionIndicesCount = positionIndices.getCount();
1731 
1732 		if ( dataIndices.getCount() != positionIndicesCount )
1733 		{
1734 			switch (meshPrimitive->getPrimitiveType())
1735 			{
1736 			case COLLADAFW::MeshPrimitive::TRIANGLES:
1737 				{
1738 					faceIndex += positionIndicesCount/3;
1739 					break;
1740 				}
1741 			case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
1742 			case COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
1743 				{
1744 					faceIndex += (positionIndicesCount > 2) ? (positionIndicesCount - 2) : 0;
1745 					break;
1746 				}
1747 			}
1748 			// todo handle error
1749 			return true;
1750 		}
1751 		else
1752 		{
1753 			return false;
1754 		}
1755 	}
1756 
1757 
1758 } // namespace COLLADAMax
1759