#include "WorldObject.h" #include "../chinese_postman/ChinesePostman.h" #include "tiny_obj_loader.h" struct pair_hash { inline std::size_t operator()(const std::pair& v) const { return v.first * 31 + v.second; } }; WorldObject::WorldObject(juce::InputStream& stream) { tinyobj::ObjReaderConfig reader_config; tinyobj::ObjReader reader; reader.ParseFromString(stream.readEntireStreamAsString().toStdString(), "", reader_config); vs = reader.GetAttrib().vertices; numVertices = vs.size() / 3; std::vector shapes = reader.GetShapes(); std::unordered_set, pair_hash> edge_set; for (auto& shape : shapes) { int i = 0; int face = 0; while (i < shape.mesh.indices.size()) { int prevVertex = -1; for (int j = 0; j < shape.mesh.num_face_vertices[face]; j++) { int vertex = shape.mesh.indices[i].vertex_index; if (prevVertex != -1) { edge_set.insert(std::make_pair(prevVertex, vertex)); } prevVertex = vertex; i++; } face++; } } std::list> edge_list; for (auto& edge : edge_set) { edge_list.push_back(edge); } Graph graph(numVertices, edge_list); pair, double> solution = ChinesePostman(graph); list& path = solution.first; double x = 0.0, y = 0.0, z = 0.0; double max = 0.0; for (int i = 0; i < numVertices; i++) { x += vs[i * 3]; y += vs[i * 3 + 1]; z += vs[i * 3 + 2]; if (std::abs(vs[i * 3]) > max) { max = std::abs(vs[i * 3]); } if (std::abs(vs[i * 3 + 1]) > max) { max = std::abs(vs[i * 3 + 1]); } if (std::abs(vs[i * 3 + 2]) > max) { max = std::abs(vs[i * 3 + 2]); } } x /= numVertices; y /= numVertices; z /= numVertices; for (int i = 0; i < numVertices; i++) { vs[i * 3] = (vs[i * 3] - x) / max; vs[i * 3 + 1] = (vs[i * 3 + 1] - y) / max; vs[i * 3 + 2] = (vs[i * 3 + 2] - z) / max; } int prevVertex = -1; for (auto& vertex : path) { if (prevVertex != -1) { double x1 = vs[prevVertex * 3]; double y1 = vs[prevVertex * 3 + 1]; double z1 = vs[prevVertex * 3 + 2]; double x2 = vs[vertex * 3]; double y2 = vs[vertex * 3 + 1]; double z2 = vs[vertex * 3 + 2]; edges.push_back(Line3D(x1, y1, z1, x2, y2, z2)); } prevVertex = vertex; } }