Added a happy accident?
This commit is contained in:
parent
270435c4d6
commit
5a222dcc93
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
## Highest priority:
|
## Highest priority:
|
||||||
|
|
||||||
|
- Make a series of guidelines for *exactly* how to order
|
||||||
|
transformations so that I'm actually constructing things to be
|
||||||
|
correct instead of just throwing shit at the wall
|
||||||
- Adaptive subdivision - which means having to generalize past some
|
- Adaptive subdivision - which means having to generalize past some
|
||||||
`vmap` stuff.
|
`vmap` stuff.
|
||||||
- Try some non-deterministic examples
|
- Try some non-deterministic examples
|
||||||
@ -56,3 +59,6 @@
|
|||||||
- Would being able to name a rule node (perhaps conditionally under
|
- Would being able to name a rule node (perhaps conditionally under
|
||||||
some compile-time flag) help for debugging?
|
some compile-time flag) help for debugging?
|
||||||
- Use an actual logging framework.
|
- Use an actual logging framework.
|
||||||
|
- Take a square. Wrap it around to a torus. Now add a twist (about
|
||||||
|
the axis that is normal to the square). This is simple, but it looks
|
||||||
|
pretty cool.
|
||||||
|
|||||||
111
src/examples.rs
111
src/examples.rs
@ -140,6 +140,7 @@ pub fn twist(f: f32, subdiv: usize) -> Rule<()> {
|
|||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct TorusCtxt {
|
pub struct TorusCtxt {
|
||||||
init: bool,
|
init: bool,
|
||||||
|
count: usize,
|
||||||
stack: [Transform; 3],
|
stack: [Transform; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,22 +163,25 @@ pub fn twisty_torus() -> Rule<TorusCtxt> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let rad = 1.0;
|
let rad = 1.0;
|
||||||
let rad2 = 5.0;
|
let rad2 = 8.0;
|
||||||
let dx0 = 2.0;
|
let dx0 = 2.0;
|
||||||
let ang = 0.1;
|
let ang = 0.1;
|
||||||
|
|
||||||
let recur = move |self_: Rc<Rule<TorusCtxt>>| -> RuleEval<TorusCtxt> {
|
let recur = move |self_: Rc<Rule<TorusCtxt>>| -> RuleEval<TorusCtxt> {
|
||||||
//let y = &Vector3::y_axis();
|
let x = &Vector3::x_axis();
|
||||||
let z = &Vector3::z_axis();
|
let z = &Vector3::z_axis();
|
||||||
let stack = self_.ctxt.stack;
|
let stack = self_.ctxt.stack;
|
||||||
|
let count = self_.ctxt.count;
|
||||||
let next_rule = Rule {
|
let next_rule = Rule {
|
||||||
eval: self_.eval.clone(),
|
eval: self_.eval.clone(),
|
||||||
ctxt: TorusCtxt {
|
ctxt: TorusCtxt {
|
||||||
init: false,
|
init: false,
|
||||||
|
count: count + 1,
|
||||||
stack: [
|
stack: [
|
||||||
stack[0],
|
Transform::new().translate(0.1, 0.0, 0.0).rotate(x, 0.01) * stack[0],
|
||||||
Transform::new().rotate(z, 0.05) * stack[1],
|
// stack[0], //Transform::new().rotate(z, 0.05 * (count as f32)).translate(0.0, rad2, 0.0),
|
||||||
Transform::new().translate(0.0, 0.0, 0.1) * stack[2],
|
Transform::new().rotate(z, 0.30) * stack[1],
|
||||||
|
stack[2],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -218,6 +222,103 @@ pub fn twisty_torus() -> Rule<TorusCtxt> {
|
|||||||
eval: Rc::new(recur),
|
eval: Rc::new(recur),
|
||||||
ctxt: TorusCtxt {
|
ctxt: TorusCtxt {
|
||||||
init: true,
|
init: true,
|
||||||
|
count: 0,
|
||||||
|
stack: [
|
||||||
|
Transform::new().translate(0.0, rad2, 0.0),
|
||||||
|
Transform::new().translate(rad, 0.0, 0.0),
|
||||||
|
Transform::new(), // .translate(dx0, 0.0, 0.0),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This was a mistake that I'd like to understand later:
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct WindChimeCtxt {
|
||||||
|
init: bool,
|
||||||
|
count: usize,
|
||||||
|
stack: [Transform; 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wind_chime_mistake_thing() -> Rule<WindChimeCtxt> {
|
||||||
|
let subdiv = 8;
|
||||||
|
let seed = 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),
|
||||||
|
];
|
||||||
|
let seed = util::subdivide_cycle(&seed, subdiv);
|
||||||
|
|
||||||
|
let n = seed.len();
|
||||||
|
let geom = Rc::new(util::zigzag_to_parent(seed.clone(), n));
|
||||||
|
let (vc, faces) = util::connect_convex(&seed, true);
|
||||||
|
let final_geom = Rc::new(OpenMesh {
|
||||||
|
verts: vec![vc],
|
||||||
|
faces: faces,
|
||||||
|
});
|
||||||
|
|
||||||
|
let rad = 1.0;
|
||||||
|
let rad2 = 8.0;
|
||||||
|
let dx0 = 2.0;
|
||||||
|
let ang = 0.1;
|
||||||
|
|
||||||
|
let recur = move |self_: Rc<Rule<WindChimeCtxt>>| -> RuleEval<WindChimeCtxt> {
|
||||||
|
let x = &Vector3::x_axis();
|
||||||
|
let z = &Vector3::z_axis();
|
||||||
|
let stack = self_.ctxt.stack;
|
||||||
|
let count = self_.ctxt.count;
|
||||||
|
let next_rule = Rule {
|
||||||
|
eval: self_.eval.clone(),
|
||||||
|
ctxt: WindChimeCtxt {
|
||||||
|
init: false,
|
||||||
|
count: count + 1,
|
||||||
|
stack: [
|
||||||
|
Transform::new().rotate(x, 0.01) * stack[0],
|
||||||
|
// stack[0], //Transform::new().rotate(z, 0.05 * (count as f32)).translate(0.0, rad2, 0.0),
|
||||||
|
Transform::new().rotate(z, 0.30) * stack[1],
|
||||||
|
Transform::new().translate(0.1, 0.0, 0.0) * stack[2],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let xf = stack.iter().fold(Transform::new(), |acc,m| acc * (*m));
|
||||||
|
if self_.ctxt.init {
|
||||||
|
let mut s2 = seed.clone();
|
||||||
|
let (centroid, f) = util::connect_convex(&s2, false);
|
||||||
|
s2.push(centroid);
|
||||||
|
let n2 = s2.len();
|
||||||
|
let g = OpenMesh { verts: s2, faces: f };
|
||||||
|
RuleEval {
|
||||||
|
geom: Rc::new(g.transform(&xf)),
|
||||||
|
final_geom: Rc::new(prim::empty_mesh()),
|
||||||
|
children: vec![
|
||||||
|
Child {
|
||||||
|
rule: Rc::new(next_rule),
|
||||||
|
xf: Transform::new(),
|
||||||
|
vmap: (0..n2).collect(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RuleEval {
|
||||||
|
geom: Rc::new(geom.transform(&xf)),
|
||||||
|
final_geom: Rc::new(final_geom.transform(&xf)),
|
||||||
|
children: vec![
|
||||||
|
Child {
|
||||||
|
rule: Rc::new(next_rule),
|
||||||
|
xf: Transform::new(),
|
||||||
|
vmap: (0..n).collect(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Rule {
|
||||||
|
eval: Rc::new(recur),
|
||||||
|
ctxt: WindChimeCtxt {
|
||||||
|
init: true,
|
||||||
|
count: 0,
|
||||||
stack: [
|
stack: [
|
||||||
Transform::new().translate(0.0, rad2, 0.0),
|
Transform::new().translate(0.0, rad2, 0.0),
|
||||||
Transform::new().translate(rad, 0.0, 0.0),
|
Transform::new().translate(rad, 0.0, 0.0),
|
||||||
|
|||||||
33
src/lib.rs
33
src/lib.rs
@ -14,6 +14,7 @@ mod tests {
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use rule::Rule;
|
use rule::Rule;
|
||||||
|
use nalgebra::*;
|
||||||
|
|
||||||
fn run_test<S>(rule: Rule<S>, iters: usize, name: &str, use_old: bool) {
|
fn run_test<S>(rule: Rule<S>, iters: usize, name: &str, use_old: bool) {
|
||||||
let r = Rc::new(rule);
|
let r = Rc::new(rule);
|
||||||
@ -37,9 +38,33 @@ mod tests {
|
|||||||
mesh.write_stl_file(&fname).unwrap();
|
mesh.write_stl_file(&fname).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn xform_order() {
|
||||||
|
let geom = prim::cube();
|
||||||
|
|
||||||
|
let y = &Vector3::y_axis();
|
||||||
|
|
||||||
|
let dx = 4.0;
|
||||||
|
let r = -0.5;
|
||||||
|
|
||||||
|
let trans = xform::Transform::new().translate(dx, 0.0, 0.0);
|
||||||
|
let rot = xform::Transform::new().rotate(y, r);
|
||||||
|
|
||||||
|
let xf1 = trans.rotate(y, r);
|
||||||
|
let xf2 = rot.translate(dx, 0.0, 0.0);
|
||||||
|
|
||||||
|
// Rotate entire space, *then* translate in that rotated plane:
|
||||||
|
geom.transform(&trans).transform(&rot).write_stl_file("xform_apply_trans_rot.stl").unwrap();
|
||||||
|
geom.transform(&(rot * trans)).write_stl_file("xform_mul_rot_trans.stl").unwrap();
|
||||||
|
geom.transform(&xf2).write_stl_file("xform_rot_trans.stl").unwrap();
|
||||||
|
// Translate cube, *then* rotate it:
|
||||||
|
geom.transform(&rot).transform(&trans).write_stl_file("xform_apply_rot_trans.stl").unwrap();
|
||||||
|
geom.transform(&(trans * rot)).write_stl_file("xform_mul_trans_rot.stl").unwrap();
|
||||||
|
geom.transform(&xf1).write_stl_file("xform_trans_rot.stl").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: These tests don't test any conditions, so this is useful
|
// TODO: These tests don't test any conditions, so this is useful
|
||||||
// short-hand to run, but not very meaningful as a test.
|
// short-hand to run, but not very meaningful as a test.
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cube_thing() {
|
fn cube_thing() {
|
||||||
run_test(examples::cube_thing(), 3, "cube_thing3", false);
|
run_test(examples::cube_thing(), 3, "cube_thing3", false);
|
||||||
@ -52,7 +77,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn twisty_torus() {
|
fn twisty_torus() {
|
||||||
run_test(examples::twisty_torus(), 50, "twisty_torus", false);
|
run_test(examples::twisty_torus(), 400, "twisty_torus", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wind_chime_mistake_thing() {
|
||||||
|
run_test(examples::wind_chime_mistake_thing(), 400, "wind_chime_mistake_thing", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This one is very time-consuming to run:
|
// This one is very time-consuming to run:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user