Exemple #1
0
bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh)  // checks if mesh has supported primitive types: lines, polylist, triangles, triangle_fans
{
	COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();

	const std::string &name = bc_get_dae_name(mesh);
	int hole_count = 0;

	for (unsigned i = 0; i < prim_arr.getCount(); i++) {
		
		COLLADAFW::MeshPrimitive *mp = prim_arr[i];
		COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType();

		const char *type_str = bc_primTypeToStr(type);
		
		// OpenCollada passes POLYGONS type for <polylist>
		if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {

			COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
			COLLADAFW::Polygons::VertexCountArray& vca = mpvc->getGroupedVerticesVertexCountArray();
			
			for (unsigned int j = 0; j < vca.getCount(); j++) {
				int count = vca[j];
				if (abs(count) < 3) {
					fprintf(stderr, "ERROR: Primitive %s in %s has at least one face with vertex count < 3\n",
					        type_str, name.c_str());
					return false;
				}
				if (count < 0)
				{
					hole_count ++;
				}
			}

			if (hole_count > 0)
			{
				fprintf(stderr, "WARNING: Primitive %s in %s: %d holes not imported (unsupported)\n", type_str, name.c_str(), hole_count);
			}
		}

		else if (type == COLLADAFW::MeshPrimitive::LINES) {
			// TODO: Add Checker for line syntax here
		}

		else if (type != COLLADAFW::MeshPrimitive::TRIANGLES && type != COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
			fprintf(stderr, "ERROR: Primitive type %s is not supported.\n", type_str);
			return false;
		}
	}
	
	if (mesh->getPositions().empty()) {
		fprintf(stderr, "ERROR: Mesh %s has no vertices.\n", name.c_str());
		return false;
	}

	return true;
}
 static shared_ptr <GLTF::GLTFPrimitive> ConvertOpenCOLLADAMeshPrimitive(
                                                                         COLLADAFW::MeshPrimitive *openCOLLADAMeshPrimitive,
                                                                         IndicesVector &primitiveIndicesVector)
 {
     shared_ptr <GLTF::GLTFPrimitive> cvtPrimitive(new GLTF::GLTFPrimitive());
     
     // We want to match OpenGL/ES mode , as WebGL spec points to OpenGL/ES spec...
     // "Symbolic constants GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, and GL_TRIANGLES are accepted."
     std::string type;
     bool shouldTriangulate = false;
     
     switch(openCOLLADAMeshPrimitive->getPrimitiveType()) {
             //these 2 requires transforms
         case COLLADAFW::MeshPrimitive::POLYLIST:
         case COLLADAFW::MeshPrimitive::POLYGONS:
             // FIXME: perform conversion, but until not done report error
             //these mode are supported by WebGL
             shouldTriangulate = true;
             //force triangles
             type = "TRIANGLES";
             break;
         case  COLLADAFW::MeshPrimitive::LINES:
             type = "LINES";
             break;
         case  COLLADAFW::MeshPrimitive::LINE_STRIPS:
             type = "LINE_STRIP";
             break;
             
         case  COLLADAFW::MeshPrimitive::TRIANGLES:
             type = "TRIANGLES";
             break;
             
         case  COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
             type = "TRIANGLE_FANS";
             break;
             
         case  COLLADAFW::MeshPrimitive::TRIANGLE_STRIPS:
             type = "TRIANGLE_STRIPS";
             break;
             
         case  COLLADAFW::MeshPrimitive::POINTS:
             type = "POINTS";
             break;
         default:
             break;
     }
     
     cvtPrimitive->setMaterialObjectID((unsigned int)openCOLLADAMeshPrimitive->getMaterialId());
     cvtPrimitive->setType(type);
     
     //count of indices , it must be the same for all kind of indices
     size_t count = openCOLLADAMeshPrimitive->getPositionIndices().getCount();
     
     //vertex
     //IndexList &positionIndexList = openCOLLADAMeshPrimitive->getPositionIndices();
     unsigned int *indices = openCOLLADAMeshPrimitive->getPositionIndices().getData();
     unsigned int *verticesCountArray = 0;
     unsigned int vcount = 0;   //count of elements in the array containing the count of indices per polygon & polylist.
     
     if (shouldTriangulate) {
         unsigned int triangulatedIndicesCount = 0;
         //We have to upcast to polygon to retrieve the array of vertexCount
         //OpenCOLLADA use polylist as polygon.
         COLLADAFW::Polygons *polygon = (COLLADAFW::Polygons*)openCOLLADAMeshPrimitive;
         const COLLADAFW::Polygons::VertexCountArray& vertexCountArray = polygon->getGroupedVerticesVertexCountArray();
         vcount = (unsigned int)vertexCountArray.getCount();
         verticesCountArray = (unsigned int*)malloc(sizeof(unsigned int) * vcount);
         for (size_t i = 0; i < vcount; i++) {
             verticesCountArray[i] = polygon->getGroupedVerticesVertexCount(i);;
         }
         indices = createTrianglesFromPolylist(verticesCountArray, indices, vcount, &triangulatedIndicesCount);
         count = triangulatedIndicesCount;
     }
     
     shared_ptr <GLTFBufferView> positionBuffer = createBufferViewWithAllocatedBuffer(indices, 0, count * sizeof(unsigned int), shouldTriangulate ? true : false);
     
     shared_ptr <GLTF::GLTFIndices> positionIndices(new GLTF::GLTFIndices(positionBuffer,count));
     
     __AppendIndices(cvtPrimitive, primitiveIndicesVector, positionIndices, POSITION, 0);
     
     if (openCOLLADAMeshPrimitive->hasNormalIndices()) {
         unsigned int triangulatedIndicesCount = 0;
         indices = openCOLLADAMeshPrimitive->getNormalIndices().getData();
         if (shouldTriangulate) {
             indices = createTrianglesFromPolylist(verticesCountArray, indices, vcount, &triangulatedIndicesCount);
             count = triangulatedIndicesCount;
         }
         
         shared_ptr <GLTF::GLTFBufferView> normalBuffer = createBufferViewWithAllocatedBuffer(indices, 0, count * sizeof(unsigned int), shouldTriangulate ? true : false);
         shared_ptr <GLTF::GLTFIndices> normalIndices(new GLTF::GLTFIndices(normalBuffer,
                                                                            count));
         __AppendIndices(cvtPrimitive, primitiveIndicesVector, normalIndices, NORMAL, 0);
     }
     
     if (openCOLLADAMeshPrimitive->hasColorIndices()) {
         COLLADAFW::IndexListArray& colorListArray = openCOLLADAMeshPrimitive->getColorIndicesArray();
         for (size_t i = 0 ; i < colorListArray.getCount() ; i++) {
             COLLADAFW::IndexList* indexList = openCOLLADAMeshPrimitive->getColorIndices(i);
             __HandleIndexList(i,
                               indexList,
                               GLTF::COLOR,
                               shouldTriangulate,
                               count,
                               vcount,
                               verticesCountArray,
                               cvtPrimitive,
                               primitiveIndicesVector);
         }
     }
     
     if (openCOLLADAMeshPrimitive->hasUVCoordIndices()) {
         COLLADAFW::IndexListArray& uvListArray = openCOLLADAMeshPrimitive->getUVCoordIndicesArray();
         for (size_t i = 0 ; i < uvListArray.getCount() ; i++) {
             COLLADAFW::IndexList* indexList = openCOLLADAMeshPrimitive->getUVCoordIndices(i);
             __HandleIndexList(i,
                               indexList,
                               GLTF::TEXCOORD,
                               shouldTriangulate,
                               count,
                               vcount,
                               verticesCountArray,
                               cvtPrimitive,
                               primitiveIndicesVector);
         }
     }
     
     if (verticesCountArray) {
         free(verticesCountArray);
     }
     
     return cvtPrimitive;
 }
