Skip to content

Commit

Permalink
cache intermediate results (elalish#199)
Browse files Browse the repository at this point in the history
  • Loading branch information
pca006132 committed Sep 20, 2022
1 parent f6839a3 commit d81d2fa
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 23 deletions.
2 changes: 0 additions & 2 deletions samples/src/rounded_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,10 @@ Manifold RoundedFrame(float edgeLength, float radius, int circularSegments) {

Manifold edge1 = corner + edge;
edge1 = edge1.Rotate(-90).Translate({-edgeLength / 2, -edgeLength / 2, 0});
edge1.NumVert(); // Force caching

Manifold edge2 = edge1.Rotate(0, 0, 180);
edge2 += edge1;
edge2 += edge.Translate({-edgeLength / 2, -edgeLength / 2, 0});
edge2.NumVert();

Manifold edge4 = edge2.Rotate(0, 0, 90);
edge4 += edge2;
Expand Down
36 changes: 20 additions & 16 deletions src/manifold/src/csg_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,36 +230,36 @@ CsgOpNode::CsgOpNode() {}

CsgOpNode::CsgOpNode(const std::vector<std::shared_ptr<CsgNode>> &children,
Manifold::OpType op)
: children_(children) {
: impl_(std::make_shared<Impl>()) {
impl_->children_ = children;
SetOp(op);
// opportunisticly flatten the tree without costly evaluation
GetChildren(false);
}

CsgOpNode::CsgOpNode(std::vector<std::shared_ptr<CsgNode>> &&children,
Manifold::OpType op)
: children_(children) {
: impl_(std::make_shared<Impl>()) {
impl_->children_ = children;
SetOp(op);
// opportunisticly flatten the tree without costly evaluation
GetChildren(false);
}

std::shared_ptr<CsgNode> CsgOpNode::Transform(const glm::mat4x3 &m) const {
auto node = std::make_shared<CsgOpNode>();
node->children_ = children_;
node->op_ = op_;
node->impl_ = impl_;
node->transform_ = m * glm::mat4(transform_);
node->simplified_ = simplified_;
node->flattened_ = flattened_;
return node;
}

std::shared_ptr<CsgLeafNode> CsgOpNode::ToLeafNode() const {
if (cache_ != nullptr) return cache_;
if (children_.empty()) return nullptr;
if (impl_->children_.empty()) return nullptr;
// turn the children into leaf nodes
GetChildren();
switch (op_) {
auto &children_ = impl_->children_;
switch (impl_->op_) {
case CsgNodeType::UNION:
BatchUnion();
break;
Expand Down Expand Up @@ -341,6 +341,7 @@ void CsgOpNode::BatchBoolean(
*/
void CsgOpNode::BatchUnion() const {
std::vector<std::shared_ptr<const Manifold::Impl>> impls;
auto &children_ = impl_->children_;
for (auto &child : children_) {
impls.push_back(std::dynamic_pointer_cast<CsgLeafNode>(child)->GetImpl());
}
Expand All @@ -358,15 +359,18 @@ void CsgOpNode::BatchUnion() const {
*/
std::vector<std::shared_ptr<CsgNode>> &CsgOpNode::GetChildren(
bool finalize) const {
if (children_.empty() || (simplified_ && !finalize) || flattened_)
auto &children_ = impl_->children_;
if (children_.empty() || (impl_->simplified_ && !finalize) ||
impl_->flattened_)
return children_;
simplified_ = true;
flattened_ = finalize;
impl_->simplified_ = true;
impl_->flattened_ = finalize;
std::vector<std::shared_ptr<CsgNode>> newChildren;

CsgNodeType op = op_;
CsgNodeType op = impl_->op_;
for (auto &child : children_) {
if (child->GetNodeType() == op) {
if (child->GetNodeType() == op && child.use_count() == 1 &&
std::dynamic_pointer_cast<CsgOpNode>(child)->impl_.use_count() == 1) {
auto grandchildren =
std::dynamic_pointer_cast<CsgOpNode>(child)->GetChildren(finalize);
int start = children_.size();
Expand All @@ -391,13 +395,13 @@ std::vector<std::shared_ptr<CsgNode>> &CsgOpNode::GetChildren(
void CsgOpNode::SetOp(Manifold::OpType op) {
switch (op) {
case Manifold::OpType::ADD:
op_ = CsgNodeType::UNION;
impl_->op_ = CsgNodeType::UNION;
break;
case Manifold::OpType::SUBTRACT:
op_ = CsgNodeType::DIFFERENCE;
impl_->op_ = CsgNodeType::DIFFERENCE;
break;
case Manifold::OpType::INTERSECT:
op_ = CsgNodeType::INTERSECTION;
impl_->op_ = CsgNodeType::INTERSECTION;
break;
}
}
Expand Down
13 changes: 8 additions & 5 deletions src/manifold/src/csg_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,21 @@ class CsgOpNode final : public CsgNode {

std::shared_ptr<CsgLeafNode> ToLeafNode() const override;

CsgNodeType GetNodeType() const override { return op_; }
CsgNodeType GetNodeType() const override { return impl_->op_; }

glm::mat4x3 GetTransform() const override;

private:
CsgNodeType op_;
struct Impl {
CsgNodeType op_;
mutable std::vector<std::shared_ptr<CsgNode>> children_;
mutable bool simplified_ = false;
mutable bool flattened_ = false;
};
std::shared_ptr<Impl> impl_ = nullptr;
glm::mat4x3 transform_ = glm::mat4x3(1.0f);
// the following fields are for lazy evaluation, so they are mutable
mutable std::vector<std::shared_ptr<CsgNode>> children_;
mutable std::shared_ptr<CsgLeafNode> cache_ = nullptr;
mutable bool simplified_ = false;
mutable bool flattened_ = false;

void SetOp(Manifold::OpType);

Expand Down

0 comments on commit d81d2fa

Please sign in to comment.