Prepare 0.2.0 usability release and refresh desktop demo
This commit is contained in:
1 parent
a094fa46b5
commit
ab05b24dee
54 files changed
+4888
-234
No files matched your search
+21
-2
@@ -64,6 +64,13 @@ pub struct Mesh {
|
||||
/// Per edge: a seam between two pieces of the same smooth surface (not drawn).
|
||||
#[serde(default)]
|
||||
pub seams: Vec<bool>,
|
||||
/// Display-only tangent joins. Edge identities, picking and face groups stay intact.
|
||||
#[serde(skip)]
|
||||
pub smooth_edges: Vec<bool>,
|
||||
/// Display-protected boundaries: certified current creases or authored splits.
|
||||
/// Overrides coarse seam fits; not a geometric/topological authority.
|
||||
#[serde(skip)]
|
||||
pub sharp_edges: Vec<bool>,
|
||||
/// Per edge: the B-rep faces it bounds (one or two).
|
||||
#[serde(default)]
|
||||
pub edge_faces: Vec<Vec<u32>>,
|
||||
@@ -78,6 +85,15 @@ pub struct MeshMeasure {
|
||||
}
|
||||
|
||||
impl Mesh {
|
||||
/// Visibility in shaded edge presentation, independent of selection/topology.
|
||||
pub fn shaded_edge_visible(&self, index: usize) -> bool {
|
||||
self.edge_pickable(index) && !self.smooth_edges.get(index).copied().unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn edge_pickable(&self, index: usize) -> bool {
|
||||
!self.seams.get(index).copied().unwrap_or(false) || self.sharp_edges.get(index).copied().unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Edges bounding face `f`.
|
||||
pub fn face_edges(&self, f: u32) -> Vec<usize> {
|
||||
self.edge_faces.iter().enumerate().filter(|(_, fs)| fs.contains(&f)).map(|(i, _)| i).collect()
|
||||
@@ -88,7 +104,10 @@ impl Mesh {
|
||||
let mut todo = vec![face];
|
||||
while let Some(f) = todo.pop() {
|
||||
for (ei, fs) in self.edge_faces.iter().enumerate() {
|
||||
if !self.seams.get(ei).copied().unwrap_or(false) || !fs.iter().any(|x| *x as usize == f) {
|
||||
if !self.seams.get(ei).copied().unwrap_or(false)
|
||||
|| self.sharp_edges.get(ei).copied().unwrap_or(false)
|
||||
|| !fs.iter().any(|x| *x as usize == f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for &next in fs {
|
||||
@@ -176,7 +195,7 @@ impl Mesh {
|
||||
while let Some(cur) = todo.pop() {
|
||||
let Some(ce) = ends(cur) else { continue };
|
||||
for (i, _) in self.edges.iter().enumerate() {
|
||||
if chain.contains(&i) || self.seams.get(i).copied().unwrap_or(false) {
|
||||
if chain.contains(&i) || !self.edge_pickable(i) {
|
||||
continue;
|
||||
}
|
||||
let Some(ne) = ends(i) else { continue };
|
||||
|
||||
@@ -6,7 +6,41 @@ fn cube_mesh(s: f64) -> Mesh {
|
||||
let triangles =
|
||||
vec![[0, 2, 1], [0, 3, 2], [4, 5, 6], [4, 6, 7], [0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5], [2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7]];
|
||||
let n = triangles.len();
|
||||
Mesh { normals: vec![Vec3::Z; 8], positions, triangles, tri_face: vec![0; n], edges: vec![], seams: vec![], edge_faces: vec![] }
|
||||
Mesh {
|
||||
normals: vec![Vec3::Z; 8],
|
||||
positions,
|
||||
triangles,
|
||||
tri_face: vec![0; n],
|
||||
edges: vec![],
|
||||
seams: vec![],
|
||||
smooth_edges: vec![],
|
||||
sharp_edges: vec![],
|
||||
edge_faces: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_edge_masks_keep_identity_and_break_only_certified_sharp_patches() {
|
||||
let mut mesh =
|
||||
Mesh { edges: vec![vec![Vec3::ZERO, Vec3::Z]; 2], edge_faces: vec![vec![0, 1], vec![1, 2]], seams: vec![true, true], ..Mesh::default() };
|
||||
let stored = serde_json::to_value(&mesh).unwrap();
|
||||
assert_eq!(mesh.surface_patch(0), vec![0, 1, 2]);
|
||||
mesh.smooth_edges = vec![true, false];
|
||||
assert_eq!(mesh.surface_patch(0), vec![0, 1, 2]);
|
||||
assert!(!mesh.shaded_edge_visible(0));
|
||||
mesh.smooth_edges[0] = false;
|
||||
mesh.sharp_edges = vec![true, false];
|
||||
assert!(mesh.shaded_edge_visible(0));
|
||||
assert!(mesh.edge_pickable(0));
|
||||
assert!(!mesh.edge_pickable(1));
|
||||
assert_eq!(mesh.surface_patch(0), vec![0]);
|
||||
assert_eq!(mesh.surface_patch(1), vec![1, 2]);
|
||||
assert_eq!(mesh.edges.len(), 2);
|
||||
assert_eq!(mesh.face_edges(1), vec![0, 1]);
|
||||
assert_eq!(serde_json::to_value(&mesh).unwrap(), stored);
|
||||
let reopened: Mesh = serde_json::from_value(stored).unwrap();
|
||||
assert!(reopened.smooth_edges.is_empty() && reopened.sharp_edges.is_empty());
|
||||
assert!(Mesh::default().shaded_edge_visible(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user