Skip to main content

polyscope_rs/
surface_mesh.rs

1//! Surface mesh registration and manipulation.
2//!
3//! Surface meshes are triangular or polygonal meshes. This module provides
4//! functions to register meshes and add quantities to them.
5//!
6//! polyscope-rs supports arbitrary n-gon faces (triangles, quads, pentagons, etc.).
7//! Polygonal faces are automatically fan-triangulated for rendering while
8//! preserving the original face structure for wireframe display.
9//!
10//! # Example
11//!
12//! ```no_run
13//! use polyscope_rs::*;
14//!
15//! fn main() -> Result<()> {
16//!     init()?;
17//!
18//!     let vertices = vec![
19//!         Vec3::new(0.0, 0.0, 0.0),
20//!         Vec3::new(1.0, 0.0, 0.0),
21//!         Vec3::new(1.0, 1.0, 0.0),
22//!         Vec3::new(0.0, 1.0, 0.0),
23//!     ];
24//!     let faces = vec![[0u32, 1, 2], [0, 2, 3]];
25//!
26//!     let mesh = register_surface_mesh("quad", vertices, faces);
27//!     mesh.set_surface_color(Vec3::new(0.2, 0.5, 0.8))
28//!         .set_show_edges(true);
29//!
30//!     show();
31//!     Ok(())
32//! }
33//! ```
34
35use crate::{SurfaceMesh, Vec2, Vec3, Vec4, with_context_mut};
36use glam::UVec3;
37
38/// Trait for face data that can be converted to the internal polygon format.
39///
40/// Implemented for:
41/// - `Vec<UVec3>` — triangle-only meshes
42/// - `Vec<[u32; 3]>` — triangle-only meshes (array form)
43/// - `Vec<Vec<u32>>` — arbitrary polygon meshes (triangles, quads, pentagons, etc.)
44pub trait IntoFaceList {
45    /// Converts to the internal polygon face representation.
46    fn into_face_list(self) -> Vec<Vec<u32>>;
47}
48
49impl IntoFaceList for Vec<UVec3> {
50    fn into_face_list(self) -> Vec<Vec<u32>> {
51        self.into_iter().map(|f| vec![f.x, f.y, f.z]).collect()
52    }
53}
54
55impl IntoFaceList for Vec<[u32; 3]> {
56    fn into_face_list(self) -> Vec<Vec<u32>> {
57        self.into_iter().map(|f| f.to_vec()).collect()
58    }
59}
60
61impl IntoFaceList for Vec<Vec<u32>> {
62    fn into_face_list(self) -> Vec<Vec<u32>> {
63        self
64    }
65}
66
67/// Registers a surface mesh with polyscope.
68///
69/// Accepts any face format implementing [`IntoFaceList`]:
70/// - `Vec<UVec3>` or `Vec<[u32; 3]>` for triangle meshes
71/// - `Vec<Vec<u32>>` for arbitrary polygon meshes (triangles, quads, n-gons)
72///
73/// Polygonal faces are automatically fan-triangulated for rendering while
74/// preserving the original face structure for quantities and wireframe display.
75///
76/// # Panics
77///
78/// Panics if any face has fewer than 3 vertices or contains out-of-bounds
79/// vertex indices.
80pub fn register_surface_mesh(
81    name: impl Into<String>,
82    vertices: Vec<Vec3>,
83    faces: impl IntoFaceList,
84) -> SurfaceMeshHandle {
85    let name = name.into();
86    let faces = faces.into_face_list();
87    let n_verts = vertices.len();
88
89    // Validate faces
90    for (i, face) in faces.iter().enumerate() {
91        assert!(
92            face.len() >= 3,
93            "Face {i} has {} vertices (minimum 3 required)",
94            face.len()
95        );
96        for &idx in face {
97            assert!(
98                (idx as usize) < n_verts,
99                "Face {i} contains vertex index {idx} but mesh only has {n_verts} vertices"
100            );
101        }
102    }
103
104    let mesh = SurfaceMesh::new(name.clone(), vertices, faces);
105
106    with_context_mut(|ctx| {
107        ctx.registry
108            .register(Box::new(mesh))
109            .expect("failed to register surface mesh");
110        ctx.update_extents();
111    });
112
113    SurfaceMeshHandle { name }
114}
115
116impl_structure_accessors! {
117    get_fn = get_surface_mesh,
118    with_fn = with_surface_mesh,
119    with_ref_fn = with_surface_mesh_ref,
120    handle = SurfaceMeshHandle,
121    type_name = "SurfaceMesh",
122    rust_type = SurfaceMesh,
123    doc_name = "surface mesh"
124}
125
126/// Handle for a registered surface mesh.
127///
128/// This handle provides methods to add quantities and configure the
129/// appearance of a surface mesh. Methods return `&Self` to allow chaining.
130///
131/// # Example
132///
133/// ```no_run
134/// use polyscope_rs::*;
135///
136/// init().unwrap();
137/// let vertices = vec![Vec3::ZERO, Vec3::X, Vec3::Y];
138/// let faces = vec![[0u32, 1, 2]];
139/// let mesh = register_surface_mesh("mesh", vertices, faces);
140/// mesh.set_surface_color(Vec3::new(1.0, 0.5, 0.0))
141///     .set_show_edges(true)
142///     .add_vertex_scalar_quantity("height", vec![0.0, 1.0, 0.5]);
143/// ```
144#[derive(Clone)]
145pub struct SurfaceMeshHandle {
146    name: String,
147}
148
149impl SurfaceMeshHandle {
150    /// Returns the name of this mesh.
151    #[must_use]
152    pub fn name(&self) -> &str {
153        &self.name
154    }
155
156    // -- Appearance setters --
157
158    /// Sets the surface color.
159    pub fn set_surface_color(&self, color: Vec3) -> &Self {
160        with_surface_mesh(&self.name, |mesh| {
161            mesh.set_surface_color(color);
162        });
163        self
164    }
165
166    /// Sets the edge color.
167    pub fn set_edge_color(&self, color: Vec3) -> &Self {
168        with_surface_mesh(&self.name, |mesh| {
169            mesh.set_edge_color(color);
170        });
171        self
172    }
173
174    /// Sets the edge width.
175    pub fn set_edge_width(&self, width: f32) -> &Self {
176        with_surface_mesh(&self.name, |mesh| {
177            mesh.set_edge_width(width);
178        });
179        self
180    }
181
182    /// Sets whether edges are shown.
183    pub fn set_show_edges(&self, show: bool) -> &Self {
184        with_surface_mesh(&self.name, |mesh| {
185            mesh.set_show_edges(show);
186        });
187        self
188    }
189
190    /// Sets the backface color.
191    pub fn set_backface_color(&self, color: Vec3) -> &Self {
192        with_surface_mesh(&self.name, |mesh| {
193            mesh.set_backface_color(color);
194        });
195        self
196    }
197
198    /// Sets the transparency (0.0 = opaque, 1.0 = fully transparent).
199    pub fn set_transparency(&self, transparency: f32) -> &Self {
200        with_surface_mesh(&self.name, |mesh| {
201            mesh.set_transparency(transparency);
202        });
203        self
204    }
205
206    /// Sets the material.
207    pub fn set_material(&self, material: &str) -> &Self {
208        use polyscope_core::Structure;
209        with_surface_mesh(&self.name, |mesh| {
210            mesh.set_material(material);
211        });
212        self
213    }
214
215    // -- Quantity methods --
216
217    /// Adds a vertex scalar quantity.
218    pub fn add_vertex_scalar_quantity(&self, name: &str, values: Vec<f32>) -> &Self {
219        with_surface_mesh(&self.name, |mesh| {
220            mesh.add_vertex_scalar_quantity(name, values);
221        });
222        self
223    }
224
225    /// Adds a face scalar quantity.
226    pub fn add_face_scalar_quantity(&self, name: &str, values: Vec<f32>) -> &Self {
227        with_surface_mesh(&self.name, |mesh| {
228            mesh.add_face_scalar_quantity(name, values);
229        });
230        self
231    }
232
233    /// Adds a vertex color quantity (RGB, alpha defaults to 1.0).
234    pub fn add_vertex_color_quantity(&self, name: &str, colors: Vec<Vec3>) -> &Self {
235        with_surface_mesh(&self.name, |mesh| {
236            mesh.add_vertex_color_quantity(name, colors);
237        });
238        self
239    }
240
241    /// Adds a vertex color quantity with explicit per-vertex RGBA alpha values.
242    ///
243    /// Use this to specify per-vertex transparency. Requires Pretty (depth peeling)
244    /// transparency mode to render correctly (set via appearance settings).
245    pub fn add_vertex_color_quantity_with_alpha(&self, name: &str, colors: Vec<Vec4>) -> &Self {
246        with_surface_mesh(&self.name, |mesh| {
247            mesh.add_vertex_color_quantity_with_alpha(name, colors);
248        });
249        self
250    }
251
252    /// Adds a face color quantity (RGB, alpha defaults to 1.0).
253    pub fn add_face_color_quantity(&self, name: &str, colors: Vec<Vec3>) -> &Self {
254        with_surface_mesh(&self.name, |mesh| {
255            mesh.add_face_color_quantity(name, colors);
256        });
257        self
258    }
259
260    /// Adds a face color quantity with explicit per-face RGBA alpha values.
261    ///
262    /// Use this to specify per-face transparency. Requires Pretty (depth peeling)
263    /// transparency mode to render correctly (set via appearance settings).
264    pub fn add_face_color_quantity_with_alpha(&self, name: &str, colors: Vec<Vec4>) -> &Self {
265        with_surface_mesh(&self.name, |mesh| {
266            mesh.add_face_color_quantity_with_alpha(name, colors);
267        });
268        self
269    }
270
271    /// Adds a vertex vector quantity (auto-scaled).
272    pub fn add_vertex_vector_quantity(&self, name: &str, vectors: Vec<Vec3>) -> &Self {
273        with_surface_mesh(&self.name, |mesh| {
274            mesh.add_vertex_vector_quantity(name, vectors);
275        });
276        self
277    }
278
279    /// Adds a face vector quantity (auto-scaled).
280    pub fn add_face_vector_quantity(&self, name: &str, vectors: Vec<Vec3>) -> &Self {
281        with_surface_mesh(&self.name, |mesh| {
282            mesh.add_face_vector_quantity(name, vectors);
283        });
284        self
285    }
286
287    /// Adds a vertex parameterization (UV) quantity.
288    pub fn add_vertex_parameterization_quantity(&self, name: &str, coords: Vec<Vec2>) -> &Self {
289        with_surface_mesh(&self.name, |mesh| {
290            mesh.add_vertex_parameterization_quantity(name, coords);
291        });
292        self
293    }
294
295    /// Adds a corner parameterization (UV) quantity.
296    pub fn add_corner_parameterization_quantity(&self, name: &str, coords: Vec<Vec2>) -> &Self {
297        with_surface_mesh(&self.name, |mesh| {
298            mesh.add_corner_parameterization_quantity(name, coords);
299        });
300        self
301    }
302
303    /// Adds a vertex intrinsic vector quantity with explicit tangent basis (auto-scaled).
304    pub fn add_vertex_intrinsic_vector_quantity(
305        &self,
306        name: &str,
307        vectors: Vec<Vec2>,
308        basis_x: Vec<Vec3>,
309        basis_y: Vec<Vec3>,
310    ) -> &Self {
311        with_surface_mesh(&self.name, |mesh| {
312            mesh.add_vertex_intrinsic_vector_quantity(name, vectors, basis_x, basis_y);
313        });
314        self
315    }
316
317    /// Adds a vertex intrinsic vector quantity with auto-computed tangent basis.
318    pub fn add_vertex_intrinsic_vector_quantity_auto(
319        &self,
320        name: &str,
321        vectors: Vec<Vec2>,
322    ) -> &Self {
323        with_surface_mesh(&self.name, |mesh| {
324            mesh.add_vertex_intrinsic_vector_quantity_auto(name, vectors);
325        });
326        self
327    }
328
329    /// Adds a face intrinsic vector quantity with explicit tangent basis (auto-scaled).
330    pub fn add_face_intrinsic_vector_quantity(
331        &self,
332        name: &str,
333        vectors: Vec<Vec2>,
334        basis_x: Vec<Vec3>,
335        basis_y: Vec<Vec3>,
336    ) -> &Self {
337        with_surface_mesh(&self.name, |mesh| {
338            mesh.add_face_intrinsic_vector_quantity(name, vectors, basis_x, basis_y);
339        });
340        self
341    }
342
343    /// Adds a face intrinsic vector quantity with auto-computed tangent basis.
344    pub fn add_face_intrinsic_vector_quantity_auto(&self, name: &str, vectors: Vec<Vec2>) -> &Self {
345        with_surface_mesh(&self.name, |mesh| {
346            mesh.add_face_intrinsic_vector_quantity_auto(name, vectors);
347        });
348        self
349    }
350
351    /// Adds a one-form quantity (edge-based differential form, auto-scaled).
352    pub fn add_one_form_quantity(
353        &self,
354        name: &str,
355        values: Vec<f32>,
356        orientations: Vec<bool>,
357    ) -> &Self {
358        with_surface_mesh(&self.name, |mesh| {
359            mesh.add_one_form_quantity(name, values, orientations);
360        });
361        self
362    }
363}