Added helper function to avoid juggling of indices
This commit is contained in:
parent
558bd062d9
commit
45ab4ed9e0
@ -3,8 +3,7 @@
|
||||
## Highest priority:
|
||||
|
||||
- If my `closure_try2` branch seems to be working: start converting
|
||||
other things and cleaning them up. Modify `twist` to have the
|
||||
things I wrote this for in the first place!
|
||||
other things and cleaning everything up. (`twist` is still ugly.)
|
||||
- See `automata_scratch/examples.py` and implement some of the tougher
|
||||
examples.
|
||||
- `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:
|
||||
the clockwise boundaries, the zigzag connections, the iterating over
|
||||
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
|
||||
- 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.
|
||||
|
||||
## 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),
|
||||
], &xf);
|
||||
//let seed_sub = util::subdivide_cycle(&seed, subdiv);
|
||||
let dx0: f32 = 1.5;
|
||||
let dy: f32 = 0.1/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 xform = |dx, i, ang0| -> Mat4 {
|
||||
(geometry::Rotation3::from_axis_angle(&y, ang0 + (qtr * (i as f32))).to_homogeneous() *
|
||||
let xform = |dx, i, ang0, div| -> Mat4 {
|
||||
(geometry::Rotation3::from_axis_angle(&y, ang0 + (qtr / div * (i as f32))).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_sub = util::subdivide_cycle(&seed_orig, subdiv);
|
||||
@ -447,32 +446,23 @@ fn twist(f: f32, subdiv: usize) -> Rule {
|
||||
|
||||
let c = Child {
|
||||
rule: Rc::new(Rule { eval: (recur.clone())(incr) }),
|
||||
xf: xform(dx, i, ang0),
|
||||
vmap: ((n+1)*i..(n+1)*(i+count)).collect(), // N.B.
|
||||
// note 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.
|
||||
xf: xform,
|
||||
vmap: (0..(n+1)).collect(),
|
||||
// N.B. n+1, not n. the +1 is for the centroid below
|
||||
};
|
||||
let mut vs = transform(&seed_sub, &c.xf);
|
||||
let mut vs = transform(&seed_sub, &xform);
|
||||
// and in the process, generate faces for these seeds:
|
||||
let (centroid, f) = util::connect_convex(&vs, false);
|
||||
vs.push(centroid);
|
||||
(c, OpenMesh { verts: vs, faces: f })
|
||||
(OpenMesh { verts: vs, faces: f }, c)
|
||||
};
|
||||
|
||||
// First generate 'count' children, each one shifted/rotated
|
||||
// differently:
|
||||
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 + 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();
|
||||
// Generate 'count' children, shifted/rotated differently:
|
||||
let children_inner = (0..count).map(|i| make_child(i, incr_inner, xform(dx0, i, 0.0, 1.0)));
|
||||
let children_outer = (0..count).map(|i| make_child(i, incr_outer, xform(dx0*2.0, i, qtr/2.0, 2.0)));
|
||||
|
||||
RuleEval {
|
||||
geom: OpenMesh::append(meshes),
|
||||
final_geom: prim::empty_mesh(),
|
||||
children: children,
|
||||
}
|
||||
RuleEval::from_pairs(
|
||||
children_inner.chain(children_outer), prim::empty_mesh())
|
||||
};
|
||||
|
||||
Rule { eval: Box::new(start) }
|
||||
|
||||
@ -45,10 +45,16 @@ pub struct 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>,
|
||||
T: IntoIterator<Item = U>
|
||||
{
|
||||
let mut offsets: Vec<usize> = vec![];
|
||||
let mut v: Vec<Vertex> = vec![];
|
||||
let mut f: Vec<Tag> = vec![];
|
||||
for mesh_ in meshes {
|
||||
@ -57,6 +63,7 @@ impl OpenMesh {
|
||||
// Position in 'verts' at which we're appending
|
||||
// mesh.verts, which we need to know to shift indices:
|
||||
let offset = v.len();
|
||||
offsets.push(offset);
|
||||
|
||||
// Copy all vertices:
|
||||
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.
|
||||
|
||||
33
src/rule.rs
33
src/rule.rs
@ -1,5 +1,6 @@
|
||||
use crate::openmesh::{OpenMesh, Tag, Mat4};
|
||||
//use crate::prim;
|
||||
use std::borrow::Borrow;
|
||||
use std::rc::Rc;
|
||||
|
||||
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