| 63 | } |
| 64 | |
| 65 | void ColladaSerializer::ColladaExporter::ColladaGeometries::write( |
| 66 | const std::string &mesh_id, const std::string &/**<@todo 'default_material_name' unused, remove? */, |
| 67 | const std::vector<double>& positions, const std::vector<double>& normals, |
| 68 | const std::vector<int>& faces, const std::vector<int>& edges, |
| 69 | const std::vector<int>& material_ids, const std::vector<ifcopenshell::geometry::taxonomy::style::ptr>& /**<@todo 'materials' unused, remove? */, |
| 70 | const std::vector<double>& uvs, const std::vector<std::string>& material_references) |
| 71 | { |
| 72 | openMesh(mesh_id); |
| 73 | |
| 74 | // The normals vector can be empty for example when the WELD_VERTICES setting is used. |
| 75 | // IfcOpenShell does not provide them with multiple face normals collapsed into a single vertex. |
| 76 | const bool has_normals = !normals.empty(); |
| 77 | const bool has_uvs = !uvs.empty(); |
| 78 | |
| 79 | addFloatSource(mesh_id, COLLADASW::LibraryGeometries::POSITIONS_SOURCE_ID_SUFFIX, positions); |
| 80 | if (has_normals) { |
| 81 | addFloatSource(mesh_id, COLLADASW::LibraryGeometries::NORMALS_SOURCE_ID_SUFFIX, normals); |
| 82 | if (has_uvs) { |
| 83 | addFloatSource(mesh_id, COLLADASW::LibraryGeometries::TEXCOORDS_SOURCE_ID_SUFFIX, uvs, "UV"); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | COLLADASW::VerticesElement vertices(mSW); |
| 88 | vertices.setId(mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX ); |
| 89 | vertices.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::POSITION, "#" + mesh_id + COLLADASW::LibraryGeometries::POSITIONS_SOURCE_ID_SUFFIX)); |
| 90 | vertices.add(); |
| 91 | |
| 92 | std::vector<int>::const_iterator index_range_start = faces.begin(); |
| 93 | std::vector<int>::const_iterator material_it = material_ids.begin(); |
| 94 | int previous_material_id = -1; |
| 95 | for (std::vector<int>::const_iterator it = faces.begin(); !faces.empty(); it += 3) { |
| 96 | |
| 97 | int current_material_id = 0; |
| 98 | if (material_it != material_ids.end()) { |
| 99 | // In order for the last range of equal material ids to be output as well, this loop iterates |
| 100 | // one element past the end of the vector. This needs to be observed when incrementing. |
| 101 | current_material_id = *(material_it++); |
| 102 | } |
| 103 | |
| 104 | const size_t num_triangles = std::distance(index_range_start, it) / 3; |
| 105 | if ((previous_material_id != current_material_id && num_triangles > 0) || (it == faces.end())) { |
| 106 | COLLADASW::Triangles triangles(mSW); |
| 107 | |
| 108 | std::string material_name = material_references[previous_material_id]; |
| 109 | triangles.setMaterial(material_name); |
| 110 | triangles.setCount((unsigned long)num_triangles); |
| 111 | int offset = 0; |
| 112 | triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX,"#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, offset++)); |
| 113 | if (has_normals) { |
| 114 | triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::NORMAL,"#" + mesh_id + COLLADASW::LibraryGeometries::NORMALS_SOURCE_ID_SUFFIX, offset++)); |
| 115 | } |
| 116 | if (has_uvs) { |
| 117 | triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::TEXCOORD,"#" + mesh_id + COLLADASW::LibraryGeometries::TEXCOORDS_SOURCE_ID_SUFFIX, offset++)); |
| 118 | } |
| 119 | triangles.prepareToAppendValues(); |
| 120 | for (std::vector<int>::const_iterator jt = index_range_start; jt != it; ++jt) { |
| 121 | const int idx = *jt; |
| 122 | if (has_normals && has_uvs) { |