Scratch work

This commit is contained in:
Chris Hodapp 2020-02-29 10:47:44 -05:00
parent 4c626f6358
commit 2dd056ad4a
3 changed files with 117 additions and 25 deletions

View File

@ -2,7 +2,7 @@ use nalgebra::*;
//pub mod examples;
use crate::openmesh::{OpenMesh, Tag, Mat4, Vertex, vertex};
use crate::rule::{Rule, RuleStep, Child};
use crate::rule::{Rule, RuleEval, Child};
use crate::prim;
use crate::util;
@ -34,8 +34,8 @@ impl CurveHorn {
}
}
fn start(&self) -> RuleStep<Self> {
RuleStep {
fn start(&self) -> RuleEval<Self> {
RuleEval {
geom: OpenMesh {
verts: self.seed.clone(),
faces: vec![],
@ -56,7 +56,7 @@ impl CurveHorn {
}
}
fn recur(&self) -> RuleStep<Self> {
fn recur(&self) -> RuleEval<Self> {
let verts = self.seed.clone();
let next_verts: Vec<Vertex> = verts.iter().map(|v| self.incr * v).collect();
@ -89,7 +89,7 @@ impl CurveHorn {
],
};
RuleStep{
RuleEval{
geom: geom,
final_geom: final_geom,
children: vec![
@ -112,7 +112,7 @@ impl CubeThing {
CubeThing {}
}
fn rec(&self) -> RuleStep<Self> {
fn rec(&self) -> RuleEval<Self> {
let mesh = prim::cube();
@ -143,7 +143,7 @@ impl CubeThing {
}
};
RuleStep {
RuleEval {
geom: mesh,
final_geom: prim::empty_mesh(),
children: turns.iter().map(gen_rulestep).collect(),
@ -161,7 +161,7 @@ impl RamHorn {
}
// Conversion from Python & automata_scratch
fn start(&self) -> RuleStep<Self> {
fn start(&self) -> RuleEval<Self> {
let opening_xform = |i| {
let r = std::f32::consts::FRAC_PI_2 * i;
((geometry::Rotation3::from_axis_angle(
@ -170,7 +170,7 @@ impl RamHorn {
Matrix4::new_scaling(0.5) *
geometry::Translation3::new(0.0, 0.0, -1.0).to_homogeneous())
};
RuleStep {
RuleEval {
geom: OpenMesh {
verts: vec![
// 'Top' vertices:
@ -242,7 +242,7 @@ impl RamHorn {
}
}
fn ram_horn(&self) -> RuleStep<Self> {
fn ram_horn(&self) -> RuleEval<Self> {
let v = Unit::new_normalize(Vector3::new(-1.0, 0.0, 1.0));
let incr: Mat4 = geometry::Translation3::new(0.0, 0.0, 0.8).to_homogeneous() *
geometry::Rotation3::from_axis_angle(&v, 0.3).to_homogeneous() *
@ -274,7 +274,7 @@ impl RamHorn {
Tag::Parent(0), Tag::Parent(3), Tag::Parent(2),
],
};
RuleStep {
RuleEval {
geom: geom,
final_geom: final_geom,
children: vec![
@ -321,7 +321,7 @@ impl Twist {
}
// Meant to be a copy of twist_from_gen from Python & automata_scratch
pub fn start(&self) -> RuleStep<Twist> {
pub fn start(&self) -> RuleEval<Twist> {
let n = self.seed.len();
@ -351,7 +351,7 @@ impl Twist {
verts.extend(self.seed_sub.iter().map(|v| child.xf * v));
}
RuleStep {
RuleEval {
geom: OpenMesh {
verts: verts,
faces: vec![],
@ -362,7 +362,7 @@ impl Twist {
}
}
pub fn recur(&self) -> RuleStep<Twist> {
pub fn recur(&self) -> RuleEval<Twist> {
let y = &Vector3::y_axis();
let incr = geometry::Translation3::new(-self.dx0, 0.0, 0.0).to_homogeneous() *
geometry::Rotation3::from_axis_angle(y, self.ang).to_homogeneous() *
@ -372,7 +372,7 @@ impl Twist {
let seed_sub = util::subdivide_cycle(&seed_orig, self.subdiv);
let n = seed_sub.len();
RuleStep {
RuleEval {
geom: OpenMesh {
verts: seed_sub,
faces: util::parallel_zigzag_faces(n),

View File

@ -8,7 +8,7 @@ use crate::prim;
/// geometry
pub enum Rule<A> {
/// Produce some geometry, and possibly recurse further.
Recurse(fn (&A) -> RuleStep<A>),
Recurse(fn (&A) -> RuleEval<A>),
/// Produce nothing and recurse no further.
EmptyRule,
}
@ -17,7 +17,7 @@ pub enum Rule<A> {
// no function call.
// TODO: Do I benefit with Rc<Rule> below so Rule can be shared?
/// `RuleStep` supplies the results of evaluating some `Rule` for one
/// `RuleEval` supplies the results of evaluating some `Rule` for one
/// iteration: it contains the geometry produced at this step
/// (`geom`), and it tells what to do next depending on whether
/// recursion continues further, or is stopped here (due to hitting
@ -28,7 +28,7 @@ pub enum Rule<A> {
/// - if recursion continues, the rules of `children` are evaluated,
/// and the resultant geometry is transformed and then connected with
/// `geom`.
pub struct RuleStep<A> {
pub struct RuleEval<A> {
/// The geometry generated at just this iteration
pub geom: OpenMesh,
@ -77,9 +77,9 @@ impl<A> Rule<A> {
// rather than repeatedly transforming meshes, it stacks
// transformations and then applies them all at once.
/// Convert this `Rule` to mesh data, recursively. `iters_left`
/// sets the maximum recursion depth. This returns (geometry,
/// number of rule evaluations).
/// Convert this `Rule` to mesh data, recursively (depth first).
/// `iters_left` sets the maximum recursion depth. This returns
/// (geometry, number of rule evaluations).
pub fn to_mesh(&self, arg: &A, iters_left: u32) -> (OpenMesh, u32) {
let mut evals: u32 = 1;
@ -87,7 +87,7 @@ impl<A> Rule<A> {
if iters_left <= 0 {
match self {
Rule::Recurse(f) => {
let rs: RuleStep<A> = f(arg);
let rs: RuleEval<A> = f(arg);
return (rs.final_geom, 1);
}
Rule::EmptyRule => {
@ -98,7 +98,7 @@ impl<A> Rule<A> {
match self {
Rule::Recurse(f) => {
let rs: RuleStep<A> = f(arg);
let rs: RuleEval<A> = f(arg);
// TODO: This logic is more or less right, but it
// could perhaps use some un-tupling or something.
@ -121,4 +121,96 @@ impl<A> Rule<A> {
}
}
}
pub fn to_mesh_iter(&self, arg: &A, max_depth: usize) -> (OpenMesh, u32) {
let mut geom = prim::empty_mesh();
let mut stack: Vec<(RuleEval<A>, usize)> = vec![];
match self {
Rule::Recurse(f) => stack.push((f(arg), 0)),
Rule::EmptyRule => {},
}
loop {
let n = stack.len(); // TODO: Just keep a running total.
// We can increment/decrement as we push/pop.
let (eval, idx) = stack[n-1];
// note that:
// stack[n-2].children[idx] = eval (so to speak)
// I can't do the above. I can either...
// - Implement Copy for RuleEval.
// - push/pop all over the place and deal with the Option
// unpacking and the extra state-changes.
// - use something nicer than RuleEval?
// I can't borrow it because a mutable borrow is already
// done with the pop?
// I don't need to share geometry. I use geometry only
// once (though I may need to be careful on the rules with
// final_geom), though that's not yet implemented.
// Deriving automatically puts the Copy constraint on A,
// and I am not sure I want to deal with that - but I have
// to be able to copy Child regardless, thus Rule.
// Function pointers support Copy, so Rule is fine.
// Vectors by design do *not*.
// Seems a little bizarre that none of this affects
// recursive to_mesh... what am I doing differently?
// See if it is time to backtrack:
if n > max_depth || eval.children.is_empty() {
// This has no parents:
if n < 2 {
break;
}
// Backtrack:
stack.pop();
// TODO: Pop transform off of stack
// If possible, step to the next sibling:
let (parent, _) = &stack[n-2];
if (idx + 1) < parent.children.len() {
let sib = parent.children[idx + 1];
match sib.rule {
Rule::Recurse(f) => {
let eval_sib = f(arg);
stack.push((eval_sib, idx + 1));
// TODO: Push transform onto stack
// TODO: Append geometry
},
Rule::EmptyRule => {
// Nowhere to recurse further
}
}
}
continue;
} else {
// Otherwise, try to recurse to first child:
let child = eval.children[0];
match child.rule {
Rule::Recurse(f) => {
let eval_child = f(arg);
stack.push((eval_child, 0));
// TODO: Push transform onto stack
// TODO: Append geometry
}
Rule::EmptyRule => {
// Do nothing.
}
}
}
}
// TODO: Return right number
return (geom, 0);
}
}

View File

@ -1,5 +1,5 @@
use crate::openmesh::{OpenMesh, Tag, Mat4, Vertex, vertex};
use crate::rule::{Rule, RuleStep, Child};
use crate::openmesh::{Tag, Vertex};
//use crate::rule::{Rule, Child};
/// Linearly subdivides a list of points that are to be treated as a
/// cycle. This produces 'count' points for every element of 'p'