From ecfdcd67fb6767a7fc2ada8d42ad7d04a1c74ce8 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Sun, 5 Jun 2022 22:15:45 +0800 Subject: [PATCH] flatten the tree on the fly if possible --- manifold/src/csg_tree.cpp | 16 ++++++++++++---- manifold/src/csg_tree.h | 3 ++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/manifold/src/csg_tree.cpp b/manifold/src/csg_tree.cpp index c7c027e3c..652bf19b6 100644 --- a/manifold/src/csg_tree.cpp +++ b/manifold/src/csg_tree.cpp @@ -216,12 +216,16 @@ CsgOpNode::CsgOpNode(const std::vector> &children, Manifold::OpType op) : children_(children) { SetOp(op); + // opportunisticly flatten the tree without costly evaluation + GetChildren(false); } CsgOpNode::CsgOpNode(std::vector> &&children, Manifold::OpType op) : children_(children) { SetOp(op); + // opportunisticly flatten the tree without costly evaluation + GetChildren(false); } std::shared_ptr CsgOpNode::Transform(const glm::mat4x3 &m) const { @@ -230,6 +234,7 @@ std::shared_ptr CsgOpNode::Transform(const glm::mat4x3 &m) const { node->op_ = op_; node->transform_ = m * glm::mat4(transform_); node->simplified = simplified; + node->flattened = flattened; return node; } @@ -382,25 +387,28 @@ void CsgOpNode::BatchUnion() const { /** * Flatten the children to a list of leaf nodes and return them. + * If finalize is true, the list will be guaranteed to be a list of leaf nodes + * (i.e. no ops). Otherwise, the list may contain ops. * Note that this function will not apply the transform to children, as they may * be shared with other nodes. */ -std::vector> &CsgOpNode::GetChildren() const { - if (children_.empty() || simplified) return children_; +std::vector> &CsgOpNode::GetChildren(bool finalize) const { + if (children_.empty() || (simplified && !finalize) || flattened) return children_; simplified = true; + flattened = finalize; std::vector> newChildren; CsgNodeType op = op_; for (auto &child : children_) { if (child->GetNodeType() == op) { auto grandchildren = - std::dynamic_pointer_cast(child)->GetChildren(); + std::dynamic_pointer_cast(child)->GetChildren(finalize); int start = children_.size(); for (auto &grandchild : grandchildren) { newChildren.push_back(grandchild->Transform(child->GetTransform())); } } else { - if (child->GetNodeType() == CsgNodeType::LEAF) { + if (!finalize || child->GetNodeType() == CsgNodeType::LEAF) { newChildren.push_back(child); } else { newChildren.push_back(child->ToLeafNode()); diff --git a/manifold/src/csg_tree.h b/manifold/src/csg_tree.h index c1ac601bd..5962eef8c 100644 --- a/manifold/src/csg_tree.h +++ b/manifold/src/csg_tree.h @@ -72,6 +72,7 @@ class CsgOpNode final : public CsgNode { mutable std::vector> children_; mutable std::shared_ptr cache_ = nullptr; mutable bool simplified = false; + mutable bool flattened = false; void SetOp(Manifold::OpType); @@ -81,7 +82,7 @@ class CsgOpNode final : public CsgNode { void BatchUnion() const; - std::vector> &GetChildren() const; + std::vector> &GetChildren(bool finalize = true) const; }; } // namespace manifold