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); } } }