My ramhorn_branch example finally works. It's just ugly.
Also, might be generating non-manifold geometry in certain cases.
This commit is contained in:
parent
5f27239525
commit
aba2e24e26
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
## Highest priority:
|
## Highest priority:
|
||||||
|
|
||||||
|
- Clean up `ramhorn_branch` because it's fugly. Also, fix
|
||||||
|
non-manifold stuff at higher recursions.
|
||||||
- See `automata_scratch/examples.py` and implement some of the tougher
|
- See `automata_scratch/examples.py` and implement some of the tougher
|
||||||
examples.
|
examples.
|
||||||
- `spiral_nested_2` & `spiral_nested_3` (how to compose
|
- `spiral_nested_2` & `spiral_nested_3` (how to compose
|
||||||
efficiently?)
|
efficiently?)
|
||||||
- `twisty_torus`
|
- `twisty_torus`
|
||||||
- `ram_horn_branch` - Can I pass depth via a closure? Do I need
|
|
||||||
mutual recursion for this?
|
|
||||||
|
|
||||||
## Important but less critical:
|
## Important but less critical:
|
||||||
|
|
||||||
@ -38,6 +38,10 @@
|
|||||||
- the closure can move them
|
- the closure can move them
|
||||||
- Use an actual logging framework.
|
- Use an actual logging framework.
|
||||||
- Migrate tests to... well... actual tests.
|
- Migrate tests to... well... actual tests.
|
||||||
|
- I am starting to see a pattern emerge in how I have to modularize
|
||||||
|
things around closures. What can a macro do for me here?
|
||||||
|
- swept-isocontour stuff from
|
||||||
|
`/mnt/dev/graphics_misc/isosurfaces_2018_2019/spiral*.py`
|
||||||
|
|
||||||
## If I'm bored:
|
## If I'm bored:
|
||||||
|
|
||||||
|
|||||||
149
src/examples.rs
149
src/examples.rs
@ -278,11 +278,11 @@ struct RamHornCtxt {
|
|||||||
depth: usize,
|
depth: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ramhorn_twist(depth: usize) -> Rule<RamHornCtxt> {
|
fn ramhorn_branch(depth: usize) -> Rule<RamHornCtxt> {
|
||||||
|
|
||||||
// Quarter-turn in radians:
|
// Quarter-turn in radians:
|
||||||
let qtr = std::f32::consts::FRAC_PI_2;
|
//let qtr = std::f32::consts::FRAC_PI_2;
|
||||||
let z = Vector3::z_axis();
|
//let z = Vector3::z_axis();
|
||||||
|
|
||||||
let v = Unit::new_normalize(Vector3::new(-1.0, 0.0, 1.0));
|
let v = Unit::new_normalize(Vector3::new(-1.0, 0.0, 1.0));
|
||||||
let incr: Transform = Transform::new().
|
let incr: Transform = Transform::new().
|
||||||
@ -318,56 +318,6 @@ fn ramhorn_twist(depth: usize) -> Rule<RamHornCtxt> {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
let recur = move |self_: Rc<Rule<RamHornCtxt>>| -> RuleEval<RamHornCtxt> {
|
|
||||||
let children = if self_.ctxt.depth <= 0 {
|
|
||||||
let next_rule = Rc::new(Rule {
|
|
||||||
eval: self_.eval.clone(),
|
|
||||||
ctxt: RamHornCtxt { depth },
|
|
||||||
});
|
|
||||||
vec![
|
|
||||||
Child {
|
|
||||||
rule: next_rule.clone(),
|
|
||||||
xf: incr.scale(0.5).translate(1.0, 1.0, 2.0).rotate(&z, qtr*0.0),
|
|
||||||
vmap: vec![0,1,2,3],
|
|
||||||
},
|
|
||||||
Child {
|
|
||||||
rule: next_rule.clone(),
|
|
||||||
xf: incr.scale(0.5).translate(-1.0, 1.0, 2.0).rotate(&z, qtr*1.0),
|
|
||||||
vmap: vec![0,1,2,3],
|
|
||||||
},
|
|
||||||
Child {
|
|
||||||
rule: next_rule.clone(),
|
|
||||||
xf: incr.scale(0.5).translate(-1.0, -1.0, 2.0).rotate(&z, qtr*2.0),
|
|
||||||
vmap: vec![0,1,2,3],
|
|
||||||
},
|
|
||||||
Child {
|
|
||||||
rule: next_rule.clone(),
|
|
||||||
xf: incr.scale(0.5).translate(1.0, -1.0, 2.0).rotate(&z, qtr*3.0),
|
|
||||||
vmap: vec![0,1,2,3],
|
|
||||||
},
|
|
||||||
// TODO: Factor out repetition
|
|
||||||
// TODO: Produce midpoint/centroid vertices like 'start' does below
|
|
||||||
]
|
|
||||||
} else {
|
|
||||||
let next_rule = Rule {
|
|
||||||
eval: self_.eval.clone(),
|
|
||||||
ctxt: RamHornCtxt { depth: self_.ctxt.depth - 1 },
|
|
||||||
};
|
|
||||||
vec![
|
|
||||||
Child {
|
|
||||||
rule: Rc::new(next_rule),
|
|
||||||
xf: incr,
|
|
||||||
vmap: vec![0,1,2,3],
|
|
||||||
},
|
|
||||||
]
|
|
||||||
};
|
|
||||||
RuleEval {
|
|
||||||
geom: geom.clone(),
|
|
||||||
final_geom: final_geom.clone(),
|
|
||||||
children: children,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let opening_xform = |i| {
|
let opening_xform = |i| {
|
||||||
let r = std::f32::consts::FRAC_PI_2 * i;
|
let r = std::f32::consts::FRAC_PI_2 * i;
|
||||||
Transform::new().
|
Transform::new().
|
||||||
@ -377,11 +327,7 @@ fn ramhorn_twist(depth: usize) -> Rule<RamHornCtxt> {
|
|||||||
translate(0.0, 0.0, -1.0)
|
translate(0.0, 0.0, -1.0)
|
||||||
};
|
};
|
||||||
|
|
||||||
let trans = move |self_: Rc<Rule<RamHornCtxt>>| -> RuleEval<RamHornCtxt> {
|
let trans_verts = vec![
|
||||||
|
|
||||||
RuleEval {
|
|
||||||
geom: Rc::new(OpenMesh {
|
|
||||||
verts: vec![
|
|
||||||
// 'Top' vertices:
|
// 'Top' vertices:
|
||||||
vertex(-0.5, -0.5, 1.0), // 0 (above 9)
|
vertex(-0.5, -0.5, 1.0), // 0 (above 9)
|
||||||
vertex(-0.5, 0.5, 1.0), // 1 (above 10)
|
vertex(-0.5, 0.5, 1.0), // 1 (above 10)
|
||||||
@ -394,8 +340,8 @@ fn ramhorn_twist(depth: usize) -> Rule<RamHornCtxt> {
|
|||||||
vertex( 0.0, -0.5, 1.0), // 7 (connects 3-0)
|
vertex( 0.0, -0.5, 1.0), // 7 (connects 3-0)
|
||||||
// Top middle:
|
// Top middle:
|
||||||
vertex( 0.0, 0.0, 1.0), // 8
|
vertex( 0.0, 0.0, 1.0), // 8
|
||||||
],
|
];
|
||||||
faces: vec![
|
let trans_faces = vec![
|
||||||
// two faces straddling edge from vertex 0:
|
// two faces straddling edge from vertex 0:
|
||||||
Tag::Parent(0), Tag::Body(0), Tag::Body(4),
|
Tag::Parent(0), Tag::Body(0), Tag::Body(4),
|
||||||
Tag::Parent(0), Tag::Body(7), Tag::Body(0),
|
Tag::Parent(0), Tag::Body(7), Tag::Body(0),
|
||||||
@ -413,35 +359,72 @@ fn ramhorn_twist(depth: usize) -> Rule<RamHornCtxt> {
|
|||||||
Tag::Parent(1), Tag::Body(5), Tag::Parent(2),
|
Tag::Parent(1), Tag::Body(5), Tag::Parent(2),
|
||||||
Tag::Parent(2), Tag::Body(6), Tag::Parent(3),
|
Tag::Parent(2), Tag::Body(6), Tag::Parent(3),
|
||||||
Tag::Parent(3), Tag::Body(7), Tag::Parent(0),
|
Tag::Parent(3), Tag::Body(7), Tag::Parent(0),
|
||||||
],
|
];
|
||||||
}),
|
let trans_geom = Rc::new(OpenMesh {
|
||||||
final_geom: Rc::new(prim::empty_mesh()),
|
verts: trans_verts.clone(),
|
||||||
children: vec![
|
faces: trans_faces.clone(),
|
||||||
|
});
|
||||||
|
let trans_children = move |recur: RuleFn<RamHornCtxt>, ctxt: RamHornCtxt| {
|
||||||
|
vec![
|
||||||
Child {
|
Child {
|
||||||
rule: Rc::new(Rule { eval: Rc::new(recur.clone()), ctxt: self_.ctxt }),
|
rule: Rc::new(Rule { eval: recur.clone(), ctxt }),
|
||||||
xf: opening_xform(0.0),
|
xf: opening_xform(0.0),
|
||||||
vmap: vec![5,2,6,8],
|
vmap: vec![5,2,6,8],
|
||||||
},
|
},
|
||||||
Child {
|
Child {
|
||||||
rule: Rc::new(Rule { eval: Rc::new(recur.clone()), ctxt: self_.ctxt }),
|
rule: Rc::new(Rule { eval: recur.clone(), ctxt }),
|
||||||
xf: opening_xform(1.0),
|
xf: opening_xform(1.0),
|
||||||
vmap: vec![4,1,5,8],
|
vmap: vec![4,1,5,8],
|
||||||
},
|
},
|
||||||
Child {
|
Child {
|
||||||
rule: Rc::new(Rule { eval: Rc::new(recur.clone()), ctxt: self_.ctxt }),
|
rule: Rc::new(Rule { eval: recur.clone(), ctxt }),
|
||||||
xf: opening_xform(2.0),
|
xf: opening_xform(2.0),
|
||||||
vmap: vec![7,0,4,8],
|
vmap: vec![7,0,4,8],
|
||||||
},
|
},
|
||||||
Child {
|
Child {
|
||||||
rule: Rc::new(Rule { eval: Rc::new(recur.clone()), ctxt: self_.ctxt }),
|
rule: Rc::new(Rule { eval: recur.clone(), ctxt }),
|
||||||
xf: opening_xform(3.0),
|
xf: opening_xform(3.0),
|
||||||
vmap: vec![6,3,7,8],
|
vmap: vec![6,3,7,8],
|
||||||
},
|
},
|
||||||
// TODO: These vertex mappings appear to be right.
|
// TODO: These vertex mappings appear to be right.
|
||||||
// Explain *why* they are right.
|
// Explain *why* they are right.
|
||||||
// TODO: Factor out the repetition here.
|
// TODO: Factor out the repetition here.
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
let tg = trans_geom.clone();
|
||||||
|
let recur = move |self_: Rc<Rule<RamHornCtxt>>| -> RuleEval<RamHornCtxt> {
|
||||||
|
if self_.ctxt.depth <= 0 {
|
||||||
|
RuleEval {
|
||||||
|
geom: tg.clone(),
|
||||||
|
final_geom: Rc::new(prim::empty_mesh()),
|
||||||
|
children: trans_children(self_.eval.clone(), RamHornCtxt { depth }),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let next_rule = Rule {
|
||||||
|
eval: self_.eval.clone(),
|
||||||
|
ctxt: RamHornCtxt { depth: self_.ctxt.depth - 1 },
|
||||||
|
};
|
||||||
|
RuleEval {
|
||||||
|
geom: geom.clone(),
|
||||||
|
final_geom: final_geom.clone(),
|
||||||
|
children: vec![
|
||||||
|
Child {
|
||||||
|
rule: Rc::new(next_rule),
|
||||||
|
xf: incr,
|
||||||
|
vmap: vec![0,1,2,3],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let trans = move |self_: Rc<Rule<RamHornCtxt>>| -> RuleEval<RamHornCtxt> {
|
||||||
|
RuleEval {
|
||||||
|
geom: trans_geom.clone(),
|
||||||
|
final_geom: Rc::new(prim::empty_mesh()),
|
||||||
|
children: trans_children(Rc::new(recur.clone()), self_.ctxt),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let start = move |self_: Rc<Rule<RamHornCtxt>>| -> RuleEval<RamHornCtxt> {
|
let start = move |self_: Rc<Rule<RamHornCtxt>>| -> RuleEval<RamHornCtxt> {
|
||||||
@ -594,28 +577,22 @@ impl CurveHorn {
|
|||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
|
||||||
fn run_test<S>(r: &Rc<Rule<S>>, iters: usize, name: &str) {
|
fn run_test<S>(r: &Rc<Rule<S>>, iters: usize, name: &str, use_old: bool) {
|
||||||
println!("Running {}...", name);
|
println!("---------------------------------------------------");
|
||||||
let (mesh, nodes) = Rule::to_mesh(r.clone(), iters);
|
println!("Running {} with {}...",
|
||||||
println!("Evaluated {} rules", nodes);
|
name, if use_old { "to_mesh" } else { "to_mesh_iter" });
|
||||||
let fname = format!("{}.stl", name);
|
|
||||||
println!("Writing {}...", fname);
|
|
||||||
mesh.write_stl_file(&fname).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run_test_iter<S>(r: &Rc<Rule<S>>, iters: usize, name: &str) {
|
|
||||||
println!("Running {}...", name);
|
|
||||||
if false {
|
if false {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let n = 5;
|
let n = 5;
|
||||||
for i in 0..n {
|
for _ in 0..n {
|
||||||
Rule::to_mesh_iter(r.clone(), iters);
|
Rule::to_mesh_iter(r.clone(), iters);
|
||||||
}
|
}
|
||||||
let elapsed = start.elapsed();
|
let elapsed = start.elapsed();
|
||||||
println!("DEBUG: {} ms per run", elapsed.as_millis() / n);
|
println!("DEBUG: {} ms per run", elapsed.as_millis() / n);
|
||||||
}
|
}
|
||||||
let (mesh, nodes) = Rule::to_mesh_iter(r.clone(), iters);
|
let mesh_fn = if use_old { Rule::to_mesh } else { Rule::to_mesh_iter };
|
||||||
println!("Evaluated {} rules", nodes);
|
let (mesh, nodes) = mesh_fn(r.clone(), iters);
|
||||||
|
println!("Evaluated {} rules to {} verts", nodes, mesh.verts.len());
|
||||||
let fname = format!("{}.stl", name);
|
let fname = format!("{}.stl", name);
|
||||||
println!("Writing {}...", fname);
|
println!("Writing {}...", fname);
|
||||||
mesh.write_stl_file(&fname).unwrap();
|
mesh.write_stl_file(&fname).unwrap();
|
||||||
@ -643,8 +620,8 @@ pub fn main() {
|
|||||||
// let f = 20;
|
// let f = 20;
|
||||||
// run_test_iter(Twist::init(f as f32, 32), 100*f, "twist2");
|
// run_test_iter(Twist::init(f as f32, 32), 100*f, "twist2");
|
||||||
|
|
||||||
run_test_iter(&Rc::new(cube_thing()), 3, "cube_thing3");
|
run_test(&Rc::new(cube_thing()), 3, "cube_thing3", false);
|
||||||
run_test_iter(&Rc::new(twist(1.0, 2)), 200, "twist");
|
run_test(&Rc::new(twist(1.0, 2)), 200, "twist", false);
|
||||||
run_test_iter(&Rc::new(ramhorn()), 100, "ram_horn3");
|
run_test(&Rc::new(ramhorn()), 100, "ram_horn3", false);
|
||||||
run_test_iter(&Rc::new(ramhorn_twist(5)), 30, "ram_horn3b_bug");
|
run_test(&Rc::new(ramhorn_branch(4)), 22, "ram_horn_branch", false);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user