Meh, kind of over trying to roll my own subdivision crap
This commit is contained in:
parent
701b1df915
commit
545b7c9a60
15
README.md
15
README.md
@ -2,17 +2,10 @@
|
|||||||
|
|
||||||
## Highest priority:
|
## Highest priority:
|
||||||
|
|
||||||
- Add better docs and possibly abstraction to `dcel.rs`, *before*
|
- Just scrap `parametric_mesh` as much as possible and use existing
|
||||||
it's widely used. Possibly rename too.
|
tools (e.g. OpenSubdiv) because this DCEL method is just painful for
|
||||||
- `dcel.rs` needs a helper method for subdivision.
|
what it is and I have some questions on how it can even work
|
||||||
- Redo `examples::parametric_mesh` along the following lines:
|
theoretically.
|
||||||
- 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
|
|
||||||
- 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.
|
||||||
|
|||||||
68
src/dcel.rs
68
src/dcel.rs
@ -134,10 +134,9 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i,h) in self.halfedges.iter().enumerate() {
|
for (i,h) in self.halfedges.iter().enumerate() {
|
||||||
let twin = if h.has_twin {
|
let twin = if h.has_twin { format!(", twin half-edge {}", h.twin_halfedge)
|
||||||
format!(", twin half-edge {}", h.twin_halfedge)
|
|
||||||
} else {
|
} else {
|
||||||
String::from("")
|
format!(", no twin")
|
||||||
};
|
};
|
||||||
let v1 = self.verts[h.vert].v;
|
let v1 = self.verts[h.vert].v;
|
||||||
let v2 = self.verts[self.halfedges[h.next_halfedge].vert].v;
|
let v2 = self.verts[self.halfedges[h.next_halfedge].vert].v;
|
||||||
@ -485,22 +484,43 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
(f_n, [e_n, e_n+1, e_n+2])
|
(f_n, [e_n, e_n+1, e_n+2])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split_face(&mut self, face: usize, verts: Vec<V>) {
|
/// Splits a face (assumed to be a triangle) in this mesh by splitting
|
||||||
|
/// its half-edges, in order, at the vertices given, and then creating
|
||||||
|
/// half-edges between each pair of them.
|
||||||
|
///
|
||||||
|
/// This returns; (new face indices, updated face indices). That is,
|
||||||
|
/// the first vector is new face indices that were created, and the
|
||||||
|
/// second is existing face indices that were reused (but the faces
|
||||||
|
/// were updated).
|
||||||
|
///
|
||||||
|
/// This splits the given face into 4 smaller faces, and it splits the
|
||||||
|
/// three *bordering* faces each into 2 faces. That is, this
|
||||||
|
/// increases the number of faces by 6 and the number of vertices
|
||||||
|
/// by 3.
|
||||||
|
///
|
||||||
|
/// Right now, this requires that every halfedge of `face` has a twin.
|
||||||
|
/// If this is not the case, this returns `None` and does not subdivide.
|
||||||
|
/// This behavior will likely be changed in the future.
|
||||||
|
///
|
||||||
|
/// Disclaimer: This code is completely awful; just don't use it.
|
||||||
|
pub fn full_subdiv_face(&mut self, face: usize, verts: Vec<V>) -> Option<(Vec<usize>, Vec<usize>)> {
|
||||||
// 'verts' maps 1:1 to vertices for 'face' (i.e. face_to_verts).
|
// 'verts' maps 1:1 to vertices for 'face' (i.e. face_to_verts).
|
||||||
|
|
||||||
let mut edge_idx = self.faces[face].halfedge;
|
let mut edge_idx = self.faces[face].halfedge;
|
||||||
let n = verts.len();
|
let n = verts.len();
|
||||||
|
|
||||||
//
|
let mut faces_new = vec![];
|
||||||
let new_edges: Vec<(usize, usize)> = verts.iter().map(|v| {
|
let mut faces_upd = vec![];
|
||||||
|
|
||||||
println!("DEBUG: halfedge 3: {:?}", self.halfedges[3]);
|
let mut fail = false;
|
||||||
println!("DEBUG: halfedge {}: {:?}", self.halfedges[3].next_halfedge, self.halfedges[self.halfedges[3].next_halfedge]);
|
let new_edges: Vec<(usize, usize)> = verts.iter().map(|v| {
|
||||||
|
|
||||||
// As we iterate over every vertex, we walk the half-edges:
|
// As we iterate over every vertex, we walk the half-edges:
|
||||||
let mut edge = self.halfedges[edge_idx].clone();
|
let mut edge = self.halfedges[edge_idx].clone();
|
||||||
if !edge.has_twin {
|
if !edge.has_twin {
|
||||||
panic!("Halfedge {} has no twin, and split_face (for now) requires twins", edge_idx);
|
println!("Halfedge {} has no twin, and split_face (for now) requires twins", edge_idx);
|
||||||
|
fail = true;
|
||||||
|
return (0,0);
|
||||||
}
|
}
|
||||||
// TODO: Remove the above limitation and just don't try to split
|
// TODO: Remove the above limitation and just don't try to split
|
||||||
// nonexistent twins. I think all logic works the same way.
|
// nonexistent twins. I think all logic works the same way.
|
||||||
@ -516,10 +536,8 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
// Half of edge_idx is split into j_edge.
|
// Half of edge_idx is split into j_edge.
|
||||||
// Half of twin_idx (its twin) is split into i_edge.
|
// Half of twin_idx (its twin) is split into i_edge.
|
||||||
|
|
||||||
println!("DEBUG: edge_idx={} next_idx={} twin_idx={} i_edge={} j_edge={}", edge_idx, next_idx, twin_idx, i_edge, j_edge);
|
|
||||||
// This is where the vertex will be inserted:
|
// This is where the vertex will be inserted:
|
||||||
let v_idx = self.num_verts;
|
let v_idx = self.num_verts;
|
||||||
println!("DEBUG: adding v_idx={}", v_idx);
|
|
||||||
self.verts.push(DCELVertex {
|
self.verts.push(DCELVertex {
|
||||||
v: *v,
|
v: *v,
|
||||||
halfedge: i_edge, // j_edge is also fine
|
halfedge: i_edge, // j_edge is also fine
|
||||||
@ -531,7 +549,6 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
|
|
||||||
twin.twin_halfedge = j_edge;
|
twin.twin_halfedge = j_edge;
|
||||||
let i_next = twin.next_halfedge;
|
let i_next = twin.next_halfedge;
|
||||||
println!("DEBUG: new twin of {} = {}; new twin of {} = {}", edge_idx, i_edge, twin_idx, j_edge);
|
|
||||||
|
|
||||||
self.halfedges.push(DCELHalfEdge {
|
self.halfedges.push(DCELHalfEdge {
|
||||||
vert: v_idx,
|
vert: v_idx,
|
||||||
@ -541,8 +558,6 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
next_halfedge: i_next,
|
next_halfedge: i_next,
|
||||||
prev_halfedge: twin_idx,
|
prev_halfedge: twin_idx,
|
||||||
}); // i_edge
|
}); // i_edge
|
||||||
println!("DEBUG: edge {}: vert {} twin {} next {} prev {} (ends at vertex {})", i_edge, v_idx, edge_idx, i_next, twin_idx, self.halfedges[self.halfedges[twin_idx].next_halfedge].vert);
|
|
||||||
|
|
||||||
self.halfedges.push(DCELHalfEdge {
|
self.halfedges.push(DCELHalfEdge {
|
||||||
vert: v_idx,
|
vert: v_idx,
|
||||||
face: 0, // This is set properly in the next loop
|
face: 0, // This is set properly in the next loop
|
||||||
@ -551,7 +566,6 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
next_halfedge: j_next,
|
next_halfedge: j_next,
|
||||||
prev_halfedge: edge_idx,
|
prev_halfedge: edge_idx,
|
||||||
}); // j_edge
|
}); // j_edge
|
||||||
println!("DEBUG: edge {}: vert {} twin {} next {} prev {} (ends at vertex {})", j_edge, v_idx, twin_idx, j_next, edge_idx, self.halfedges[self.halfedges[edge_idx].next_halfedge].vert);
|
|
||||||
|
|
||||||
self.num_halfedges += 2;
|
self.num_halfedges += 2;
|
||||||
|
|
||||||
@ -565,7 +579,9 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
r
|
r
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
println!("DEBUG: {:?}", new_edges);
|
if fail {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
// We then must connect some edges up 'across' vertices
|
// We then must connect some edges up 'across' vertices
|
||||||
// in order to form the smaller face at each vertex.
|
// in order to form the smaller face at each vertex.
|
||||||
@ -585,9 +601,6 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
// And the face here:
|
// And the face here:
|
||||||
let face_new = self.num_faces;
|
let face_new = self.num_faces;
|
||||||
|
|
||||||
println!("DEBUG: i0={} i1={} ep_idx={} en_idx={} e_cross_idx={} e_twin_idx={} face_new={}",
|
|
||||||
i0, i1, ep_idx, en_idx, e_cross_idx, e_twin_idx, face_new);
|
|
||||||
|
|
||||||
// So, the vertex for i0 had two halfedges (one pointing in,
|
// So, the vertex for i0 had two halfedges (one pointing in,
|
||||||
// one pointing out). We split both those half-edges earlier.
|
// one pointing out). We split both those half-edges earlier.
|
||||||
// en_idx & ep_idx are the halves that are nearest the
|
// en_idx & ep_idx are the halves that are nearest the
|
||||||
@ -604,7 +617,6 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
next_halfedge: ep_idx,
|
next_halfedge: ep_idx,
|
||||||
prev_halfedge: en_idx,
|
prev_halfedge: en_idx,
|
||||||
}); // e_cross_idx
|
}); // e_cross_idx
|
||||||
println!("DEBUG: edge {}: vert {} twin {} next {} prev {} (ends at vertex {})", e_cross_idx, self.halfedges[en_idx].vert, e_twin_idx, ep_idx, en_idx, self.halfedges[self.halfedges[e_cross_idx].next_halfedge].vert);
|
|
||||||
|
|
||||||
// It also requires a twin half-edge. These all form a single
|
// It also requires a twin half-edge. These all form a single
|
||||||
// central face with each edge sharing a boundary with the
|
// central face with each edge sharing a boundary with the
|
||||||
@ -617,24 +629,21 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
next_halfedge: 0, // TODO
|
next_halfedge: 0, // TODO
|
||||||
prev_halfedge: 0, // TODO
|
prev_halfedge: 0, // TODO
|
||||||
}); // e_twin_idx
|
}); // e_twin_idx
|
||||||
println!("DEBUG: edge {}: vert {} twin {} next/prev incorrect", e_twin_idx, self.halfedges[ep_idx].vert, e_cross_idx);
|
|
||||||
|
|
||||||
self.num_halfedges += 2;
|
self.num_halfedges += 2;
|
||||||
|
|
||||||
// en/ep also need directed to 'new' edges and each other
|
// en/ep also need directed to 'new' edges and each other
|
||||||
self.halfedges[en_idx].prev_halfedge = ep_idx;
|
self.halfedges[en_idx].prev_halfedge = ep_idx;
|
||||||
self.halfedges[en_idx].next_halfedge = e_cross_idx;
|
self.halfedges[en_idx].next_halfedge = e_cross_idx;
|
||||||
println!("DEBUG: edge {}: now next {} prev {} ends at vert {}", en_idx, e_cross_idx, ep_idx, self.halfedges[self.halfedges[en_idx].next_halfedge].vert);
|
|
||||||
|
|
||||||
self.halfedges[ep_idx].next_halfedge = en_idx;
|
self.halfedges[ep_idx].next_halfedge = en_idx;
|
||||||
self.halfedges[ep_idx].prev_halfedge = e_cross_idx;
|
self.halfedges[ep_idx].prev_halfedge = e_cross_idx;
|
||||||
println!("DEBUG: edge {}: now next {} prev {} ends at vert {}", ep_idx, en_idx, e_cross_idx, self.halfedges[self.halfedges[ep_idx].next_halfedge].vert);
|
|
||||||
|
|
||||||
self.halfedges[ep_idx].face = face_new;
|
self.halfedges[ep_idx].face = face_new;
|
||||||
|
|
||||||
self.faces.push(DCELFace {
|
self.faces.push(DCELFace {
|
||||||
halfedge: e_cross_idx, // en_idx or ep_idx is fine too
|
halfedge: e_cross_idx, // en_idx or ep_idx is fine too
|
||||||
});
|
}); // face_new
|
||||||
|
faces_new.push(face_new);
|
||||||
self.num_faces += 1;
|
self.num_faces += 1;
|
||||||
|
|
||||||
// We also need to split the opposite side to make the two
|
// We also need to split the opposite side to make the two
|
||||||
@ -674,8 +683,10 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
self.faces.push(DCELFace {
|
self.faces.push(DCELFace {
|
||||||
halfedge: outer2, // base2 or edge_side2 is fine too
|
halfedge: outer2, // base2 or edge_side2 is fine too
|
||||||
});
|
});
|
||||||
|
faces_new.push(self.num_faces);
|
||||||
self.num_faces += 1;
|
self.num_faces += 1;
|
||||||
self.faces[face1].halfedge = outer1; // base1 or edge_side1 is fine too
|
self.faces[face1].halfedge = outer1; // base1 or edge_side1 is fine too
|
||||||
|
faces_upd.push(face1);
|
||||||
|
|
||||||
self.halfedges[outer1].next_halfedge = edge_side1;
|
self.halfedges[outer1].next_halfedge = edge_side1;
|
||||||
self.halfedges[outer1].prev_halfedge = base1;
|
self.halfedges[outer1].prev_halfedge = base1;
|
||||||
@ -691,13 +702,9 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
self.halfedges[base2].prev_halfedge = outer2;
|
self.halfedges[base2].prev_halfedge = outer2;
|
||||||
self.halfedges[base2].next_halfedge = edge_side2;
|
self.halfedges[base2].next_halfedge = edge_side2;
|
||||||
|
|
||||||
println!("DEBUG: base1={} base2={} outer1={} outer2={} face1={} face2={} edge_side1={} edge_side2={}",
|
|
||||||
base1, base2, outer1, outer2, face1, face2, edge_side1, edge_side2);
|
|
||||||
e_twin_idx
|
e_twin_idx
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
println!("DEBUG: cross_edges={:?}", twin_edges);
|
|
||||||
|
|
||||||
for i0 in 0..n {
|
for i0 in 0..n {
|
||||||
let i1 = (i0 + 1) % n;
|
let i1 = (i0 + 1) % n;
|
||||||
|
|
||||||
@ -709,6 +716,9 @@ impl<V: Copy + std::fmt::Debug> DCELMesh<V> {
|
|||||||
// We need something at this index, and the other three already have
|
// We need something at this index, and the other three already have
|
||||||
// indices, so reuse it for the smaller central face:
|
// indices, so reuse it for the smaller central face:
|
||||||
self.faces[face].halfedge = e_twin_idx;
|
self.faces[face].halfedge = e_twin_idx;
|
||||||
|
faces_upd.push(face);
|
||||||
|
|
||||||
|
return Some((faces_new, faces_upd));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_mesh<F>(&self, f: F) -> Mesh
|
pub fn convert_mesh<F>(&self, f: F) -> Mesh
|
||||||
|
|||||||
@ -1268,11 +1268,11 @@ 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),
|
||||||
];
|
];
|
||||||
let base_verts = util::subdivide_cycle(&base_verts, 4);
|
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 = 15.0;
|
let t1 = 15;
|
||||||
let xform = |t: f32| -> Transform {
|
let xform = |t: f32| -> Transform {
|
||||||
id().
|
id().
|
||||||
translate(0.0, 0.0, t/5.0).
|
translate(0.0, 0.0, t/5.0).
|
||||||
@ -1280,7 +1280,7 @@ pub fn test_parametric() -> Mesh {
|
|||||||
scale((0.8).powf(t))
|
scale((0.8).powf(t))
|
||||||
};
|
};
|
||||||
|
|
||||||
crate::rule::parametric_mesh(base_verts, xform, t0, t1, 0.001)
|
crate::rule::parametric_mesh(base_verts, xform, t0, t1, 0.01)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_dcel(fname: &str) {
|
pub fn test_dcel(fname: &str) {
|
||||||
@ -1325,18 +1325,19 @@ pub fn test_dcel(fname: &str) {
|
|||||||
println!("f3 verts: {:?}", mesh.face_to_verts(f3));
|
println!("f3 verts: {:?}", mesh.face_to_verts(f3));
|
||||||
println!("f4 verts: {:?}", mesh.face_to_verts(f4));
|
println!("f4 verts: {:?}", mesh.face_to_verts(f4));
|
||||||
|
|
||||||
println!("DCEL mesh: ");
|
//println!("DCEL mesh: ");
|
||||||
mesh.print();
|
//mesh.print();
|
||||||
|
|
||||||
mesh.split_face(f1, vec![
|
let faces = mesh.full_subdiv_face(f1, vec![
|
||||||
vertex(-0.5, 0.0, 0.0),
|
vertex(-0.5, 0.0, 0.0),
|
||||||
vertex(0.0, 0.5, 0.0),
|
vertex(0.0, 0.5, 0.0),
|
||||||
vertex(0.0, 0.0, 0.0),
|
vertex(0.0, 0.0, 0.0),
|
||||||
]);
|
]);
|
||||||
|
println!("full_subdiv_face returned: {:?}", faces);
|
||||||
|
|
||||||
println!("DCEL mesh after subdiv");
|
//println!("DCEL mesh after subdiv");
|
||||||
mesh.check();
|
//mesh.check();
|
||||||
mesh.print();
|
//mesh.print();
|
||||||
|
|
||||||
let mesh_conv = mesh.convert_mesh(|i| i);
|
let mesh_conv = mesh.convert_mesh(|i| i);
|
||||||
|
|
||||||
|
|||||||
81
src/rule.rs
81
src/rule.rs
@ -1,6 +1,7 @@
|
|||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::f32;
|
use std::f32;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::mesh::{Mesh, MeshFunc, VertexUnion};
|
use crate::mesh::{Mesh, MeshFunc, VertexUnion};
|
||||||
use crate::xform::{Transform, Vertex};
|
use crate::xform::{Transform, Vertex};
|
||||||
@ -658,11 +659,25 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
|
|||||||
|
|
||||||
// A stack of face indices for faces in 'mesh' that are still
|
// A stack of face indices for faces in 'mesh' that are still
|
||||||
// undergoing subdivision
|
// undergoing subdivision
|
||||||
let mut stack: Vec<usize> = (0..mesh.num_faces).collect();
|
|
||||||
|
|
||||||
while !stack.is_empty() {
|
let mut stack: HashMap<usize, usize> = (0..mesh.num_faces).map(|i| (i, 0)).collect();
|
||||||
let face = stack.pop().unwrap();
|
|
||||||
println!("DEBUG: Examining face: {:?}", face);
|
let max_subdiv = 1;
|
||||||
|
|
||||||
|
// This is masked off because it's just horrible:
|
||||||
|
while false && !stack.is_empty() {
|
||||||
|
|
||||||
|
let (face, count) = match stack.iter().next() {
|
||||||
|
None => break,
|
||||||
|
Some((f, c)) => (*f, *c),
|
||||||
|
};
|
||||||
|
stack.remove(&face);
|
||||||
|
|
||||||
|
println!("DEBUG: Examining face: {:?} ({} subdivs)", face, count);
|
||||||
|
|
||||||
|
if count >= max_subdiv {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let v_idx = mesh.face_to_verts(face);
|
let v_idx = mesh.face_to_verts(face);
|
||||||
if v_idx.len() != 3 {
|
if v_idx.len() != 3 {
|
||||||
@ -703,17 +718,18 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
|
|||||||
|
|
||||||
let d = p.xyz().dot(&normal);
|
let d = p.xyz().dot(&normal);
|
||||||
|
|
||||||
|
if d.is_nan() {
|
||||||
|
println!("DEBUG: p={:?} normal={:?}", p, normal);
|
||||||
|
println!("DEBUG: a={:?} b={:?}", a, b);
|
||||||
|
println!("DEBUG: v0={:?} v1={:?} v2={:?}", v0, v1, v2);
|
||||||
|
//panic!("Distance is NaN?");
|
||||||
|
println!("DEBUG: distance is NaN?");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
println!("DEBUG: t_mid={} v_mid={},{},{} p={},{},{}", t_mid, v_mid.x, v_mid.y, v_mid.z, p.x, p.y, p.z);
|
println!("DEBUG: t_mid={} v_mid={},{},{} p={},{},{}", t_mid, v_mid.x, v_mid.y, v_mid.z, p.x, p.y, p.z);
|
||||||
println!("DEBUG: d={}", d);
|
println!("DEBUG: d={}", d);
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
/*
|
|
||||||
let n = verts.len();
|
|
||||||
verts.push(p);
|
|
||||||
faces.push(face.verts[0]);
|
|
||||||
faces.push(face.verts[1]);
|
|
||||||
faces.push(n);
|
|
||||||
*/
|
|
||||||
if (d <= max_err) {
|
if (d <= max_err) {
|
||||||
// This triangle is already in the mesh, and already popped
|
// This triangle is already in the mesh, and already popped
|
||||||
// off of the stack. We're done.
|
// off of the stack. We're done.
|
||||||
@ -728,28 +744,35 @@ pub fn parametric_mesh<F>(frame: Vec<Vertex>, f: F, t0: f32, t1: f32, max_err: f
|
|||||||
|
|
||||||
// This split is done in 'parameter' space:
|
// This split is done in 'parameter' space:
|
||||||
let pairs = [(0,1), (1,2), (0,2)];
|
let pairs = [(0,1), (1,2), (0,2)];
|
||||||
let mut mids: Vec<Vertex> = pairs.iter().map(|(i,j)| {
|
let mut mids: Vec<VertexTrajectory> = pairs.iter().map(|(i,j)| {
|
||||||
let t = (tr[*i].t + tr[*j].t) / 2.0;
|
let t = (tr[*i].t + tr[*j].t) / 2.0;
|
||||||
let v = (tr[*i].frame_vert + tr[*j].frame_vert) / 2.0;
|
let v = (tr[*i].frame_vert + tr[*j].frame_vert) / 2.0;
|
||||||
f(t).mtx * v
|
VertexTrajectory {
|
||||||
|
vert: f(t).mtx * v,
|
||||||
|
frame_vert: v,
|
||||||
|
t: t,
|
||||||
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
// DEBUG
|
// TODO: Get indices of added faces and put these on the stack too
|
||||||
//let n = verts.len();
|
match mesh.full_subdiv_face(face, mids) {
|
||||||
// Index n+0 is (0,1), n+1 is (1,2), n+2 is (0,2)
|
None => {},
|
||||||
/*
|
Some((new, upd)) => {
|
||||||
verts.append(&mut mids);
|
|
||||||
faces[face.face] = n + 0;
|
// The 'updated' faces can remain on the stack if they
|
||||||
faces[face.face + 1] = n + 1;
|
// already were there. If they were taken off of the stack
|
||||||
faces[face.face + 2] = n + 2;
|
// because they were too small, they are now even smaller,
|
||||||
faces.extend_from_slice(&[
|
// so it is fine to leave them off.
|
||||||
face.verts[0], n + 0, n + 2,
|
stack.extend(new.iter().map(|i| (*i, count + 1)));
|
||||||
face.verts[1], n + 1, n + 0,
|
stack.extend(upd.iter().map(|i| (*i, count + 1)));
|
||||||
face.verts[2], n + 2, n + 1,
|
// TODO: Why does the resultant mesh have holes if I do this
|
||||||
//n + 0, n + 1, n + 2,
|
// and then increase max_subdiv?
|
||||||
]);
|
},
|
||||||
*/
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//mesh.print();
|
||||||
|
|
||||||
return mesh.convert_mesh(|i| i.vert );
|
return mesh.convert_mesh(|i| i.vert );
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user