re_types/archetypes/
mesh3d_ext.rs1use arrow::array::{self, Array as _};
2
3use crate::{
4 archetypes,
5 components::{self},
6};
7
8use super::Mesh3D;
9
10#[derive(thiserror::Error, Debug)]
11pub enum Mesh3DError {
12 #[error(
13 "No indices were specified, so the number of positions must be divisible by 9 [(xyz xyz xyz), …], got {0}"
14 )]
15 PositionsAreNotTriangles(usize),
16
17 #[error("Index out of bounds: got index={index} with {num_vertices} vertices")]
18 IndexOutOfBounds { index: u32, num_vertices: usize },
19
20 #[error(
21 "Positions & normals array must have the same length, \
22 got positions={0} vs. normals={1}"
23 )]
24 MismatchedPositionsNormals(usize, usize),
25}
26
27impl Mesh3D {
28 #[inline]
30 pub fn with_albedo_texture_image(mut self, image: impl Into<archetypes::Image>) -> Self {
31 let image = image.into();
32
33 self.albedo_texture_format = image
34 .format
35 .map(|batch| batch.with_descriptor_override(Self::descriptor_albedo_texture_format()));
36 self.albedo_texture_buffer = image
37 .buffer
38 .map(|batch| batch.with_descriptor_override(Self::descriptor_albedo_texture_buffer()));
39 self
40 }
41
42 #[inline]
44 pub fn with_albedo_texture(
45 self,
46 image_format: impl Into<components::ImageFormat>,
47 image_buffer: impl Into<components::ImageBuffer>,
48 ) -> Self {
49 self.with_albedo_texture_format(image_format)
50 .with_albedo_texture_buffer(image_buffer)
51 }
52
53 #[track_caller]
58 pub fn sanity_check(&self) -> Result<(), Mesh3DError> {
59 let num_vertices = self.num_vertices();
60
61 let index_data = self.triangle_indices.as_ref().map(|indices| {
62 array::as_fixed_size_list_array(&indices.array)
63 .values()
64 .to_data()
65 });
66
67 if let Some(index_data) = index_data {
68 for index in index_data.buffer::<u32>(0) {
69 if num_vertices <= *index as usize {
70 return Err(Mesh3DError::IndexOutOfBounds {
71 index: *index,
72 num_vertices,
73 });
74 }
75 }
76 } else if !num_vertices.is_multiple_of(9) {
77 return Err(Mesh3DError::PositionsAreNotTriangles(num_vertices));
78 }
79
80 if let Some(normals) = &self.vertex_normals
81 && normals.array.len() != num_vertices
82 {
83 return Err(Mesh3DError::MismatchedPositionsNormals(
84 num_vertices,
85 normals.array.len(),
86 ));
87 }
88
89 Ok(())
90 }
91
92 #[inline]
94 pub fn num_vertices(&self) -> usize {
95 self.vertex_positions
96 .as_ref()
97 .map_or(0, |positions| positions.array.len())
98 }
99
100 #[inline]
102 pub fn num_triangles(&self) -> usize {
103 if let Some(triangle_indices) = self.triangle_indices.as_ref() {
104 triangle_indices.array.len()
105 } else {
106 self.num_vertices() / 3
107 }
108 }
109}