From 6a3a19db2106ecd8daf3c603e39bddd462189f9e Mon Sep 17 00:00:00 2001 From: Chris Hodapp Date: Sat, 6 Jun 2020 11:06:45 -0400 Subject: [PATCH] Fixed a few more bugs in parametric_mesh. More remain... --- src/dcel.rs | 18 ++++++++---- src/examples.rs | 2 +- src/rule.rs | 75 ++++++++++++++++++++++++++++++++----------------- 3 files changed, 62 insertions(+), 33 deletions(-) diff --git a/src/dcel.rs b/src/dcel.rs index 0a758dd..9a0da51 100644 --- a/src/dcel.rs +++ b/src/dcel.rs @@ -353,8 +353,9 @@ impl DCELMesh { let twin_halfedge = &self.halfedges[twin]; let v1 = self.halfedges[twin_halfedge.next_halfedge].vert; let v2 = twin_halfedge.vert; + // twin is: v2 -> v1 - // Insert 'twin' half-edge first: + // Insert *its* twin, v1 -> v2, first: self.halfedges.push(DCELHalfEdge { vert: v1, face: f_n, @@ -363,6 +364,11 @@ impl DCELMesh { next_halfedge: e_n + 1, prev_halfedge: e_n + 2, }); + // DEBUG + if self.halfedges[twin].has_twin { + panic!(format!("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; self.halfedges.push(DCELHalfEdge { @@ -429,7 +435,6 @@ impl DCELMesh { // twin1 is: v1 -> v2, twin2 is: v3 -> v1. // so the twin of twin1 must be: v2 -> v1 - // and the twin of twin2 must be: v1 -> v3 self.halfedges.push(DCELHalfEdge { vert: v2, face: f_n, @@ -440,24 +445,25 @@ impl DCELMesh { }); // index e_n self.halfedges[twin1_idx].has_twin = true; self.halfedges[twin1_idx].twin_halfedge = e_n; + // and the twin of twin2 must be: v1 -> v3 self.halfedges.push(DCELHalfEdge { - vert: v3, + vert: v1, face: f_n, has_twin: true, twin_halfedge: twin2_idx, next_halfedge: e_n + 2, prev_halfedge: e_n, }); // index e_n + 1 + self.halfedges[twin2_idx].has_twin = true; + self.halfedges[twin2_idx].twin_halfedge = e_n + 1; self.halfedges.push(DCELHalfEdge { - vert: v1, + vert: v3, face: f_n, has_twin: false, twin_halfedge: 0, next_halfedge: e_n, prev_halfedge: e_n + 1, }); // index e_n + 2 - self.halfedges[twin2_idx].has_twin = true; - self.halfedges[twin2_idx].twin_halfedge = e_n + 1; self.num_halfedges += 3; // Finally, add the face (any halfedge is fine): diff --git a/src/examples.rs b/src/examples.rs index da92f05..202657b 100644 --- a/src/examples.rs +++ b/src/examples.rs @@ -1272,7 +1272,7 @@ pub fn test_parametric() -> Mesh { //let base_verts = util::subdivide_cycle(&base_verts, 16); let t0 = 0.0; - let t1 = 16.0; + let t1 = 1.0; let xform = |t: f32| -> Transform { id().translate(0.0, 0.0, t/5.0)/*. rotate(&Vector3::z_axis(), -t/2.0). diff --git a/src/rule.rs b/src/rule.rs index b70169b..96ea3b5 100644 --- a/src/rule.rs +++ b/src/rule.rs @@ -432,7 +432,29 @@ pub fn parametric_mesh(frame: Vec, f: F, t0: f32, t1: f32, max_err: f while !frontier.is_empty() { for (i, f) in frontier.iter().enumerate() { - println!("DEBUG: frontier[{}]: vert={},{},{} t={} halfedges={:?}", i, f.vert.x, f.vert.y, f.vert.z, f.t, f.halfedges); + println!("DEBUG: frontier[{}]: vert={},{},{} vert_idx={:?} t={} halfedges={:?}", i, f.vert.x, f.vert.y, f.vert.z, f.vert_idx, f.t, f.halfedges); + match f.vert_idx { + Some(vert) => { + match f.halfedges[1] { + Some(idx) => { + if mesh.halfedges[idx].vert != vert { + println!(" Error: halfedge[1]={} starts at {}, should start at {}", idx, mesh.halfedges[idx].vert, vert); + } + }, + None => {}, + }; + match f.halfedges[0] { + Some(idx) => { + let v2 = mesh.halfedges[mesh.halfedges[idx].next_halfedge].vert; + if v2 != vert { + println!(" Error: halfedge[0]={} ends at {}, should start at {}", idx, v2, vert); + } + }, + None => {}, + }; + }, + None => {}, + }; } // Pick a vertex to advance. @@ -457,7 +479,8 @@ pub fn parametric_mesh(frame: Vec, f: F, t0: f32, t1: f32, max_err: f // the furthest we can go while remaining within 'err', i.e. when we // make our connections we look at how far points on the *edges* // diverge from the trajectory of the continuous transformation). - let mut dt = (t1 - t0) / 100.0; + //let mut dt = (t1 - t0) / 100.0; + let mut dt = (t1 - t0) / 10.0; let vf = v.frame_vert; for iter in 0..0 /*100*/ { // DEBUG: Re-enable // Consider an edge from f(v.t)*vf to f(v.t + dt)*vf. @@ -502,50 +525,54 @@ pub fn parametric_mesh(frame: Vec, f: F, t0: f32, t1: f32, max_err: f println!("l1={} l2={} l3={}", l1, l2, l3); */ - // Add two faces to our mesh. (They share two vertices, and thus - // the boundary in between those vertices.) - let (f1, edges1) = match v.halfedges[0] { + // Add two faces to our mesh. They share two vertices, and thus + // the boundary in between those vertices. + + // First face: connect 'prior' frontier vertex to 'v' & 'v_next'. + // 'f1' is that face, 'edge1' connects prior vertex and 'v_next'. + // 'edge_v_next' connects 'v_next' and 'v' (in that order!) + let (f1, edge1, edge_v_next) = match v.halfedges[0] { // However, the way we add the face depends on whether we are // adding to an existing boundary or not: None => { let neighbor = &frontier[(i + n - 1) % n]; println!("DEBUG: add_face()"); - let (f1, edges1) = mesh.add_face([ - VertSpec::New(v_next), + let (f1, edges) = mesh.add_face([ + VertSpec::New(v_next), // edges[0]: v_next -> v match v.vert_idx { None => VertSpec::New(v.vert), Some(idx) => VertSpec::Idx(idx), - }, + }, // edges[1]: v -> neighbor match neighbor.vert_idx { None => VertSpec::New(neighbor.vert), Some(idx) => VertSpec::Idx(idx), - }, + }, // edges[2]: neighbor -> v_next ]); if neighbor.vert_idx.is_none() { // If neighbor.vert_idx is None, then we had to // add its vertex to the mesh for the face we just // made - so mark it in the frontier: - frontier[(i + n - 1) % n].vert_idx = Some(mesh.halfedges[edges1[2]].vert); - // edges[2] is because this is the position of - // neighbor.vert_idx in add_face. + frontier[(i + n - 1) % n].vert_idx = Some(mesh.halfedges[edges[2]].vert); } - (f1, edges1) + (f1, edges[2], edges[0]) }, Some(edge_idx) => { println!("DEBUG: add_face_twin1({},{})", edge_idx, v_next); - 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 + (f1, edges[1], edges[2]) }, }; - println!("DEBUG: edges1={:?}", edges1); + println!("DEBUG: edge1={} edge_v_next={}", edge1, edge_v_next); // DEBUG mesh.check(); mesh.print(); - // edge2 should be: the half-edge connecting the 'neighbor' frontier - // vertex to v_next + // edge2 should be: the half-edge connecting the 'next' frontier + // vertex to 'v_next' let (f2, edge2) = match v.halfedges[1] { // Likewise, the way we add the second face depends on // the same (but for the other side). Regardless, @@ -553,7 +580,7 @@ pub fn parametric_mesh(frame: Vec, f: F, t0: f32, t1: f32, max_err: f // is edges1[0]. None => { let neighbor = &frontier[(i + 1) % n]; - let (f2, edges) = mesh.add_face_twin1(edges1[0], neighbor.vert); + let (f2, edges) = mesh.add_face_twin1(edge_v_next, neighbor.vert); if neighbor.vert_idx.is_none() { // Reasoning here is identical to "If neighbor.vert_idx @@ -564,8 +591,7 @@ pub fn parametric_mesh(frame: Vec, f: F, t0: f32, t1: f32, max_err: f (f2, edges[1]) }, Some(edge_idx) => { - let (f2, edges) = mesh.add_face_twin2(edge_idx, edges1[2]); - // TODO: Why edges1[2]? + let (f2, edges) = mesh.add_face_twin2(edge_v_next, edge1); (f2, edges[2]) }, }; @@ -591,11 +617,8 @@ pub fn parametric_mesh(frame: Vec, f: F, t0: f32, t1: f32, max_err: f vert: v_next, frame_vert: vf, t: t, - halfedges: [Some(edges1[2]), Some(edge2)], - // Note that edges1[2] *starts* at the new vertex, and - // edge2 *ends* at it. - // DEBUG: The above comment is wrong, but why? - vert_idx: Some(mesh.halfedges[edges1[2]].vert), + halfedges: [Some(edge1), Some(edge2)], + vert_idx: Some(mesh.halfedges[edge_v_next].vert), }; /* @@ -713,5 +736,5 @@ pub fn parametric_mesh(frame: Vec, f: F, t0: f32, t1: f32, max_err: f */ } - return Mesh { faces: vec![], verts: vec![] }; + return dcel::convert_mesh(&mesh); } \ No newline at end of file