Add hacky example of (incorrect) double spiral in twist()
This commit is contained in:
parent
96f8004df2
commit
21ce55d141
@ -3,7 +3,7 @@ use nalgebra::*;
|
|||||||
//pub mod examples;
|
//pub mod examples;
|
||||||
|
|
||||||
use crate::openmesh::{OpenMesh, Tag, Mat4, Vertex, vertex, transform};
|
use crate::openmesh::{OpenMesh, Tag, Mat4, Vertex, vertex, transform};
|
||||||
use crate::rule::{Rule, RuleEval, Child};
|
use crate::rule::{Rule, RuleFn, RuleEval, Child};
|
||||||
use crate::prim;
|
use crate::prim;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
use crate::scratch;
|
use crate::scratch;
|
||||||
@ -375,24 +375,26 @@ 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 seed_sub = util::subdivide_cycle(&seed, subdiv);
|
||||||
let dx0: f32 = 2.0;
|
let dx0: f32 = 2.0;
|
||||||
let dy: f32 = 0.1/f;
|
let dy: f32 = 0.1/f;
|
||||||
let ang: f32 = 0.1/f;
|
let ang: f32 = 0.1/f;
|
||||||
let count: usize = 4;
|
let count: usize = 4;
|
||||||
|
|
||||||
let n = seed_sub.len();
|
|
||||||
|
|
||||||
// Quarter-turn in radians:
|
// Quarter-turn in radians:
|
||||||
let qtr = std::f32::consts::FRAC_PI_2;
|
let qtr = std::f32::consts::FRAC_PI_2;
|
||||||
let y = Vector3::y_axis();
|
let y = Vector3::y_axis();
|
||||||
|
|
||||||
let incr = geometry::Translation3::new(-dx0, 0.0, 0.0).to_homogeneous() *
|
let incr_inner = geometry::Translation3::new(-dx0, 0.0, 0.0).to_homogeneous() *
|
||||||
geometry::Rotation3::from_axis_angle(&y, ang).to_homogeneous() *
|
geometry::Rotation3::from_axis_angle(&y, ang).to_homogeneous() *
|
||||||
geometry::Translation3::new(dx0, dy, 0.0).to_homogeneous();
|
geometry::Translation3::new(dx0, dy, 0.0).to_homogeneous();
|
||||||
|
let incr_outer = geometry::Translation3::new(-dx0*2.0, 0.0, 0.0).to_homogeneous() *
|
||||||
|
geometry::Rotation3::from_axis_angle(&y, ang/2.0).to_homogeneous() *
|
||||||
|
geometry::Translation3::new(dx0*2.0, dy, 0.0).to_homogeneous();
|
||||||
|
|
||||||
let seed_orig = transform(&seed, &incr);
|
let seed_orig = transform(&seed, &incr_inner);
|
||||||
let seed_sub = util::subdivide_cycle(&seed_orig, subdiv);
|
let seed_sub = util::subdivide_cycle(&seed_orig, subdiv);
|
||||||
|
let n = seed_sub.len();
|
||||||
|
|
||||||
let geom = OpenMesh {
|
let geom = OpenMesh {
|
||||||
verts: seed_sub.clone(),
|
verts: seed_sub.clone(),
|
||||||
@ -404,41 +406,55 @@ fn twist(f: f32, subdiv: usize) -> Rule {
|
|||||||
faces: faces.clone(),
|
faces: faces.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let recur = move |self_: Rc<Rule>| -> RuleEval {
|
let recur = move |incr: Mat4| -> RuleFn {
|
||||||
// TODO: Why clone geometry here if I just have to clone it
|
let c = move |self_: Rc<Rule>| -> RuleEval {
|
||||||
// later on? Seems like Rc may be much easier (if I can't
|
// TODO: Why clone geometry here if I just have to clone it
|
||||||
// borrow directly - which is probably the case).
|
// later on? Seems like Rc may be much easier (if I can't
|
||||||
RuleEval {
|
// borrow directly - which is probably the case).
|
||||||
geom: geom.clone(),
|
RuleEval {
|
||||||
final_geom: final_geom.clone(),
|
geom: geom.clone(),
|
||||||
children: vec![
|
final_geom: final_geom.clone(),
|
||||||
Child {
|
children: vec![
|
||||||
rule: self_.clone(),
|
Child {
|
||||||
xf: incr,
|
rule: self_.clone(),
|
||||||
vmap: (0..n).collect(),
|
xf: incr,
|
||||||
},
|
vmap: (0..n).collect(),
|
||||||
],
|
},
|
||||||
}
|
],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Box::new(c)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: so there's incr_inner & incr_outer that I wanted to
|
||||||
|
// parametrize over. why is it so ugly to do so?
|
||||||
|
|
||||||
let start = move |self_: Rc<Rule>| -> RuleEval {
|
let start = move |self_: Rc<Rule>| -> RuleEval {
|
||||||
|
|
||||||
let xform = |i| {
|
let xform = |dx, i| {
|
||||||
(geometry::Rotation3::from_axis_angle(&y, qtr * (i as f32)).to_homogeneous() *
|
(geometry::Rotation3::from_axis_angle(&y, qtr * (i as f32)).to_homogeneous() *
|
||||||
geometry::Translation3::new(dx0, 0.0, 0.0).to_homogeneous())
|
geometry::Translation3::new(dx, 0.0, 0.0).to_homogeneous())
|
||||||
};
|
};
|
||||||
|
|
||||||
// First generate 'count' children, each one shifted/rotated
|
// First generate 'count' children, each one shifted/rotated
|
||||||
// differently:
|
// differently:
|
||||||
let children: Vec<Child> = (0..count).map(|i| {
|
let children_inner = (0..count).map(|i| {
|
||||||
let xf = xform(i);
|
|
||||||
Child {
|
Child {
|
||||||
rule: Rc::new(Rule { eval: Box::new(recur.clone()) }),
|
rule: Rc::new(Rule { eval: (recur.clone())(incr_inner) }),
|
||||||
xf: xf,
|
xf: xform(dx0, i),
|
||||||
vmap: ((n+1)*i..(n+1)*(i+count)).collect(), // N.B.
|
vmap: ((n+1)*i..(n+1)*(i+count)).collect(), // N.B.
|
||||||
// note n+1, not n. the +1 is for the centroid below
|
// note n+1, not n. the +1 is for the centroid below
|
||||||
}
|
}
|
||||||
}).collect();
|
});
|
||||||
|
let children_outer = (0..count).map(|i| {
|
||||||
|
Child {
|
||||||
|
rule: Rc::new(Rule { eval: (recur.clone())(incr_outer) }),
|
||||||
|
xf: xform(dx0*2.0, i),
|
||||||
|
vmap: ((n+1)*i..(n+1)*(i+count)).collect(), // N.B.
|
||||||
|
// note n+1, not n. the +1 is for the centroid below
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let children: Vec<Child> = children_inner.chain(children_outer).collect();
|
||||||
|
|
||||||
// Use byproducts of this to make 'count' copies of 'seed' with
|
// Use byproducts of this to make 'count' copies of 'seed' with
|
||||||
// this same transform:
|
// this same transform:
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
use nalgebra::*;
|
use nalgebra::*;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::borrow::Borrow;
|
||||||
|
|
||||||
/// A type for mesh vertices. Initialize with [vertex][self::vertex].
|
/// A type for mesh vertices. Initialize with [vertex][self::vertex].
|
||||||
pub type Vertex = Vector4<f32>;
|
pub type Vertex = Vector4<f32>;
|
||||||
@ -44,11 +45,15 @@ pub struct OpenMesh {
|
|||||||
|
|
||||||
impl OpenMesh {
|
impl OpenMesh {
|
||||||
|
|
||||||
pub fn append<T: IntoIterator<Item = OpenMesh>>(meshes: T) -> OpenMesh
|
pub fn append<T, U>(meshes: T) -> OpenMesh
|
||||||
|
where U: Borrow<OpenMesh>,
|
||||||
|
T: IntoIterator<Item = U>
|
||||||
{
|
{
|
||||||
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 {
|
||||||
|
let mesh = mesh_.borrow();
|
||||||
|
|
||||||
// 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();
|
||||||
|
|||||||
@ -2,13 +2,15 @@ use crate::openmesh::{OpenMesh, Tag, Mat4};
|
|||||||
//use crate::prim;
|
//use crate::prim;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub type RuleFn = Box<dyn Fn(Rc<Rule>) -> RuleEval>;
|
||||||
|
|
||||||
/// Definition of a rule. In general, a `Rule`:
|
/// Definition of a rule. In general, a `Rule`:
|
||||||
///
|
///
|
||||||
/// - produces geometry when it is evaluated
|
/// - produces geometry when it is evaluated
|
||||||
/// - tells what other rules to invoke, and what to do with their
|
/// - tells what other rules to invoke, and what to do with their
|
||||||
/// geometry
|
/// geometry
|
||||||
pub struct Rule {
|
pub struct Rule {
|
||||||
pub eval: Box<dyn Fn(Rc<Rule>) -> RuleEval>,
|
pub eval: RuleFn,
|
||||||
}
|
}
|
||||||
// TODO: It may be possible to have just a 'static' rule that requires
|
// TODO: It may be possible to have just a 'static' rule that requires
|
||||||
// no function call.
|
// no function call.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user