1use crate::validation::{Checked, Error};
2use crate::{accessor, extensions, material, Extras, Index};
3use gltf_derive::Validate;
4use serde::{de, ser};
5use serde_derive::{Deserialize, Serialize};
6use serde_json::from_value;
7use std::collections::BTreeMap;
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] = &[
33 POINTS,
34 LINES,
35 LINE_LOOP,
36 LINE_STRIP,
37 TRIANGLES,
38 TRIANGLE_STRIP,
39 TRIANGLE_FAN,
40];
41
42pub const VALID_MORPH_TARGETS: &[&str] = &["POSITION", "NORMAL", "TANGENT"];
44
45#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
47pub enum Mode {
48 Points = 1,
50
51 Lines,
53
54 LineLoop,
56
57 LineStrip,
59
60 Triangles,
62
63 TriangleStrip,
65
66 TriangleFan,
68}
69
70#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
75pub struct Mesh {
76 #[serde(default, skip_serializing_if = "Option::is_none")]
78 pub extensions: Option<extensions::mesh::Mesh>,
79
80 #[serde(default)]
82 #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
83 #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
84 pub extras: Extras,
85
86 #[cfg(feature = "names")]
88 #[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
89 pub name: Option<String>,
90
91 pub primitives: Vec<Primitive>,
93
94 #[serde(skip_serializing_if = "Option::is_none")]
96 pub weights: Option<Vec<f32>>,
97}
98
99#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
101#[gltf(validate_hook = "primitive_validate_hook")]
102pub struct Primitive {
103 pub attributes: BTreeMap<Checked<Semantic>, Index<accessor::Accessor>>,
106
107 #[serde(default, skip_serializing_if = "Option::is_none")]
109 pub extensions: Option<extensions::mesh::Primitive>,
110
111 #[serde(default)]
113 #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
114 #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
115 pub extras: Extras,
116
117 #[serde(skip_serializing_if = "Option::is_none")]
119 pub indices: Option<Index<accessor::Accessor>>,
120
121 #[serde(skip_serializing_if = "Option::is_none")]
123 pub material: Option<Index<material::Material>>,
124
125 #[serde(default, skip_serializing_if = "is_primitive_mode_default")]
127 pub mode: Checked<Mode>,
128
129 #[serde(skip_serializing_if = "Option::is_none")]
133 pub targets: Option<Vec<MorphTarget>>,
134}
135
136fn is_primitive_mode_default(mode: &Checked<Mode>) -> bool {
137 *mode == Checked::Valid(Mode::Triangles)
138}
139
140fn primitive_validate_hook<P, R>(primitive: &Primitive, root: &crate::Root, path: P, report: &mut R)
141where
142 P: Fn() -> crate::Path,
143 R: FnMut(&dyn Fn() -> crate::Path, crate::validation::Error),
144{
145 let position_path = &|| path().field("attributes").key("POSITION");
146 if let Some(pos_accessor_index) = primitive
147 .attributes
148 .get(&Checked::Valid(Semantic::Positions))
149 {
150 let pos_accessor = &root.accessors[pos_accessor_index.value()];
152
153 let min_path = &|| position_path().field("min");
154 if let Some(ref min) = pos_accessor.min {
155 if from_value::<[f32; 3]>(min.clone()).is_err() {
156 report(min_path, Error::Invalid);
157 }
158 } else {
159 report(min_path, Error::Missing);
160 }
161
162 let max_path = &|| position_path().field("max");
163 if let Some(ref max) = pos_accessor.max {
164 if from_value::<[f32; 3]>(max.clone()).is_err() {
165 report(max_path, Error::Invalid);
166 }
167 } else {
168 report(max_path, Error::Missing);
169 }
170 } else {
171 report(position_path, Error::Missing);
172 }
173}
174
175#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
177pub struct MorphTarget {
178 #[serde(rename = "POSITION")]
180 #[serde(skip_serializing_if = "Option::is_none")]
181 pub positions: Option<Index<accessor::Accessor>>,
182
183 #[serde(rename = "NORMAL")]
185 #[serde(skip_serializing_if = "Option::is_none")]
186 pub normals: Option<Index<accessor::Accessor>>,
187
188 #[serde(rename = "TANGENT")]
190 #[serde(skip_serializing_if = "Option::is_none")]
191 pub tangents: Option<Index<accessor::Accessor>>,
192}
193
194#[derive(Clone, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
196pub enum Semantic {
197 #[cfg(feature = "extras")]
199 Extras(String),
200
201 Positions,
203
204 Normals,
206
207 Tangents,
210
211 Colors(u32),
213
214 TexCoords(u32),
216
217 Joints(u32),
219
220 Weights(u32),
222}
223
224impl Default for Mode {
225 fn default() -> Mode {
226 Mode::Triangles
227 }
228}
229
230impl Mode {
231 pub fn as_gl_enum(self) -> u32 {
233 match self {
234 Mode::Points => POINTS,
235 Mode::Lines => LINES,
236 Mode::LineLoop => LINE_LOOP,
237 Mode::LineStrip => LINE_STRIP,
238 Mode::Triangles => TRIANGLES,
239 Mode::TriangleStrip => TRIANGLE_STRIP,
240 Mode::TriangleFan => TRIANGLE_FAN,
241 }
242 }
243}
244
245impl<'de> de::Deserialize<'de> for Checked<Mode> {
246 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
247 where
248 D: de::Deserializer<'de>,
249 {
250 struct Visitor;
251 impl<'de> de::Visitor<'de> for Visitor {
252 type Value = Checked<Mode>;
253
254 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
255 write!(f, "any of: {:?}", VALID_MODES)
256 }
257
258 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
259 where
260 E: de::Error,
261 {
262 use self::Mode::*;
263 use crate::validation::Checked::*;
264 Ok(match value as u32 {
265 POINTS => Valid(Points),
266 LINES => Valid(Lines),
267 LINE_LOOP => Valid(LineLoop),
268 LINE_STRIP => Valid(LineStrip),
269 TRIANGLES => Valid(Triangles),
270 TRIANGLE_STRIP => Valid(TriangleStrip),
271 TRIANGLE_FAN => Valid(TriangleFan),
272 _ => Invalid,
273 })
274 }
275 }
276 deserializer.deserialize_u64(Visitor)
277 }
278}
279
280impl ser::Serialize for Mode {
281 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
282 where
283 S: ser::Serializer,
284 {
285 serializer.serialize_u32(self.as_gl_enum())
286 }
287}
288
289impl Semantic {
290 fn checked(s: &str) -> Checked<Self> {
291 use self::Semantic::*;
292 use crate::validation::Checked::*;
293 match s {
294 "NORMAL" => Valid(Normals),
295 "POSITION" => Valid(Positions),
296 "TANGENT" => Valid(Tangents),
297 #[cfg(feature = "extras")]
298 _ if s.starts_with('_') => Valid(Extras(s[1..].to_string())),
299 _ if s.starts_with("COLOR_") => match s["COLOR_".len()..].parse() {
300 Ok(set) => Valid(Colors(set)),
301 Err(_) => Invalid,
302 },
303 _ if s.starts_with("TEXCOORD_") => match s["TEXCOORD_".len()..].parse() {
304 Ok(set) => Valid(TexCoords(set)),
305 Err(_) => Invalid,
306 },
307 _ if s.starts_with("JOINTS_") => match s["JOINTS_".len()..].parse() {
308 Ok(set) => Valid(Joints(set)),
309 Err(_) => Invalid,
310 },
311 _ if s.starts_with("WEIGHTS_") => match s["WEIGHTS_".len()..].parse() {
312 Ok(set) => Valid(Weights(set)),
313 Err(_) => Invalid,
314 },
315 _ => Invalid,
316 }
317 }
318}
319
320impl ser::Serialize for Semantic {
321 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
322 where
323 S: ser::Serializer,
324 {
325 serializer.serialize_str(&self.to_string())
326 }
327}
328
329impl ToString for Semantic {
330 fn to_string(&self) -> String {
331 use self::Semantic::*;
332 match *self {
333 Positions => "POSITION".into(),
334 Normals => "NORMAL".into(),
335 Tangents => "TANGENT".into(),
336 Colors(set) => format!("COLOR_{}", set),
337 TexCoords(set) => format!("TEXCOORD_{}", set),
338 Joints(set) => format!("JOINTS_{}", set),
339 Weights(set) => format!("WEIGHTS_{}", set),
340 #[cfg(feature = "extras")]
341 Extras(ref name) => format!("_{}", name),
342 }
343 }
344}
345
346impl ToString for Checked<Semantic> {
347 fn to_string(&self) -> String {
348 match *self {
349 Checked::Valid(ref semantic) => semantic.to_string(),
350 Checked::Invalid => "<invalid semantic name>".into(),
351 }
352 }
353}
354
355impl<'de> de::Deserialize<'de> for Checked<Semantic> {
356 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
357 where
358 D: de::Deserializer<'de>,
359 {
360 struct Visitor;
361 impl<'de> de::Visitor<'de> for Visitor {
362 type Value = Checked<Semantic>;
363
364 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
365 write!(f, "semantic name")
366 }
367
368 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
369 where
370 E: de::Error,
371 {
372 Ok(Semantic::checked(value))
373 }
374 }
375 deserializer.deserialize_str(Visitor)
376 }
377}