Scratch work
This commit is contained in:
parent
4c626f6358
commit
2dd056ad4a
@ -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),
|
||||
|
||||
108
src/rule.rs
108
src/rule.rs
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -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'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user