Twist: closed beginning & end properly.

Yes, it checks out as a manifold mesh too.
This commit is contained in:
Chris Hodapp 2020-03-07 18:53:15 -05:00
parent 84b7bd0b21
commit 9746adf39c
4 changed files with 73 additions and 13 deletions

View File

@ -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");
} }

View File

@ -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 {

View File

@ -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];

View File

@ -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)
}