Working direct-function-call example for 'barbs'
This commit is contained in:
parent
17fbd4d3a3
commit
004f665e4b
104
src/examples.rs
104
src/examples.rs
@ -50,6 +50,110 @@ pub fn cube_thing() -> Rule<()> {
|
|||||||
Rule { eval: Rc::new(rec), ctxt: () }
|
Rule { eval: Rc::new(rec), ctxt: () }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct BarbsCtxt {
|
||||||
|
base_incr: Transform,
|
||||||
|
barb_incr: Transform,
|
||||||
|
sides: [Transform; 4],
|
||||||
|
base: Vec<Vertex>,
|
||||||
|
|
||||||
|
verts: Vec<Vertex>,
|
||||||
|
faces: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BarbsCtxt {
|
||||||
|
pub fn new() -> BarbsCtxt {
|
||||||
|
// Incremental transform from each stage to the next:
|
||||||
|
let base_incr = id().translate(0.0, 0.0, 1.0).
|
||||||
|
rotate(&Vector3::z_axis(), 0.15).
|
||||||
|
rotate(&Vector3::x_axis(), 0.1).
|
||||||
|
scale(0.95);
|
||||||
|
let barb_incr = id().translate(0.0, 0.0, 0.5).
|
||||||
|
rotate(&Vector3::y_axis(), -0.2).
|
||||||
|
scale(0.8);
|
||||||
|
// 'Base' vertices, used throughout:
|
||||||
|
let base = vec![
|
||||||
|
vertex(-0.5, -0.5, 0.0),
|
||||||
|
vertex(-0.5, 0.5, 0.0),
|
||||||
|
vertex( 0.5, 0.5, 0.0),
|
||||||
|
vertex( 0.5, -0.5, 0.0),
|
||||||
|
];
|
||||||
|
// sides[i] gives transformation from a 'base' layer to the
|
||||||
|
// i'th side (0 to 3):
|
||||||
|
let mut sides: [Transform; 4] = [id(); 4];
|
||||||
|
for i in 0..4 {
|
||||||
|
sides[i] = id().
|
||||||
|
rotate(&Vector3::z_axis(), -FRAC_PI_2 * (i as f32)).
|
||||||
|
rotate(&Vector3::y_axis(), -FRAC_PI_2).
|
||||||
|
translate(0.5, 0.0, 0.5);// * barb_incr;
|
||||||
|
}
|
||||||
|
BarbsCtxt {
|
||||||
|
base_incr: base_incr,
|
||||||
|
barb_incr: barb_incr,
|
||||||
|
base: base,
|
||||||
|
sides: sides,
|
||||||
|
verts: vec![],
|
||||||
|
faces: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn barb(&mut self, iters: usize, xform: Transform, bound: [usize; 4]) {
|
||||||
|
|
||||||
|
if iters <= 0 {
|
||||||
|
self.faces.extend_from_slice(&[
|
||||||
|
bound[0], bound[2], bound[1],
|
||||||
|
bound[0], bound[3], bound[2],
|
||||||
|
]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let xform2 = xform * self.barb_incr;
|
||||||
|
let g = xform2.transform(&self.base);
|
||||||
|
let (a0, a1) = self.verts.append_indexed(g);
|
||||||
|
|
||||||
|
self.faces.append(&mut util::parallel_zigzag2(bound.to_vec(), a0..a1));
|
||||||
|
|
||||||
|
self.barb(iters - 1, xform2, [a0, a0+1, a0+2, a0+3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main(&mut self, iters: usize, xform: Transform, bound: [usize; 4]) {
|
||||||
|
|
||||||
|
if iters <= 0 {
|
||||||
|
self.faces.extend_from_slice(&[
|
||||||
|
bound[0], bound[2], bound[1],
|
||||||
|
bound[0], bound[3], bound[2],
|
||||||
|
]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let xform2 = xform * self.base_incr;
|
||||||
|
let g = xform2.transform(&self.base);
|
||||||
|
let (a0, _) = self.verts.append_indexed(g);
|
||||||
|
|
||||||
|
// TODO: Isn't there some cleaner way?
|
||||||
|
self.main(iters - 1, xform2, [a0, a0+1, a0+2, a0+3]);
|
||||||
|
self.barb(iters - 1, xform * self.sides[0], [bound[0], bound[1], a0+1, a0+0]);
|
||||||
|
self.barb(iters - 1, xform * self.sides[1], [bound[1], bound[2], a0+2, a0+1]);
|
||||||
|
self.barb(iters - 1, xform * self.sides[2], [bound[2], bound[3], a0+3, a0+2]);
|
||||||
|
self.barb(iters - 1, xform * self.sides[3], [bound[3], bound[0], a0+0, a0+3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(mut self, iters: usize) -> Mesh {
|
||||||
|
self.verts.append(&mut self.base.clone());
|
||||||
|
self.faces.extend_from_slice(&[
|
||||||
|
0, 1, 2,
|
||||||
|
0, 2, 3,
|
||||||
|
]);
|
||||||
|
|
||||||
|
self.main(iters, id(), [0,1,2,3]);
|
||||||
|
|
||||||
|
return Mesh {
|
||||||
|
verts: self.verts,
|
||||||
|
faces: self.faces,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn barbs(random: bool) -> Rule<()> {
|
pub fn barbs(random: bool) -> Rule<()> {
|
||||||
|
|
||||||
let (b0, bn);
|
let (b0, bn);
|
||||||
|
|||||||
15
src/lib.rs
15
src/lib.rs
@ -76,6 +76,21 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn barbs() { run_test(examples::barbs(false), 80, "barbs", false); }
|
fn barbs() { run_test(examples::barbs(false), 80, "barbs", false); }
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn barbs_direct() {
|
||||||
|
let name = "barbs_test";
|
||||||
|
println!("---------------------------------------------------");
|
||||||
|
let b = examples::BarbsCtxt::new();
|
||||||
|
let m = b.run(100);
|
||||||
|
|
||||||
|
println!("Got {} verts...", m.verts.len());
|
||||||
|
|
||||||
|
let fname = format!("{}.stl", name);
|
||||||
|
println!("Writing {}...", fname);
|
||||||
|
m.write_stl_file(&fname).unwrap();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn barbs_random() { run_test(examples::barbs(true), 80, "barbs_random", false); }
|
fn barbs_random() { run_test(examples::barbs(true), 80, "barbs_random", false); }
|
||||||
|
|
||||||
|
|||||||
@ -217,7 +217,12 @@ impl MeshFunc {
|
|||||||
faces.extend(child.faces.iter().map(|n| {
|
faces.extend(child.faces.iter().map(|n| {
|
||||||
let f = match child.verts[*n] {
|
let f = match child.verts[*n] {
|
||||||
VertexUnion::Vertex(_) => remap[*n],
|
VertexUnion::Vertex(_) => remap[*n],
|
||||||
VertexUnion::Arg(m) => arg_vals[m],
|
VertexUnion::Arg(m) => {
|
||||||
|
println!("remap face: vert {} arg {} = vert {} ({:?})",
|
||||||
|
*n, m, arg_vals[m], verts[arg_vals[m]]
|
||||||
|
);
|
||||||
|
arg_vals[m]
|
||||||
|
},
|
||||||
};
|
};
|
||||||
if f >= verts.len() {
|
if f >= verts.len() {
|
||||||
panic!("face >= num_verts")
|
panic!("face >= num_verts")
|
||||||
|
|||||||
31
src/util.rs
31
src/util.rs
@ -1,5 +1,5 @@
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use crate::mesh::{MeshFunc, VertexUnion};
|
use crate::mesh::{Mesh, MeshFunc, VertexUnion};
|
||||||
use crate::xform::{Vertex};
|
use crate::xform::{Vertex};
|
||||||
|
|
||||||
/// This is like `vec!`, but it can handle elements that are given
|
/// This is like `vec!`, but it can handle elements that are given
|
||||||
@ -85,6 +85,35 @@ pub fn parallel_zigzag(verts: Vec<VertexUnion>, main: Range<usize>, parent: Rang
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parallel_zigzag_mesh(verts: Vec<Vertex>, main: Range<usize>, parent: Range<usize>) -> Mesh {
|
||||||
|
Mesh {
|
||||||
|
verts: verts,
|
||||||
|
faces: parallel_zigzag_faces(main, parent),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parallel_zigzag2<T,U>(main: T, parent: U) -> Vec<usize>
|
||||||
|
where T: IntoIterator<Item=usize>, U: IntoIterator<Item=usize>
|
||||||
|
{
|
||||||
|
let m: Vec<usize> = main.into_iter().collect();
|
||||||
|
let p: Vec<usize> = parent.into_iter().collect();
|
||||||
|
let l = m.len();
|
||||||
|
if l != p.len() {
|
||||||
|
panic!("Vectors must be the same size!")
|
||||||
|
}
|
||||||
|
|
||||||
|
(0..l).map(|i0| {
|
||||||
|
// i0 is an *offset* for the 'current' index.
|
||||||
|
// i1 is for the 'next' index, wrapping back to 0.
|
||||||
|
let i1 = (i0 + 1) % l;
|
||||||
|
vec![
|
||||||
|
// Mind winding order!
|
||||||
|
m[i1], p[i0], m[i0],
|
||||||
|
p[i1], p[i0], m[i1],
|
||||||
|
]
|
||||||
|
}).flatten().collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn centroid(verts: &Vec<Vertex>) -> Vertex {
|
pub fn centroid(verts: &Vec<Vertex>) -> Vertex {
|
||||||
let n = verts.len();
|
let n = verts.len();
|
||||||
let mut centroid = Vertex::new(0.0, 0.0, 0.0, 0.0);
|
let mut centroid = Vertex::new(0.0, 0.0, 0.0, 0.0);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user