Finally got this bloody subdivision method working. I think.
This commit is contained in:
parent
6c7b9695af
commit
701b1df915
238
src/dcel.rs
238
src/dcel.rs
@ -380,8 +380,8 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
||||
});
|
||||
// DEBUG
|
||||
if self.halfedges[twin].has_twin {
|
||||
panic!(format!("Trying to add twin to {}, which already has twin ({})",
|
||||
twin, self.halfedges[twin].twin_halfedge));
|
||||
panic!("Trying to add twin to {}, which already has twin ({})",
|
||||
twin, self.halfedges[twin].twin_halfedge);
|
||||
}
|
||||
self.halfedges[twin].has_twin = true;
|
||||
self.halfedges[twin].twin_halfedge = e_n;
|
||||
@ -440,8 +440,8 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
||||
let v3 = twin2.vert;
|
||||
|
||||
if v1 != self.halfedges[twin2.next_halfedge].vert {
|
||||
panic!(format!("twin2 ({}) must end where twin1 ({}) begins, but does not (vertex {} vs. {})",
|
||||
twin2_idx, twin1_idx, self.halfedges[twin2.next_halfedge].vert, v1));
|
||||
panic!("twin2 ({}) must end where twin1 ({}) begins, but does not (vertex {} vs. {})",
|
||||
twin2_idx, twin1_idx, self.halfedges[twin2.next_halfedge].vert, v1);
|
||||
}
|
||||
|
||||
// twin1 is: v1 -> v2, twin2 is: v3 -> v1.
|
||||
@ -485,6 +485,232 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
||||
(f_n, [e_n, e_n+1, e_n+2])
|
||||
}
|
||||
|
||||
pub fn split_face(&mut self, face: usize, verts: Vec<V>) {
|
||||
// 'verts' maps 1:1 to vertices for 'face' (i.e. face_to_verts).
|
||||
|
||||
let mut edge_idx = self.faces[face].halfedge;
|
||||
let n = verts.len();
|
||||
|
||||
//
|
||||
let new_edges: Vec<(usize, usize)> = verts.iter().map(|v| {
|
||||
|
||||
println!("DEBUG: halfedge 3: {:?}", self.halfedges[3]);
|
||||
println!("DEBUG: halfedge {}: {:?}", self.halfedges[3].next_halfedge, self.halfedges[self.halfedges[3].next_halfedge]);
|
||||
|
||||
// As we iterate over every vertex, we walk the half-edges:
|
||||
let mut edge = self.halfedges[edge_idx].clone();
|
||||
if !edge.has_twin {
|
||||
panic!("Halfedge {} has no twin, and split_face (for now) requires twins", edge_idx);
|
||||
}
|
||||
// TODO: Remove the above limitation and just don't try to split
|
||||
// nonexistent twins. I think all logic works the same way.
|
||||
|
||||
let next_idx = edge.next_halfedge;
|
||||
let twin_idx = edge.twin_halfedge;
|
||||
let mut twin = self.halfedges[twin_idx].clone();
|
||||
|
||||
// This half-edge, and its twin, are both split (at this
|
||||
// vertex). Half-edges i & j will be the new ones created.
|
||||
let i_edge = self.num_halfedges;
|
||||
let j_edge = i_edge + 1;
|
||||
// Half of edge_idx is split into j_edge.
|
||||
// Half of twin_idx (its twin) is split into i_edge.
|
||||
|
||||
println!("DEBUG: edge_idx={} next_idx={} twin_idx={} i_edge={} j_edge={}", edge_idx, next_idx, twin_idx, i_edge, j_edge);
|
||||
// This is where the vertex will be inserted:
|
||||
let v_idx = self.num_verts;
|
||||
println!("DEBUG: adding v_idx={}", v_idx);
|
||||
self.verts.push(DCELVertex {
|
||||
v: *v,
|
||||
halfedge: i_edge, // j_edge is also fine
|
||||
});
|
||||
self.num_verts += 1;
|
||||
|
||||
edge.twin_halfedge = i_edge;
|
||||
let j_next = edge.next_halfedge;
|
||||
|
||||
twin.twin_halfedge = j_edge;
|
||||
let i_next = twin.next_halfedge;
|
||||
println!("DEBUG: new twin of {} = {}; new twin of {} = {}", edge_idx, i_edge, twin_idx, j_edge);
|
||||
|
||||
self.halfedges.push(DCELHalfEdge {
|
||||
vert: v_idx,
|
||||
face: 0, // This is set properly in the next loop
|
||||
has_twin: true,
|
||||
twin_halfedge: edge_idx,
|
||||
next_halfedge: i_next,
|
||||
prev_halfedge: twin_idx,
|
||||
}); // i_edge
|
||||
println!("DEBUG: edge {}: vert {} twin {} next {} prev {} (ends at vertex {})", i_edge, v_idx, edge_idx, i_next, twin_idx, self.halfedges[self.halfedges[twin_idx].next_halfedge].vert);
|
||||
|
||||
self.halfedges.push(DCELHalfEdge {
|
||||
vert: v_idx,
|
||||
face: 0, // This is set properly in the next loop
|
||||
has_twin: true,
|
||||
twin_halfedge: twin_idx,
|
||||
next_halfedge: j_next,
|
||||
prev_halfedge: edge_idx,
|
||||
}); // j_edge
|
||||
println!("DEBUG: edge {}: vert {} twin {} next {} prev {} (ends at vertex {})", j_edge, v_idx, twin_idx, j_next, edge_idx, self.halfedges[self.halfedges[edge_idx].next_halfedge].vert);
|
||||
|
||||
self.num_halfedges += 2;
|
||||
|
||||
self.halfedges[edge_idx] = edge;
|
||||
self.halfedges[twin_idx] = twin;
|
||||
|
||||
let r = (edge_idx, j_edge);
|
||||
|
||||
edge_idx = next_idx;
|
||||
|
||||
r
|
||||
}).collect();
|
||||
|
||||
println!("DEBUG: {:?}", new_edges);
|
||||
|
||||
// We then must connect some edges up 'across' vertices
|
||||
// in order to form the smaller face at each vertex.
|
||||
//
|
||||
// This is outside the loop because we need one iteration's
|
||||
// value (any iteration, doesn't matter) to reassign a face:
|
||||
let mut e_twin_idx = 0;
|
||||
let twin_edges: Vec<usize> = (0..n).map(|i0| {
|
||||
let i1 = (i0 + 1) % n;
|
||||
|
||||
let (_, ep_idx) = new_edges[i0];
|
||||
let (en_idx, _) = new_edges[i1];
|
||||
|
||||
// Halfedges will be inserted here:
|
||||
let e_cross_idx = self.num_halfedges;
|
||||
e_twin_idx = e_cross_idx + 1;
|
||||
// And the face here:
|
||||
let face_new = self.num_faces;
|
||||
|
||||
println!("DEBUG: i0={} i1={} ep_idx={} en_idx={} e_cross_idx={} e_twin_idx={} face_new={}",
|
||||
i0, i1, ep_idx, en_idx, e_cross_idx, e_twin_idx, face_new);
|
||||
|
||||
// So, the vertex for i0 had two halfedges (one pointing in,
|
||||
// one pointing out). We split both those half-edges earlier.
|
||||
// en_idx & ep_idx are the halves that are nearest the
|
||||
// vertex. The point of below is to form a smaller triangle
|
||||
// (which includes this vertex, and the point at which both
|
||||
// edges were split). This requires a half-edge from ep_idx
|
||||
// (which *starts* where the other was split) to en_idx (which
|
||||
// *ends* where one edge was split).
|
||||
self.halfedges.push(DCELHalfEdge {
|
||||
vert: self.halfedges[self.halfedges[en_idx].twin_halfedge].vert,
|
||||
face: face_new,
|
||||
has_twin: true,
|
||||
twin_halfedge: e_twin_idx,
|
||||
next_halfedge: ep_idx,
|
||||
prev_halfedge: en_idx,
|
||||
}); // e_cross_idx
|
||||
println!("DEBUG: edge {}: vert {} twin {} next {} prev {} (ends at vertex {})", e_cross_idx, self.halfedges[en_idx].vert, e_twin_idx, ep_idx, en_idx, self.halfedges[self.halfedges[e_cross_idx].next_halfedge].vert);
|
||||
|
||||
// It also requires a twin half-edge. These all form a single
|
||||
// central face with each edge sharing a boundary with the
|
||||
// 'cross' edge we just created.
|
||||
self.halfedges.push(DCELHalfEdge {
|
||||
vert: self.halfedges[ep_idx].vert,
|
||||
face: face, // Reuse index for the smaller *central* face
|
||||
has_twin: true,
|
||||
twin_halfedge: e_cross_idx,
|
||||
next_halfedge: 0, // TODO
|
||||
prev_halfedge: 0, // TODO
|
||||
}); // e_twin_idx
|
||||
println!("DEBUG: edge {}: vert {} twin {} next/prev incorrect", e_twin_idx, self.halfedges[ep_idx].vert, e_cross_idx);
|
||||
|
||||
self.num_halfedges += 2;
|
||||
|
||||
// en/ep also need directed to 'new' edges and each other
|
||||
self.halfedges[en_idx].prev_halfedge = ep_idx;
|
||||
self.halfedges[en_idx].next_halfedge = e_cross_idx;
|
||||
println!("DEBUG: edge {}: now next {} prev {} ends at vert {}", en_idx, e_cross_idx, ep_idx, self.halfedges[self.halfedges[en_idx].next_halfedge].vert);
|
||||
|
||||
self.halfedges[ep_idx].next_halfedge = en_idx;
|
||||
self.halfedges[ep_idx].prev_halfedge = e_cross_idx;
|
||||
println!("DEBUG: edge {}: now next {} prev {} ends at vert {}", ep_idx, en_idx, e_cross_idx, self.halfedges[self.halfedges[ep_idx].next_halfedge].vert);
|
||||
|
||||
self.halfedges[ep_idx].face = face_new;
|
||||
|
||||
self.faces.push(DCELFace {
|
||||
halfedge: e_cross_idx, // en_idx or ep_idx is fine too
|
||||
});
|
||||
self.num_faces += 1;
|
||||
|
||||
// We also need to split the opposite side to make the two
|
||||
// 'side' triangles (which means two new half-edges).
|
||||
// First, we have to find the halfedge that starts the
|
||||
// 'opposite' vertex (outer2):
|
||||
let base1 = self.halfedges[en_idx].twin_halfedge;
|
||||
let base2 = self.halfedges[base1].prev_halfedge;
|
||||
let outer1 = self.halfedges[base1].next_halfedge;
|
||||
let outer2 = self.halfedges[outer1].next_halfedge;
|
||||
let v_opp = self.halfedges[outer2].vert;
|
||||
// One face will reuse the old index:
|
||||
let face1 = self.halfedges[outer2].face;
|
||||
// Another will be inserted at this index:
|
||||
let face2 = self.num_faces;
|
||||
// Half-edges will be inserted here:
|
||||
let edge_side1 = self.num_halfedges;
|
||||
let edge_side2 = edge_side1 + 1;
|
||||
self.halfedges.push(DCELHalfEdge {
|
||||
vert: v_opp,
|
||||
face: face1,
|
||||
has_twin: true,
|
||||
twin_halfedge: edge_side2,
|
||||
next_halfedge: base1,
|
||||
prev_halfedge: outer1,
|
||||
}); // edge_side1
|
||||
self.halfedges.push(DCELHalfEdge {
|
||||
vert: self.halfedges[base1].vert,
|
||||
face: face2,
|
||||
has_twin: true,
|
||||
twin_halfedge: edge_side1,
|
||||
next_halfedge: outer2,
|
||||
prev_halfedge: base2,
|
||||
}); // edge_side2
|
||||
self.num_halfedges += 2;
|
||||
|
||||
self.faces.push(DCELFace {
|
||||
halfedge: outer2, // base2 or edge_side2 is fine too
|
||||
});
|
||||
self.num_faces += 1;
|
||||
self.faces[face1].halfedge = outer1; // base1 or edge_side1 is fine too
|
||||
|
||||
self.halfedges[outer1].next_halfedge = edge_side1;
|
||||
self.halfedges[outer1].prev_halfedge = base1;
|
||||
self.halfedges[outer1].face = face1;
|
||||
self.halfedges[base1].face = face1;
|
||||
self.halfedges[base1].prev_halfedge = edge_side1;
|
||||
self.halfedges[base1].next_halfedge = outer1;
|
||||
|
||||
self.halfedges[outer2].next_halfedge = base2;
|
||||
self.halfedges[outer2].prev_halfedge = edge_side2;
|
||||
self.halfedges[outer2].face = face2;
|
||||
self.halfedges[base2].face = face2;
|
||||
self.halfedges[base2].prev_halfedge = outer2;
|
||||
self.halfedges[base2].next_halfedge = edge_side2;
|
||||
|
||||
println!("DEBUG: base1={} base2={} outer1={} outer2={} face1={} face2={} edge_side1={} edge_side2={}",
|
||||
base1, base2, outer1, outer2, face1, face2, edge_side1, edge_side2);
|
||||
e_twin_idx
|
||||
}).collect();
|
||||
|
||||
println!("DEBUG: cross_edges={:?}", twin_edges);
|
||||
|
||||
for i0 in 0..n {
|
||||
let i1 = (i0 + 1) % n;
|
||||
|
||||
self.halfedges[twin_edges[i0]].next_halfedge = twin_edges[i1];
|
||||
self.halfedges[twin_edges[i1]].prev_halfedge = twin_edges[i0];
|
||||
}
|
||||
|
||||
// We split up original 'face' completely and created four new faces,
|
||||
// We need something at this index, and the other three already have
|
||||
// indices, so reuse it for the smaller central face:
|
||||
self.faces[face].halfedge = e_twin_idx;
|
||||
}
|
||||
|
||||
pub fn convert_mesh<F>(&self, f: F) -> Mesh
|
||||
where F: Fn(V) -> Vertex,
|
||||
{
|
||||
@ -503,8 +729,8 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
||||
let h2 = &self.halfedges[e2];
|
||||
faces[3*i + 2] = h2.vert;
|
||||
if h2.next_halfedge != e0 {
|
||||
panic!(format!("Face {}: half-edges {},{},{} return to {}, not {}",
|
||||
i, e0, e1, e2, h2.next_halfedge, e0));
|
||||
panic!("Face {}: half-edges {},{},{} return to {}, not {}",
|
||||
i, e0, e1, e2, h2.next_halfedge, e0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1325,7 +1325,18 @@ pub fn test_dcel(fname: &str) {
|
||||
println!("f3 verts: {:?}", mesh.face_to_verts(f3));
|
||||
println!("f4 verts: {:?}", mesh.face_to_verts(f4));
|
||||
|
||||
println!("DCEL mesh = {}", mesh);
|
||||
println!("DCEL mesh: ");
|
||||
mesh.print();
|
||||
|
||||
mesh.split_face(f1, vec![
|
||||
vertex(-0.5, 0.0, 0.0),
|
||||
vertex(0.0, 0.5, 0.0),
|
||||
vertex(0.0, 0.0, 0.0),
|
||||
]);
|
||||
|
||||
println!("DCEL mesh after subdiv");
|
||||
mesh.check();
|
||||
mesh.print();
|
||||
|
||||
let mesh_conv = mesh.convert_mesh(|i| i);
|
||||
|
||||
|
||||
@ -666,7 +666,7 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
|
||||
|
||||
let v_idx = mesh.face_to_verts(face);
|
||||
if v_idx.len() != 3 {
|
||||
panic!(format!("Face {} has {} vertices, not 3?", face, v_idx.len()));
|
||||
panic!("Face {} has {} vertices, not 3?", face, v_idx.len());
|
||||
}
|
||||
let tr = [mesh.verts[v_idx[0]].v,
|
||||
mesh.verts[v_idx[1]].v,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user