Twist: closed beginning & end properly.
Yes, it checks out as a manifold mesh too.
This commit is contained in:
parent
84b7bd0b21
commit
9746adf39c
@ -303,12 +303,13 @@ impl Twist {
|
|||||||
|
|
||||||
pub fn init() -> (Twist, Rule<Twist>) {
|
pub fn init() -> (Twist, Rule<Twist>) {
|
||||||
let subdiv = 2;
|
let subdiv = 2;
|
||||||
|
let xf = geometry::Rotation3::from_axis_angle(&Vector3::x_axis(), -0.7).to_homogeneous();
|
||||||
let seed = vec![
|
let seed = vec![
|
||||||
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),
|
||||||
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),
|
||||||
];
|
].iter().map(|v| xf * v).collect();
|
||||||
let seed_sub = util::subdivide_cycle(&seed, subdiv);
|
let seed_sub = util::subdivide_cycle(&seed, subdiv);
|
||||||
let t = Twist {
|
let t = Twist {
|
||||||
dx0: 2.0,
|
dx0: 2.0,
|
||||||
@ -342,23 +343,23 @@ impl Twist {
|
|||||||
Child {
|
Child {
|
||||||
rule: Rule { eval: Self::recur },
|
rule: Rule { eval: Self::recur },
|
||||||
xf: xf,
|
xf: xf,
|
||||||
vmap: (n*i..n*(i+self.count)).collect(), // N.B.
|
vmap: ((n+1)*i..(n+1)*(i+self.count)).collect(), // N.B.
|
||||||
|
// note n+1, not n. the +1 is for the centroid below
|
||||||
}
|
}
|
||||||
}).collect();
|
}).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:
|
||||||
let mut verts = vec![];
|
let meshes = children.iter().map(|child| {
|
||||||
for child in &children {
|
let mut vs = self.seed_sub.iter().map(|v| child.xf * v).collect();
|
||||||
verts.extend(self.seed_sub.iter().map(|v| child.xf * v));
|
// and in the process, generate faces for these seeds:
|
||||||
}
|
let (centroid, f) = util::connect_convex(&vs, false);
|
||||||
|
vs.push(centroid);
|
||||||
|
OpenMesh { verts: vs, faces: f }
|
||||||
|
});
|
||||||
|
|
||||||
RuleEval {
|
RuleEval {
|
||||||
geom: OpenMesh {
|
geom: OpenMesh::append(meshes),
|
||||||
verts: verts,
|
|
||||||
faces: vec![],
|
|
||||||
// TODO: Close these initial faces off
|
|
||||||
},
|
|
||||||
final_geom: prim::empty_mesh(),
|
final_geom: prim::empty_mesh(),
|
||||||
children: children,
|
children: children,
|
||||||
}
|
}
|
||||||
@ -373,13 +374,15 @@ impl Twist {
|
|||||||
let seed_orig = self.seed.iter().map(|v| incr * v).collect();
|
let seed_orig = self.seed.iter().map(|v| incr * v).collect();
|
||||||
let seed_sub = util::subdivide_cycle(&seed_orig, self.subdiv);
|
let seed_sub = util::subdivide_cycle(&seed_orig, self.subdiv);
|
||||||
let n = seed_sub.len();
|
let n = seed_sub.len();
|
||||||
|
|
||||||
|
let (vc, faces) = util::connect_convex(&seed_sub, true);
|
||||||
|
|
||||||
RuleEval {
|
RuleEval {
|
||||||
geom: OpenMesh {
|
geom: OpenMesh {
|
||||||
verts: seed_sub,
|
verts: seed_sub,
|
||||||
faces: util::parallel_zigzag_faces(n),
|
faces: util::parallel_zigzag_faces(n),
|
||||||
},
|
},
|
||||||
final_geom: prim::empty_mesh(), // TODO: Close properly
|
final_geom: OpenMesh { verts: vec![vc], faces },
|
||||||
children: vec![
|
children: vec![
|
||||||
Child {
|
Child {
|
||||||
rule: Rule { eval: Self::recur },
|
rule: Rule { eval: Self::recur },
|
||||||
@ -439,5 +442,5 @@ pub fn main() {
|
|||||||
// TODO: If I increase the above from 100 to ~150, Blender reports
|
// TODO: If I increase the above from 100 to ~150, Blender reports
|
||||||
// that the very tips are non-manifold. I am wondering if this is
|
// that the very tips are non-manifold. I am wondering if this is
|
||||||
// some sort of numerical precision issue.
|
// some sort of numerical precision issue.
|
||||||
run_test_iter(Twist::init(), 200, "twist2");
|
run_test_iter(Twist::init(), 100, "twist2");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,31 @@ pub struct OpenMesh {
|
|||||||
|
|
||||||
impl OpenMesh {
|
impl OpenMesh {
|
||||||
|
|
||||||
|
pub fn append<T>(meshes: T) -> OpenMesh
|
||||||
|
where T: IntoIterator<Item = OpenMesh>
|
||||||
|
{
|
||||||
|
let mut v: Vec<Vertex> = vec![];
|
||||||
|
let mut f: Vec<Tag> = vec![];
|
||||||
|
for mesh in meshes {
|
||||||
|
// Position in 'verts' at which we're appending
|
||||||
|
// mesh.verts, which we need to know to shift indices:
|
||||||
|
let offset = v.len();
|
||||||
|
|
||||||
|
// Copy all vertices:
|
||||||
|
v.append(&mut mesh.verts.clone());
|
||||||
|
// Append its faces, applying offset:
|
||||||
|
f.extend(mesh.faces.iter().map(|t| {
|
||||||
|
match t {
|
||||||
|
Tag::Body(n) => Tag::Body(n + offset),
|
||||||
|
Tag::Parent(_) => panic!("Cannot append() if mesh has parent references!"),
|
||||||
|
// TODO: Handle the above
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenMesh { verts: v, faces: f }
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a new `OpenMesh` whose vertices have been transformed.
|
/// Returns a new `OpenMesh` whose vertices have been transformed.
|
||||||
pub fn transform(&self, xfm: &Mat4) -> OpenMesh {
|
pub fn transform(&self, xfm: &Mat4) -> OpenMesh {
|
||||||
OpenMesh {
|
OpenMesh {
|
||||||
|
|||||||
@ -150,6 +150,12 @@ impl<A> Rule<A> {
|
|||||||
// s = the 'current' state:
|
// s = the 'current' state:
|
||||||
let s = &mut stack[n-1];
|
let s = &mut stack[n-1];
|
||||||
let depth = s.depth;
|
let depth = s.depth;
|
||||||
|
|
||||||
|
if s.rules.is_empty() {
|
||||||
|
stack.pop();
|
||||||
|
n -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Evaluate the rule:
|
// Evaluate the rule:
|
||||||
let child = &s.rules[s.next];
|
let child = &s.rules[s.next];
|
||||||
|
|||||||
26
src/util.rs
26
src/util.rs
@ -29,3 +29,29 @@ pub fn parallel_zigzag_faces(count: usize) -> Vec<Tag> {
|
|||||||
]
|
]
|
||||||
}).flatten().collect()
|
}).flatten().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn connect_convex(verts: &Vec<Vertex>, as_parent: bool) -> (Vertex, Vec<Tag>) {
|
||||||
|
let n = verts.len();
|
||||||
|
let mut centroid = Vertex::new(0.0, 0.0, 0.0, 0.0);
|
||||||
|
for v in verts {
|
||||||
|
centroid += v;
|
||||||
|
}
|
||||||
|
centroid /= n as f32;
|
||||||
|
|
||||||
|
let faces: Vec<Tag> = {
|
||||||
|
if as_parent {
|
||||||
|
(0..n).map(|f1| {
|
||||||
|
let f2 = (f1 + 1) % n;
|
||||||
|
vec![Tag::Parent(f2), Tag::Parent(f1), Tag::Body(0)]
|
||||||
|
}).flatten().collect()
|
||||||
|
} else {
|
||||||
|
(0..n).map(|f1| {
|
||||||
|
let f2 = (f1 + 1) % n;
|
||||||
|
// n is used for new center vertex
|
||||||
|
vec![Tag::Body(f1), Tag::Body(f2), Tag::Body(n)]
|
||||||
|
}).flatten().collect()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(centroid, faces)
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user