Add some notes; restore more complex parametric example

This commit is contained in:
Chris Hodapp 2020-06-06 16:50:25 -04:00
parent 41ea254537
commit 729baf5aa3
3 changed files with 32 additions and 24 deletions

View File

@ -6,13 +6,14 @@
it's widely used. Possibly rename too.
- `dcel.rs` needs a helper method for subdivision.
- Redo `examples::parametric_mesh` along the following lines:
- Make a crappy mesh (as a DCEL) like my 'early' method.
- DONE: Make a crappy mesh (as a DCEL) like my 'early' method.
- Use my method from around 2020-05-21, and my pile of loose notes,
to subdivide - with the help of DCEL.
- Document `parametric_mesh` better. It is pretty hairy and could
also benefit from some modularity.
- parametric_mesh: My err/max_err code seems to sometimes give very high
dt values, e.g. if I use just a translation as my transform
- parametric_mesh: Fix ending behavior.
- Get identical or near-identical meshes to `ramhorn_branch` from
Python. (Should just be a matter of tweaking parameters.)
- Look at performance.
@ -65,6 +66,8 @@
## Research Areas
- Can I use automatic differentiation in any way here to avoid the
numerical annoyances?
- [Geometry and Algorithms for Computer Aided Design (Hartmann)](https://www2.mathematik.tu-darmstadt.de/~ehartmann/cdgen0104.pdf)
- https://en.wikipedia.org/wiki/Surface_triangulation
- https://www.cs.cmu.edu/~quake/triangle.html

View File

@ -1266,20 +1266,21 @@ pub fn test_parametric() -> Mesh {
vertex(-1.0, -1.0, 0.0),
vertex(-1.0, 1.0, 0.0),
vertex( 1.0, 1.0, 0.0),
//vertex( 1.0, -1.0, 0.0),
vertex( 1.0, -1.0, 0.0),
];
//let base_verts = util::subdivide_cycle(&base_verts, 2);
//let base_verts = util::subdivide_cycle(&base_verts, 16);
let base_verts = util::subdivide_cycle(&base_verts, 16);
let t0 = 0.0;
let t1 = 50.0;
let t1 = 15.0;
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).
scale((0.8).powf(t))*/
scale((0.8).powf(t))
};
crate::rule::parametric_mesh(base_verts, xform, t0, t1, 0.005)
crate::rule::parametric_mesh(base_verts, xform, t0, t1, 0.001)
}
pub fn test_dcel(fname: &str) {

View File

@ -431,6 +431,7 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
// reaches t=t1 - in a way that forms the mesh we want.
while !frontier.is_empty() {
/*
for (i, f) in frontier.iter().enumerate() {
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 {
@ -456,6 +457,7 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
None => {},
};
}
*/
// Pick a vertex to advance.
//
@ -477,16 +479,16 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
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
// 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) / 10.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
for iter in 0..100 {
// Consider an edge from f(v.t)*vf to f(v.t + dt)*vf.
// These two endpoints have zero error from the trajectory
// (because they are directly on it).
@ -532,7 +534,7 @@ 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
// the boundary in between those vertices.
println!("DEBUG: Adding 1st face");
//println!("DEBUG: Adding 1st face");
// First face: connect prior frontier vertex to 'v' & 'v_next'.
// f1 is that face,
@ -543,7 +545,7 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
// adding to an existing boundary or not:
None => {
let neighbor = &frontier[i_prev];
println!("DEBUG: add_face()");
//println!("DEBUG: add_face()");
let (f1, edges) = mesh.add_face([
VertSpec::New(v_next), // edges[0]: v_next -> v
match v.vert_idx {
@ -567,7 +569,7 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
},
Some(edge_idx) => {
// 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);
//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);
// edges[0] is twin of edge_idx, thus v -> neighbor
// edges[1] is neighbor -> v_next
@ -575,13 +577,13 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
(f1, edges[1], edges[2])
},
};
println!("DEBUG: edge1={} edge_v_next={}", edge1, edge_v_next);
//println!("DEBUG: edge1={} edge_v_next={}", edge1, edge_v_next);
// DEBUG
mesh.check();
mesh.print();
//mesh.check();
//mesh.print();
println!("DEBUG: Adding 2nd face");
//println!("DEBUG: Adding 2nd face");
// Second face: connect next frontier vertex to 'v' & 'v_next'.
// f2 is that face.
// edge2 is: v_next -> next frontier vertex
@ -617,21 +619,21 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
(f2, edges[1])
},
Some(edge_idx) => {
println!("DEBUG: add_face_twin2({}, {})", edge_idx, edge_v_next);
//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);
//println!("DEBUG: add_face_twin2 returned {:?}", edges);
(f2, edges[2])
},
};
println!("DEBUG: edge2={}", edge2);
//println!("DEBUG: edge2={}", edge2);
// DEBUG
println!("DEBUG: Added 2nd face");
mesh.check();
mesh.print();
//println!("DEBUG: Added 2nd face");
//mesh.check();
//mesh.print();
// The 'shared' half-edge should start at v.vert - hence edges[1].
@ -651,6 +653,8 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
halfedges: [Some(edge1), Some(edge2)],
vert_idx: Some(mesh.halfedges[edge_v_next].vert),
};
// Since 'halfedges' forms more or less a doubly-linked list, we
// must go to previous & next vertices and update them:
frontier[i_prev].halfedges[1] = Some(edge1);
frontier[i_next].halfedges[0] = Some(edge2);