Added helper function to avoid juggling of indices
This commit is contained in:
parent
558bd062d9
commit
45ab4ed9e0
@ -3,8 +3,7 @@
|
|||||||
## Highest priority:
|
## Highest priority:
|
||||||
|
|
||||||
- If my `closure_try2` branch seems to be working: start converting
|
- If my `closure_try2` branch seems to be working: start converting
|
||||||
other things and cleaning them up. Modify `twist` to have the
|
other things and cleaning everything up. (`twist` is still ugly.)
|
||||||
things I wrote this for in the first place!
|
|
||||||
- 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
|
||||||
@ -21,10 +20,12 @@
|
|||||||
- What patterns can I factor out? I do some things regularly, like:
|
- What patterns can I factor out? I do some things regularly, like:
|
||||||
the clockwise boundaries, the zigzag connections, the iterating over
|
the clockwise boundaries, the zigzag connections, the iterating over
|
||||||
a `Vec<Vertex>` to transform each element and make another vector.
|
a `Vec<Vertex>` to transform each element and make another vector.
|
||||||
- I have seen many of my bugs come from: all this arithmetic on
|
|
||||||
indices. I generate vertex maps more or less manually.
|
|
||||||
- Docs on modules
|
- Docs on modules
|
||||||
- Grep for all TODOs in code, really.
|
- Grep for all TODOs in code, really.
|
||||||
|
- Look at performance. Can I save on copies of geometry by using
|
||||||
|
`Rc<OpenMesh>` or the like? In many cases I have nothing but copied
|
||||||
|
geometry. Can I pre-allocate vectors instead of
|
||||||
|
extending/appending?
|
||||||
- Look at everything in README.md in automata_scratch.
|
- Look at everything in README.md in automata_scratch.
|
||||||
|
|
||||||
## If I'm bored:
|
## If I'm bored:
|
||||||
|
|||||||
@ -375,7 +375,6 @@ fn twist(f: f32, subdiv: usize) -> Rule {
|
|||||||
vertex( 0.5, 0.0, 0.5),
|
vertex( 0.5, 0.0, 0.5),
|
||||||
vertex(-0.5, 0.0, 0.5),
|
vertex(-0.5, 0.0, 0.5),
|
||||||
], &xf);
|
], &xf);
|
||||||
//let seed_sub = util::subdivide_cycle(&seed, subdiv);
|
|
||||||
let dx0: f32 = 1.5;
|
let dx0: f32 = 1.5;
|
||||||
let dy: f32 = 0.1/f;
|
let dy: f32 = 0.1/f;
|
||||||
let ang: f32 = 0.05/f;
|
let ang: f32 = 0.05/f;
|
||||||
@ -434,12 +433,12 @@ fn twist(f: f32, subdiv: usize) -> Rule {
|
|||||||
|
|
||||||
let start = move |self_: Rc<Rule>| -> RuleEval {
|
let start = move |self_: Rc<Rule>| -> RuleEval {
|
||||||
|
|
||||||
let xform = |dx, i, ang0| -> Mat4 {
|
let xform = |dx, i, ang0, div| -> Mat4 {
|
||||||
(geometry::Rotation3::from_axis_angle(&y, ang0 + (qtr * (i as f32))).to_homogeneous() *
|
(geometry::Rotation3::from_axis_angle(&y, ang0 + (qtr / div * (i as f32))).to_homogeneous() *
|
||||||
geometry::Translation3::new(dx, 0.0, 0.0).to_homogeneous())
|
geometry::Translation3::new(dx, 0.0, 0.0).to_homogeneous())
|
||||||
};
|
};
|
||||||
|
|
||||||
let make_child = |i, dx, incr, ang0| -> (Child, OpenMesh) {
|
let make_child = |i, incr, xform| -> (OpenMesh, Child) {
|
||||||
|
|
||||||
let seed_orig = transform(&seed, &incr);
|
let seed_orig = transform(&seed, &incr);
|
||||||
let seed_sub = util::subdivide_cycle(&seed_orig, subdiv);
|
let seed_sub = util::subdivide_cycle(&seed_orig, subdiv);
|
||||||
@ -447,32 +446,23 @@ fn twist(f: f32, subdiv: usize) -> Rule {
|
|||||||
|
|
||||||
let c = Child {
|
let c = Child {
|
||||||
rule: Rc::new(Rule { eval: (recur.clone())(incr) }),
|
rule: Rc::new(Rule { eval: (recur.clone())(incr) }),
|
||||||
xf: xform(dx, i, ang0),
|
xf: xform,
|
||||||
vmap: ((n+1)*i..(n+1)*(i+count)).collect(), // N.B.
|
vmap: (0..(n+1)).collect(),
|
||||||
// note n+1, not n. the +1 is for the centroid below
|
// N.B. n+1, not n. the +1 is for the centroid below
|
||||||
// TODO: The above vmap is wrong when I call
|
|
||||||
// 'make_child' twice and then append.
|
|
||||||
};
|
};
|
||||||
let mut vs = transform(&seed_sub, &c.xf);
|
let mut vs = transform(&seed_sub, &xform);
|
||||||
// and in the process, generate faces for these seeds:
|
// and in the process, generate faces for these seeds:
|
||||||
let (centroid, f) = util::connect_convex(&vs, false);
|
let (centroid, f) = util::connect_convex(&vs, false);
|
||||||
vs.push(centroid);
|
vs.push(centroid);
|
||||||
(c, OpenMesh { verts: vs, faces: f })
|
(OpenMesh { verts: vs, faces: f }, c)
|
||||||
};
|
};
|
||||||
|
|
||||||
// First generate 'count' children, each one shifted/rotated
|
// Generate 'count' children, shifted/rotated differently:
|
||||||
// differently:
|
let children_inner = (0..count).map(|i| make_child(i, incr_inner, xform(dx0, i, 0.0, 1.0)));
|
||||||
let children_inner = (0..count).map(|i| make_child(i, dx0, incr_inner, 0.0));
|
let children_outer = (0..count).map(|i| make_child(i, incr_outer, xform(dx0*2.0, i, qtr/2.0, 2.0)));
|
||||||
let children_outer = (0..count).map(|i| make_child(i + count, dx0*2.0, incr_outer, qtr/2.0));
|
|
||||||
// TODO: the +count is only to work around vmap kludges
|
|
||||||
|
|
||||||
let (children, meshes): (Vec<_>, Vec<_>) = children_inner.chain(children_outer).unzip();
|
RuleEval::from_pairs(
|
||||||
|
children_inner.chain(children_outer), prim::empty_mesh())
|
||||||
RuleEval {
|
|
||||||
geom: OpenMesh::append(meshes),
|
|
||||||
final_geom: prim::empty_mesh(),
|
|
||||||
children: children,
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rule { eval: Box::new(start) }
|
Rule { eval: Box::new(start) }
|
||||||
|
|||||||
@ -45,10 +45,16 @@ pub struct OpenMesh {
|
|||||||
|
|
||||||
impl OpenMesh {
|
impl OpenMesh {
|
||||||
|
|
||||||
pub fn append<T, U>(meshes: T) -> OpenMesh
|
/// Appends any number of meshes together. Returns both a single
|
||||||
|
/// mesh, and a vector which gives the offset by which each
|
||||||
|
/// corresponding input mesh was shifted. That is, for the i'th
|
||||||
|
/// index in `meshes`, all of its triangle indices were shifted by
|
||||||
|
/// the i'th offset in the resultant mesh.
|
||||||
|
pub fn append<T, U>(meshes: T) -> (OpenMesh, Vec<usize>)
|
||||||
where U: Borrow<OpenMesh>,
|
where U: Borrow<OpenMesh>,
|
||||||
T: IntoIterator<Item = U>
|
T: IntoIterator<Item = U>
|
||||||
{
|
{
|
||||||
|
let mut offsets: Vec<usize> = vec![];
|
||||||
let mut v: Vec<Vertex> = vec![];
|
let mut v: Vec<Vertex> = vec![];
|
||||||
let mut f: Vec<Tag> = vec![];
|
let mut f: Vec<Tag> = vec![];
|
||||||
for mesh_ in meshes {
|
for mesh_ in meshes {
|
||||||
@ -57,6 +63,7 @@ impl OpenMesh {
|
|||||||
// Position in 'verts' at which we're appending
|
// Position in 'verts' at which we're appending
|
||||||
// mesh.verts, which we need to know to shift indices:
|
// mesh.verts, which we need to know to shift indices:
|
||||||
let offset = v.len();
|
let offset = v.len();
|
||||||
|
offsets.push(offset);
|
||||||
|
|
||||||
// Copy all vertices:
|
// Copy all vertices:
|
||||||
v.append(&mut mesh.verts.clone());
|
v.append(&mut mesh.verts.clone());
|
||||||
@ -70,7 +77,7 @@ impl OpenMesh {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenMesh { verts: v, faces: f }
|
(OpenMesh { verts: v, faces: f }, offsets)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new `OpenMesh` whose vertices have been transformed.
|
/// Returns a new `OpenMesh` whose vertices have been transformed.
|
||||||
|
|||||||
33
src/rule.rs
33
src/rule.rs
@ -1,5 +1,6 @@
|
|||||||
use crate::openmesh::{OpenMesh, Tag, Mat4};
|
use crate::openmesh::{OpenMesh, Tag, Mat4};
|
||||||
//use crate::prim;
|
//use crate::prim;
|
||||||
|
use std::borrow::Borrow;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub type RuleFn = Box<dyn Fn(Rc<Rule>) -> RuleEval>;
|
pub type RuleFn = Box<dyn Fn(Rc<Rule>) -> RuleEval>;
|
||||||
@ -254,3 +255,35 @@ impl Rule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RuleEval {
|
||||||
|
/// Turn an iterator of (OpenMesh, Child) into a single RuleEval.
|
||||||
|
/// All meshes are merged, and the `vmap` in each child has the
|
||||||
|
/// correct offsets applied to account for this merge.
|
||||||
|
///
|
||||||
|
/// (`final_geom` is passed through to the RuleEval unmodified.)
|
||||||
|
pub fn from_pairs<T, U>(m: T, final_geom: OpenMesh) -> RuleEval
|
||||||
|
where U: Borrow<OpenMesh>,
|
||||||
|
T: IntoIterator<Item = (U, Child)>
|
||||||
|
{
|
||||||
|
let (meshes, children): (Vec<_>, Vec<_>) = m.into_iter().unzip();
|
||||||
|
let (mesh, offsets) = OpenMesh::append(meshes);
|
||||||
|
|
||||||
|
// Patch up vmap in each child, and copy everything else:
|
||||||
|
let children2: Vec<Child> = children.iter().zip(offsets.iter()).map(|(c,off)| {
|
||||||
|
Child {
|
||||||
|
rule: c.rule.clone(),
|
||||||
|
xf: c.xf.clone(),
|
||||||
|
// simply add offset:
|
||||||
|
vmap: c.vmap.iter().map(|i| i + off).collect(),
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
RuleEval {
|
||||||
|
geom: mesh,
|
||||||
|
final_geom: final_geom,
|
||||||
|
children: children2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user