Fixed a few more bugs in parametric_mesh. More remain...

This commit is contained in:
Chris Hodapp 2020-06-06 11:06:45 -04:00
parent 39072e0c30
commit 6a3a19db21
3 changed files with 62 additions and 33 deletions

View File

@ -353,8 +353,9 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
let twin_halfedge = &self.halfedges[twin]; let twin_halfedge = &self.halfedges[twin];
let v1 = self.halfedges[twin_halfedge.next_halfedge].vert; let v1 = self.halfedges[twin_halfedge.next_halfedge].vert;
let v2 = twin_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 { self.halfedges.push(DCELHalfEdge {
vert: v1, vert: v1,
face: f_n, face: f_n,
@ -363,6 +364,11 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
next_halfedge: e_n + 1, next_halfedge: e_n + 1,
prev_halfedge: e_n + 2, 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].has_twin = true;
self.halfedges[twin].twin_halfedge = e_n; self.halfedges[twin].twin_halfedge = e_n;
self.halfedges.push(DCELHalfEdge { self.halfedges.push(DCELHalfEdge {
@ -429,7 +435,6 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
// twin1 is: v1 -> v2, twin2 is: v3 -> v1. // twin1 is: v1 -> v2, twin2 is: v3 -> v1.
// so the twin of twin1 must be: v2 -> v1 // so the twin of twin1 must be: v2 -> v1
// and the twin of twin2 must be: v1 -> v3
self.halfedges.push(DCELHalfEdge { self.halfedges.push(DCELHalfEdge {
vert: v2, vert: v2,
face: f_n, face: f_n,
@ -440,24 +445,25 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
}); // index e_n }); // index e_n
self.halfedges[twin1_idx].has_twin = true; self.halfedges[twin1_idx].has_twin = true;
self.halfedges[twin1_idx].twin_halfedge = e_n; self.halfedges[twin1_idx].twin_halfedge = e_n;
// and the twin of twin2 must be: v1 -> v3
self.halfedges.push(DCELHalfEdge { self.halfedges.push(DCELHalfEdge {
vert: v3, vert: v1,
face: f_n, face: f_n,
has_twin: true, has_twin: true,
twin_halfedge: twin2_idx, twin_halfedge: twin2_idx,
next_halfedge: e_n + 2, next_halfedge: e_n + 2,
prev_halfedge: e_n, prev_halfedge: e_n,
}); // index e_n + 1 }); // index e_n + 1
self.halfedges[twin2_idx].has_twin = true;
self.halfedges[twin2_idx].twin_halfedge = e_n + 1;
self.halfedges.push(DCELHalfEdge { self.halfedges.push(DCELHalfEdge {
vert: v1, vert: v3,
face: f_n, face: f_n,
has_twin: false, has_twin: false,
twin_halfedge: 0, twin_halfedge: 0,
next_halfedge: e_n, next_halfedge: e_n,
prev_halfedge: e_n + 1, prev_halfedge: e_n + 1,
}); // index e_n + 2 }); // index e_n + 2
self.halfedges[twin2_idx].has_twin = true;
self.halfedges[twin2_idx].twin_halfedge = e_n + 1;
self.num_halfedges += 3; self.num_halfedges += 3;
// Finally, add the face (any halfedge is fine): // Finally, add the face (any halfedge is fine):

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 = 16.0; let t1 = 1.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

@ -432,7 +432,29 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
while !frontier.is_empty() { while !frontier.is_empty() {
for (i, f) in frontier.iter().enumerate() { 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. // Pick a vertex to advance.
@ -457,7 +479,8 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
// the furthest we can go while remaining within 'err', i.e. when we // 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* // make our connections we look at how far points on the *edges*
// diverge from the trajectory of the continuous transformation). // 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; let vf = v.frame_vert;
for iter in 0..0 /*100*/ { // DEBUG: Re-enable for iter in 0..0 /*100*/ { // DEBUG: Re-enable
// Consider an edge from f(v.t)*vf to f(v.t + dt)*vf. // Consider an edge from f(v.t)*vf to f(v.t + dt)*vf.
@ -502,50 +525,54 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
println!("l1={} l2={} l3={}", l1, l2, l3); println!("l1={} l2={} l3={}", l1, l2, l3);
*/ */
// 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.
let (f1, edges1) = match v.halfedges[0] {
// 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 // 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 + n - 1) % n];
println!("DEBUG: add_face()"); println!("DEBUG: add_face()");
let (f1, edges1) = mesh.add_face([ let (f1, edges) = mesh.add_face([
VertSpec::New(v_next), VertSpec::New(v_next), // edges[0]: v_next -> v
match v.vert_idx { match v.vert_idx {
None => VertSpec::New(v.vert), None => VertSpec::New(v.vert),
Some(idx) => VertSpec::Idx(idx), Some(idx) => VertSpec::Idx(idx),
}, }, // edges[1]: v -> neighbor
match neighbor.vert_idx { match neighbor.vert_idx {
None => VertSpec::New(neighbor.vert), None => VertSpec::New(neighbor.vert),
Some(idx) => VertSpec::Idx(idx), Some(idx) => VertSpec::Idx(idx),
}, }, // edges[2]: neighbor -> v_next
]); ]);
if neighbor.vert_idx.is_none() { if neighbor.vert_idx.is_none() {
// 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[edges1[2]].vert); frontier[(i + n - 1) % n].vert_idx = Some(mesh.halfedges[edges[2]].vert);
// edges[2] is because this is the position of
// neighbor.vert_idx in add_face.
} }
(f1, edges1) (f1, edges[2], edges[0])
}, },
Some(edge_idx) => { Some(edge_idx) => {
println!("DEBUG: add_face_twin1({},{})", edge_idx, v_next); 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 // DEBUG
mesh.check(); mesh.check();
mesh.print(); mesh.print();
// edge2 should be: the half-edge connecting the 'neighbor' frontier // edge2 should be: the half-edge connecting the 'next' frontier
// vertex to v_next // vertex to 'v_next'
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,
@ -553,7 +580,7 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
// is edges1[0]. // is edges1[0].
None => { None => {
let neighbor = &frontier[(i + 1) % n]; 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() { if neighbor.vert_idx.is_none() {
// Reasoning here is identical to "If neighbor.vert_idx // Reasoning here is identical to "If neighbor.vert_idx
@ -564,8 +591,7 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
(f2, edges[1]) (f2, edges[1])
}, },
Some(edge_idx) => { Some(edge_idx) => {
let (f2, edges) = mesh.add_face_twin2(edge_idx, edges1[2]); let (f2, edges) = mesh.add_face_twin2(edge_v_next, edge1);
// TODO: Why edges1[2]?
(f2, edges[2]) (f2, edges[2])
}, },
}; };
@ -591,11 +617,8 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
vert: v_next, vert: v_next,
frame_vert: vf, frame_vert: vf,
t: t, t: t,
halfedges: [Some(edges1[2]), Some(edge2)], halfedges: [Some(edge1), Some(edge2)],
// Note that edges1[2] *starts* at the new vertex, and vert_idx: Some(mesh.halfedges[edge_v_next].vert),
// edge2 *ends* at it.
// DEBUG: The above comment is wrong, but why?
vert_idx: Some(mesh.halfedges[edges1[2]].vert),
}; };
/* /*
@ -713,5 +736,5 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
*/ */
} }
return Mesh { faces: vec![], verts: vec![] }; return dcel::convert_mesh(&mesh);
} }