Add some notes; restore more complex parametric example
This commit is contained in:
parent
41ea254537
commit
729baf5aa3
@ -6,13 +6,14 @@
|
|||||||
it's widely used. Possibly rename too.
|
it's widely used. Possibly rename too.
|
||||||
- `dcel.rs` needs a helper method for subdivision.
|
- `dcel.rs` needs a helper method for subdivision.
|
||||||
- Redo `examples::parametric_mesh` along the following lines:
|
- 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,
|
- Use my method from around 2020-05-21, and my pile of loose notes,
|
||||||
to subdivide - with the help of DCEL.
|
to subdivide - with the help of DCEL.
|
||||||
- Document `parametric_mesh` better. It is pretty hairy and could
|
- Document `parametric_mesh` better. It is pretty hairy and could
|
||||||
also benefit from some modularity.
|
also benefit from some modularity.
|
||||||
- parametric_mesh: My err/max_err code seems to sometimes give very high
|
- 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
|
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
|
- Get identical or near-identical meshes to `ramhorn_branch` from
|
||||||
Python. (Should just be a matter of tweaking parameters.)
|
Python. (Should just be a matter of tweaking parameters.)
|
||||||
- Look at performance.
|
- Look at performance.
|
||||||
@ -65,6 +66,8 @@
|
|||||||
|
|
||||||
## Research Areas
|
## 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)
|
- [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://en.wikipedia.org/wiki/Surface_triangulation
|
||||||
- https://www.cs.cmu.edu/~quake/triangle.html
|
- https://www.cs.cmu.edu/~quake/triangle.html
|
||||||
|
|||||||
@ -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),
|
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, 2);
|
||||||
//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 = 50.0;
|
let t1 = 15.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).
|
||||||
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) {
|
pub fn test_dcel(fname: &str) {
|
||||||
|
|||||||
38
src/rule.rs
38
src/rule.rs
@ -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.
|
// reaches t=t1 - in a way that forms the mesh we want.
|
||||||
|
|
||||||
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={},{},{} vert_idx={:?} t={} halfedges={:?}", i, f.vert.x, f.vert.y, f.vert.z, f.vert_idx, 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 {
|
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 => {},
|
None => {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Pick a vertex to advance.
|
// 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_prev = (i + n - 1) % n;
|
||||||
let i_next = (i + 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
|
||||||
// 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 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..100 {
|
||||||
// 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.
|
||||||
// These two endpoints have zero error from the trajectory
|
// These two endpoints have zero error from the trajectory
|
||||||
// (because they are directly on it).
|
// (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
|
// Add two faces to our mesh. They share two vertices, and thus
|
||||||
// the boundary in between those vertices.
|
// 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'.
|
// First face: connect prior frontier vertex to 'v' & 'v_next'.
|
||||||
// f1 is that face,
|
// 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:
|
// adding to an existing boundary or not:
|
||||||
None => {
|
None => {
|
||||||
let neighbor = &frontier[i_prev];
|
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
|
||||||
match v.vert_idx {
|
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) => {
|
Some(edge_idx) => {
|
||||||
// edge_idx is half-edge from prior frontier vertex to 'v'
|
// 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);
|
let (f1, edges) = mesh.add_face_twin1(edge_idx, v_next);
|
||||||
// edges[0] is twin of edge_idx, thus v -> neighbor
|
// edges[0] is twin of edge_idx, thus v -> neighbor
|
||||||
// edges[1] is neighbor -> v_next
|
// 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])
|
(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
|
// DEBUG
|
||||||
mesh.check();
|
//mesh.check();
|
||||||
mesh.print();
|
//mesh.print();
|
||||||
|
|
||||||
println!("DEBUG: Adding 2nd face");
|
//println!("DEBUG: Adding 2nd face");
|
||||||
// Second face: connect next frontier vertex to 'v' & 'v_next'.
|
// Second face: connect next frontier vertex to 'v' & 'v_next'.
|
||||||
// f2 is that face.
|
// f2 is that face.
|
||||||
// edge2 is: v_next -> next frontier vertex
|
// 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])
|
(f2, edges[1])
|
||||||
},
|
},
|
||||||
Some(edge_idx) => {
|
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);
|
let (f2, edges) = mesh.add_face_twin2(edge_idx, edge_v_next);
|
||||||
// edges[0] is twin of edge_idx, thus: neighbor -> v
|
// edges[0] is twin of edge_idx, thus: neighbor -> v
|
||||||
// edges[1] is twin of edge_v_next, thus: v -> v_next
|
// edges[1] is twin of edge_v_next, thus: v -> v_next
|
||||||
// edges[2] is: v_next -> neighbor
|
// edges[2] is: v_next -> neighbor
|
||||||
println!("DEBUG: add_face_twin2 returned {:?}", edges);
|
//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: Added 2nd face");
|
//println!("DEBUG: Added 2nd face");
|
||||||
mesh.check();
|
//mesh.check();
|
||||||
mesh.print();
|
//mesh.print();
|
||||||
|
|
||||||
// The 'shared' half-edge should start at v.vert - hence edges[1].
|
// 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)],
|
halfedges: [Some(edge1), Some(edge2)],
|
||||||
vert_idx: Some(mesh.halfedges[edge_v_next].vert),
|
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_prev].halfedges[1] = Some(edge1);
|
||||||
frontier[i_next].halfedges[0] = Some(edge2);
|
frontier[i_next].halfedges[0] = Some(edge2);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user