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(&mut 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)]
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    None,
63    /// Uses unsigned 8 bit integer for each index.
64    U8(Vec<u8>),
65    /// Uses unsigned 16 bit integer for each index.
66    U16(Vec<u16>),
67    /// Uses unsigned 32 bit integer for each index.
68    U32(Vec<u32>),
69}
70
71impl Indices {
72    ///
73    /// Converts all the indices as `u32` data type.
74    ///
75    pub fn into_u32(self) -> Option<Vec<u32>> {
76        match self {
77            Self::None => None,
78            Self::U8(mut values) => Some(values.drain(..).map(|i| i as u32).collect::<Vec<_>>()),
79            Self::U16(mut values) => Some(values.drain(..).map(|i| i as u32).collect::<Vec<_>>()),
80            Self::U32(values) => Some(values),
81        }
82    }
83
84    ///
85    /// Clones and converts all the indices as `u32` data type.
86    ///
87    pub fn to_u32(&self) -> Option<Vec<u32>> {
88        match self {
89            Self::None => None,
90            Self::U8(values) => Some(values.iter().map(|i| *i as u32).collect::<Vec<_>>()),
91            Self::U16(values) => Some(values.iter().map(|i| *i as u32).collect::<Vec<_>>()),
92            Self::U32(values) => Some(values.clone()),
93        }
94    }
95
96    ///
97    /// Returns the number of indices.
98    ///
99    pub fn len(&self) -> Option<usize> {
100        match self {
101            Self::None => None,
102            Self::U8(values) => Some(values.len()),
103            Self::U16(values) => Some(values.len()),
104            Self::U32(values) => Some(values.len()),
105        }
106    }
107
108    ///
109    /// Returns whether the set of indices is empty.
110    ///
111    pub fn is_empty(&self) -> bool {
112        self.len().map(|i| i == 0).unwrap_or(true)
113    }
114}
115
116impl std::default::Default for Indices {
117    fn default() -> Self {
118        Self::None
119    }
120}
121
122///
123/// An array of positions. Supports f32 and f64 data types.
124///
125#[derive(Clone)]
126#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
127pub enum Positions {
128    /// Uses 32 bit float for the vertex positions.
129    F32(Vec<Vec3>),
130    /// Uses 64 bit float for the vertex positions.
131    F64(Vec<Vector3<f64>>),
132}
133
134impl Positions {
135    ///
136    /// Converts and returns all the positions as `f32` data type.
137    ///
138    pub fn into_f32(self) -> Vec<Vec3> {
139        match self {
140            Self::F32(values) => values,
141            Self::F64(mut values) => values
142                .drain(..)
143                .map(|v| Vec3::new(v.x as f32, v.y as f32, v.z as f32))
144                .collect::<Vec<_>>(),
145        }
146    }
147
148    ///
149    /// Clones and converts all the positions as `f32` data type.
150    ///
151    pub fn to_f32(&self) -> Vec<Vec3> {
152        match self {
153            Self::F32(values) => values.clone(),
154            Self::F64(values) => values
155                .iter()
156                .map(|v| Vec3::new(v.x as f32, v.y as f32, v.z as f32))
157                .collect::<Vec<_>>(),
158        }
159    }
160    ///
161    /// Converts and returns all the positions as `f64` data type.
162    ///
163    pub fn into_f64(self) -> Vec<Vector3<f64>> {
164        match self {
165            Self::F32(mut values) => values
166                .drain(..)
167                .map(|v| Vector3::new(v.x as f64, v.y as f64, v.z as f64))
168                .collect::<Vec<_>>(),
169            Self::F64(values) => values,
170        }
171    }
172
173    ///
174    /// Clones and converts all the positions as `f64` data type.
175    ///
176    pub fn to_f64(&self) -> Vec<Vector3<f64>> {
177        match self {
178            Self::F32(values) => values
179                .iter()
180                .map(|v| Vector3::new(v.x as f64, v.y as f64, v.z as f64))
181                .collect::<Vec<_>>(),
182            Self::F64(values) => values.clone(),
183        }
184    }
185
186    ///
187    /// Returns the number of positions.
188    ///
189    pub fn len(&self) -> usize {
190        match self {
191            Self::F32(values) => values.len(),
192            Self::F64(values) => values.len(),
193        }
194    }
195
196    ///
197    /// Returns whether the set of positions is empty.
198    ///
199    #[must_use]
200    pub fn is_empty(&self) -> bool {
201        self.len() == 0
202    }
203
204    ///
205    /// Computes the [AxisAlignedBoundingBox] for these positions.
206    ///
207    pub fn compute_aabb(&self) -> AxisAlignedBoundingBox {
208        match self {
209            Positions::F32(ref positions) => AxisAlignedBoundingBox::new_with_positions(positions),
210            Positions::F64(ref positions) => AxisAlignedBoundingBox::new_with_positions(
211                &positions
212                    .iter()
213                    .map(|v| Vec3::new(v.x as f32, v.y as f32, v.z as f32))
214                    .collect::<Vec<_>>(),
215            ),
216        }
217    }
218}
219
220impl std::default::Default for Positions {
221    fn default() -> Self {
222        Self::F32(Vec::new())
223    }
224}
225
226impl std::fmt::Debug for Positions {
227    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
228        let mut d = f.debug_struct("Positions");
229        match self {
230            Self::F32(ind) => d.field("f32", &ind.len()),
231            Self::F64(ind) => d.field("f64", &ind.len()),
232        };
233        d.finish()
234    }
235}