Sierpinski ish thing working
This commit is contained in:
parent
35daf01b8a
commit
8146d4fea8
@ -21,6 +21,13 @@ from a 'parent' rule, besides being able to connect to its
|
|||||||
vertices - and sometimes the "refining" part of things
|
vertices - and sometimes the "refining" part of things
|
||||||
required this in order to work right.
|
required this in order to work right.
|
||||||
|
|
||||||
|
I've also disliked how much my model felt like it tied me
|
||||||
|
down to the "triangle mesh" representation. I haven't
|
||||||
|
found a good way to build up higher-level representations
|
||||||
|
to modularise and compose - but haven't given up yet on
|
||||||
|
this. In some sense it is a conflict of goals because
|
||||||
|
the aim was correct-by-construction triangle meshes.
|
||||||
|
|
||||||
Also, I did this in order to learn the Rust language, and I
|
Also, I did this in order to learn the Rust language, and I
|
||||||
repeatedly kept bumping into the conclusion that Rust was
|
repeatedly kept bumping into the conclusion that Rust was
|
||||||
just not the right language for this. I was in need of things
|
just not the right language for this. I was in need of things
|
||||||
|
|||||||
193
src/examples.rs
193
src/examples.rs
@ -166,36 +166,52 @@ pub fn barbs(random: bool) -> Rule<()> {
|
|||||||
|
|
||||||
pub fn pyramid() -> Rule<()> {
|
pub fn pyramid() -> Rule<()> {
|
||||||
|
|
||||||
// base_verts are for a triangle in the XY plane, centered at
|
|
||||||
// (0,0,0), with unit sidelength:
|
|
||||||
let (b0, bn);
|
|
||||||
let rt3 = (3.0).sqrt();
|
let rt3 = (3.0).sqrt();
|
||||||
let rt6 = (6.0).sqrt();
|
let rt6 = (6.0).sqrt();
|
||||||
let base_verts: Vec<VertexUnion> = vec_indexed![
|
|
||||||
@b0 VertexUnion::Vertex(vertex( rt3/3.0, 0.0, 0.0)),
|
// base_verts are for a unit-sidelength tetrahedron and its midpoints.
|
||||||
VertexUnion::Vertex(vertex( -rt3/6.0, -1.0/2.0, 0.0)),
|
// Its *base* sits in the XY plane, centered at (0,0,0).
|
||||||
VertexUnion::Vertex(vertex( -rt3/6.0, 1.0/2.0, 0.0)),
|
// Indices:
|
||||||
VertexUnion::Vertex(vertex( 0.0, 0.0, rt6/3.0)),
|
// b0,b1,b2 = base vertices; t = 'top' vertex.
|
||||||
@bn,
|
// m01, m12, m20 = midpoints of (b0,b1), (b1,b2), (b2,b0).
|
||||||
];
|
// bm0, bm1, bm2 = midpoints of (b0,t), (b1,t), (b2,t).
|
||||||
|
let (b0, b1, b2, t, m01, m12, m20, bm0, bm1, bm2);
|
||||||
|
let base_verts: Vec<VertexUnion> = {
|
||||||
|
let v0 = vertex(rt3/3.0, 0.0, 0.0);
|
||||||
|
let v1 = vertex(-rt3/6.0, -1.0/2.0, 0.0);
|
||||||
|
let v2 = vertex(-rt3/6.0, 1.0/2.0, 0.0);
|
||||||
|
let vt = vertex(0.0, 0.0, rt6/3.0);
|
||||||
|
vec_indexed![
|
||||||
|
@b0 VertexUnion::Vertex(v0),
|
||||||
|
@b1 VertexUnion::Vertex(v1),
|
||||||
|
@b2 VertexUnion::Vertex(v2),
|
||||||
|
@t VertexUnion::Vertex(vt),
|
||||||
|
@m01 VertexUnion::Vertex((v0+v1)/2.0),
|
||||||
|
@m12 VertexUnion::Vertex((v1+v2)/2.0),
|
||||||
|
@m20 VertexUnion::Vertex((v2+v0)/2.0),
|
||||||
|
@bm0 VertexUnion::Vertex((v0+vt)/2.0),
|
||||||
|
@bm1 VertexUnion::Vertex((v1+vt)/2.0),
|
||||||
|
@bm2 VertexUnion::Vertex((v2+vt)/2.0),
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
let test = rule_fn!(() => |_s, base_verts| {
|
let test = rule_fn!(() => |_s, base_verts| {
|
||||||
let rt3 = (3.0).sqrt();
|
// Mnemonics for args:
|
||||||
let (a0, a1, a2);
|
let b0 = 0; // Base
|
||||||
let next_verts: Vec<VertexUnion> = vec_indexed![
|
let b1 = 1; // Adjacent base
|
||||||
VertexUnion::Vertex(vertex( rt3/12.0, -1.0/4.0, 0.0)),
|
let t = 2; // 'Top'
|
||||||
VertexUnion::Vertex(vertex( rt3/12.0, 1.0/4.0, 0.0)),
|
let m01 = 3; // Midpoint between b0 & b1
|
||||||
VertexUnion::Vertex(vertex(-rt3/6.0, 0.0, 0.0)),
|
let bm0 = 4; // Midpoint between b0 & t
|
||||||
@a0 VertexUnion::Arg(0),
|
let bm1 = 5; // Midpoint between b1 & t
|
||||||
@a1 VertexUnion::Arg(1),
|
|
||||||
@a2 VertexUnion::Arg(2),
|
|
||||||
// TODO: Why do I have index-out-of-range crashes if I move
|
|
||||||
// the ::Vertex(...) to the end?
|
|
||||||
];
|
|
||||||
RuleEval {
|
RuleEval {
|
||||||
geom: Rc::new(MeshFunc {
|
geom: Rc::new(MeshFunc {
|
||||||
verts: next_verts,
|
verts: vert_args(0..6),
|
||||||
faces: vec![ a0, 0, 2, a1, 1, 0, a2, 2, 1, 0, 1, 2 ],
|
faces: vec![
|
||||||
|
b0, m01, bm0,
|
||||||
|
b1, bm1, m01,
|
||||||
|
t, bm0, bm1,
|
||||||
|
m01, bm1, bm0, // middle
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
final_geom: Rc::new(MeshFunc {
|
final_geom: Rc::new(MeshFunc {
|
||||||
verts: vec![],
|
verts: vec![],
|
||||||
@ -224,16 +240,137 @@ pub fn pyramid() -> Rule<()> {
|
|||||||
RuleEval {
|
RuleEval {
|
||||||
geom: Rc::new(MeshFunc {
|
geom: Rc::new(MeshFunc {
|
||||||
verts: base_verts,
|
verts: base_verts,
|
||||||
faces: vec![ 0, 1, 2 ],
|
faces: vec![
|
||||||
|
b0, m01, m20,
|
||||||
|
b1, m12, m01,
|
||||||
|
b2, m20, m12,
|
||||||
|
m12, m20, m01,
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
final_geom: Rc::new(MeshFunc {
|
final_geom: Rc::new(MeshFunc {
|
||||||
verts: vec![],
|
verts: vec![],
|
||||||
faces: vec![],
|
faces: vec![],
|
||||||
}),
|
}),
|
||||||
children: vec![
|
children: vec![
|
||||||
child!(rule!(test, ()), base_to_side(0), 1, 0, 3),
|
child!(rule!(test, ()), base_to_side(0), b1, b0, t, m01, bm1, bm0),
|
||||||
child!(rule!(test, ()), base_to_side(1), 0, 2, 3),
|
child!(rule!(test, ()), base_to_side(1), b0, b2, t, m20, bm0, bm2),
|
||||||
child!(rule!(test, ()), base_to_side(2), 2, 1, 3),
|
child!(rule!(test, ()), base_to_side(2), b2, b1, t, m12, bm2, bm1),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Rule { eval: base, ctxt: () }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pyramid2() -> Rule<()> {
|
||||||
|
|
||||||
|
let rt3 = (3.0).sqrt();
|
||||||
|
|
||||||
|
let dz = 0.05;
|
||||||
|
|
||||||
|
// Indices:
|
||||||
|
// b+0,b+1,b+2 = base vertices
|
||||||
|
// t+0,t+1,t+2 = 'top' vertices above base
|
||||||
|
// bm01, bm12, bm20 = midpoints of (b0,b1), (b1,b2), (b2,b0).
|
||||||
|
// tm01, tm12, tm20 = midpoints of (t0,t1), (t1,t2), (t2,t0).
|
||||||
|
let (b, t, tm01, tm12, tm20);
|
||||||
|
let base_verts: Vec<VertexUnion> = {
|
||||||
|
let v0 = vertex(rt3/3.0, 0.0, 0.0);
|
||||||
|
let v1 = vertex(-rt3/6.0, 1.0/2.0, 0.0);
|
||||||
|
let v2 = vertex(-rt3/6.0, -1.0/2.0, 0.0);
|
||||||
|
let v0b = v0 + vertex(0.0, 0.0, dz);
|
||||||
|
let v1b = v1 + vertex(0.0, 0.0, dz);
|
||||||
|
let v2b = v2 + vertex(0.0, 0.0, dz);
|
||||||
|
vec_indexed![
|
||||||
|
@b VertexUnion::Vertex(v0),
|
||||||
|
VertexUnion::Vertex(v1),
|
||||||
|
VertexUnion::Vertex(v2),
|
||||||
|
@t VertexUnion::Vertex(v0b),
|
||||||
|
VertexUnion::Vertex(v1b),
|
||||||
|
VertexUnion::Vertex(v2b),
|
||||||
|
@tm01 VertexUnion::Vertex((v0b+v1b)/2.0),
|
||||||
|
@tm12 VertexUnion::Vertex((v1b+v2b)/2.0),
|
||||||
|
@tm20 VertexUnion::Vertex((v2b+v0b)/2.0),
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
let tri_split = move |i| {
|
||||||
|
let rt3 = (3.0).sqrt();
|
||||||
|
let angle = 2.0 * FRAC_PI_3 * (i as f32);
|
||||||
|
id().
|
||||||
|
rotate(&Vector3::z_axis(), angle).
|
||||||
|
translate(rt3/12.0, 0.0, 0.0).
|
||||||
|
scale(0.5).
|
||||||
|
translate(0.0, 0.0, dz)
|
||||||
|
};
|
||||||
|
|
||||||
|
let test = rule_fn!(() => |_s, base_verts| {
|
||||||
|
|
||||||
|
let mut next_verts = base_verts;
|
||||||
|
let (a0, a1) = next_verts.append_indexed(vert_args(0..3));
|
||||||
|
|
||||||
|
RuleEval {
|
||||||
|
geom: Rc::new(MeshFunc {
|
||||||
|
verts: next_verts,
|
||||||
|
faces: vec![
|
||||||
|
//a0, a0+1, a0+2,
|
||||||
|
// Outer:
|
||||||
|
tm01, a0+1, t+1,
|
||||||
|
tm01, t+0, a0+0,
|
||||||
|
tm01, a0+0, a0+1,
|
||||||
|
tm12, a0+2, t+2,
|
||||||
|
tm12, t+1, a0+1,
|
||||||
|
tm12, a0+1, a0+2,
|
||||||
|
tm20, a0+0, t+0,
|
||||||
|
tm20, t+2, a0+2,
|
||||||
|
tm20, a0+2, a0+0,
|
||||||
|
// Inner:
|
||||||
|
tm01, tm12, tm20,
|
||||||
|
// Bottom:
|
||||||
|
//b+2, b+1, b+0,
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
final_geom: Rc::new(MeshFunc {
|
||||||
|
verts: vec![],
|
||||||
|
faces: vec![],
|
||||||
|
}),
|
||||||
|
children: vec![
|
||||||
|
child!(_s, tri_split(0), t+0, tm01, tm20),
|
||||||
|
child!(_s, tri_split(1), t+1, tm12, tm01),
|
||||||
|
child!(_s, tri_split(2), t+2, tm20, tm12),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let base = rule_fn!(() => |_s, base_verts| {
|
||||||
|
RuleEval {
|
||||||
|
geom: Rc::new(MeshFunc {
|
||||||
|
verts: base_verts,
|
||||||
|
faces: vec![
|
||||||
|
// Outer:
|
||||||
|
tm01, b+1, t+1,
|
||||||
|
tm01, t+0, b+0,
|
||||||
|
tm01, b+0, b+1,
|
||||||
|
tm12, b+2, t+2,
|
||||||
|
tm12, t+1, b+1,
|
||||||
|
tm12, b+1, b+2,
|
||||||
|
tm20, b+0, t+0,
|
||||||
|
tm20, t+2, b+2,
|
||||||
|
tm20, b+2, b+0,
|
||||||
|
// Inner:
|
||||||
|
tm01, tm12, tm20,
|
||||||
|
// Bottom:
|
||||||
|
b+2, b+1, b+0,
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
final_geom: Rc::new(MeshFunc {
|
||||||
|
verts: vec![],
|
||||||
|
faces: vec![],
|
||||||
|
}),
|
||||||
|
children: vec![
|
||||||
|
child!(rule!(test, ()), tri_split(0), t+0, tm01, tm20),
|
||||||
|
child!(rule!(test, ()), tri_split(1), t+1, tm12, tm01),
|
||||||
|
child!(rule!(test, ()), tri_split(2), t+2, tm20, tm12),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -80,7 +80,7 @@ mod tests {
|
|||||||
fn barbs_random() { run_test(examples::barbs(true), 80, "barbs_random", false); }
|
fn barbs_random() { run_test(examples::barbs(true), 80, "barbs_random", false); }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pyramid() { run_test(examples::pyramid(), 3, "pyramid", false); }
|
fn pyramid() { run_test(examples::pyramid2(), 3, "pyramid2", false); }
|
||||||
/*
|
/*
|
||||||
#[test]
|
#[test]
|
||||||
fn twist() {
|
fn twist() {
|
||||||
|
|||||||
@ -85,7 +85,7 @@ pub struct Child<S> {
|
|||||||
macro_rules! child {
|
macro_rules! child {
|
||||||
( $Rule:expr, $Xform:expr, $( $Arg:expr ),* ) => {
|
( $Rule:expr, $Xform:expr, $( $Arg:expr ),* ) => {
|
||||||
Child {
|
Child {
|
||||||
rule: /*std::rc::Rc::new*/($Rule),
|
rule: /*std::rc::Rc::new*/($Rule).clone(),
|
||||||
xf: $Xform,
|
xf: $Xform,
|
||||||
arg_vals: vec![$($Arg,)*],
|
arg_vals: vec![$($Arg,)*],
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user