stereokit_rust/
mesh.rs

1use crate::{
2    StereoKitError,
3    material::{Cull, Material, MaterialT},
4    maths::{Bool32T, Bounds, Matrix, Ray, Vec2, Vec3, Vec4},
5    sk::MainThreadToken,
6    system::{IAsset, RenderLayer},
7    util::{Color32, Color128},
8};
9use std::{
10    ffi::{CStr, CString, c_char},
11    ptr::{NonNull, slice_from_raw_parts_mut},
12};
13
14/// This represents a single vertex in a Mesh, all StereoKit Meshes currently use this exact layout!
15/// It’s good to fill out all values of a Vertex explicitly, as default values for the normal (0,0,0) and color
16/// (0,0,0,0) will cause your mesh to appear completely black, or even transparent in most shaders!
17/// <https://stereokit.net/Pages/StereoKit/Vertex.html>
18///
19/// ### Examples
20/// ```
21/// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
22/// use stereokit_rust::{maths::{Vec3, Vec2, Matrix}, util::Color32, mesh::{Mesh,Vertex}, material::Material};
23///
24/// // Creating vertices with all fields specified
25/// let vertices = [
26///     Vertex::new(Vec3::ZERO,Vec3::UP,None,         Some(Color32::rgb(0, 0, 255))),
27///     Vertex::new(Vec3::X,   Vec3::UP,Some(Vec2::X),Some(Color32::rgb(255, 0, 0))),
28///     Vertex::new(Vec3::Y,   Vec3::UP,Some(Vec2::Y),Some(Color32::rgb(0,255, 0))),
29/// ];
30/// let indices = [0, 1, 2, 2, 1, 0];
31/// let mut mesh = Mesh::new();
32/// mesh.id("most_basic_mesh").keep_data(true).set_data(&vertices, &indices, true);
33/// let material = Material::pbr();
34///
35/// filename_scr = "screenshots/basic_mesh.jpeg";
36/// test_screenshot!( // !!!! Get a proper main loop !!!!
37///     mesh.draw(token, &material, Matrix::IDENTITY, None, None);
38/// );
39/// ```
40/// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/basic_mesh.jpeg" alt="screenshot" width="200">
41#[derive(Default, Debug, Copy, Clone, PartialEq)]
42#[repr(C)]
43pub struct Vertex {
44    /// Position of the vertex, in model space coordinates.
45    pub pos: Vec3,
46    /// The normal of this vertex, or the direction the vertex is facing. Preferably normalized.
47    pub norm: Vec3,
48    /// The texture coordinates at this vertex.
49    pub uv: Vec2,
50    /// The color of the vertex. If you aren’t using it, set it to white.
51    pub col: Color32,
52}
53
54impl Vertex {
55    /// Create a new Vertex.
56    /// <https://stereokit.net/Pages/StereoKit/Vertex/Vertex.html>
57    /// * `position` - Location of the vertex, this is typically meters in model space.
58    /// * `normal` - The direction the Vertex is facing. Never leave this as zero, or your lighting may turn out black!
59    ///   A good default value if you don’t know what to put here is (0,1,0), but a Mesh composed entirely of this value
60    ///   will have flat lighting.
61    /// * `texture_coordinate` - If None, set the value to Vec2::ZERO
62    /// * `color` - If None, set the value to Color32::WHITE
63    ///
64    /// ### Examples
65    /// ```
66    /// use stereokit_rust::{maths::{Vec3, Vec2}, mesh::Vertex, util::Color32};
67    ///
68    /// let vertex = Vertex::new([0.0, 0.0, 0.0], [0.0, 1.0, 0.0], None, None);
69    /// let vertex_bis = Vertex{
70    ///         pos: Vec3::new(0.0, 0.0, 0.0),
71    ///         norm: Vec3::new(0.0, 1.0, 0.0),
72    ///         uv: Vec2::ZERO,
73    ///         col: Color32::WHITE};
74    /// assert_eq!(vertex, vertex_bis);
75    ///
76    /// let vertex = Vertex::new([0.0, 0.0, 0.0], [0.0, 0.0, 0.0],
77    ///                          Some(Vec2::ZERO), Some(Color32::BLACK_TRANSPARENT) );
78    /// let vertex_default = Vertex::default();
79    /// assert_eq!(vertex, vertex_default);
80    /// ```
81    pub fn new<V: Into<Vec3>>(
82        position: V,
83        normal: V,
84        texture_coordinate: Option<Vec2>,
85        color: Option<Color32>,
86    ) -> Self {
87        let texture_coordinate = texture_coordinate.unwrap_or(Vec2::ZERO);
88        let color = color.unwrap_or(Color32::WHITE);
89        Self { pos: position.into(), norm: normal.into(), uv: texture_coordinate, col: color }
90    }
91}
92
93/// Mesh index data
94/// <https://stereokit.net/Pages/StereoKit/Mesh.html>
95pub type Inds = u32;
96
97/// For performance sensitive areas, or places dealing with large chunks of memory, it can be faster to get a reference
98/// to that memory rather than copying it! However, if this isn’t explicitly stated, it isn’t necessarily clear what’s
99/// happening. So this enum allows us to visibly specify what type of memory reference is occurring.
100/// <https://stereokit.net/Pages/StereoKit/Memory.html>
101#[derive(Debug, Copy, Clone, PartialEq, Eq)]
102#[repr(u32)]
103pub enum Memory {
104    /// The chunk of memory involved here is a reference that is still managed or used by StereoKit! You should not free
105    /// it, and be extremely cautious about modifying it.
106    Reference = 0,
107    /// This memory is now yours and you must free it yourself! Memory has been allocated, and the data has been copied
108    /// over to it. Pricey! But safe.
109    Copy = 1,
110}
111
112/// A Mesh is a single collection of triangular faces with extra surface information to enhance rendering! StereoKit
113/// meshes are composed of a list of vertices, and a list of indices to connect the vertices into faces. Nothing more
114/// than that is stored here, so typically meshes are combined with Materials, or added to Models in order to draw them.
115///
116/// Mesh vertices are composed of a position, a normal (direction of the vert), a uv coordinate (for mapping a texture
117/// to the mesh’s surface), and a 32 bit color containing red, green, blue, and alpha (transparency).
118///
119/// Mesh indices are stored as unsigned ints, so you can have a mesh with a fudgeton of verts! 4 billion or so :)
120/// <https://stereokit.net/Pages/StereoKit/Mesh.html>
121///
122/// ### Examples
123/// ```
124/// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
125/// use stereokit_rust::{maths::{Vec3, Matrix, Quat}, util::{named_colors,Color32},
126///                      mesh::Mesh, material::Material};
127///
128/// // Create Meshes
129/// let cube = Mesh::generate_cube(Vec3::ONE * 0.8, None);
130/// let sphere = Mesh::generate_sphere(1.0, None);
131///
132/// let material_cube = Material::pbr().copy();
133/// let mut material_sphere = Material::pbr().copy();
134/// material_sphere.color_tint(named_colors::GREEN);
135/// let cube_transform = Matrix::r([40.0, 50.0, 20.0]);
136///
137/// filename_scr = "screenshots/meshes.jpeg";
138/// test_screenshot!( // !!!! Get a proper main loop !!!!
139///     cube.draw(token, &material_cube, cube_transform, None, None);
140///     sphere.draw(token, &material_sphere, Matrix::IDENTITY, None, None);
141/// );
142/// ```
143/// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/meshes.jpeg" alt="screenshot" width="200">
144#[derive(Debug, PartialEq)]
145pub struct Mesh(pub NonNull<_MeshT>);
146impl Drop for Mesh {
147    fn drop(&mut self) {
148        unsafe { mesh_release(self.0.as_ptr()) }
149    }
150}
151impl AsRef<Mesh> for Mesh {
152    fn as_ref(&self) -> &Mesh {
153        self
154    }
155}
156
157/// StereoKit internal type.
158#[repr(C)]
159#[derive(Debug)]
160pub struct _MeshT {
161    _unused: [u8; 0],
162}
163/// StereoKit ffi type.
164pub type MeshT = *mut _MeshT;
165
166/// StereoKit ffi type.
167pub type VindT = u32;
168
169unsafe extern "C" {
170    pub fn mesh_find(name: *const c_char) -> MeshT;
171    pub fn mesh_create() -> MeshT;
172    pub fn mesh_copy(mesh: MeshT) -> MeshT;
173    pub fn mesh_set_id(mesh: MeshT, id: *const c_char);
174    pub fn mesh_get_id(mesh: MeshT) -> *const c_char;
175    pub fn mesh_addref(mesh: MeshT);
176    pub fn mesh_release(mesh: MeshT);
177    pub fn mesh_draw(mesh: MeshT, material: MaterialT, transform: Matrix, color_linear: Color128, layer: RenderLayer);
178    pub fn mesh_set_keep_data(mesh: MeshT, keep_data: Bool32T);
179    pub fn mesh_get_keep_data(mesh: MeshT) -> Bool32T;
180    pub fn mesh_set_data(
181        mesh: MeshT,
182        in_arr_vertices: *const Vertex,
183        vertex_count: i32,
184        in_arr_indices: *const VindT,
185        index_count: i32,
186        calculate_bounds: Bool32T,
187    );
188    pub fn mesh_set_verts(mesh: MeshT, in_arr_vertices: *const Vertex, vertex_count: i32, calculate_bounds: Bool32T);
189    pub fn mesh_get_verts(
190        mesh: MeshT,
191        out_arr_vertices: *mut *mut Vertex,
192        out_vertex_count: *mut i32,
193        reference_mode: Memory,
194    );
195    pub fn mesh_get_vert_count(mesh: MeshT) -> i32;
196    pub fn mesh_set_inds(mesh: MeshT, in_arr_indices: *const VindT, index_count: i32);
197    pub fn mesh_get_inds(
198        mesh: MeshT,
199        out_arr_indices: *mut *mut VindT,
200        out_index_count: *mut i32,
201        reference_mode: Memory,
202    );
203    pub fn mesh_get_ind_count(mesh: MeshT) -> i32;
204    pub fn mesh_set_draw_inds(mesh: MeshT, index_count: i32);
205    pub fn mesh_set_bounds(mesh: MeshT, bounds: *const Bounds);
206    pub fn mesh_get_bounds(mesh: MeshT) -> Bounds;
207    pub fn mesh_has_skin(mesh: MeshT) -> Bool32T;
208    pub fn mesh_set_skin(
209        mesh: MeshT,
210        in_arr_bone_ids_4: *const u16,
211        bone_id_4_count: i32,
212        in_arr_bone_weights: *const Vec4,
213        bone_weight_count: i32,
214        bone_resting_transforms: *const Matrix,
215        bone_count: i32,
216    );
217    pub fn mesh_update_skin(mesh: MeshT, in_arr_bone_transforms: *const Matrix, bone_count: i32);
218    pub fn mesh_ray_intersect(
219        mesh: MeshT,
220        model_space_ray: Ray,
221        cull_mode: Cull,
222        out_pt: *mut Ray,
223        out_start_inds: *mut u32,
224    ) -> Bool32T;
225    pub fn mesh_ray_intersect_bvh(
226        mesh: MeshT,
227        model_space_ray: Ray,
228        cull_mode: Cull,
229        out_pt: *mut Ray,
230        out_start_inds: *mut u32,
231    ) -> Bool32T;
232    pub fn mesh_get_triangle(
233        mesh: MeshT,
234        triangle_index: u32,
235        out_a: *mut Vertex,
236        out_b: *mut Vertex,
237        out_c: *mut Vertex,
238    ) -> Bool32T;
239    pub fn mesh_gen_plane(
240        dimensions: Vec2,
241        plane_normal: Vec3,
242        plane_top_direction: Vec3,
243        subdivisions: i32,
244        double_sided: Bool32T,
245    ) -> MeshT;
246    pub fn mesh_gen_circle(
247        diameter: f32,
248        plane_normal: Vec3,
249        plane_top_direction: Vec3,
250        spokes: i32,
251        double_sided: Bool32T,
252    ) -> MeshT;
253    pub fn mesh_gen_cube(dimensions: Vec3, subdivisions: i32) -> MeshT;
254    pub fn mesh_gen_sphere(diameter: f32, subdivisions: i32) -> MeshT;
255    pub fn mesh_gen_rounded_cube(dimensions: Vec3, edge_radius: f32, subdivisions: i32) -> MeshT;
256    pub fn mesh_gen_cylinder(diameter: f32, depth: f32, direction: Vec3, subdivisions: i32) -> MeshT;
257    pub fn mesh_gen_cone(diameter: f32, depth: f32, direction: Vec3, subdivisions: i32) -> MeshT;
258}
259
260impl IAsset for Mesh {
261    // fn id(&mut self, id: impl AsRef<str>) {
262    //     self.id(id);
263    // }
264
265    fn get_id(&self) -> &str {
266        self.get_id()
267    }
268}
269
270impl Default for Mesh {
271    /// Creates an empty Mesh asset. Use SetVerts and SetInds to add data to it!
272    /// <https://stereokit.net/Pages/StereoKit/Mesh/Mesh.html>
273    ///
274    /// see also: [`Vertex`] [`Mesh::new`]
275    fn default() -> Self {
276        Self::new()
277    }
278}
279
280impl Mesh {
281    /// Creates an empty Mesh asset. Use SetVerts and SetInds to add data to it!
282    /// <https://stereokit.net/Pages/StereoKit/Mesh/Mesh.html>
283    ///
284    /// see also [`mesh_create`] [`Mesh::default`]
285    ///
286    /// ### Examples
287    /// ```
288    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
289    /// use stereokit_rust::mesh::Mesh;
290    ///
291    /// // Create Meshes
292    /// let mesh = Mesh::new();
293    ///
294    /// assert_eq!(mesh.get_inds().len(), 0);
295    /// assert_eq!(mesh.get_verts().len(), 0);
296    /// ```
297    pub fn new() -> Mesh {
298        Mesh(NonNull::new(unsafe { mesh_create() }).unwrap())
299    }
300
301    /// Generates a plane with an arbitrary orientation that is optionally subdivided, pre-sized to the given
302    /// dimensions. UV coordinates start at the top left indicated with plane_top_direction.
303    ///
304    /// NOTE: This generates a completely new Mesh asset on the GPU, and is best done during 'initialization' of your
305    /// app/scene. You may also be interested in using the pre-generated `Mesh.Quad` asset if it already meets your
306    /// needs.
307    /// <https://stereokit.net/Pages/StereoKit/Mesh/GeneratePlane.html>
308    /// * `dimension` - How large is this plane on the XZ axis,  in meters?
309    /// * `plane_normal` - What is the normal of the surface this plane is generated on?
310    /// * `plane_top_direction` - A normal defines the plane, but this is technically a rectangle on the plane. So which
311    ///   direction is up? It's important for UVs, but doesn't need to be exact. This function takes the planeNormal as
312    ///   law, and uses this vector to find the right and up vectors via cross-products.
313    /// * `subdivisions` - Use this to add extra slices of vertices across the plane. This can be useful for some types of
314    ///   vertex-based effects! None is 0.
315    /// * `double_sided` - Should both sides of the plane be rendered?
316    ///
317    /// Returns a plane mesh, pre-sized to the given dimensions.
318    /// see also [`mesh_gen_plane`]
319    /// ### Examples
320    /// ```
321    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
322    /// use stereokit_rust::mesh::Mesh;
323    ///
324    /// // Create Meshes
325    /// let mesh = Mesh::generate_plane([1.0, 1.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], None, false);
326    /// assert_eq!(mesh.get_ind_count(), 6);
327    /// assert_eq!(mesh.get_vert_count(), 4);
328    ///
329    /// let mesh = Mesh::generate_plane([1.0, 1.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], None, true);
330    /// assert_eq!(mesh.get_ind_count(), 12);
331    /// assert_eq!(mesh.get_vert_count(), 8);
332    ///
333    /// let mesh = Mesh::generate_plane([1.0, 1.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], Some(1), true);
334    /// assert_eq!(mesh.get_ind_count(), 48);
335    /// assert_eq!(mesh.get_vert_count(), 18);
336    /// ```
337    pub fn generate_plane<V: Into<Vec3>>(
338        dimensions: impl Into<Vec2>,
339        plane_normal: V,
340        plane_top_direction: V,
341        subdivisions: Option<i32>,
342        double_sided: bool,
343    ) -> Mesh {
344        let subdivisions = subdivisions.unwrap_or(0);
345        Mesh(
346            NonNull::new(unsafe {
347                mesh_gen_plane(
348                    dimensions.into(),
349                    plane_normal.into(),
350                    plane_top_direction.into(),
351                    subdivisions,
352                    double_sided as Bool32T,
353                )
354            })
355            .unwrap(),
356        )
357    }
358
359    /// Generates a plane on the XZ axis facing up that is optionally subdivided, pre-sized to the given dimensions. UV
360    /// coordinates start at 0,0 at the -X,-Z corner, and go to 1,1 at the +X,+Z corner!
361    ///
362    /// NOTE: This generates a completely new Mesh asset on the GPU, and is best done during 'initialization' of your
363    /// app/scene. You may also be interested in using the pre-generated `Mesh.Quad` asset if it already meets your
364    /// needs.
365    /// <https://stereokit.net/Pages/StereoKit/Mesh/GeneratePlane.html>
366    /// * `dimension` - How large is this plane on the XZ axis,  in meters?
367    /// * `subdivisions` - Use this to add extra slices of vertices across the plane. This can be useful for some types of
368    ///   vertex-based effects! None is 0.
369    /// * `double_sided` - Should both sides of the plane be rendered?
370    ///
371    /// Returns a plane mesh, pre-sized to the given dimensions.
372    /// see also [`mesh_gen_plane`]
373    /// ### Examples
374    /// ```
375    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
376    /// use stereokit_rust::{mesh::{Mesh, Vertex}, maths::{Vec2, Vec3}};
377    ///
378    /// // Create Meshes
379    /// let mesh = Mesh::generate_plane_up([1.0, 1.0],  None, false);
380    /// let mesh_b = Mesh::generate_plane([1.0, 1.0], [0.0, 1.0, 0.0], [0.0, 0.0, -1.0], None, false);
381    /// assert_eq!(mesh.get_verts(), mesh_b.get_verts());
382    /// assert_eq!(mesh.get_inds(), mesh_b.get_inds());
383    /// assert_eq!(mesh.get_ind_count(), 6);
384    /// assert_eq!(mesh.get_vert_count(), 4);
385    /// let vertices0 = [
386    ///    Vertex::new([-0.5, 0.0,-0.5].into(),Vec3::UP,Some(Vec2::ZERO), None),
387    ///    Vertex::new([ 0.5, 0.0,-0.5].into(),Vec3::UP,Some(Vec2::X)   , None),
388    ///    Vertex::new([-0.5, 0.0, 0.5].into(),Vec3::UP,Some(Vec2::Y)   , None),
389    ///    Vertex::new([ 0.5, 0.0, 0.5].into(),Vec3::UP,Some(Vec2::ONE) , None),
390    ///    ];
391    /// assert_eq!(mesh.get_verts(), vertices0);
392    ///
393    /// let mesh = Mesh::generate_plane_up([1.0, 1.0], None, true);
394    /// assert_eq!(mesh.get_inds().len(), 12);
395    /// assert_eq!(mesh.get_verts().len(), 8);
396    ///
397    /// let mesh = Mesh::generate_plane_up([1.0, 1.0], Some(1), true);
398    /// assert_eq!(mesh.get_inds().len(), 48);
399    /// assert_eq!(mesh.get_verts().len(), 18);
400    /// ```
401    pub fn generate_plane_up(dimensions: impl Into<Vec2>, subdivisions: Option<i32>, double_sided: bool) -> Mesh {
402        let subdivisions = subdivisions.unwrap_or(0);
403        Mesh(
404            NonNull::new(unsafe {
405                mesh_gen_plane(dimensions.into(), Vec3::UP, Vec3::FORWARD, subdivisions, double_sided as Bool32T)
406            })
407            .unwrap(),
408        )
409    }
410
411    /// Generates a circle with an arbitrary orientation that is pre-sized to the given diameter. UV coordinates start
412    /// at the top  left indicated with 'plane_top_direction' and correspond to a unit circle centered at 0.5, 0.5.
413    ///
414    /// NOTE: This generates a completely new Mesh asset on the GPU, and is best done during 'initialization' of your
415    /// app/scene.
416    /// <https://stereokit.net/Pages/StereoKit/Mesh/GenerateCircle.html>
417    /// * `diameter` - The diameter of the circle in meters, or  2*radius. This is the full length from one side to the
418    ///   other.
419    /// * `plane_normal` - What is the normal of the surface this circle is generated on?
420    /// * `plane_top_direction` - A normal defines the plane, but this is technically a rectangle on the plane. So which
421    ///   direction is up? It's important for UVs, but doesn't need to be exact. This function takes the plane_normal as
422    ///   law, and uses this vector to find the right and up vectors via cross-products.
423    /// * `spokes` - How many vertices compose the circumference of the circle? Clamps to a minimum of 3. More is smoother,
424    ///   but less performant. if None has default value of 16.
425    /// * `double_sided` - Should both sides of the circle be  rendered?
426    ///
427    /// Returns A circle mesh, pre-sized to the given dimensions.
428    ///
429    /// see also [`mesh_gen_circle`]
430    /// ### Examples
431    /// ```
432    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
433    /// use stereokit_rust::mesh::Mesh;
434    ///
435    /// // Create Meshes
436    /// let mesh = Mesh::generate_circle(1.0, [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], None, false);
437    /// assert_eq!(mesh.get_ind_count(), 42);
438    /// assert_eq!(mesh.get_vert_count(), 16);
439    ///
440    /// let mesh = Mesh::generate_circle(1.0, [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], None, true);
441    /// assert_eq!(mesh.get_inds().len(), 84);
442    /// assert_eq!(mesh.get_verts().len(), 32);
443    ///
444    /// let mesh = Mesh::generate_circle(1.0, [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], Some(1), true);
445    /// assert_eq!(mesh.get_inds().len(), 6);
446    /// assert_eq!(mesh.get_verts().len(), 6);
447    /// ```
448    pub fn generate_circle<V: Into<Vec3>>(
449        diameter: f32,
450        plane_normal: V,
451        plane_top_direction: V,
452        spokes: Option<i32>,
453        double_sided: bool,
454    ) -> Mesh {
455        let spokes = spokes.unwrap_or(16);
456        Mesh(
457            NonNull::new(unsafe {
458                mesh_gen_circle(
459                    diameter,
460                    plane_normal.into(),
461                    plane_top_direction.into(),
462                    spokes,
463                    double_sided as Bool32T,
464                )
465            })
466            .unwrap(),
467        )
468    }
469
470    /// Generates a circle on the XZ axis facing up that is  pre-sized to the given diameter. UV coordinates correspond
471    /// to a unit  circle centered at 0.5, 0.5! That is, the right-most point on the  circle has UV coordinates 1, 0.5
472    /// and the top-most point has UV  coordinates 0.5, 1.
473    ///
474    /// NOTE: This generates a completely new Mesh asset on the GPU, and is best done during 'initialization' of your
475    /// app/scene.
476    /// <https://stereokit.net/Pages/StereoKit/Mesh/GenerateCircle.html>
477    /// * `diameter` - The diameter of the circle in meters, or  2*radius. This is the full length from one side to the
478    ///   other.
479    /// * `spokes` - How many vertices compose the circumference of the circle? Clamps to a minimum of 3. More is smoother,
480    ///   but less performant. if None has default value of 16.
481    /// * `double_sided` - Should both sides of the circle be  rendered?
482    ///
483    /// Returns A circle mesh, pre-sized to the given dimensions.
484    /// see also [`mesh_gen_circle`]
485    /// ### Examples
486    /// ```
487    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
488    /// use stereokit_rust::mesh::Mesh;
489    ///
490    /// // Create Meshes
491    /// let mesh = Mesh::generate_circle_up(1.0 , None, false);
492    /// let mesh_b = Mesh::generate_circle(1.0, [0.0, 1.0, 0.0], [0.0, 0.0, -1.0], None, false);
493    /// assert_eq!(mesh.get_verts(), mesh_b.get_verts());
494    /// assert_eq!(mesh.get_inds(), mesh_b.get_inds());
495    /// assert_eq!(mesh.get_ind_count(), 42);
496    /// assert_eq!(mesh.get_vert_count(), 16);
497    ///
498    /// let mesh = Mesh::generate_circle_up(1.0 , None, true);
499    /// assert_eq!(mesh.get_inds().len(), 84);
500    /// assert_eq!(mesh.get_verts().len(), 32);
501    ///
502    /// let mesh = Mesh::generate_circle_up(1.0 , Some(1), true);
503    /// assert_eq!(mesh.get_inds().len(), 6);
504    /// assert_eq!(mesh.get_verts().len(), 6);
505    /// ```
506    pub fn generate_circle_up(diameter: f32, spokes: Option<i32>, double_sided: bool) -> Mesh {
507        let spokes = spokes.unwrap_or(16);
508        Mesh(
509            NonNull::new(unsafe {
510                mesh_gen_circle(diameter, Vec3::UP, Vec3::FORWARD, spokes, double_sided as Bool32T)
511            })
512            .unwrap(),
513        )
514    }
515
516    /// Generates a flat-shaded cube mesh, pre-sized to the given dimensions. UV coordinates are projected flat on each
517    /// face, 0,0 -> 1,1.
518    ///
519    /// NOTE: This generates a completely new Mesh asset on the GPU, and is best done during 'initialization' of your
520    /// app/scene. You may also be interested in using the pre-generated Mesh::cube() asset if it already meets your
521    /// needs.
522    /// <https://stereokit.net/Pages/StereoKit/Mesh/GenerateCube.html>
523    /// * `dimension` - How large is this cube on each axis, in meters?
524    /// * `subdivisions` - Use this to add extra slices of vertices across the cube's faces. This can be useful for some
525    ///   types of vertex-based effects! None is 0.
526    ///
527    /// Returns a flat-shaded cube mesh, pre-sized to the given  dimensions.
528    /// see also [`mesh_gen_circle`]
529    /// ### Examples
530    /// ```
531    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
532    /// use stereokit_rust::mesh::Mesh;
533    ///
534    /// // Create Meshes
535    /// let mesh = Mesh::generate_cube([1.0, 1.0, 1.0], None);
536    /// assert_eq!(mesh.get_ind_count(), 36);
537    /// assert_eq!(mesh.get_vert_count(), 24);
538    ///
539    /// let mesh = Mesh::generate_cube([1.0, 1.0, 1.0], Some(1));
540    /// assert_eq!(mesh.get_inds().len(), 144);
541    /// assert_eq!(mesh.get_verts().len(), 54);
542    /// ```
543    pub fn generate_cube(dimensions: impl Into<Vec3>, subdivisions: Option<i32>) -> Mesh {
544        let subdivisions = subdivisions.unwrap_or(0);
545        Mesh(NonNull::new(unsafe { mesh_gen_cube(dimensions.into(), subdivisions) }).unwrap())
546    }
547
548    /// Generates a cube mesh with rounded corners, pre-sized to the given dimensions. UV coordinates are 0,0 -> 1,1 on
549    /// each face, meeting at the middle of the rounded corners.
550    ///
551    /// NOTE: This generates a completely new Mesh asset on the GPU, and is best done during 'initialization' of your
552    /// app/scene.
553    /// <https://stereokit.net/Pages/StereoKit/Mesh/GenerateRoundedCube.html>
554    /// * `dimension` - How large is this cube on each axis, in meters?
555    /// * `edge_radius` - Radius of the corner rounding, in meters.
556    /// * `subdivisions` -How many subdivisions should be used for creating the corners? A larger value results in
557    ///   smoother corners, but can decrease performance.! None is 4.
558    ///
559    /// Returns a cube mesh with rounded corners, pre-sized to the given dimensions
560    /// see also [`mesh_gen_rounded_cube`]
561    /// ### Examples
562    /// ```
563    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
564    /// use stereokit_rust::mesh::Mesh;
565    ///
566    /// // Create Meshes
567    /// let mesh = Mesh::generate_rounded_cube([1.0, 1.0, 1.0], 0.1, None);
568    /// assert_eq!(mesh.get_ind_count(), 900);
569    /// assert_eq!(mesh.get_vert_count(), 216);
570    ///
571    /// let mesh = Mesh::generate_rounded_cube([1.0, 1.0, 1.0], 0.1, Some(1));
572    /// assert_eq!(mesh.get_inds().len(), 324);
573    /// assert_eq!(mesh.get_verts().len(), 96);
574    ///
575    /// let mesh = Mesh::generate_rounded_cube([1.0, 1.0, 1.0], 0.2, Some(1));
576    /// assert_eq!(mesh.get_inds().len(), 324);
577    /// assert_eq!(mesh.get_verts().len(), 96);
578    /// ```
579    pub fn generate_rounded_cube(dimensions: impl Into<Vec3>, edge_radius: f32, subdivisions: Option<i32>) -> Mesh {
580        let subdivisions = subdivisions.unwrap_or(4);
581        Mesh(NonNull::new(unsafe { mesh_gen_rounded_cube(dimensions.into(), edge_radius, subdivisions) }).unwrap())
582    }
583
584    /// Generates a sphere mesh, pre-sized to the given diameter, created by sphereifying a subdivided cube! UV
585    /// coordinates are taken from the initial unspherified cube.
586    ///
587    /// NOTE: This generates a completely new Mesh asset on the GPU, and is best done during 'initialization' of your
588    /// app/scene. You may also be interested in using the pre-generated `Mesh::sphere()` asset if it already meets your
589    /// needs.
590    /// <https://stereokit.net/Pages/StereoKit/Mesh/GenerateSphere.html>
591    /// * `diameter` - The diameter of the sphere in meters, or 2*radius. This is the full length from one side to the other.
592    /// * `subdivisions` - How many times should the initial cube be subdivided? None is 4.
593    ///
594    /// Returns - A sphere mesh, pre-sized to the given diameter, created by sphereifying a subdivided cube! UV
595    /// coordinates are taken from the initial unspherified cube.
596    /// see also [`mesh_gen_sphere`]
597    /// ### Examples
598    /// ```
599    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
600    /// use stereokit_rust::mesh::Mesh;
601    ///
602    /// // Create Meshes
603    /// let mesh = Mesh::generate_sphere(1.0 , None);
604    /// assert_eq!(mesh.get_ind_count(), 900);
605    /// assert_eq!(mesh.get_vert_count(), 216);
606    ///
607    ///
608    /// let mesh = Mesh::generate_sphere(1.0 , Some(1));
609    /// assert_eq!(mesh.get_inds().len(), 144);
610    /// assert_eq!(mesh.get_verts().len(), 54);
611    /// ```
612    pub fn generate_sphere(diameter: f32, subdivisions: Option<i32>) -> Mesh {
613        let subdivisions = subdivisions.unwrap_or(4);
614        Mesh(NonNull::new(unsafe { mesh_gen_sphere(diameter, subdivisions) }).unwrap())
615    }
616
617    /// Generates a cylinder mesh, pre-sized to the given diameter and depth, UV coordinates are from a flattened top
618    /// view right now. Additional development is needed for making better UVs for the edges.
619    ///
620    /// NOTE: This generates a completely new Mesh asset on the GPU, and is best done during 'initialization' of your
621    /// app/scene.
622    /// <https://stereokit.net/Pages/StereoKit/Mesh/GenerateCylinder.html>
623    /// * `diameter` - Diameter of the circular part of the cylinder in meters. Diameter is 2*radius.
624    /// * `depth` - How tall is this cylinder, in meters?
625    /// * `direction` - What direction do the circular surfaces face? This is the surface normal for the top, it does not
626    ///   need to be normalized.
627    /// * `subdivisions` - How many vertices compose the edges of the cylinder? More is smoother, but less performant.
628    ///   None is 16.
629    ///
630    /// Returns a cylinder mesh, pre-sized to the given diameter and depth, UV coordinates are from a flattened top view
631    /// right now.
632    /// see also [`mesh_gen_cylinder`]
633    /// ### Examples
634    /// ```
635    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
636    /// use stereokit_rust::mesh::Mesh;
637    ///
638    /// // Create Meshes
639    /// let mesh = Mesh::generate_cylinder(1.0, 1.0, [0.0, 1.0, 0.0], None);
640    /// assert_eq!(mesh.get_ind_count(), 192);
641    /// assert_eq!(mesh.get_vert_count(), 70);
642    ///
643    /// let mesh = Mesh::generate_cylinder(1.0, 1.0, [0.0, 1.0, 0.0], Some(1));
644    /// assert_eq!(mesh.get_inds().len(), 12);
645    /// assert_eq!(mesh.get_verts().len(), 10);
646    /// ```
647    pub fn generate_cylinder(diameter: f32, depth: f32, direction: impl Into<Vec3>, subdivisions: Option<i32>) -> Mesh {
648        let subdivisions = subdivisions.unwrap_or(16);
649        Mesh(NonNull::new(unsafe { mesh_gen_cylinder(diameter, depth, direction.into(), subdivisions) }).unwrap())
650    }
651
652    /// Finds the Mesh with the matching id, and returns a reference to it. If no Mesh is found, it returns
653    /// StereoKitError::MeshFind.
654    /// <https://stereokit.net/Pages/StereoKit/Mesh/Find.html>
655    /// * `id` - The id of the Mesh to find.
656    ///
657    /// see also [`mesh_find`]
658    /// ### Examples
659    /// ```
660    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
661    /// use stereokit_rust::mesh::Mesh;
662    ///
663    /// // Create Meshes
664    /// let mut mesh = Mesh::generate_circle_up(1.0 , None, false);
665    /// mesh.id("my_circle");
666    ///
667    /// let same_mesh = Mesh::find("my_circle").expect("Mesh should be here");
668    ///
669    /// assert_eq!(mesh, same_mesh);
670    /// ```
671    pub fn find<S: AsRef<str>>(id: S) -> Result<Mesh, StereoKitError> {
672        let cstr = CString::new(id.as_ref())?;
673        match NonNull::new(unsafe { mesh_find(cstr.as_ptr()) }) {
674            Some(mesh) => Ok(Mesh(mesh)),
675            None => Err(StereoKitError::MeshFind(id.as_ref().to_owned())),
676        }
677    }
678
679    /// Creates a clone of the same reference. Basically, the new variable is the same asset. This is what you get by
680    /// calling find() method.
681    /// <https://stereokit.net/Pages/StereoKit/Mesh/Find.html>
682    ///
683    /// see also [`mesh_find()`]
684    /// ### Examples
685    /// ```
686    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
687    /// use stereokit_rust::mesh::Mesh;
688    ///
689    /// // Create Meshes
690    /// let mesh =          Mesh::generate_circle_up(1.0 , None, false);
691    /// let not_same_mesh = Mesh::generate_circle_up(1.0 , None, false);
692    ///
693    /// let same_mesh = mesh.clone_ref();
694    ///
695    /// assert_eq!(mesh, same_mesh);
696    /// assert_ne!(mesh, not_same_mesh);
697    /// ```
698    pub fn clone_ref(&self) -> Mesh {
699        Mesh(NonNull::new(unsafe { mesh_find(mesh_get_id(self.0.as_ptr())) }).expect("<asset>::clone_ref failed!"))
700    }
701
702    /// Sets the unique identifier of this asset resource! This can be helpful for debugging, managing your assets, or
703    /// finding them later on!
704    /// <https://stereokit.net/Pages/StereoKit/Mesh/Id.html>
705    /// * `id` - The unique identifier for this asset! Be sure it's unique!
706    ///
707    /// see also [`mesh_set_id`]
708    /// ### Examples
709    /// ```
710    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
711    /// use stereokit_rust::mesh::Mesh;
712    ///
713    /// // Create Meshes
714    /// let mut mesh = Mesh::generate_circle_up(1.0 , None, false);
715    /// assert!(mesh.get_id().starts_with("auto/mesh_"));
716    /// mesh.id("my_circle");
717    ///
718    /// assert_eq!(mesh.get_id(), "my_circle");
719    /// ```
720    pub fn id<S: AsRef<str>>(&mut self, id: S) -> &mut Self {
721        let cstr = CString::new(id.as_ref()).unwrap();
722        unsafe { mesh_set_id(self.0.as_ptr(), cstr.as_ptr()) };
723        self
724    }
725
726    /// This is a bounding box that encapsulates the Mesh! It's used for collision, visibility testing, UI layout, and
727    /// probably other things. While it's normally calculated from the mesh vertices, you can also override this to
728    /// suit your needs.
729    /// <https://stereokit.net/Pages/StereoKit/Mesh/Bounds.html>
730    /// * `bounds` - The bounding box to set.
731    ///
732    /// see also [`mesh_set_bounds`]
733    /// ### Examples
734    /// ```
735    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
736    /// use stereokit_rust::{maths::{Vec3, Matrix, Bounds},
737    ///                      mesh::Mesh, material::Material, util::named_colors};
738    ///
739    /// let mut sphere = Mesh::generate_sphere(1.0, None);
740    /// let material_sphere = Material::pbr();
741    /// let transform = Matrix::IDENTITY;
742    ///
743    /// let cube =   Mesh::cube();
744    /// let mut material_before = Material::ui_box();
745    /// material_before.color_tint(named_colors::GOLD)
746    ///                .border_size(0.025);
747    ///
748    /// let mut material_after = material_before.copy();
749    /// material_after.color_tint(named_colors::RED);
750    ///
751    /// let bounds = sphere.get_bounds();
752    /// let transform_before = Matrix::t_s( bounds.center, bounds.dimensions);
753    ///
754    /// sphere.bounds( Bounds::bounds_centered(Vec3::ONE * 0.7));
755    /// let new_bounds = sphere.get_bounds();
756    /// let transform_after = Matrix::t_s( new_bounds.center, new_bounds.dimensions);
757    ///
758    /// filename_scr = "screenshots/mesh_bounds.jpeg";
759    /// test_screenshot!( // !!!! Get a proper main loop !!!!
760    ///     sphere.draw(token, &material_sphere, transform, None, None);
761    ///     cube.draw(  token, &material_before, transform_before, None, None);
762    ///     cube.draw(  token, &material_after,  transform_after,  None, None);
763    /// );
764    /// ```
765    /// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/mesh_bounds.jpeg" alt="screenshot" width="200">
766    pub fn bounds(&mut self, bounds: impl AsRef<Bounds>) -> &mut Self {
767        unsafe { mesh_set_bounds(self.0.as_ptr(), bounds.as_ref() as *const Bounds) };
768        self
769    }
770
771    /// Should StereoKit keep the mesh data on the CPU for later access, or collision detection? Defaults to true. If you
772    /// set this to false before setting data, the data won't be stored. If you call this after setting data, that
773    /// stored data will be freed! If you set this to true again later on, it will not contain data until it's set again.
774    /// <https://stereokit.net/Pages/StereoKit/Mesh/KeepData.html>
775    ///
776    /// see also [`mesh_set_keep_data`]
777    /// ### Examples
778    /// ```
779    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
780    /// use stereokit_rust::{mesh::Mesh, maths::Bounds};
781    ///
782    /// // Create Meshes
783    /// let mut mesh = Mesh::generate_circle_up(1.0 , None, false);
784    /// assert_eq!(mesh.get_keep_data(), true);
785    /// assert_ne!(mesh.get_bounds(), Bounds::default());
786    ///
787    /// mesh.keep_data(false);
788    /// assert_eq!(mesh.get_keep_data(), false);
789    /// mesh.keep_data(true);
790    /// assert_eq!(mesh.get_keep_data(), true);
791    /// ```
792    pub fn keep_data(&mut self, keep_data: bool) -> &mut Self {
793        unsafe { mesh_set_keep_data(self.0.as_ptr(), keep_data as Bool32T) };
794        self
795    }
796
797    /// Assigns the vertices and indices for this Mesh! This will create a vertex buffer and index buffer object on the
798    /// graphics card. If you're calling this a second time, the buffers will be marked as dynamic and re-allocated. If
799    /// you're calling this a third time, the buffer will only re-allocate if the buffer is too small, otherwise it just
800    /// copies in the data!
801    ///
802    /// Remember to set all the relevant values! Your material will often show black if the Normals or Colors are left
803    /// at their default values.
804    ///
805    /// Calling SetData is slightly more efficient than calling SetVerts and SetInds separately.
806    /// <https://stereokit.net/Pages/StereoKit/Mesh/SetData.html>
807    /// * `vertices` - An array of vertices to add to the mesh. Remember to set all the relevant values! Your material
808    ///   will often show black if the Normals or Colors are left at their default values.
809    /// * `indices` - A list of face indices, must be a multiple of 3. Each index represents a vertex from the provided
810    ///   vertex array.
811    /// * `calculate_bounds` - If true, this will also update the Mesh's bounds based on the vertices provided. Since this
812    ///   does require iterating through all the verts with some logic, there is performance cost to doing this. If
813    ///   you're updating a mesh frequently or need all the performance you can get, setting this to false is a nice way
814    ///   to gain some speed!
815    ///
816    /// see also [`mesh_set_data`]
817    /// see example[`Vertex`]
818    pub fn set_data(&mut self, vertices: &[Vertex], indices: &[u32], calculate_bounds: bool) -> &mut Self {
819        unsafe {
820            mesh_set_data(
821                self.0.as_ptr(),
822                vertices.as_ptr(),
823                vertices.len() as i32,
824                indices.as_ptr(),
825                indices.len() as i32,
826                calculate_bounds as Bool32T,
827            )
828        };
829        self
830    }
831
832    /// Assigns the vertices for this Mesh! This will create a vertex buffer object on the graphics card. If you're
833    /// calling this a second time, the buffer will be marked as dynamic and re-allocated. If you're calling this a
834    /// third time, the buffer will only re-allocate if the buffer is too small, otherwise it just copies in the data!
835    ///
836    /// Remember to set all the relevant values! Your material will often show black if the Normals or Colors are left
837    /// at their default values.
838    /// <https://stereokit.net/Pages/StereoKit/Mesh/SetVerts.html>
839    /// * `vertices` - An array of vertices to add to the mesh. Remember to set all the relevant values! Your material
840    ///   will often show black if the Normals or Colors are left at their default values.
841    /// * `calculate_bounds` - If true, this will also update the Mesh's bounds based on the vertices provided. Since this
842    ///   does require iterating through all the verts with some logic, there is performance cost to doing this. If
843    ///   you're updating a mesh frequently or need all the performance you can get, setting this to false is a nice way
844    ///   to gain some speed!
845    ///
846    /// see also [`mesh_set_verts`] [`Vertex`] [`Mesh::set_data`]
847    /// ### Examples
848    /// ```
849    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
850    /// use stereokit_rust::{maths::{Vec2, Vec3, Matrix, Bounds}, mesh::{Mesh, Vertex},
851    ///                      material::Material, util::named_colors};
852    ///
853    /// let material = Material::pbr();
854    /// let mut square = Mesh::new();
855    /// square.set_verts(&[
856    ///     Vertex::new([-1.0, -1.0, 0.0].into(), Vec3::UP, None,            Some(named_colors::BLUE)),
857    ///     Vertex::new([ 1.0, -1.0, 0.0].into(), Vec3::UP, Some(Vec2::X),   None),
858    ///     Vertex::new([-1.0,  1.0, 0.0].into(), Vec3::UP, Some(Vec2::Y),   None),
859    ///     Vertex::new([ 1.0,  1.0, 0.0].into(), Vec3::UP, Some(Vec2::ONE), Some(named_colors::YELLOW)),
860    ///     ], true)
861    ///    .set_inds(&[0, 1, 2, 2, 1, 3]);
862    ///
863    /// filename_scr = "screenshots/mesh_set_verts.jpeg";
864    /// test_screenshot!( // !!!! Get a proper main loop !!!!
865    ///     square.draw(token, &material , Matrix::IDENTITY, None, None);
866    /// );
867    /// ```
868    /// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/mesh_set_verts.jpeg" alt="screenshot" width="200">
869    pub fn set_verts(&mut self, vertices: &[Vertex], calculate_bounds: bool) -> &mut Self {
870        unsafe {
871            mesh_set_verts(self.0.as_ptr(), vertices.as_ptr(), vertices.len() as i32, calculate_bounds as Bool32T)
872        };
873        self
874    }
875
876    /// Assigns the face indices for this Mesh! Faces are always triangles, there are only ever three indices per face.
877    /// This function will create a index buffer object on the graphics card. If you're calling this a second time, the
878    /// buffer will be marked as dynamic and re-allocated. If you're calling this a third time, the buffer will only
879    /// re-allocate if the buffer is too small, otherwise it just copies in the data!
880    /// <https://stereokit.net/Pages/StereoKit/Mesh/SetInds.html>
881    /// * `indices` - A list of face indices, must be a multiple of 3. Each index represents a vertex from the array
882    ///   assigned using SetVerts.
883    ///
884    /// see also [`mesh_set_inds`] [`Vertex`] [`Mesh::set_data`]
885    /// ### Examples
886    /// ```
887    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
888    /// use stereokit_rust::{maths::{Vec2, Vec3, Matrix, Bounds}, mesh::{Mesh, Vertex},
889    ///                      material::Material, util::named_colors};
890    ///
891    /// let material = Material::pbr();
892    /// let mut sphere = Mesh::generate_sphere(1.5, Some(16));
893    ///
894    /// // Let's remove half of the triangles.
895    /// let indices = sphere.get_inds();
896    /// let mut new_indices = vec![];
897    /// let mut iter = 0;
898    /// for i in 0..indices.len() {
899    ///     if iter < 3 {   
900    ///        new_indices.push(indices[i]);
901    ///     } else if iter == 5 {
902    ///        iter = -1;
903    ///     }
904    ///    iter += 1;
905    /// }
906    ///
907    /// sphere.set_inds(&new_indices);
908    ///
909    /// filename_scr = "screenshots/mesh_set_inds.jpeg";
910    /// test_screenshot!( // !!!! Get a proper main loop !!!!
911    ///     sphere.draw(token, &material , Matrix::IDENTITY,  Some(named_colors::PINK.into()), None);
912    /// );
913    /// ```
914    /// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/mesh_set_inds.jpeg" alt="screenshot" width="200">
915    pub fn set_inds(&mut self, indices: &[u32]) -> &mut Self {
916        unsafe { mesh_set_inds(self.0.as_ptr(), indices.as_ptr(), indices.len() as i32) };
917        self
918    }
919
920    /// Adds a mesh to the render queue for this frame! If the Hierarchy has a transform on it, that transform is
921    /// combined with the Matrix provided here.
922    /// <https://stereokit.net/Pages/StereoKit/Mesh/Draw.html>
923    /// * `material` - A Material to apply to the Mesh.
924    /// * `transform` - A Matrix that will transform the mesh from Model Space into the current Hierarchy Space.
925    /// * `color_linear` - A per-instance linear space color value to pass into the shader! Normally this gets used like a
926    ///   material tint. If you're  adventurous and don't need per-instance colors, this is a great spot to pack in
927    ///   extra per-instance data for the shader! If None has default value of WHITE
928    /// * `layer` - All visuals are rendered using a layer bit-flag. By default, all layers are rendered, but this can be
929    ///   useful for filtering out objects for different rendering purposes! For example: rendering a mesh over the
930    ///   user's head from a 3rd person perspective, but filtering it out from the 1st person perspective.If None has
931    ///   default value of Layer0
932    ///
933    /// see also [`mesh_draw`]
934    /// ### Examples
935    /// ```
936    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
937    /// use stereokit_rust::{maths::{Vec2, Vec3, Matrix, Bounds}, mesh::{Mesh, Vertex},
938    ///                      material::Material, util::named_colors, system::RenderLayer};
939    ///
940    /// let material = Material::pbr();
941    /// let cylinder1 = Mesh::generate_cylinder(0.25, 1.5, Vec3::ONE,        None);
942    /// let cylinder2 = Mesh::generate_cylinder(0.25, 1.5, [-0.5, 0.5, 0.5], None);
943    /// let cylinder3 = Mesh::generate_cylinder(0.25, 1.2, [0.0, -0.5, 0.5], None);
944    ///
945    /// filename_scr = "screenshots/mesh_draw.jpeg";
946    /// test_screenshot!( // !!!! Get a proper main loop !!!!
947    ///     cylinder1.draw(token, &material , Matrix::IDENTITY, None, None);
948    ///     cylinder2.draw(token, &material , Matrix::IDENTITY, Some(named_colors::RED.into()),
949    ///         Some(RenderLayer::Layer1));
950    ///     cylinder3.draw(token, &material , Matrix::IDENTITY, Some(named_colors::GREEN.into()),
951    ///         Some(RenderLayer::ThirdPerson));
952    /// );
953    /// ```
954    /// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/mesh_draw.jpeg" alt="screenshot" width="200">
955    pub fn draw(
956        &self,
957        _token: &MainThreadToken,
958        material: impl AsRef<Material>,
959        transform: impl Into<Matrix>,
960        color_linear: Option<Color128>,
961        layer: Option<RenderLayer>,
962    ) {
963        let color_linear: Color128 = color_linear.unwrap_or(Color128::WHITE);
964        let layer = layer.unwrap_or(RenderLayer::Layer0);
965        unsafe { mesh_draw(self.0.as_ptr(), material.as_ref().0.as_ptr(), transform.into(), color_linear, layer) }
966    }
967
968    /// Gets the unique identifier of this asset resource! This can be helpful for debugging, managing your assets, or
969    /// finding them later on!
970    /// <https://stereokit.net/Pages/StereoKit/Mesh/id.html>
971    ///
972    /// see also [`mesh_get_id`]
973    /// see example in [`Mesh::id`]
974    pub fn get_id(&self) -> &str {
975        unsafe { CStr::from_ptr(mesh_get_id(self.0.as_ptr())) }.to_str().unwrap()
976    }
977    /// This is a bounding box that encapsulates the Mesh! It's used for collision, visibility testing, UI layout, and
978    /// probably  other things. While it's normally calculated from the mesh vertices, you can also override this to
979    /// suit your needs.
980    /// <https://stereokit.net/Pages/StereoKit/Mesh/Bounds.html>
981    ///
982    /// see also [`mesh_get_bounds`]
983    /// see example in [`Mesh::bounds`]
984    pub fn get_bounds(&self) -> Bounds {
985        unsafe { mesh_get_bounds(self.0.as_ptr()) }
986    }
987
988    /// Should StereoKit keep the mesh data on the CPU for later access, or collision detection? Defaults to true. If you
989    /// set this to false before setting data, the data won't be stored. If you call this after setting data, that
990    /// stored data will be freed! If you set this to true again later on, it will not contain data until it's set again.
991    /// <https://stereokit.net/Pages/StereoKit/Mesh/KeepData.html>
992    ///
993    /// see also [`mesh_get_keep_data`]
994    /// see example in [`Mesh::keep_data`]
995    pub fn get_keep_data(&self) -> bool {
996        unsafe { mesh_get_keep_data(self.0.as_ptr()) != 0 }
997    }
998
999    /// Get the number of indices stored in this Mesh! This is available to you regardless of whether or not keep_data
1000    /// is set.
1001    /// <https://stereokit.net/Pages/StereoKit/Mesh/IndCount.html>
1002    ///
1003    /// see also [`mesh_get_ind_count`]
1004    pub fn get_ind_count(&self) -> i32 {
1005        unsafe { mesh_get_ind_count(self.0.as_ptr()) }
1006    }
1007
1008    /// Get the number of vertices stored in this Mesh! This is available to you regardless of whether or not keep_data
1009    /// is set.
1010    /// <https://stereokit.net/Pages/StereoKit/Mesh/VertCount.html>
1011    ///
1012    /// see also [`mesh_get_vert_count`]
1013    pub fn get_vert_count(&self) -> i32 {
1014        unsafe { mesh_get_vert_count(self.0.as_ptr()) }
1015    }
1016
1017    /// This marshalls the Mesh's index data into an array. If keep_data is false, then the Mesh is **not** storing
1018    /// indices on the CPU, and this information will **not** be available.
1019    ///
1020    /// Due to the way marshalling works, this is **not** a cheap function!
1021    /// <https://stereokit.net/Pages/StereoKit/Mesh/GetInds.html>
1022    /// Returns - An array of indices representing the Mesh, or null if keep_data is false.
1023    ///
1024    /// see also [Mesh::get_inds_copy] [`mesh_get_inds`]
1025    /// see example in [`Mesh::set_inds`]
1026    pub fn get_inds(&self) -> &[u32] {
1027        let inds_ptr = CString::new("H").unwrap().into_raw() as *mut *mut u32;
1028        let mut inds_len = 0;
1029        unsafe {
1030            mesh_get_inds(self.0.as_ptr(), inds_ptr, &mut inds_len, Memory::Reference);
1031            &mut *slice_from_raw_parts_mut(*inds_ptr, inds_len as usize)
1032        }
1033    }
1034
1035    /// Get the indices by value
1036    /// This marshalls the Mesh's index data into an array. If keep_data is false, then the Mesh is **not** storing
1037    /// indices on the CPU, and this information will **not** be available.
1038    ///
1039    /// Due to the way marshalling works, this is **not** a cheap function!
1040    /// <https://stereokit.net/Pages/StereoKit/Mesh/GetInds.html>
1041    ///
1042    /// see also [Mesh::get_inds] [`mesh_get_inds`]
1043    pub fn get_inds_copy(&self) -> Vec<u32> {
1044        self.get_inds().to_vec()
1045    }
1046
1047    /// This marshalls the Mesh's vertex data into an array. If keep_data is false, then the Mesh is **not** storing
1048    /// verts
1049    /// on the CPU, and this information will **not** be available.
1050    ///
1051    /// Due to the way marshalling works, this is **not** a cheap function!
1052    /// <https://stereokit.net/Pages/StereoKit/Mesh/GetVerts.html>
1053    ///
1054    /// see also [Mesh::get_verts_copy] [`mesh_get_verts`]
1055    /// see example in [`Mesh::set_verts`]
1056    pub fn get_verts(&self) -> &[Vertex] {
1057        let verts_pointer = CString::new("H").unwrap().into_raw() as *mut *mut Vertex;
1058        let mut verts_len = 0;
1059        unsafe {
1060            mesh_get_verts(self.0.as_ptr(), verts_pointer, &mut verts_len, Memory::Reference);
1061            &mut *slice_from_raw_parts_mut(*verts_pointer, verts_len as usize)
1062        }
1063    }
1064
1065    /// Get the vertices by value
1066    /// This marshalls the Mesh's vertex data into an array. If keep_data is false, then the Mesh is **not** storing
1067    /// verts
1068    /// on the CPU, and this information will **not** be available.
1069    ///
1070    /// Due to the way marshalling works, this is **not** a cheap function!
1071    /// <https://stereokit.net/Pages/StereoKit/Mesh/GetVerts.html>
1072    ///
1073    /// see also [Mesh::get_verts] [`mesh_get_verts`]
1074    pub fn get_verts_copy(&self) -> Vec<Vertex> {
1075        self.get_verts().to_vec()
1076    }
1077
1078    /// Retrieves the vertices associated with a particular triangle on the Mesh.
1079    /// <https://stereokit.net/Pages/StereoKit/Mesh/GetTriangle.html>
1080    /// * `triangle_index` - Starting index of the triangle, should be a multiple of 3.
1081    ///
1082    /// Returns an array of 3 vertices if triangle index was valid.
1083    /// see also [`mesh_get_triangle`]
1084    /// ### Examples
1085    /// ```
1086    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
1087    /// use stereokit_rust::{maths::{Vec2, Vec3, Matrix, Bounds}, mesh::{Mesh, Vertex},
1088    ///                      material::Material, util::named_colors, system::RenderLayer};
1089    ///
1090    /// let material = Material::pbr();
1091    /// let plane = Mesh::generate_plane_up(Vec2::ONE, None, false);
1092    /// assert_eq!(plane.get_vert_count(), 4, "plane should have 4 vertices");
1093    /// assert_eq!(plane.get_ind_count(), 6, "plane should have 6 indices");
1094    ///
1095    /// let triangle0 = plane.get_triangle(0 * 3).expect("triangle 0 should exist");    
1096    /// let triangle1 = plane.get_triangle(1 * 3).expect("triangle 1 should exist");
1097    /// //assert!(plane.get_triangle(5).is_some(), "triangle 5 should exist");
1098    /// assert!(plane.get_triangle(2 * 3).is_none(), "triangle 6 should not exist");
1099    ///
1100    /// let vertices0 = [
1101    ///    Vertex::new([ 0.5, 0.0, 0.5].into(),Vec3::UP,Some(Vec2::ONE) , None),
1102    ///    Vertex::new([ 0.5, 0.0,-0.5].into(),Vec3::UP,Some(Vec2::X)   , None),
1103    ///    Vertex::new([-0.5, 0.0,-0.5].into(),Vec3::UP,Some(Vec2::ZERO), None),
1104    ///    ];
1105    /// assert_eq!(triangle0, vertices0);
1106    ///
1107    /// let vertices1 = [
1108    ///    Vertex::new([-0.5, 0.0, 0.5].into(),Vec3::UP,Some(Vec2::Y)   , None),
1109    ///    Vertex::new([ 0.5, 0.0, 0.5].into(),Vec3::UP,Some(Vec2::ONE) , None),
1110    ///    Vertex::new([-0.5, 0.0,-0.5].into(),Vec3::UP,Some(Vec2::ZERO), None),
1111    ///    ];
1112    /// assert_eq!(triangle1, vertices1);
1113    /// ```
1114    pub fn get_triangle(&self, triangle_index: u32) -> Option<[Vertex; 3]> {
1115        let mut v_a = Vertex::default();
1116        let mut v_b = Vertex::default();
1117        let mut v_c = Vertex::default();
1118        let out_a: *mut Vertex = &mut v_a;
1119        let out_b: *mut Vertex = &mut v_b;
1120        let out_c: *mut Vertex = &mut v_c;
1121        unsafe {
1122            match mesh_get_triangle(self.0.as_ptr(), triangle_index, out_a, out_b, out_c) != 0 {
1123                true => Some([v_a, v_b, v_c]),
1124                false => None,
1125            }
1126        }
1127    }
1128
1129    /// Checks the intersection point of a ray and this Mesh with collision data stored on the CPU. A mesh without
1130    /// collision data will always return None. Ray must be in model space, intersection point will be in model
1131    /// space too. You can use the inverse of the mesh’s world transform matrix to bring the ray into model space,
1132    /// see the example in the docs!
1133    /// <https://stereokit.net/Pages/StereoKit/Mesh/Intersect.html>
1134    /// * `model_space_ray` - Ray must be in model space, the intersection point will be in model space too. You can use the
1135    ///   inverse of the mesh's world transform matrix to bring the ray into model space, see the example in the docs!
1136    /// * `cull` - If None has default value of Cull::Back.
1137    ///
1138    /// Returns a tuple with
1139    /// - The intersection point of the ray and the mesh, if an intersection  occurs. This is in model space, and must
1140    ///   be transformed back into world space later.
1141    /// - The indice of the mesh where the intersection occurs.
1142    ///
1143    /// see also [`mesh_ray_intersect`] [`Ray::intersect_mesh`]
1144    /// ### Examples
1145    /// ```
1146    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
1147    /// use stereokit_rust::{maths::{Vec3, Matrix, Quat, Ray}, system::Lines,
1148    ///     util::{named_colors}, mesh::Mesh, material::{Material, Cull}};
1149    ///
1150    /// // Create Meshes
1151    /// let cube = Mesh::generate_cube(Vec3::ONE * 0.8, None);
1152    /// let sphere = Mesh::generate_sphere(1.0, Some(4));
1153    ///
1154    /// let material = Material::pbr().copy();
1155    /// let transform = Matrix::r(Quat::from_angles(40.0, 50.0, 20.0));
1156    /// let inv = transform.get_inverse();
1157    ///
1158    /// let ray = Ray::new([-1.0, 2.0, 2.5 ], [1.0, -2.0, -2.25]);
1159    /// let inv_ray = inv.transform_ray(ray);
1160    ///
1161    /// let (contact_cube, ind_cube) = cube.intersect( inv_ray, Some(Cull::Back))
1162    ///     .expect("Ray should touch cube");
1163    /// assert_eq!(ind_cube, 12);
1164    ///
1165    /// let transform_contact_cube = Matrix::t_s(
1166    ///     transform.transform_point(contact_cube), Vec3::ONE * 0.1);
1167    ///
1168    /// filename_scr = "screenshots/mesh_intersect.jpeg";
1169    /// test_screenshot!( // !!!! Get a proper main loop !!!!
1170    ///     cube.draw(token, &material, transform, Some(named_colors::CYAN.into()), None);
1171    ///     Lines::add_ray(token, ray, 2.2, named_colors::WHITE, None, 0.02);
1172    ///     sphere.draw(token, &material, transform_contact_cube, Some(named_colors::YELLOW.into()), None );
1173    /// );
1174    /// ```
1175    /// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/mesh_intersect.jpeg" alt="screenshot" width="200">
1176    #[inline]
1177    pub fn intersect(&self, model_space_ray: Ray, cull: Option<Cull>) -> Option<(Vec3, VindT)> {
1178        model_space_ray.intersect_mesh(self, cull)
1179    }
1180
1181    /// Checks the intersection point of a Ray and this Mesh with collision data stored on the CPU. A mesh without
1182    /// collision data will always return false. Ray must be in model space, intersection point will be in model
1183    /// space too. You can use the inverse of the mesh’s world transform matrix to bring the ray into model space,
1184    /// see the example in the docs!
1185    /// <https://stereokit.net/Pages/StereoKit/Mesh/Intersect.html>
1186    /// * `model_space_ray` - Ray must be in model space, the intersection point will be in model space too. You can use the
1187    ///   inverse of the mesh's world transform matrix to bring the ray into model space, see the example in the docs!
1188    /// * `cull` - If None has default value of Cull::Back.
1189    /// * `out_model_space_ray` -The intersection point and surface direction of the ray and the mesh, if an intersection
1190    ///   occurs. This is in model space, and must be transformed back into world space later. Direction is not
1191    ///   guaranteed to be normalized, especially if your own model->world transform contains scale/skew in it.
1192    /// * `out_start_inds` - The index of the first index of the triangle that was hit
1193    ///
1194    /// Returns true if an intersection occurs.
1195    /// see also [`mesh_ray_intersect`] [`Ray::intersect_mesh`] [`Mesh::intersect`]
1196    /// ### Examples
1197    /// ```
1198    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
1199    /// use stereokit_rust::{maths::{Vec3, Matrix, Quat, Ray}, system::Lines,
1200    ///     util::{named_colors}, mesh::Mesh, material::{Material, Cull}};
1201    ///
1202    /// // Create Meshes
1203    /// let cube = Mesh::generate_cube(Vec3::ONE * 0.8, None);
1204    /// let sphere = Mesh::generate_sphere(1.0, Some(4));
1205    ///
1206    /// let material = Material::pbr().copy();
1207    /// let transform = Matrix::r(Quat::from_angles(40.0, 50.0, 20.0));
1208    /// let inv = transform.get_inverse();
1209    ///
1210    /// let ray = Ray::new([-3.0, 2.0, 0.5 ], [3.0, -2.0, -0.25]);
1211    /// let inv_ray = inv.transform_ray(ray);
1212    ///
1213    /// let (mut contact_sphere_ray, mut ind_sphere) = (Ray::default(), 0u32);
1214    /// assert!(sphere.intersect_to_ptr(inv_ray, Some(Cull::Front),
1215    ///             &mut contact_sphere_ray, &mut ind_sphere)
1216    ///     ,"Ray should touch sphere");
1217    ///
1218    /// let (mut contact_cube_ray, mut ind_cube) = (Ray::default(), 0u32);
1219    /// assert!( cube.intersect_to_ptr(
1220    ///             inv_ray, Some(Cull::Back),
1221    ///             &mut contact_cube_ray, &mut ind_cube)
1222    ///     ,"Ray should touch cube");
1223    ///
1224    /// assert_eq!(ind_sphere, 672);
1225    /// assert_eq!(ind_cube, 9);
1226    ///
1227    /// assert_eq!(transform.transform_ray(contact_sphere_ray),
1228    ///         Ray { position:  Vec3 { x: 0.36746234, y: -0.244975, z: 0.21937825 },
1229    ///               direction: Vec3 { x: 0.58682406, y: -0.6427875, z: 0.49240398 }});
1230    /// assert_eq!(transform.transform_ray(contact_cube_ray),
1231    ///         Ray { position:  Vec3 { x: -0.39531866, y: 0.26354572, z: 0.2829433 },
1232    ///               direction: Vec3 { x: -0.77243483, y: -0.2620026, z: 0.57853174 } });
1233    /// ```
1234    #[inline]
1235    #[allow(clippy::not_unsafe_ptr_arg_deref)]
1236    pub fn intersect_to_ptr(
1237        &self,
1238        ray: Ray,
1239        cull: Option<Cull>,
1240        out_model_space_ray: *mut Ray,
1241        out_start_inds: *mut u32,
1242    ) -> bool {
1243        ray.intersect_mesh_to_ptr(self, cull, out_model_space_ray, out_start_inds)
1244    }
1245
1246    /// A cube with dimensions of (1,1,1), this is equivalent to Mesh.GenerateCube(Vec3.One).
1247    /// <https://stereokit.net/Pages/StereoKit/Mesh/Cube.html>
1248    ///
1249    /// ### Examples
1250    /// ```
1251    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
1252    /// use stereokit_rust::mesh::Mesh;
1253    ///
1254    /// // Get the mesh
1255    /// let mesh = Mesh::cube();
1256    /// assert_eq!(mesh.get_id(), "default/mesh_cube");
1257    /// ```
1258    pub fn cube() -> Self {
1259        Mesh::find("default/mesh_cube").unwrap()
1260    }
1261
1262    /// A default quad mesh, 2 triangles, 4 verts, from (-0.5,-0.5,0) to (0.5,0.5,0) and facing forward on the Z axis
1263    /// (0,0,-1). White vertex colors, and UVs from (1,1) at vertex (-0.5,-0.5,0) to (0,0) at vertex (0.5,0.5,0).
1264    /// <https://stereokit.net/Pages/StereoKit/Mesh/Quad.html>
1265    ///
1266    /// ### Examples
1267    /// ```
1268    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
1269    /// use stereokit_rust::mesh::Mesh;
1270    ///
1271    /// // Get the mesh
1272    /// let mesh = Mesh::screen_quad();
1273    /// assert_eq!(mesh.get_id(), "default/mesh_screen_quad");
1274    /// ```
1275    pub fn screen_quad() -> Self {
1276        Mesh::find("default/mesh_screen_quad").unwrap()
1277    }
1278
1279    // see screen_quad instead ! TODO: Why this ?
1280    // <https://stereokit.net/Pages/StereoKit/Mesh/Quad.html>
1281    // pub fn quad() -> Self {
1282    //     Mesh::find("default/mesh_quad").unwrap()
1283    // }
1284
1285    /// A sphere mesh with a diameter of 1. This is equivalent to Mesh.GenerateSphere(1,4).
1286    /// <https://stereokit.net/Pages/StereoKit/Mesh/Sphere.html>
1287    ///
1288    /// ### Examples
1289    /// ```
1290    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
1291    /// use stereokit_rust::mesh::Mesh;
1292    ///
1293    /// // Get the mesh
1294    /// let mesh = Mesh::sphere();
1295    /// assert_eq!(mesh.get_id(), "default/mesh_sphere");
1296    /// ```
1297    pub fn sphere() -> Self {
1298        Mesh::find("default/mesh_sphere").unwrap()
1299    }
1300
1301    /// A clone mesh of the left hand
1302    /// <https://stereokit.net/Pages/StereoKit/Mesh.html>
1303    ///
1304    /// ### Examples
1305    /// ```
1306    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
1307    /// use stereokit_rust::mesh::Mesh;
1308    ///
1309    /// // Get the mesh
1310    /// let mesh = Mesh::left_hand();
1311    /// assert_eq!(mesh.get_id(), "default/mesh_lefthand");
1312    /// ```
1313    /// <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/left_hand.jpeg" alt="screenshot" width="200">
1314    pub fn left_hand() -> Self {
1315        Mesh::find("default/mesh_lefthand").unwrap()
1316    }
1317
1318    /// A clone mesh of the right hand
1319    /// <https://stereokit.net/Pages/StereoKit/Mesh.html>
1320    ///
1321    /// ### Examples
1322    /// ```
1323    /// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
1324    /// use stereokit_rust::mesh::Mesh;
1325    ///
1326    /// // Get the mesh
1327    /// let mesh = Mesh::right_hand();
1328    /// assert_eq!(mesh.get_id(), "default/mesh_righthand");
1329    /// ```
1330    pub fn right_hand() -> Self {
1331        Mesh::find("default/mesh_righthand").unwrap()
1332    }
1333}