1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use macaw::BoundingBox;
use macaw::ColorRgba8;
use macaw::Vec3;
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "with_speedy", derive(speedy::Writable, speedy::Readable))]
pub struct MeshBounds {
pub bounding_box_min: Vec3,
pub bounding_box_max: Vec3,
pub bounding_sphere_radius: f32,
}
impl MeshBounds {
#[inline]
pub fn bounding_box(&self) -> BoundingBox {
BoundingBox::from_min_max(self.bounding_box_min, self.bounding_box_max)
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "with_speedy", derive(speedy::Writable, speedy::Readable))]
pub struct MeshData {
pub name: String,
pub indices: Vec<u32>,
pub positions: Vec<[f32; 3]>,
pub normals: Option<Vec<[f32; 3]>>,
pub colors: Option<Vec<ColorRgba8>>,
}
impl MeshData {
pub fn validate(&self) -> Result<(), String> {
if self.indices.len() % 3 != 0 {
return Err(
"Index count not divisible by 3, which is required for triangle lists".to_owned(),
);
}
if !self.indices.is_empty() {
let max = *self.indices.iter().max().unwrap();
if max >= self.positions.len() as u32 {
return Err(format!(
"Index out of bounds: {}, vertex count: {}",
max,
self.positions.len()
));
}
}
if let Some(normals) = &self.normals {
if normals.len() != self.positions.len() {
return Err(format!(
"Mismatch in amount of normals vs positions: {} vs {}",
normals.len(),
self.positions.len()
));
}
}
if let Some(colors) = &self.colors {
if colors.len() != self.positions.len() {
return Err(format!(
"Mismatch in amount of colors vs positions: {} vs {}",
colors.len(),
self.positions.len()
));
}
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "with_serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "with_speedy", derive(speedy::Writable, speedy::Readable))]
pub struct Mesh {
pub bounding_box_min: Vec3,
pub bounding_box_max: Vec3,
pub bounding_sphere_radius: f32,
pub primitive_count: u64,
pub data: Option<MeshData>,
}
impl Mesh {
pub fn empty() -> Self {
Self {
bounding_box_min: Vec3::ZERO,
bounding_box_max: Vec3::ZERO,
bounding_sphere_radius: 0.0,
primitive_count: 0,
data: None,
}
}
pub fn validate(&self) -> Result<(), String> {
if let Some(data) = &self.data {
data.validate()
} else {
Ok(())
}
}
pub fn get_bounds(&self) -> MeshBounds {
MeshBounds {
bounding_box_min: self.bounding_box_min,
bounding_box_max: self.bounding_box_max,
bounding_sphere_radius: self.bounding_sphere_radius,
}
}
}
impl Default for Mesh {
fn default() -> Self {
Self::empty()
}
}