Fix pesky-ass bug in DCEL (I think). Debug statements remain.
This commit is contained in:
parent
dbaadea466
commit
39072e0c30
13
README.md
13
README.md
@ -2,12 +2,17 @@
|
|||||||
|
|
||||||
## Highest priority:
|
## Highest priority:
|
||||||
|
|
||||||
- Work on my doubly-connected edge list so I can complete some other
|
- Add better docs and possibly abstraction to `dcel.rs`, *before*
|
||||||
things below!
|
it's widely used. Possibly rename too.
|
||||||
- Implement the continuous parametric transformations from 2020-05-07
|
- `dcel.rs` needs a helper method for subdivision.
|
||||||
in my notes. This will require some new abstractions.
|
- Redo `examples::parametric_mesh` along the following lines:
|
||||||
|
- 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
|
- 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
|
||||||
|
dt values, e.g. if I use just a translation as my transform
|
||||||
- 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.
|
||||||
|
|||||||
19
src/dcel.rs
19
src/dcel.rs
@ -139,7 +139,12 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
} else {
|
} else {
|
||||||
String::from("")
|
String::from("")
|
||||||
};
|
};
|
||||||
println!("Halfedge {}: vert {}, face {}, prev: {}, next: {}{}", i, h.vert, h.face, h.prev_halfedge, h.next_halfedge, twin)
|
let v1 = self.verts[h.vert].v;
|
||||||
|
let v2 = self.verts[self.halfedges[h.next_halfedge].vert].v;
|
||||||
|
println!("Halfedge {}: vert {} (to {}), face {}, prev: {}, next: {}{}, ({:?} to {:?})",
|
||||||
|
i, h.vert, self.halfedges[h.next_halfedge].vert, h.face,
|
||||||
|
h.prev_halfedge, h.next_halfedge, twin,
|
||||||
|
v1, v2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,6 +205,10 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
println!("Halfedge {} has twin {}, but reverse isn't true",
|
println!("Halfedge {} has twin {}, but reverse isn't true",
|
||||||
i, edge.twin_halfedge);
|
i, edge.twin_halfedge);
|
||||||
pass = false;
|
pass = false;
|
||||||
|
} else if edge.vert != self.halfedges[twin.next_halfedge].vert {
|
||||||
|
println!("Halfedge {} starts at vertex {} but twin {} ends at vertex {}",
|
||||||
|
i, edge.vert, edge.twin_halfedge, self.halfedges[twin.next_halfedge].vert);
|
||||||
|
pass = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let p = edge.prev_halfedge;
|
let p = edge.prev_halfedge;
|
||||||
@ -398,6 +407,7 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
/// 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`.
|
||||||
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:
|
||||||
@ -417,8 +427,11 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
twin2_idx, twin1_idx, self.halfedges[twin2.next_halfedge].vert, v1));
|
twin2_idx, twin1_idx, self.halfedges[twin2.next_halfedge].vert, v1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
self.halfedges.push(DCELHalfEdge {
|
||||||
vert: v1,
|
vert: v2,
|
||||||
face: f_n,
|
face: f_n,
|
||||||
has_twin: true,
|
has_twin: true,
|
||||||
twin_halfedge: twin1_idx,
|
twin_halfedge: twin1_idx,
|
||||||
@ -436,7 +449,7 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
prev_halfedge: e_n,
|
prev_halfedge: e_n,
|
||||||
}); // index e_n + 1
|
}); // index e_n + 1
|
||||||
self.halfedges.push(DCELHalfEdge {
|
self.halfedges.push(DCELHalfEdge {
|
||||||
vert: v2,
|
vert: v1,
|
||||||
face: f_n,
|
face: f_n,
|
||||||
has_twin: false,
|
has_twin: false,
|
||||||
twin_halfedge: 0,
|
twin_halfedge: 0,
|
||||||
|
|||||||
@ -12,6 +12,7 @@ use crate::xform::{Transform, Vertex, vertex, Mat4, id};
|
|||||||
use crate::rule::{Rule, RuleFn, RuleEval, Child};
|
use crate::rule::{Rule, RuleFn, RuleEval, Child};
|
||||||
use crate::prim;
|
use crate::prim;
|
||||||
use crate::dcel;
|
use crate::dcel;
|
||||||
|
use crate::dcel::{DCELMesh, VertSpec};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub fn cube_thing() -> Rule<()> {
|
pub fn cube_thing() -> Rule<()> {
|
||||||
@ -1262,10 +1263,10 @@ impl CurveHorn {
|
|||||||
pub fn test_parametric() -> Mesh {
|
pub fn test_parametric() -> Mesh {
|
||||||
|
|
||||||
let base_verts: Vec<Vertex> = vec![
|
let base_verts: Vec<Vertex> = vec![
|
||||||
vertex(-0.5, -0.5, 0.0),
|
vertex(-1.0, -1.0, 0.0),
|
||||||
vertex(-0.5, 0.5, 0.0),
|
vertex(-1.0, 1.0, 0.0),
|
||||||
vertex( 0.5, 0.5, 0.0),
|
vertex( 1.0, 1.0, 0.0),
|
||||||
vertex( 0.5, -0.5, 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);
|
||||||
@ -1273,9 +1274,9 @@ pub fn test_parametric() -> Mesh {
|
|||||||
let t0 = 0.0;
|
let t0 = 0.0;
|
||||||
let t1 = 16.0;
|
let t1 = 16.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.005)
|
||||||
@ -1283,24 +1284,25 @@ pub fn test_parametric() -> Mesh {
|
|||||||
|
|
||||||
pub fn test_dcel(fname: &str) {
|
pub fn test_dcel(fname: &str) {
|
||||||
let mut mesh: dcel::DCELMesh<Vertex> = dcel::DCELMesh::new();
|
let mut mesh: dcel::DCELMesh<Vertex> = dcel::DCELMesh::new();
|
||||||
let f1 = mesh.add_face([
|
let (f1, _) = mesh.add_face([
|
||||||
vertex(-0.5, -0.5, 0.0),
|
VertSpec::New(vertex(-0.5, -0.5, 0.0)),
|
||||||
vertex(-0.5, 0.5, 0.0),
|
VertSpec::New(vertex(-0.5, 0.5, 0.0)),
|
||||||
vertex( 0.5, 0.5, 0.0),
|
VertSpec::New(vertex( 0.5, 0.5, 0.0)),
|
||||||
]);
|
]);
|
||||||
mesh.check();
|
mesh.check();
|
||||||
let f2 = mesh.add_face_twin1(mesh.faces[f1].halfedge, vertex(0.0, 0.0, 1.0));
|
let (f2, edges) = mesh.add_face_twin1(mesh.faces[f1].halfedge, vertex(0.0, 0.0, 1.0));
|
||||||
mesh.check();
|
mesh.check();
|
||||||
|
|
||||||
// Find the shared edge:
|
// From add_face_twin1, edges[0] is always the 'shared' edge:
|
||||||
let mut shared: Option<(usize, usize)> = None;
|
let edge = edges[0];
|
||||||
for e in mesh.face_to_halfedges(f1) {
|
let twin = {
|
||||||
let he = &mesh.halfedges[e];
|
let he = &mesh.halfedges[edge];
|
||||||
if he.has_twin {
|
if he.has_twin {
|
||||||
shared = Some((e, he.twin_halfedge));
|
he.twin_halfedge
|
||||||
|
} else {
|
||||||
|
panic!("Can't find shared edge!");
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
let (edge, twin) = shared.unwrap();
|
|
||||||
println!("Shared edges = {},{}", edge, twin);
|
println!("Shared edges = {},{}", edge, twin);
|
||||||
|
|
||||||
let ep = mesh.halfedges[edge].prev_halfedge;
|
let ep = mesh.halfedges[edge].prev_halfedge;
|
||||||
@ -1312,9 +1314,9 @@ pub fn test_dcel(fname: &str) {
|
|||||||
println!("DCEL mesh = {}", mesh);
|
println!("DCEL mesh = {}", mesh);
|
||||||
// As we're making *twin* halfedges, we go against the edge
|
// As we're making *twin* halfedges, we go against the edge
|
||||||
// direction:
|
// direction:
|
||||||
let f3 = mesh.add_face_twin2(en, tp);
|
let (f3, _) = mesh.add_face_twin2(en, tp);
|
||||||
mesh.check();
|
mesh.check();
|
||||||
let f4 = mesh.add_face_twin2(tn, ep);
|
let (f4, _) = mesh.add_face_twin2(tn, ep);
|
||||||
mesh.check();
|
mesh.check();
|
||||||
|
|
||||||
println!("f1 verts: {:?}", mesh.face_to_verts(f1));
|
println!("f1 verts: {:?}", mesh.face_to_verts(f1));
|
||||||
|
|||||||
159
src/rule.rs
159
src/rule.rs
@ -1,10 +1,12 @@
|
|||||||
use crate::mesh::{Mesh, MeshFunc, VertexUnion};
|
|
||||||
use crate::xform::{Transform, Vertex};
|
|
||||||
//use crate::prim;
|
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::f32;
|
use std::f32;
|
||||||
|
|
||||||
|
use crate::mesh::{Mesh, MeshFunc, VertexUnion};
|
||||||
|
use crate::xform::{Transform, Vertex};
|
||||||
|
use crate::dcel;
|
||||||
|
use crate::dcel::{DCELMesh, VertSpec};
|
||||||
|
|
||||||
pub type RuleFn<S> = Rc<dyn Fn(Rc<Rule<S>>) -> RuleEval<S>>;
|
pub type RuleFn<S> = Rc<dyn Fn(Rc<Rule<S>>) -> RuleEval<S>>;
|
||||||
|
|
||||||
/// Definition of a rule. In general, a `Rule`:
|
/// Definition of a rule. In general, a `Rule`:
|
||||||
@ -364,19 +366,27 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
|
|||||||
panic!("frame must have at least 3 vertices");
|
panic!("frame must have at least 3 vertices");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut mesh: DCELMesh<Vertex> = DCELMesh::new();
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct frontierVert {
|
struct frontierVert {
|
||||||
vert: Vertex, // Vertex position
|
// Vertex position
|
||||||
t: f32, // Parameter value; f(t) should equal vert
|
vert: Vertex,
|
||||||
frame_vert: Vertex, // "Starting" vertex position, i.e. at f(t0).
|
// Parameter value; f(t) should equal vert
|
||||||
// Always either a frame vertex, or a linear combination of two
|
t: f32,
|
||||||
// neighboring ones.
|
// "Starting" vertex position, i.e. at f(t0). Always either a frame
|
||||||
mesh_idx: usize, // Index of this vertex in the mesh
|
// vertex, or a linear combination of two neighboring ones.
|
||||||
// (If it's in 'frontier', the vertex is in the mesh).
|
frame_vert: Vertex,
|
||||||
neighbor: [usize; 2], // Indices of 'frontier' of each neighbor
|
// If the boundaries on either side of this vertex lie on a face
|
||||||
side_faces: [(usize,bool); 2], // The two faces (given as an index
|
// (which is the case for all vertices *except* the initial ones),
|
||||||
// into 'faces' below) which contain the edge from this vertex to
|
// then this gives the halfedges of those boundaries. halfedges[0]
|
||||||
// its neighbors. If the bool is false, there is no face.
|
// connects the 'prior' vertex on the frontier to this, and
|
||||||
|
// halfedges[1] connect this to the 'next' vertex on the fronter.
|
||||||
|
// (Direction matters. If halfedges[0] is given, it must *end* at
|
||||||
|
// 'vert'. If halfedges[1] is given, it must *begin* at 'vert'.)
|
||||||
|
halfedges: [Option<usize>; 2],
|
||||||
|
// If this vertex is already in 'mesh', its vertex index there:
|
||||||
|
vert_idx: Option<usize>,
|
||||||
};
|
};
|
||||||
|
|
||||||
// A face that is still undergoing subdivision. This is used for a stack
|
// A face that is still undergoing subdivision. This is used for a stack
|
||||||
@ -409,9 +419,8 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
|
|||||||
vert: *v,
|
vert: *v,
|
||||||
t: t0,
|
t: t0,
|
||||||
frame_vert: *v,
|
frame_vert: *v,
|
||||||
mesh_idx: i,
|
halfedges: [None; 2],
|
||||||
neighbor: [(i - 1) % n, (i + 1) % n],
|
vert_idx: None,
|
||||||
side_faces: [(0, false); 2], // initial vertices have no faces
|
|
||||||
}).collect();
|
}).collect();
|
||||||
// Every vertex in 'frontier' has a trajectory it follows - which is
|
// Every vertex in 'frontier' has a trajectory it follows - which is
|
||||||
// simply the position as we transform the original vertex by f(t),
|
// simply the position as we transform the original vertex by f(t),
|
||||||
@ -421,18 +430,9 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
|
|||||||
// new triangles every time we advance one, until each vertex
|
// new triangles every time we advance one, until each vertex
|
||||||
// reaches t=t1 - in a way that forms the mesh we want.
|
// reaches t=t1 - in a way that forms the mesh we want.
|
||||||
|
|
||||||
// That mesh will be built up here, starting with frame vertices:
|
|
||||||
// (note initial value of mesh_idx)
|
|
||||||
let mut verts: Vec<Vertex> = frame.clone();
|
|
||||||
let mut faces: Vec<usize> = vec![];
|
|
||||||
|
|
||||||
// 'stack' is cleared at every iteration below, and contains faces that
|
|
||||||
// may still require subdivision.
|
|
||||||
let mut stack: Vec<tempFace> = vec![];
|
|
||||||
|
|
||||||
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={} mesh_idx={} neighbor={:?}", i, f.vert.x, f.vert.y, f.vert.z, f.t, f.mesh_idx, f.neighbor);
|
println!("DEBUG: frontier[{}]: vert={},{},{} t={} halfedges={:?}", i, f.vert.x, f.vert.y, f.vert.z, f.t, f.halfedges);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick a vertex to advance.
|
// Pick a vertex to advance.
|
||||||
@ -451,7 +451,7 @@ 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.
|
||||||
|
|
||||||
println!("DEBUG: Moving 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
|
||||||
@ -459,7 +459,7 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
|
|||||||
// 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 vf = v.frame_vert;
|
let vf = v.frame_vert;
|
||||||
for iter in 0..100 {
|
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.
|
||||||
// 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).
|
||||||
@ -502,30 +502,103 @@ 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 this vertex to our mesh:
|
// Add two faces to our mesh. (They share two vertices, and thus
|
||||||
let v_next_idx = verts.len();
|
// the boundary in between those vertices.)
|
||||||
verts.push(v_next);
|
let (f1, edges1) = 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),
|
||||||
|
match v.vert_idx {
|
||||||
|
None => VertSpec::New(v.vert),
|
||||||
|
Some(idx) => VertSpec::Idx(idx),
|
||||||
|
},
|
||||||
|
match neighbor.vert_idx {
|
||||||
|
None => VertSpec::New(neighbor.vert),
|
||||||
|
Some(idx) => VertSpec::Idx(idx),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
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.
|
||||||
|
}
|
||||||
|
|
||||||
|
(f1, edges1)
|
||||||
|
},
|
||||||
|
Some(edge_idx) => {
|
||||||
|
println!("DEBUG: add_face_twin1({},{})", edge_idx, v_next);
|
||||||
|
mesh.add_face_twin1(edge_idx, v_next)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
println!("DEBUG: edges1={:?}", edges1);
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
mesh.check();
|
||||||
|
mesh.print();
|
||||||
|
|
||||||
|
// edge2 should be: the half-edge connecting the 'neighbor' 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,
|
||||||
|
// they share the boundary between v_next and v.vert - which
|
||||||
|
// is edges1[0].
|
||||||
|
None => {
|
||||||
|
let neighbor = &frontier[(i + 1) % n];
|
||||||
|
let (f2, edges) = mesh.add_face_twin1(edges1[0], neighbor.vert);
|
||||||
|
|
||||||
|
if neighbor.vert_idx.is_none() {
|
||||||
|
// Reasoning here is identical to "If neighbor.vert_idx
|
||||||
|
// is None..." above:
|
||||||
|
frontier[(i + 1) % n].vert_idx = Some(mesh.halfedges[edges[2]].vert);
|
||||||
|
}
|
||||||
|
|
||||||
|
(f2, edges[1])
|
||||||
|
},
|
||||||
|
Some(edge_idx) => {
|
||||||
|
let (f2, edges) = mesh.add_face_twin2(edge_idx, edges1[2]);
|
||||||
|
// TODO: Why edges1[2]?
|
||||||
|
(f2, edges[2])
|
||||||
|
},
|
||||||
|
};
|
||||||
|
println!("DEBUG: edge2={}", edge2);
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
println!("DEBUG: 2nd face");
|
||||||
|
mesh.check();
|
||||||
|
mesh.print();
|
||||||
|
|
||||||
|
// The 'shared' half-edge should start at v.vert - hence edges[1].
|
||||||
|
|
||||||
// and add two faces:
|
// and add two faces:
|
||||||
let face_idx = faces.len();
|
/*
|
||||||
faces.append(&mut vec![
|
faces.append(&mut vec![
|
||||||
v_next_idx, v.mesh_idx, frontier[v.neighbor[0]].mesh_idx, // face_idx
|
v_next_idx, v.mesh_idx, frontier[v.neighbor[0]].mesh_idx, // face_idx
|
||||||
v.mesh_idx, v_next_idx, frontier[v.neighbor[1]].mesh_idx, // face_idx + 1
|
v.mesh_idx, v_next_idx, frontier[v.neighbor[1]].mesh_idx, // face_idx + 1
|
||||||
]);
|
]);
|
||||||
|
*/
|
||||||
|
|
||||||
// Replace this vertex in the frontier:
|
// Replace this vertex in the frontier:
|
||||||
frontier[i] = frontierVert {
|
frontier[i] = frontierVert {
|
||||||
vert: v_next,
|
vert: v_next,
|
||||||
frame_vert: vf,
|
frame_vert: vf,
|
||||||
mesh_idx: v_next_idx,
|
|
||||||
t: t,
|
t: t,
|
||||||
neighbor: v.neighbor,
|
halfedges: [Some(edges1[2]), Some(edge2)],
|
||||||
side_faces: [(face_idx, true), (face_idx + 1, true)],
|
// 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),
|
||||||
};
|
};
|
||||||
// Note above that we added two edges that include v_next_idx:
|
|
||||||
// (frontier[v.neighbor[0]].mesh_idx, v_next_idx)
|
|
||||||
// (frontier[v.neighbor[1]].mesh_idx, v_next_idx)
|
|
||||||
// hence, side_faces has the respective face for each.
|
|
||||||
|
|
||||||
|
/*
|
||||||
// Also add these faces to the stack of triangles to check for
|
// Also add these faces to the stack of triangles to check for
|
||||||
// subdivision. They may be replaced.
|
// subdivision. They may be replaced.
|
||||||
let f0 = &frontier[v.neighbor[0]];
|
let f0 = &frontier[v.neighbor[0]];
|
||||||
@ -548,7 +621,8 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
|
|||||||
// several vertices sit in the same trajectory (thus, same 'frame'
|
// several vertices sit in the same trajectory (thus, same 'frame'
|
||||||
// vertex).
|
// vertex).
|
||||||
|
|
||||||
while !stack.is_empty() {
|
// TODO: Move this logic elsewhere
|
||||||
|
while false && !stack.is_empty() {
|
||||||
let face = stack.pop().unwrap();
|
let face = stack.pop().unwrap();
|
||||||
println!("DEBUG: Examining face: {:?}", face);
|
println!("DEBUG: Examining face: {:?}", face);
|
||||||
let v0 = verts[face.verts[0]];
|
let v0 = verts[face.verts[0]];
|
||||||
@ -636,7 +710,8 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
|
|||||||
// If they refer to the same face I may be invalidating
|
// If they refer to the same face I may be invalidating
|
||||||
// something here!
|
// something here!
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
return Mesh { verts, faces };
|
return Mesh { faces: vec![], verts: vec![] };
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user