Possibly the actual actual bug fix

This commit is contained in:
Chris Hodapp 2020-06-06 16:23:19 -04:00
parent 6a3a19db21
commit 41ea254537
3 changed files with 74 additions and 29 deletions

View File

@ -344,6 +344,20 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
pub fn add_face_twin1(&mut self, twin: usize, vert: V) -> (usize, [usize; 3]) { pub fn add_face_twin1(&mut self, twin: usize, vert: V) -> (usize, [usize; 3]) {
// 'vert' will be at index v_n: // 'vert' will be at index v_n:
let v_n = self.num_verts; let v_n = self.num_verts;
// The half-edges will be at indices e_n, e_n+1, e_n+2:
let e_n = self.num_halfedges;
self.verts.push(DCELVertex {
v: vert,
halfedge: e_n + 2,
});
self.num_verts += 1;
self.add_face_twin1_ref(twin, v_n)
}
/// Like `add_face_twin1`, but for a vertex already present in the
/// mesh rather than a new one. All else is identical.
pub fn add_face_twin1_ref(&mut self, twin: usize, vert_idx: usize) -> (usize, [usize; 3]) {
// The face will be at index f_n: // The face will be at index f_n:
let f_n = self.num_faces; let f_n = self.num_faces;
// The half-edges will be at indices e_n, e_n+1, e_n+2: // The half-edges will be at indices e_n, e_n+1, e_n+2:
@ -380,7 +394,7 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
prev_halfedge: e_n, prev_halfedge: e_n,
}); });
self.halfedges.push(DCELHalfEdge { self.halfedges.push(DCELHalfEdge {
vert: v_n, vert: vert_idx,
face: f_n, face: f_n,
has_twin: false, has_twin: false,
twin_halfedge: 0, twin_halfedge: 0,
@ -390,13 +404,6 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
self.num_halfedges += 3; self.num_halfedges += 3;
// Since the 2nd halfedge we inserted (e_n + 2) has origin v_n:
self.verts.push(DCELVertex {
v: vert,
halfedge: e_n + 2,
});
self.num_verts += 1;
// Finally, add the face (any halfedge is fine): // Finally, add the face (any halfedge is fine):
self.faces.push(DCELFace { halfedge: e_n }); self.faces.push(DCELFace { halfedge: e_n });
self.num_faces += 1; self.num_faces += 1;
@ -412,8 +419,12 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
/// the next half-edge's twin will be twin2. /// the next half-edge's twin will be twin2.
/// Also: halfedge `twin2_idx` must end at the vertex that starts /// Also: halfedge `twin2_idx` must end at the vertex that starts
/// `twin1_idx`. /// `twin1_idx`.
///
/// Returns (face index, halfedge indices). Halfedge indices begin
/// at the twin halfedge to twin1, then twin halfedge of
/// twin2, then the 'new' halfedge (which starts where twin2 starts,
/// and ends where twin1 ends).
pub fn add_face_twin2(&mut self, twin1_idx: usize, twin2_idx: usize) -> (usize, [usize; 3]) { pub fn add_face_twin2(&mut self, twin1_idx: usize, twin2_idx: usize) -> (usize, [usize; 3]) {
println!("DEBUG: add_face_twin2({},{})", twin1_idx, twin2_idx);
// The face will be at index f_n: // The face will be at index f_n:
let f_n = self.num_faces; let f_n = self.num_faces;
// The half-edges will be at indices e_n, e_n+1, e_n+2: // The half-edges will be at indices e_n, e_n+1, e_n+2:
@ -456,6 +467,7 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
}); // index e_n + 1 }); // index e_n + 1
self.halfedges[twin2_idx].has_twin = true; self.halfedges[twin2_idx].has_twin = true;
self.halfedges[twin2_idx].twin_halfedge = e_n + 1; self.halfedges[twin2_idx].twin_halfedge = e_n + 1;
// and final edge must be v3 -> v2:
self.halfedges.push(DCELHalfEdge { self.halfedges.push(DCELHalfEdge {
vert: v3, vert: v3,
face: f_n, face: f_n,

View File

@ -1272,7 +1272,7 @@ pub fn test_parametric() -> Mesh {
//let base_verts = util::subdivide_cycle(&base_verts, 16); //let base_verts = util::subdivide_cycle(&base_verts, 16);
let t0 = 0.0; let t0 = 0.0;
let t1 = 1.0; let t1 = 50.0;
let xform = |t: f32| -> Transform { let xform = |t: f32| -> Transform {
id().translate(0.0, 0.0, t/5.0)/*. id().translate(0.0, 0.0, t/5.0)/*.
rotate(&Vector3::z_axis(), -t/2.0). rotate(&Vector3::z_axis(), -t/2.0).

View File

@ -473,6 +473,10 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
// TODO: Fix boundary behavior here and make sure final topology // TODO: Fix boundary behavior here and make sure final topology
// is right. // is right.
// Indices (into 'frontier') of previous and next:
let i_prev = (i + n - 1) % n;
let i_next = (i + 1) % n;
println!("DEBUG: Moving frontier vertex {}, {:?} (t={}, frame_vert={:?})", i, v.vert, v.t, v.frame_vert); println!("DEBUG: Moving frontier vertex {}, {:?} (t={}, frame_vert={:?})", i, v.vert, v.t, v.frame_vert);
// Move this vertex further along, i.e. t + dt. (dt is set by // Move this vertex further along, i.e. t + dt. (dt is set by
@ -528,14 +532,17 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
// Add two faces to our mesh. They share two vertices, and thus // Add two faces to our mesh. They share two vertices, and thus
// the boundary in between those vertices. // the boundary in between those vertices.
// First face: connect 'prior' frontier vertex to 'v' & 'v_next'. println!("DEBUG: Adding 1st face");
// 'f1' is that face, 'edge1' connects prior vertex and 'v_next'.
// 'edge_v_next' connects 'v_next' and 'v' (in that order!) // First face: connect prior frontier vertex to 'v' & 'v_next'.
// f1 is that face,
// edge1 is: prior frontier vertex -> v_next.
// edge_v_next is: v_next -> v
let (f1, edge1, edge_v_next) = match v.halfedges[0] { let (f1, edge1, edge_v_next) = match v.halfedges[0] {
// However, the way we add the face depends on whether we are // However, the way we add the face depends on whether we are
// adding to an existing boundary or not: // adding to an existing boundary or not:
None => { None => {
let neighbor = &frontier[(i + n - 1) % n]; let neighbor = &frontier[i_prev];
println!("DEBUG: add_face()"); println!("DEBUG: add_face()");
let (f1, edges) = mesh.add_face([ let (f1, edges) = mesh.add_face([
VertSpec::New(v_next), // edges[0]: v_next -> v VertSpec::New(v_next), // edges[0]: v_next -> v
@ -553,15 +560,18 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
// If neighbor.vert_idx is None, then we had to // If neighbor.vert_idx is None, then we had to
// add its vertex to the mesh for the face we just // add its vertex to the mesh for the face we just
// made - so mark it in the frontier: // made - so mark it in the frontier:
frontier[(i + n - 1) % n].vert_idx = Some(mesh.halfedges[edges[2]].vert); frontier[i_prev].vert_idx = Some(mesh.halfedges[edges[2]].vert);
} }
(f1, edges[2], edges[0]) (f1, edges[2], edges[0])
}, },
Some(edge_idx) => { Some(edge_idx) => {
println!("DEBUG: add_face_twin1({},{})", edge_idx, v_next); // edge_idx is half-edge from prior frontier vertex to 'v'
println!("DEBUG: add_face_twin1({}, ({},{},{}))", edge_idx, v_next.x, v_next.y, v_next.z);
let (f1, edges) = mesh.add_face_twin1(edge_idx, v_next); let (f1, edges) = mesh.add_face_twin1(edge_idx, v_next);
// Note the order of half-edges from add_face_twin1 // edges[0] is twin of edge_idx, thus v -> neighbor
// edges[1] is neighbor -> v_next
// edges[2] is v_next -> v
(f1, edges[1], edges[2]) (f1, edges[1], edges[2])
}, },
}; };
@ -571,34 +581,55 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
mesh.check(); mesh.check();
mesh.print(); mesh.print();
// edge2 should be: the half-edge connecting the 'next' frontier println!("DEBUG: Adding 2nd face");
// vertex to 'v_next' // Second face: connect next frontier vertex to 'v' & 'v_next'.
// f2 is that face.
// edge2 is: v_next -> next frontier vertex
let (f2, edge2) = match v.halfedges[1] { let (f2, edge2) = match v.halfedges[1] {
// Likewise, the way we add the second face depends on // Likewise, the way we add the second face depends on
// the same (but for the other side). Regardless, // the same (but for the other side). Regardless,
// they share the boundary between v_next and v.vert - which // they share the boundary between v_next and v.vert - which
// is edges1[0]. // is edges1[0].
None => { None => {
let neighbor = &frontier[(i + 1) % n]; let neighbor = &frontier[i_next];
let (f2, edges) = mesh.add_face_twin1(edge_v_next, neighbor.vert);
if neighbor.vert_idx.is_none() { let (f2, edges) = match neighbor.vert_idx {
None => {
let v = neighbor.vert;
println!("DEBUG: add_face_twin1({}, ({},{},{}))", edge_v_next, v.x, v.y, v.z);
let (f2, edges) = mesh.add_face_twin1(edge_v_next, neighbor.vert);
// Reasoning here is identical to "If neighbor.vert_idx // Reasoning here is identical to "If neighbor.vert_idx
// is None..." above: // is None..." above:
frontier[(i + 1) % n].vert_idx = Some(mesh.halfedges[edges[2]].vert); frontier[i_next].vert_idx = Some(mesh.halfedges[edges[2]].vert);
(f2, edges)
},
Some(vert_idx) => {
println!("DEBUG: add_face_twin1_ref({}, {})", edge_v_next, vert_idx);
mesh.add_face_twin1_ref(edge_v_next, vert_idx)
} }
};
// For either branch:
// edges[0] is twin of edge_v_next, thus: v -> v_next
// edges[1] is: v_next -> neighbor
// egdes[2] is: neighbor -> v
(f2, edges[1]) (f2, edges[1])
}, },
Some(edge_idx) => { Some(edge_idx) => {
let (f2, edges) = mesh.add_face_twin2(edge_v_next, edge1); println!("DEBUG: add_face_twin2({}, {})", edge_idx, edge_v_next);
let (f2, edges) = mesh.add_face_twin2(edge_idx, edge_v_next);
// edges[0] is twin of edge_idx, thus: neighbor -> v
// edges[1] is twin of edge_v_next, thus: v -> v_next
// edges[2] is: v_next -> neighbor
println!("DEBUG: add_face_twin2 returned {:?}", edges);
(f2, edges[2]) (f2, edges[2])
}, },
}; };
println!("DEBUG: edge2={}", edge2); println!("DEBUG: edge2={}", edge2);
// DEBUG // DEBUG
println!("DEBUG: 2nd face"); println!("DEBUG: Added 2nd face");
mesh.check(); mesh.check();
mesh.print(); mesh.print();
@ -620,6 +651,8 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
halfedges: [Some(edge1), Some(edge2)], halfedges: [Some(edge1), Some(edge2)],
vert_idx: Some(mesh.halfedges[edge_v_next].vert), vert_idx: Some(mesh.halfedges[edge_v_next].vert),
}; };
frontier[i_prev].halfedges[1] = Some(edge1);
frontier[i_next].halfedges[0] = Some(edge2);
/* /*
// Also add these faces to the stack of triangles to check for // Also add these faces to the stack of triangles to check for