diff --git a/Cargo.toml b/Cargo.toml index e74db42..a0dbef0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,11 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[profile.release] +# Unoptimized debug builds are too slow to profile +# having debug info doesn't hurt perf for now +debug = true + [dependencies] euclid = "0.20.7" nalgebra = "0.19.0" diff --git a/src/examples.rs b/src/examples.rs index 39d4518..5def7e0 100644 --- a/src/examples.rs +++ b/src/examples.rs @@ -31,8 +31,8 @@ fn cube_thing() -> Rule { let xforms = turns.iter().map(|xf| xf.scale(0.5).translate(6.0, 0.0, 0.0)); RuleEval { - geom: prim::cube(), - final_geom: prim::empty_mesh(), + geom: Rc::new(prim::cube()), + final_geom: Rc::new(prim::empty_mesh()), children: xforms.map(move |xf| Child { rule: self_.clone(), xf: xf, @@ -75,13 +75,13 @@ fn twist(f: f32, subdiv: usize) -> Rule { let seed_next = incr.transform(&seed2); - let geom: OpenMesh = util::zigzag_to_parent(seed_next.clone(), n); + let geom = Rc::new(util::zigzag_to_parent(seed_next.clone(), n)); // TODO: Cleanliness fix - why not just make these return meshes? let (vc, faces) = util::connect_convex(&seed_next, true); - let final_geom = OpenMesh { + let final_geom = Rc::new(OpenMesh { verts: vec![vc], faces: faces, - }; + }); let c = move |self_: Rc| -> RuleEval { // TODO: Why clone geometry here if I just have to clone it @@ -142,38 +142,39 @@ fn ramhorn() -> Rule { translate(0.0, 0.0, 0.8). rotate(&v, 0.3). scale(0.9); + + let seed = vec![ + vertex(-0.5, -0.5, 1.0), + vertex(-0.5, 0.5, 1.0), + vertex( 0.5, 0.5, 1.0), + vertex( 0.5, -0.5, 1.0), + ]; + let next = incr.transform(&seed); + let geom = Rc::new(OpenMesh { + verts: next, + faces: vec![ + Tag::Body(1), Tag::Parent(0), Tag::Body(0), + Tag::Parent(1), Tag::Parent(0), Tag::Body(1), + Tag::Body(2), Tag::Parent(1), Tag::Body(1), + Tag::Parent(2), Tag::Parent(1), Tag::Body(2), + Tag::Body(3), Tag::Parent(2), Tag::Body(2), + 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), + ], + }); + let final_geom = Rc::new(OpenMesh { + verts: vec![], + faces: vec![ + Tag::Parent(0), Tag::Parent(2), Tag::Parent(1), + Tag::Parent(0), Tag::Parent(3), Tag::Parent(2), + ], + }); let recur = move |self_: Rc| -> RuleEval { - let seed = vec![ - vertex(-0.5, -0.5, 1.0), - vertex(-0.5, 0.5, 1.0), - vertex( 0.5, 0.5, 1.0), - vertex( 0.5, -0.5, 1.0), - ]; - let next = incr.transform(&seed); - let geom = OpenMesh { - verts: next, - faces: vec![ - Tag::Body(1), Tag::Parent(0), Tag::Body(0), - Tag::Parent(1), Tag::Parent(0), Tag::Body(1), - Tag::Body(2), Tag::Parent(1), Tag::Body(1), - Tag::Parent(2), Tag::Parent(1), Tag::Body(2), - Tag::Body(3), Tag::Parent(2), Tag::Body(2), - 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), - ], - }; - let final_geom = OpenMesh { - verts: vec![], - faces: vec![ - Tag::Parent(0), Tag::Parent(2), Tag::Parent(1), - Tag::Parent(0), Tag::Parent(3), Tag::Parent(2), - ], - }; RuleEval { - geom: geom, - final_geom: final_geom, + geom: geom.clone(), + final_geom: final_geom.clone(), children: vec![ Child { rule: self_.clone(), @@ -198,7 +199,7 @@ fn ramhorn() -> Rule { //let ofn = opening_xform.clone(); RuleEval { - geom: OpenMesh { + geom: Rc::new(OpenMesh { verts: vec![ // 'Top' vertices: vertex(-0.5, -0.5, 1.0), // 0 (above 9) @@ -240,8 +241,8 @@ fn ramhorn() -> Rule { Tag::Body(11), Tag::Body(6), Tag::Body(12), Tag::Body(12), Tag::Body(7), Tag::Body(9), ], - }, - final_geom: prim::empty_mesh(), + }), + final_geom: Rc::new(prim::empty_mesh()), children: vec![ Child { rule: Rc::new(Rule { eval: Box::new(recur.clone()) }), diff --git a/src/openmesh.rs b/src/openmesh.rs index 2114549..4a4a0c8 100644 --- a/src/openmesh.rs +++ b/src/openmesh.rs @@ -130,7 +130,11 @@ impl OpenMesh { /// That is, the vertices of 'children[i]' begin at vertex /// 'offset[i]' of the new mesh. This is needed in some cases for /// adjusting a parent vertex mapping, like 'vmap' of Rule::Child. - pub fn connect(&self, children: &Vec<(OpenMesh, &Vec)>) -> (OpenMesh, Vec) { + pub fn connect(&self, children: T) -> (OpenMesh, Vec) + where U: Borrow, + T: IntoIterator)> + //pub fn connect(&self, children: &Vec<(OpenMesh, Vec)>) -> (OpenMesh, Vec) + { // TODO: Clean up this description a bit // TODO: Clean up Vec stuff @@ -140,8 +144,10 @@ impl OpenMesh { let mut offsets: Vec = vec![]; - for (child,mapping) in children { + for (child_,mapping) in children { + let child = child_.borrow(); + // body_offset corresponds to the position in 'verts' at // which we're appending everything in 'child.verts' - // thus, the offset we shift all indices in 'children' by. diff --git a/src/rule.rs b/src/rule.rs index 8c82d50..2adf93f 100644 --- a/src/rule.rs +++ b/src/rule.rs @@ -36,7 +36,7 @@ pub struct Rule { /// `geom`. pub struct RuleEval { /// The geometry generated at just this iteration - pub geom: OpenMesh, + pub geom: Rc, /// The "final" geometry that is merged with `geom` via /// `connect()` in the event that recursion stops. This must be @@ -44,7 +44,7 @@ pub struct RuleEval { /// /// Parent vertex references will be resolved directly to `geom` /// with no mapping. - pub final_geom: OpenMesh, + pub final_geom: Rc, /// The child invocations (used if recursion continues). The /// 'parent' mesh, from the perspective of all geometry produced @@ -92,7 +92,7 @@ impl Rule { let rs: RuleEval = (s.eval)(s.clone()); if iters_left <= 0 { - return (rs.final_geom, 1); + return ((*rs.final_geom).clone(), 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. @@ -101,7 +101,7 @@ impl Rule { // TODO: This logic is more or less right, but it // could perhaps use some un-tupling or something. - let subgeom: Vec<(OpenMesh, &Vec)> = rs.children.iter().map(|sub| { + let subgeom: Vec<(OpenMesh, Vec)> = rs.children.iter().map(|sub| { // Get sub-geometry (still un-transformed): let (submesh, eval) = Rule::to_mesh(sub.rule.clone(), iters_left - 1); // Tally up eval count: @@ -109,11 +109,12 @@ impl Rule { let m2 = submesh.transform(&sub.xf); - (m2, &sub.vmap) + (m2, sub.vmap.clone()) + // TODO: Fix clone? }).collect(); // Connect geometry from this rule (not child rules): - return (rs.geom.connect(&subgeom).0, evals); + return (rs.geom.connect(subgeom).0, evals); } /// This should be identical to to_mesh, but implemented @@ -147,7 +148,7 @@ impl Rule { xf: Transform::new(), depth: max_depth, }]; - let mut geom = eval.geom; + let mut geom = (*eval.geom).clone(); // Number of times we've evaluated a Rule: let mut eval_count = 1; @@ -203,9 +204,10 @@ impl Rule { m_ + 1 }; let vmap: Vec = (0..m).collect(); - let (geom2, _) = new_geom.connect(&vec![(final_geom, &vmap)]); + let (geom2, _) = new_geom.connect(vec![(final_geom, vmap)]); - geom = geom.connect(&vec![(geom2, &child.vmap)]).0; + geom = geom.connect(vec![(geom2, child.vmap.clone())]).0; + // TODO: Fix clone? // and backtrack: stack.pop(); @@ -213,7 +215,7 @@ impl Rule { continue; } - let (g, offsets) = geom.connect(&vec![(new_geom, &child.vmap)]); + let (g, offsets) = geom.connect(vec![(new_geom, child.vmap.clone())]); geom = g; // 'new_geom' may itself be parent geometry for @@ -281,8 +283,8 @@ impl RuleEval { }).collect(); RuleEval { - geom: mesh, - final_geom: final_geom, + geom: Rc::new(mesh), + final_geom: Rc::new(final_geom), children: children2, } }