diff --git a/README.md b/README.md
index 9fb5c6a..9b68e34 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,6 @@
## Highest priority:
-- Continue fixing `to_mesh_iter`, which still doesn't yet handle
- branching because (for one thing) it never tracks depth properly in
- order to backtrack.
- Clean up `twist` - maybe make a struct or trait.
- Do transforms compose in the *reverse* of automata_scratch? This
appears to be the case.
diff --git a/src/rule.rs b/src/rule.rs
index 58c0627..7595d4a 100644
--- a/src/rule.rs
+++ b/src/rule.rs
@@ -1,4 +1,4 @@
-use crate::openmesh::{OpenMesh, Mat4};
+use crate::openmesh::{OpenMesh, Tag, Mat4};
use crate::prim;
/// Definition of a rule. In general, a `Rule`:
@@ -84,6 +84,9 @@ impl Rule {
let rs: RuleEval = (self.eval)(arg);
if iters_left <= 0 {
return (rs.final_geom, 1);
+ // TODO: This is probably wrong because of the way that
+ // sub.vmap is used below. final_geom is not supposed to
+ // have any vertex mapping applied.
}
// TODO: This logic is more or less right, but it
@@ -114,10 +117,11 @@ impl Rule {
rules: Vec>,
// The next element of 'children' to handle:
next: usize,
- // The world transform of the *parent* of 'rules', that
- // is, not including any transform of any element of
- // 'rules'.
+ // World transform of the *parent* of 'rules', that is,
+ // not including any transform of any element of 'rules'.
xf: Mat4,
+ // How many levels 'deeper' can we recurse?
+ depth: usize,
}
// 'stack' stores at its last element our "current" State in
@@ -125,17 +129,16 @@ impl Rule {
// be processed next. Every element prior to this is previous
// states which must be kept around for further backtracking
// (usually because they involve multiple rules).
- let mut stack: Vec> = vec![];
- let mut geom = prim::empty_mesh();
-
- // Set up the stack's initial state - evaluate our own rule
+ //
+ // We evaluate our own rule to initialize the stack:
let eval = (self.eval)(arg);
- stack.push(State {
+ let mut stack: Vec> = vec![State {
rules: eval.children,
next: 0,
xf: nalgebra::geometry::Transform3::identity().to_homogeneous(),
- });
- geom = eval.geom;
+ depth: max_depth,
+ }];
+ let mut geom = eval.geom;
// Number of times we've evaluated a Rule:
let mut eval_count = 1;
@@ -145,28 +148,14 @@ impl Rule {
while !stack.is_empty() {
- // TODO: This, more elegantly?
- if eval_count > max_depth {
- break;
- }
-
- println!("DEBUG: stack has len {}", n);
+ // s = the 'current' state:
let s = &mut stack[n-1];
-
- if s.next >= s.rules.len() {
- // If we've run out of child rules, have the *parent* node (if one) move on:
- if n >= 2 {
- stack[n-2].next += 1;
- }
- // and backtrack:
- stack.pop();
- n -= 1;
- // (if there isn't one, it makes no difference,
- // because the loop will end)
- continue;
- }
+ let depth = s.depth;
+ // TODO: remove
+ //println!("DEBUG: stack has len {}; depth={}", n, depth);
let child = &s.rules[s.next];
+
// Evaluate the rule:
let mut eval = (child.rule.eval)(arg);
eval_count += 1;
@@ -177,8 +166,48 @@ impl Rule {
// This rule produced some geometry which we'll
// combine with the 'global' geometry:
let new_geom = eval.geom.transform(&xf);
- println!("DEBUG: Connecting {} faces, vmap={:?}, faces={:?}",
- new_geom.verts.len(), child.vmap, new_geom.faces);
+
+ // See if we can still recurse further:
+ if depth <= 0 {
+ // TODO: remove
+ //println!("DEBUG: backtracing, depth={}, s.next = {}, s.rules.len() = {}",
+ // depth, s.next, s.rules.len());
+
+ // As we're stopping recursion, we need to connect
+ // final_geom with all else in order to actually close
+ // geometry properly:
+ let final_geom = eval.final_geom.transform(&xf);
+ // TODO: Fix the awful hack below. I do this only to
+ // generate an identity mapping for vmap when I don't
+ // actually need vmap.
+ let m = {
+ let mut m_ = 0;
+ for f in &final_geom.faces {
+ match f {
+ Tag::Parent(i) => {
+ if *i > m_ {
+ m_ = *i;
+ }
+ }
+ _ => {}
+ }
+ }
+ m_ + 1
+ };
+ let vmap: Vec = (0..m).collect();
+ let (geom2, _) = new_geom.connect(&vec![(final_geom, &vmap)]);
+
+ geom = geom.connect(&vec![(geom2, &child.vmap)]).0;
+
+ // and backtrack:
+ stack.pop();
+ n -= 1;
+ continue;
+ }
+
+ // TODO: remove
+ //println!("DEBUG: Connecting {} faces, vmap={:?}, faces={:?}",
+ // new_geom.verts.len(), child.vmap, new_geom.faces);
let (g, offsets) = geom.connect(&vec![(new_geom, &child.vmap)]);
geom = g;
@@ -197,29 +226,27 @@ impl Rule {
}).collect();
}
- // TODO: Why does below work?
- if (s.next + 1) >= s.rules.len() {
+ // We're done evaluating this rule, so increment 'next'.
+ // If that was the last rule at this level (i.e. ignoring
+ // eval.children), remove it - we're done with it.
+ s.next += 1;
+ if s.next >= s.rules.len() {
let m = stack.len();
- if m >= 2 {
- stack[m-2].next += 1;
- }
stack.pop();
n -= 1;
}
- // I guess we are "done" with the rule after we've
- // evaluated it, and it is then safe to increment
- // s.next.
-
- // Recurse further (i.e. put more onto stack):
- stack.push(State {
- rules: eval.children,
- next: 0,
- xf: xf,
- });
- n += 1;
+
+ if !eval.children.is_empty() {
+ // Recurse further (i.e. put more onto stack):
+ stack.push(State {
+ rules: eval.children,
+ next: 0,
+ xf: xf,
+ depth: depth - 1,
+ });
+ n += 1;
+ }
}
- // TODO: Recursion depth? What does that even mean here?
- // Maybe something more like 'branch depth'?
// TODO: Handle final_geom