Fixed ram_horn example, slight refactor on to_mesh

This commit is contained in:
Chris Hodapp 2020-02-22 08:26:27 -05:00
parent 436cb0bbc4
commit c594538644
4 changed files with 39 additions and 33 deletions

View File

@ -2,15 +2,15 @@
## Highest priority:
- See `ram_horn_*` and `curve_horn_*` TODOs: these are both solved by
some sort of parent-vertex-mapping layer. The only other way around
this that I need is to require that rule functions exist in
explictly separate forms.
- Consider trampolining `to_mesh`. My call stack seems needlessly
deep in spots. Can I make tail-recursive?
- Clean up my 'parent vertex mapping' thingy, *and* come up with
meaningful terms to discuss it.
- Do transforms compose in the *reverse* of automata_scratch? This
appears to be the case.
## Important but less critical:
- Consider trampolining `to_mesh`. My call stack seems needlessly
deep in spots. Can I make tail-recursive?
- Grep for all TODOs in code, really.
- Look at everything in README.md in automata_scratch.
- Implement some of the tougher examples from the above too, e.g. the

View File

@ -119,11 +119,11 @@ fn cube_thing_rule() -> RuleStep {
// Conversion from Python & automata_scratch
fn ram_horn_start() -> RuleStep {
let opening_xform = |i| {
(geometry::Translation3::new(0.0, 0.0, -1.0).to_homogeneous() *
Matrix4::new_scaling(0.5) *
((geometry::Rotation3::from_axis_angle(
&nalgebra::Vector3::z_axis(), i).to_homogeneous()) *
geometry::Translation3::new(0.25, 0.25, 1.0).to_homogeneous() *
geometry::Rotation3::from_axis_angle(
&nalgebra::Vector3::z_axis(), i).to_homogeneous())
Matrix4::new_scaling(0.5) *
geometry::Translation3::new(0.0, 0.0, -1.0).to_homogeneous())
};
RuleStep {
geom: OpenMesh {
@ -171,19 +171,21 @@ fn ram_horn_start() -> RuleStep {
},
final_geom: prim::empty_mesh(),
children: vec![
(Rule::Recurse(ram_horn), opening_xform(0.0), vec![0,4,8,7]),
(Rule::Recurse(ram_horn), opening_xform(std::f32::consts::FRAC_PI_2), vec![1,5,8,4]),
(Rule::Recurse(ram_horn), opening_xform(std::f32::consts::FRAC_PI_2*2.0), vec![2,6,8,5]),
(Rule::Recurse(ram_horn), opening_xform(std::f32::consts::FRAC_PI_2*3.0), vec![3,7,8,6]),
(Rule::Recurse(ram_horn), opening_xform(0.0), vec![5,2,6,8]),
(Rule::Recurse(ram_horn), opening_xform(std::f32::consts::FRAC_PI_2), vec![4,1,5,8]),
(Rule::Recurse(ram_horn), opening_xform(std::f32::consts::FRAC_PI_2*2.0), vec![7,0,4,8]),
(Rule::Recurse(ram_horn), opening_xform(std::f32::consts::FRAC_PI_2*3.0), vec![6,3,7,8]),
// TODO: These vertex mappings appear to be right.
// Understand *why* they are right.
],
}
}
fn ram_horn() -> RuleStep {
let v = Unit::new_normalize(Vector3::new(-1.0, 0.0, 1.0));
let incr: Mat4 = Matrix4::new_scaling(0.9) *
let incr: Mat4 = geometry::Translation3::new(0.0, 0.0, 0.8).to_homogeneous() *
geometry::Rotation3::from_axis_angle(&v, 0.3).to_homogeneous() *
geometry::Translation3::new(0.0, 0.0, 0.8).to_homogeneous();
Matrix4::new_scaling(0.9);
let seed = vec![
vertex(-0.5, -0.5, 1.0),
vertex(-0.5, 0.5, 1.0),
@ -202,10 +204,6 @@ fn ram_horn() -> RuleStep {
Tag::Parent(3), Tag::Parent(2), Tag::Body(3),
Tag::Body(0), Tag::Parent(3), Tag::Body(3),
Tag::Parent(0), Tag::Parent(3), Tag::Body(0),
// TODO: These are correct once the recursion is already
// going - but they are wrong at the start! Note how I'm
// never using the 'midpoint' vertex from the parent,
// Tag::Parent(8).
],
};
let final_geom = OpenMesh {
@ -238,6 +236,8 @@ pub fn main() {
};
run_test(Rule::Recurse(cube_thing_rule), 3, "cube_thing");
// this can't work on its own because the resultant OpenMesh still
// has parent references:
//run_test(Rule::Recurse(curve_horn_thing_rule), 100, "curve_horn_thing");
run_test(Rule::Recurse(curve_horn_start), 100, "curve_horn2");
run_test(Rule::Recurse(ram_horn_start), 200, "ram_horn");

View File

@ -84,7 +84,8 @@ impl OpenMesh {
stl_io::write_stl(writer, triangles.iter())
}
pub fn connect(&self, others: &Vec<(OpenMesh, Vec<usize>)>) -> OpenMesh {
pub fn connect(&self, others: &Vec<(OpenMesh, &Vec<usize>)>) -> OpenMesh {
// TODO: Clean up Vec<usize> stuff
// Copy body vertices & faces:
let mut verts: Vec<Vertex> = self.verts.clone();

View File

@ -26,6 +26,9 @@ pub struct RuleStep {
// Child rules, paired with the transform that will be applied to
// all of their geometry and parent vertex mappings
pub children: Vec<(Rule, Mat4, Vec<usize>)>,
// TODO: Clean this up, perhaps change the tuple to something
// saner.
// TODO: Also, document & rename this more clearly.
}
impl Rule {
@ -57,21 +60,23 @@ impl Rule {
match self {
Rule::Recurse(f) => {
let rs: RuleStep = f();
// TODO: This logic is more or less right, but it
// could perhaps use some un-tupling or something.
// Get sub-geometry (from child rules) and transform it:
let subgeom: Vec<(OpenMesh, Mat4, u32, Vec<usize>)> = rs.children.iter().map(|(subrule, subxform, mapping)| {
let (m,n) = subrule.to_mesh(iters_left - 1);
(m, *subxform, n, mapping.clone())
}).collect();
// Tally up node count:
subgeom.iter().for_each(|(_,_,n,_)| nodes += n);
let g: Vec<(OpenMesh, Vec<usize>)> = subgeom.iter().map(|(m,x,_,mv)| (m.transform(*x), mv.clone())).collect();
// TODO: Not clone twice
let subgeom: Vec<(OpenMesh, &Vec<usize>)> = rs.children.iter().map(
|(subrule, subxform, vmap)| {
// Get sub-geometry (still un-transformed):
let (submesh,n) = subrule.to_mesh(iters_left - 1);
// Tally up node count:
nodes += n;
let m2 = submesh.transform(*subxform);
(m2, vmap)
}).collect();
// Connect geometry from this rule (not child rules):
return (rs.geom.connect(&g), nodes);
return (rs.geom.connect(&subgeom), nodes);
}
Rule::EmptyRule => {
return (prim::empty_mesh(), nodes);