Skip to main content

three_d_asset/
geometry.rs

1//!
2//! Contain geometry asset definitions.
3//!
4
5mod point_cloud;
6pub use point_cloud::*;
7
8mod tri_mesh;
9pub use tri_mesh::*;
10
11pub use crate::prelude::*;
12
13///
14/// A CPU-side version of a geometry.
15///
16#[derive(Debug, Clone)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18pub enum Geometry {
19    /// Points geometry
20    Points(PointCloud),
21    /// Triangle geometry
22    Triangles(TriMesh),
23}
24
25impl Geometry {
26    ///
27    /// Computes normals if it is relevant for the geometry.
28    ///
29    pub fn compute_normals(&mut self) {
30        if let Self::Triangles(mesh) = self {
31            mesh.compute_normals()
32        }
33    }
34
35    ///
36    /// Computes tangents if it is relevant for the geometry.
37    ///
38    pub fn compute_tangents(&mut self) {
39        if let Self::Triangles(mesh) = self {
40            mesh.compute_tangents()
41        }
42    }
43
44    ///
45    /// Computes the [AxisAlignedBoundingBox] for this geometry.
46    ///
47    pub fn compute_aabb(&self) -> AxisAlignedBoundingBox {
48        match self {
49            Self::Triangles(mesh) => mesh.compute_aabb(),
50            Self::Points(point_cloud) => point_cloud.compute_aabb(),
51        }
52    }
53}
54
55///
56/// An array of indices. Supports different data types.
57///
58#[derive(Clone, Debug, Default)]
59#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
60pub enum Indices {
61    /// Do not use indices, ie. the faces are all unconnected.
62    #[default]
63    None,
64    /// Uses unsigned 8 bit integer for each index.
65    U8(Vec<u8>),
66    /// Uses unsigned 16 bit integer for each index.
67    U16(Vec<u16>),
68    /// Uses unsigned 32 bit integer for each index.
69    U32(Vec<u32>),
70}
71
72impl Indices {
73    ///
74    /// Converts all the indices as `u32` data type.
75    ///
76    pub fn into_u32(self) -> Option<Vec<u32>> {
77        match self {
78            Self::None => None,
79            Self::U8(mut values) => Some(values.drain(..).map(|i| i as u32).collect::<Vec<_>>()),
80            Self::U16(mut values) => Some(values.drain(..).map(|i| i as u32).collect::<Vec<_>>()),
81            Self::U32(values) => Some(values),
82        }
83    }
84
85    ///
86    /// Clones and converts all the indices as `u32` data type.
87    ///
88    pub fn to_u32(&self) -> Option<Vec<u32>> {
89        match self {
90            Self::None => None,
91            Self::U8(values) => Some(values.iter().map(|i| *i as u32).collect::<Vec<_>>()),
92            Self::U16(values) => Some(values.iter().map(|i| *i as u32).collect::<Vec<_>>()),
93            Self::U32(values) => Some(values.clone()),
94        }
95    }
96
97    ///
98    /// Returns the number of indices.
99    ///
100    pub fn len(&self) -> Option<usize> {
101        match self {
102            Self::None => None,
103            Self::U8(values) => Some(values.len()),
104            Self::U16(values) => Some(values.len()),
105            Self::U32(values) => Some(values.len()),
106        }
107    }
108
109    ///
110    /// Returns whether the set of indices is empty.
111    ///
112    pub fn is_empty(&self) -> bool {
113        self.len().map(|i| i == 0).unwrap_or(true)
114    }
115}
116
117///
118/// An array of positions. Supports f32 and f64 data types.
119///
120#[derive(Clone)]
121#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
122pub enum Positions {
123    /// Uses 32 bit float for the vertex positions.
124    F32(Vec<Vec3>),
125    /// Uses 64 bit float for the vertex positions.
126    F64(Vec<Vector3<f64>>),
127}
128
129impl Positions {
130    ///
131    /// Converts and returns all the positions as `f32` data type.
132    ///
133    pub fn into_f32(self) -> Vec<Vec3> {
134        match self {
135            Self::F32(values) => values,
136            Self::F64(mut values) => values
137                .drain(..)
138                .map(|v| Vec3::new(v.x as f32, v.y as f32, v.z as f32))
139                .collect::<Vec<_>>(),
140        }
141    }
142
143    ///
144    /// Clones and converts all the positions as `f32` data type.
145    ///
146    pub fn to_f32(&self) -> Vec<Vec3> {
147        match self {
148            Self::F32(values) => values.clone(),
149            Self::F64(values) => values
150                .iter()
151                .map(|v| Vec3::new(v.x as f32, v.y as f32, v.z as f32))
152                .collect::<Vec<_>>(),
153        }
154    }
155    ///
156    /// Converts and returns all the positions as `f64` data type.
157    ///
158    pub fn into_f64(self) -> Vec<Vector3<f64>> {
159        match self {
160            Self::F32(mut values) => values
161                .drain(..)
162                .map(|v| Vector3::new(v.x as f64, v.y as f64, v.z as f64))
163                .collect::<Vec<_>>(),
164            Self::F64(values) => values,
165        }
166    }
167
168    ///
169    /// Clones and converts all the positions as `f64` data type.
170    ///
171    pub fn to_f64(&self) -> Vec<Vector3<f64>> {
172        match self {
173            Self::F32(values) => values
174                .iter()
175                .map(|v| Vector3::new(v.x as f64, v.y as f64, v.z as f64))
176                .collect::<Vec<_>>(),
177            Self::F64(values) => values.clone(),
178        }
179    }
180
181    ///
182    /// Returns the number of positions.
183    ///
184    pub fn len(&self) -> usize {
185        match self {
186            Self::F32(values) => values.len(),
187            Self::F64(values) => values.len(),
188        }
189    }
190
191    ///
192    /// Returns whether the set of positions is empty.
193    ///
194    #[must_use]
195    pub fn is_empty(&self) -> bool {
196        self.len() == 0
197    }
198
199    ///
200    /// Computes the [AxisAlignedBoundingBox] for these positions.
201    ///
202    pub fn compute_aabb(&self) -> AxisAlignedBoundingBox {
203        match self {
204            Positions::F32(ref positions) => AxisAlignedBoundingBox::new_with_positions(positions),
205            Positions::F64(ref positions) => AxisAlignedBoundingBox::new_with_positions(
206                &positions
207                    .iter()
208                    .map(|v| Vec3::new(v.x as f32, v.y as f32, v.z as f32))
209                    .collect::<Vec<_>>(),
210            ),
211        }
212    }
213}
214
215impl std::default::Default for Positions {
216    fn default() -> Self {
217        Self::F32(Vec::new())
218    }
219}
220
221impl std::fmt::Debug for Positions {
222    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223        let mut d = f.debug_struct("Positions");
224        match self {
225            Self::F32(ind) => d.field("f32", &ind.len()),
226            Self::F64(ind) => d.field("f64", &ind.len()),
227        };
228        d.finish()
229    }
230}