diff options
-rw-r--r-- | assetFactory/faceController.cpp | 126 | ||||
-rw-r--r-- | assetFactory/faceController.h | 3 |
2 files changed, 68 insertions, 61 deletions
diff --git a/assetFactory/faceController.cpp b/assetFactory/faceController.cpp index 6493300..bafbee2 100644 --- a/assetFactory/faceController.cpp +++ b/assetFactory/faceController.cpp @@ -14,82 +14,86 @@ FaceController::apply(ModelFactoryMesh & mesh, const StyleStack & parents, const }); } +std::string +FaceController::getAdjacentFaceName( + const ModelFactoryMesh & mesh, const std::span<const OpenMesh::FaceHandle> ofrange, OpenMesh::FaceHandle nf) +{ + const auto nfrange = mesh.ff_range(nf); + if (const auto target = std::find_first_of(ofrange.begin(), ofrange.end(), nfrange.begin(), nfrange.end()); + target != ofrange.end()) { + return mesh.property(mesh.nameFaceProperty, *target); + }; + return {}; +}; + void FaceController::applySingle(ModelFactoryMesh & mesh, const StyleStack & parents, const std::string & name, Shape::CreatedFaces & faces) const { - const auto getAdjacentFaceName = [&mesh](const auto & ofrange, OpenMesh::FaceHandle nf) -> std::string { - const auto nfrange = mesh.ff_range(nf); - if (const auto target = std::find_first_of(ofrange.begin(), ofrange.end(), nfrange.begin(), nfrange.end()); - target != ofrange.end()) { - return mesh.property(mesh.nameFaceProperty, *target); - }; - return {}; - }; - const auto controlledFaces {materializeRange(faces.equal_range(name))}; if (controlledFaces.empty()) { throw std::runtime_error("Named face(s) do not exist: " + name); } if (!type.empty()) { - const auto mutation = getMatrix(); faces.erase(name); - for (const auto & cf : controlledFaces) { - // get points - const auto baseVertices {materializeRange(mesh.fv_range(cf.second))}; - auto points = std::accumulate(baseVertices.begin(), baseVertices.end(), std::vector<glm::vec3> {}, - [&mesh](auto && out, auto && v) { - out.push_back(mesh.point(v)); - return std::move(out); - }); - const auto vertexCount = points.size(); - const auto centre = mesh.calc_face_centroid(cf.second); - if (type == "extrude") { - Shape::CreatedFaces newFaces; - // mutate points - std::for_each(points.begin(), points.end(), [&mutation, ¢re](auto && p) { - p = centre + ((p - centre) % mutation); - }); - // create new vertices - std::vector<OpenMesh::VertexHandle> vertices; - std::transform(points.begin(), points.end(), std::back_inserter(vertices), [&mesh](auto && p) { - return mesh.add_vertex(p); - }); - // create new faces - const auto ofrange = materializeRange(mesh.ff_range(cf.second)); - mesh.delete_face(cf.second); - for (size_t idx {}; idx < vertexCount; ++idx) { - const auto next = (idx + 1) % vertexCount; - const auto newFace - = mesh.add_face({baseVertices[idx], baseVertices[next], vertices[next], vertices[idx]}); - auto & newFaceName = mesh.property(mesh.nameFaceProperty, newFace); - newFaceName = getAdjacentFaceName(ofrange, newFace); - newFaces.emplace(newFaceName, newFace); - } - newFaces.emplace(name, mesh.add_face(vertices)); - if (smooth) { - for (const auto & [name, face] : newFaces) { - mesh.property(mesh.smoothFaceProperty, face) = true; - } - } - applyStyle(mesh, parents + this, newFaces); - for (const auto & [subFaceName, faceController] : faceControllers) { - faceController->apply(mesh, parents + this, subFaceName, newFaces); - } - faces.merge(std::move(newFaces)); - } - else { - mesh.property(mesh.smoothFaceProperty, cf.second) = smooth; - applyStyle(mesh, parents + this, cf.second); + } + for (const auto & [faceName, faceHandle] : controlledFaces) { + if (type == "extrude") { + auto newFaces = extrude(mesh, faceName, faceHandle); + applyStyle(mesh, parents + this, newFaces); + for (const auto & [subFaceName, faceController] : faceControllers) { + faceController->apply(mesh, parents + this, subFaceName, newFaces); } + faces.merge(std::move(newFaces)); } - } - else { - for (const auto & cf : controlledFaces) { - applyStyle(mesh, parents + this, cf.second); + else { + mesh.property(mesh.smoothFaceProperty, faceHandle) = smooth; + applyStyle(mesh, parents + this, faceHandle); } } + for (const auto & [faceName, faceHandle] : controlledFaces) { + mesh.property(mesh.smoothFaceProperty, faceHandle) = smooth; + applyStyle(mesh, parents + this, faceHandle); + } +} + +Shape::CreatedFaces +FaceController::extrude(ModelFactoryMesh & mesh, const std::string & faceName, OpenMesh::FaceHandle faceHandle) const +{ + // get points + const auto baseVertices {materializeRange(mesh.fv_range(faceHandle))}; + auto points = std::accumulate( + baseVertices.begin(), baseVertices.end(), std::vector<glm::vec3> {}, [&mesh](auto && out, auto && v) { + out.push_back(mesh.point(v)); + return std::move(out); + }); + const auto vertexCount = points.size(); + const auto centre = mesh.calc_face_centroid(faceHandle); + Shape::CreatedFaces newFaces; + // mutate points + std::for_each(points.begin(), points.end(), [mutation = getMatrix(), ¢re](auto && p) { + p = centre + ((p - centre) % mutation); + }); + // create new vertices + std::vector<OpenMesh::VertexHandle> vertices; + std::transform(points.begin(), points.end(), std::back_inserter(vertices), [&mesh](auto && p) { + return mesh.add_vertex(p); + }); + // create new faces + const auto ofrange = materializeRange(mesh.ff_range(faceHandle)); + mesh.delete_face(faceHandle); + for (size_t idx {}; idx < vertexCount; ++idx) { + const auto next = (idx + 1) % vertexCount; + const auto newFace = mesh.add_face({baseVertices[idx], baseVertices[next], vertices[next], vertices[idx]}); + auto & newFaceName = mesh.property(mesh.nameFaceProperty, newFace); + newFaceName = getAdjacentFaceName(mesh, ofrange, newFace); + newFaces.emplace(newFaceName, newFace); + mesh.property(mesh.smoothFaceProperty, newFace) = smooth; + } + mesh.property(mesh.smoothFaceProperty, newFaces.emplace(faceName, mesh.add_face(vertices))->second) = smooth; + + return newFaces; } bool diff --git a/assetFactory/faceController.h b/assetFactory/faceController.h index 890aafa..962a516 100644 --- a/assetFactory/faceController.h +++ b/assetFactory/faceController.h @@ -31,4 +31,7 @@ private: void applySingle(ModelFactoryMesh & mesh, const Style::StyleStack & parents, const std::string & name, Shape::CreatedFaces & faces) const; + static std::string getAdjacentFaceName(const ModelFactoryMesh & mesh, + const std::span<const OpenMesh::FaceHandle> ofrange, OpenMesh::FaceHandle nf); + Shape::CreatedFaces extrude(ModelFactoryMesh & mesh, const std::string & faceName, OpenMesh::FaceHandle) const; }; |