// =================================================================
// Return the number of faces by summing up
// the facecounts of the parts.
// hint: This is done because mesh->getFacesCount() does
// count loose edges as extra faces, which is not what we want here.
// =================================================================
void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
{
	COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives();
	int total_poly_count  = 0;
	int total_loop_count  = 0;

	// collect edge_count and face_count from all parts
	for (int i = 0; i < prim_arr.getCount(); i++) {
		COLLADAFW::MeshPrimitive *mp = prim_arr[i];
		int type = mp->getPrimitiveType();
		switch (type) {
			case COLLADAFW::MeshPrimitive::TRIANGLES:
			case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
			case COLLADAFW::MeshPrimitive::POLYLIST:
			case COLLADAFW::MeshPrimitive::POLYGONS:
			{
				COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
				size_t prim_poly_count    = mpvc->getFaceCount();

				size_t prim_loop_count    = 0;
				for (int index=0; index < prim_poly_count; index++) {
					prim_loop_count += get_vertex_count(mpvc, index);
				}

				total_poly_count += prim_poly_count;
				total_loop_count += prim_loop_count;

				break;
			}
			default:
				break;
		}
	}

	// Add the data containers
	if (total_poly_count > 0) {
		me->totpoly = total_poly_count;
		me->totloop = total_loop_count;
		me->mpoly   = (MPoly *)CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, me->totpoly);
		me->mloop   = (MLoop *)CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, me->totloop);

		unsigned int totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount();
		for (int i = 0; i < totuvset; i++) {
			if (collada_mesh->getUVCoords().getLength(i) == 0) {
				totuvset = 0;
				break;
			}
		}

		if (totuvset > 0) {
			for (int i = 0; i < totuvset; i++) {
				COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getUVCoords().getInputInfosArray()[i];
				COLLADAFW::String &uvname = info->mName;
				// Allocate space for UV_data
				CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname.c_str());
				CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, uvname.c_str());
			}
			// activate the first uv map
			me->mtpoly  = (MTexPoly *)CustomData_get_layer_n(&me->pdata, CD_MTEXPOLY, 0);
			me->mloopuv = (MLoopUV *) CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0);
		}

		int totcolset = collada_mesh->getColors().getInputInfosArray().getCount();
		if (totcolset > 0) {
			for (int i = 0; i < totcolset; i++) {
				COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getColors().getInputInfosArray()[i];
				COLLADAFW::String colname = extract_vcolname(info->mName);
				CustomData_add_layer_named(&me->ldata,CD_MLOOPCOL,CD_DEFAULT,NULL,me->totloop, colname.c_str());
			}
			me->mloopcol = (MLoopCol *) CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, 0);
		}

	}
}