1use crate::validation::{Checked, Error, Validate};
2use crate::{accessor, extensions, material, Index};
3use serde::{de, ser};
4use serde_derive::{Deserialize, Serialize};
5use serde_json::from_value;
6use shine_gltf_macro::Validate;
7use std::collections::HashMap;
8use std::fmt;
9
10pub const POINTS: u32 = 0;
12
13pub const LINES: u32 = 1;
15
16pub const LINE_LOOP: u32 = 2;
18
19pub const LINE_STRIP: u32 = 3;
21
22pub const TRIANGLES: u32 = 4;
24
25pub const TRIANGLE_STRIP: u32 = 5;
27
28pub const TRIANGLE_FAN: u32 = 6;
30
31pub const VALID_MODES: &[u32] = &[POINTS, LINES, LINE_LOOP, LINE_STRIP, TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN];
33
34pub const VALID_MORPH_TARGETS: &[&str] = &["POSITION", "NORMAL", "TANGENT"];
36
37#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
39pub enum Mode {
40 Points = 1,
42
43 Lines,
45
46 LineLoop,
48
49 LineStrip,
51
52 Triangles,
54
55 TriangleStrip,
57
58 TriangleFan,
60}
61
62#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
67pub struct Mesh {
68 #[serde(default, skip_serializing_if = "Option::is_none")]
70 pub extensions: Option<extensions::mesh::Mesh>,
71
72 #[serde(skip_serializing_if = "Vec::is_empty")]
74 pub primitives: Vec<Primitive>,
75
76 #[serde(skip_serializing_if = "Option::is_none")]
78 pub weights: Option<Vec<f32>>,
79}
80
81#[derive(Clone, Debug, Default, Deserialize, Serialize)]
83pub struct Primitive {
84 pub attributes: HashMap<Checked<Semantic>, Index<accessor::Accessor>>,
87
88 #[serde(default, skip_serializing_if = "Option::is_none")]
90 pub extensions: Option<extensions::mesh::Primitive>,
91
92 #[serde(skip_serializing_if = "Option::is_none")]
94 pub indices: Option<Index<accessor::Accessor>>,
95
96 #[serde(skip_serializing_if = "Option::is_none")]
98 pub material: Option<Index<material::Material>>,
99
100 #[serde(default, skip_serializing_if = "is_primitive_mode_default")]
102 pub mode: Checked<Mode>,
103
104 #[serde(skip_serializing_if = "Option::is_none")]
108 pub targets: Option<Vec<MorphTarget>>,
109}
110
111#[allow(clippy::trivially_copy_pass_by_ref)]
113fn is_primitive_mode_default(mode: &Checked<Mode>) -> bool {
114 *mode == Checked::Valid(Mode::Triangles)
115}
116
117impl Validate for Primitive {
118 fn validate_minimally<P, R>(&self, root: &crate::Root, path: P, report: &mut R)
119 where
120 P: Fn() -> crate::Path,
121 R: FnMut(&dyn Fn() -> crate::Path, crate::validation::Error),
122 {
123 self.attributes
125 .validate_minimally(root, || path().field("attributes"), report);
126 self.extensions
127 .validate_minimally(root, || path().field("extensions"), report);
128 self.indices.validate_minimally(root, || path().field("indices"), report);
129 self.material.validate_minimally(root, || path().field("material"), report);
130 self.mode.validate_minimally(root, || path().field("mode"), report);
131 self.targets.validate_minimally(root, || path().field("targets"), report);
132
133 let position_path = &|| path().field("attributes").key("POSITION");
135 if let Some(pos_accessor_index) = self.attributes.get(&Checked::Valid(Semantic::Positions)) {
136 let pos_accessor = &root.accessors[pos_accessor_index.value()];
138
139 let min_path = &|| position_path().field("min");
140 if let Some(ref min) = pos_accessor.min {
141 if from_value::<[f32; 3]>(min.clone()).is_err() {
142 report(min_path, Error::Invalid);
143 }
144 } else {
145 report(min_path, Error::Missing);
146 }
147
148 let max_path = &|| position_path().field("max");
149 if let Some(ref max) = pos_accessor.max {
150 if from_value::<[f32; 3]>(max.clone()).is_err() {
151 report(max_path, Error::Invalid);
152 }
153 } else {
154 report(max_path, Error::Missing);
155 }
156 } else {
157 report(position_path, Error::Missing);
158 }
159 }
160}
161
162#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
164pub struct MorphTarget {
165 #[serde(rename = "POSITION")]
167 #[serde(skip_serializing_if = "Option::is_none")]
168 pub positions: Option<Index<accessor::Accessor>>,
169
170 #[serde(rename = "NORMAL")]
172 #[serde(skip_serializing_if = "Option::is_none")]
173 pub normals: Option<Index<accessor::Accessor>>,
174
175 #[serde(rename = "TANGENT")]
177 #[serde(skip_serializing_if = "Option::is_none")]
178 pub tangents: Option<Index<accessor::Accessor>>,
179}
180
181#[derive(Clone, Debug, Eq, Hash, PartialEq)]
183pub enum Semantic {
184 Positions,
186
187 Normals,
189
190 Tangents,
193
194 Colors(u32),
196
197 TexCoords(u32),
199
200 Joints(u32),
202
203 Weights(u32),
205}
206
207impl Default for Mode {
208 fn default() -> Mode {
209 Mode::Triangles
210 }
211}
212
213impl Mode {
214 pub fn as_gl_enum(self) -> u32 {
216 match self {
217 Mode::Points => POINTS,
218 Mode::Lines => LINES,
219 Mode::LineLoop => LINE_LOOP,
220 Mode::LineStrip => LINE_STRIP,
221 Mode::Triangles => TRIANGLES,
222 Mode::TriangleStrip => TRIANGLE_STRIP,
223 Mode::TriangleFan => TRIANGLE_FAN,
224 }
225 }
226}
227
228impl<'de> de::Deserialize<'de> for Checked<Mode> {
229 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
230 where
231 D: de::Deserializer<'de>,
232 {
233 struct Visitor;
234 impl<'de> de::Visitor<'de> for Visitor {
235 type Value = Checked<Mode>;
236
237 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
238 write!(f, "any of: {:?}", VALID_MODES)
239 }
240
241 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
242 where
243 E: de::Error,
244 {
245 use self::Mode::*;
246 use crate::validation::Checked::*;
247 Ok(match value as u32 {
248 POINTS => Valid(Points),
249 LINES => Valid(Lines),
250 LINE_LOOP => Valid(LineLoop),
251 LINE_STRIP => Valid(LineStrip),
252 TRIANGLES => Valid(Triangles),
253 TRIANGLE_STRIP => Valid(TriangleStrip),
254 TRIANGLE_FAN => Valid(TriangleFan),
255 _ => Invalid,
256 })
257 }
258 }
259 deserializer.deserialize_u64(Visitor)
260 }
261}
262
263impl ser::Serialize for Mode {
264 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
265 where
266 S: ser::Serializer,
267 {
268 serializer.serialize_u32(self.as_gl_enum())
269 }
270}
271
272impl Semantic {
273 fn checked(s: &str) -> Checked<Self> {
274 use self::Semantic::*;
275 use crate::validation::Checked::*;
276 match s {
277 "NORMAL" => Valid(Normals),
278 "POSITION" => Valid(Positions),
279 "TANGENT" => Valid(Tangents),
280 _ if s.starts_with("COLOR_") => match s["COLOR_".len()..].parse() {
281 Ok(set) => Valid(Colors(set)),
282 Err(_) => Invalid,
283 },
284 _ if s.starts_with("TEXCOORD_") => match s["TEXCOORD_".len()..].parse() {
285 Ok(set) => Valid(TexCoords(set)),
286 Err(_) => Invalid,
287 },
288 _ if s.starts_with("JOINTS_") => match s["JOINTS_".len()..].parse() {
289 Ok(set) => Valid(Joints(set)),
290 Err(_) => Invalid,
291 },
292 _ if s.starts_with("WEIGHTS_") => match s["WEIGHTS_".len()..].parse() {
293 Ok(set) => Valid(Weights(set)),
294 Err(_) => Invalid,
295 },
296 _ => Invalid,
297 }
298 }
299}
300
301impl ser::Serialize for Semantic {
302 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
303 where
304 S: ser::Serializer,
305 {
306 serializer.serialize_str(&self.to_string())
307 }
308}
309
310impl ToString for Semantic {
311 fn to_string(&self) -> String {
312 use self::Semantic::*;
313 match *self {
314 Positions => "POSITION".into(),
315 Normals => "NORMAL".into(),
316 Tangents => "TANGENT".into(),
317 Colors(set) => format!("COLOR_{}", set),
318 TexCoords(set) => format!("TEXCOORD_{}", set),
319 Joints(set) => format!("JOINTS_{}", set),
320 Weights(set) => format!("WEIGHTS_{}", set),
321 }
322 }
323}
324
325impl ToString for Checked<Semantic> {
326 fn to_string(&self) -> String {
327 match *self {
328 Checked::Valid(ref semantic) => semantic.to_string(),
329 Checked::Invalid => "<invalid semantic name>".into(),
330 }
331 }
332}
333
334impl<'de> de::Deserialize<'de> for Checked<Semantic> {
335 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
336 where
337 D: de::Deserializer<'de>,
338 {
339 struct Visitor;
340 impl<'de> de::Visitor<'de> for Visitor {
341 type Value = Checked<Semantic>;
342
343 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
344 write!(f, "semantic name")
345 }
346
347 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
348 where
349 E: de::Error,
350 {
351 Ok(Semantic::checked(value))
352 }
353 }
354 deserializer.deserialize_str(Visitor)
355 }
356}
357
358#[macro_export]
360macro_rules! attribute_map {
361 ($( $key: ident => $val: expr ),*) => {{
362 use $crate::validation::Checked;
363 use $crate::mesh::Semantic;
364 let mut map = ::std::collections::HashMap::new();
365 $( map.insert(Checked::Valid(Semantic::$key), $val); )*
366 map
367 }}
368}
369
370#[macro_export]
372macro_rules! optional_attribute_map {
373 ($( $key: ident => $val: expr ),*) => {{
374 use $crate::validation::Checked;
375 use $crate::mesh::Semantic;
376 let mut map = ::std::collections::HashMap::new();
377 $(
378 match($val) {
379 Some(val) => {map.insert(Checked::Valid(Semantic::$key), val);}
380 None => {}
381 };
382 )*
383 map
384 }}
385}