Fixed final_geom bug in to_mesh_iter

...but then found that to_mesh probably has the same bug
This commit is contained in:
Chris Hodapp 2020-03-06 14:59:53 -05:00
parent 94dabbee25
commit 52914b2588
2 changed files with 77 additions and 53 deletions

View File

@ -2,9 +2,6 @@
## Highest priority: ## 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. - Clean up `twist` - maybe make a struct or trait.
- Do transforms compose in the *reverse* of automata_scratch? This - Do transforms compose in the *reverse* of automata_scratch? This
appears to be the case. appears to be the case.

View File

@ -1,4 +1,4 @@
use crate::openmesh::{OpenMesh, Mat4}; use crate::openmesh::{OpenMesh, Tag, Mat4};
use crate::prim; use crate::prim;
/// Definition of a rule. In general, a `Rule`: /// Definition of a rule. In general, a `Rule`:
@ -84,6 +84,9 @@ impl<A> Rule<A> {
let rs: RuleEval<A> = (self.eval)(arg); let rs: RuleEval<A> = (self.eval)(arg);
if iters_left <= 0 { if iters_left <= 0 {
return (rs.final_geom, 1); 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 // TODO: This logic is more or less right, but it
@ -114,10 +117,11 @@ impl<A> Rule<A> {
rules: Vec<Child<A>>, rules: Vec<Child<A>>,
// The next element of 'children' to handle: // The next element of 'children' to handle:
next: usize, next: usize,
// The world transform of the *parent* of 'rules', that // World transform of the *parent* of 'rules', that is,
// is, not including any transform of any element of // not including any transform of any element of 'rules'.
// 'rules'.
xf: Mat4, xf: Mat4,
// How many levels 'deeper' can we recurse?
depth: usize,
} }
// 'stack' stores at its last element our "current" State in // 'stack' stores at its last element our "current" State in
@ -125,17 +129,16 @@ impl<A> Rule<A> {
// be processed next. Every element prior to this is previous // be processed next. Every element prior to this is previous
// states which must be kept around for further backtracking // states which must be kept around for further backtracking
// (usually because they involve multiple rules). // (usually because they involve multiple rules).
let mut stack: Vec<State<A>> = vec![]; //
let mut geom = prim::empty_mesh(); // We evaluate our own rule to initialize the stack:
// Set up the stack's initial state - evaluate our own rule
let eval = (self.eval)(arg); let eval = (self.eval)(arg);
stack.push(State { let mut stack: Vec<State<A>> = vec![State {
rules: eval.children, rules: eval.children,
next: 0, next: 0,
xf: nalgebra::geometry::Transform3::identity().to_homogeneous(), xf: nalgebra::geometry::Transform3::identity().to_homogeneous(),
}); depth: max_depth,
geom = eval.geom; }];
let mut geom = eval.geom;
// Number of times we've evaluated a Rule: // Number of times we've evaluated a Rule:
let mut eval_count = 1; let mut eval_count = 1;
@ -145,28 +148,14 @@ impl<A> Rule<A> {
while !stack.is_empty() { while !stack.is_empty() {
// TODO: This, more elegantly? // s = the 'current' state:
if eval_count > max_depth {
break;
}
println!("DEBUG: stack has len {}", n);
let s = &mut stack[n-1]; let s = &mut stack[n-1];
let depth = s.depth;
if s.next >= s.rules.len() { // TODO: remove
// If we've run out of child rules, have the *parent* node (if one) move on: //println!("DEBUG: stack has len {}; depth={}", n, depth);
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 child = &s.rules[s.next]; let child = &s.rules[s.next];
// Evaluate the rule: // Evaluate the rule:
let mut eval = (child.rule.eval)(arg); let mut eval = (child.rule.eval)(arg);
eval_count += 1; eval_count += 1;
@ -177,8 +166,48 @@ impl<A> Rule<A> {
// This rule produced some geometry which we'll // This rule produced some geometry which we'll
// combine with the 'global' geometry: // combine with the 'global' geometry:
let new_geom = eval.geom.transform(&xf); 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<usize> = (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)]); let (g, offsets) = geom.connect(&vec![(new_geom, &child.vmap)]);
geom = g; geom = g;
@ -197,29 +226,27 @@ impl<A> Rule<A> {
}).collect(); }).collect();
} }
// TODO: Why does below work? // We're done evaluating this rule, so increment 'next'.
if (s.next + 1) >= s.rules.len() { // 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(); let m = stack.len();
if m >= 2 {
stack[m-2].next += 1;
}
stack.pop(); stack.pop();
n -= 1; n -= 1;
} }
// I guess we are "done" with the rule after we've
// evaluated it, and it is then safe to increment if !eval.children.is_empty() {
// s.next. // Recurse further (i.e. put more onto stack):
stack.push(State {
// Recurse further (i.e. put more onto stack): rules: eval.children,
stack.push(State { next: 0,
rules: eval.children, xf: xf,
next: 0, depth: depth - 1,
xf: xf, });
}); n += 1;
n += 1; }
} }
// TODO: Recursion depth? What does that even mean here?
// Maybe something more like 'branch depth'?
// TODO: Handle final_geom // TODO: Handle final_geom