1use alloc::string::String;
4use alloc::vec::Vec;
5use alloc::{borrow::ToOwned, collections::BTreeMap};
6use mugl::{gl_const, AddressMode, FilterMode, PrimitiveTopology};
7
8pub type Id = usize;
10
11pub type Size = usize;
13
14pub type Float = f32;
16
17pub type Map<K, V> = BTreeMap<K, V>;
18
19#[derive(Clone, Debug, Default)]
22#[cfg_attr(
23 feature = "serde",
24 derive(serde::Serialize, serde::Deserialize),
25 serde(rename_all = "camelCase"),
26 serde(default)
27)]
28#[repr(C)]
29pub struct Gltf {
30 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
31 pub accessors: Vec<Accessor>,
32 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
33 pub animations: Vec<Animation>,
34 pub asset: Asset,
35 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
36 pub buffers: Vec<Buffer>,
37 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
38 pub buffer_views: Vec<BufferView>,
39 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
40 pub cameras: Vec<Camera>,
41 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
42 pub images: Vec<Image>,
43 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
44 pub materials: Vec<Material>,
45 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
46 pub meshes: Vec<Mesh>,
47 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
48 pub nodes: Vec<Node>,
49 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
50 pub samplers: Vec<Sampler>,
51 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
52 pub scene: Option<Id>,
53 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
54 pub scenes: Vec<Scene>,
55 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
56 pub skins: Vec<Skin>,
57 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
58 pub textures: Vec<Texture>,
59 #[cfg(feature = "gltf-extras")]
60 #[cfg_attr(
61 feature = "serde",
62 serde(default),
63 serde(skip_serializing_if = "serde_json::Value::is_null")
64 )]
65 pub extras: Extras,
66 #[cfg(feature = "gltf-extensions")]
67 #[cfg_attr(
68 feature = "serde",
69 serde(default),
70 serde(skip_serializing_if = "Option::is_none")
71 )]
72 pub extensions: Option<Extensions>,
73 #[cfg(feature = "gltf-extensions")]
74 #[cfg_attr(
75 feature = "serde",
76 serde(default),
77 serde(skip_serializing_if = "Vec::is_empty")
78 )]
79 pub extensions_used: Vec<String>,
80 #[cfg(feature = "gltf-extensions")]
81 #[cfg_attr(
82 feature = "serde",
83 serde(default),
84 serde(skip_serializing_if = "Vec::is_empty")
85 )]
86 pub extensions_required: Vec<String>,
87}
88
89#[cfg(feature = "serde")]
91pub type Extras = serde_json::Value;
92
93#[cfg(feature = "serde")]
95pub type Extensions = Map<String, serde_json::Value>;
96
97#[derive(Clone, Debug)]
99#[cfg_attr(
100 feature = "serde",
101 derive(serde::Serialize, serde::Deserialize),
102 serde(rename_all = "camelCase")
103)]
104#[repr(C)]
105pub struct Asset {
106 #[cfg_attr(
107 feature = "serde",
108 serde(default),
109 serde(skip_serializing_if = "String::is_empty")
110 )]
111 pub copyright: String,
112 #[cfg_attr(
113 feature = "serde",
114 serde(default),
115 serde(skip_serializing_if = "String::is_empty")
116 )]
117 pub generator: String,
118 pub version: String,
119 #[cfg_attr(
120 feature = "serde",
121 serde(default),
122 serde(skip_serializing_if = "String::is_empty")
123 )]
124 pub min_version: String,
125 #[cfg(feature = "gltf-extras")]
126 #[cfg_attr(
127 feature = "serde",
128 serde(default),
129 serde(skip_serializing_if = "serde_json::Value::is_null")
130 )]
131 pub extras: Extras,
132 #[cfg(feature = "gltf-extensions")]
133 #[cfg_attr(
134 feature = "serde",
135 serde(default),
136 serde(skip_serializing_if = "Option::is_none")
137 )]
138 pub extensions: Option<Extensions>,
139}
140
141impl Default for Asset {
142 fn default() -> Self {
143 Self {
144 copyright: Default::default(),
145 generator: Default::default(),
146 version: "2.0".to_owned(),
147 min_version: Default::default(),
148 #[cfg(feature = "gltf-extras")]
149 extras: Default::default(),
150 #[cfg(feature = "gltf-extensions")]
151 extensions: Default::default(),
152 }
153 }
154}
155
156#[derive(Clone, Debug)]
157#[cfg_attr(
158 feature = "serde",
159 derive(serde::Serialize, serde::Deserialize),
160 serde(rename_all = "camelCase")
161)]
162#[repr(C)]
163pub struct Accessor {
164 #[cfg_attr(
165 feature = "serde",
166 serde(default),
167 serde(skip_serializing_if = "Option::is_none")
168 )]
169 pub buffer_view: Option<Id>,
170 #[cfg_attr(feature = "serde", serde(default))]
171 pub byte_offset: Size,
172 pub component_type: AccessorComponentType,
173 #[cfg_attr(feature = "serde", serde(default), serde(skip_serializing_if = "is_false"))]
174 pub normalized: bool,
175 pub count: Size,
176 #[cfg_attr(feature = "serde", serde(rename = "type"))]
177 pub ty: AccessorType,
178 #[cfg_attr(
179 feature = "serde",
180 serde(default),
181 serde(skip_serializing_if = "Vec::is_empty")
182 )]
183 pub max: Vec<f64>,
184 #[cfg_attr(
185 feature = "serde",
186 serde(default),
187 serde(skip_serializing_if = "Vec::is_empty")
188 )]
189 pub min: Vec<f64>,
190 #[cfg_attr(
191 feature = "serde",
192 serde(default),
193 serde(skip_serializing_if = "Option::is_none")
194 )]
195 pub sparse: Option<AccessorSparse>,
196 #[cfg(feature = "gltf-name")]
197 #[cfg_attr(
198 feature = "serde",
199 serde(default),
200 serde(skip_serializing_if = "String::is_empty")
201 )]
202 pub name: String,
203 #[cfg(feature = "gltf-extras")]
204 #[cfg_attr(
205 feature = "serde",
206 serde(default),
207 serde(skip_serializing_if = "serde_json::Value::is_null")
208 )]
209 pub extras: Extras,
210 #[cfg(feature = "gltf-extensions")]
211 #[cfg_attr(
212 feature = "serde",
213 serde(default),
214 serde(skip_serializing_if = "Option::is_none")
215 )]
216 pub extensions: Option<Extensions>,
217}
218
219#[derive(Clone, Debug)]
220#[cfg_attr(
221 feature = "serde",
222 derive(serde::Serialize, serde::Deserialize),
223 serde(rename_all = "camelCase")
224)]
225#[repr(C)]
226pub struct AccessorSparse {
227 pub count: Size,
228 pub indices: AccessorSparseIndices,
229 pub values: AccessorSparseValues,
230 #[cfg(feature = "gltf-extras")]
231 #[cfg_attr(
232 feature = "serde",
233 serde(default),
234 serde(skip_serializing_if = "serde_json::Value::is_null")
235 )]
236 pub extras: Extras,
237 #[cfg(feature = "gltf-extensions")]
238 #[cfg_attr(
239 feature = "serde",
240 serde(default),
241 serde(skip_serializing_if = "Option::is_none")
242 )]
243 pub extensions: Option<Extensions>,
244}
245
246#[derive(Clone, Debug)]
247#[cfg_attr(
248 feature = "serde",
249 derive(serde::Serialize, serde::Deserialize),
250 serde(rename_all = "camelCase")
251)]
252#[repr(C)]
253pub struct AccessorSparseIndices {
254 pub buffer_view: Id,
255 #[cfg_attr(feature = "serde", serde(default))]
256 pub byte_offset: Size,
257 pub component_type: AccessorIndicesComponentType,
258 #[cfg(feature = "gltf-extras")]
259 #[cfg_attr(
260 feature = "serde",
261 serde(default),
262 serde(skip_serializing_if = "serde_json::Value::is_null")
263 )]
264 pub extras: Extras,
265 #[cfg(feature = "gltf-extensions")]
266 #[cfg_attr(
267 feature = "serde",
268 serde(default),
269 serde(skip_serializing_if = "Option::is_none")
270 )]
271 pub extensions: Option<Extensions>,
272}
273
274#[derive(Clone, Debug)]
275#[cfg_attr(
276 feature = "serde",
277 derive(serde::Serialize, serde::Deserialize),
278 serde(rename_all = "camelCase")
279)]
280#[repr(C)]
281pub struct AccessorSparseValues {
282 pub buffer_view: Id,
283 #[cfg_attr(feature = "serde", serde(default))]
284 pub byte_offset: Size,
285 #[cfg(feature = "gltf-extras")]
286 #[cfg_attr(
287 feature = "serde",
288 serde(default),
289 serde(skip_serializing_if = "serde_json::Value::is_null")
290 )]
291 pub extras: Extras,
292 #[cfg(feature = "gltf-extensions")]
293 #[cfg_attr(
294 feature = "serde",
295 serde(default),
296 serde(skip_serializing_if = "Option::is_none")
297 )]
298 pub extensions: Option<Extensions>,
299}
300
301#[derive(Clone, Copy, Debug)]
302#[cfg_attr(
303 feature = "serde",
304 derive(serde::Serialize, serde::Deserialize),
305 serde(rename_all = "UPPERCASE")
306)]
307#[repr(u32)]
308pub enum AccessorType {
309 Scalar,
310 Vec2,
311 Vec3,
312 Vec4,
313 Mat2,
314 Mat3,
315 Mat4,
316}
317
318#[derive(Clone, Copy, Debug)]
319#[cfg_attr(
320 feature = "serde",
321 derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
322)]
323#[repr(u32)]
324pub enum AccessorComponentType {
325 Byte = gl_const::BYTE,
326 UnsignedByte = gl_const::UNSIGNED_BYTE,
327 Short = gl_const::SHORT,
328 UnsignedShort = gl_const::UNSIGNED_SHORT,
329 UnsignedInt = gl_const::UNSIGNED_INT,
330 Float = gl_const::FLOAT,
331}
332
333#[derive(Clone, Copy, Debug)]
334#[cfg_attr(
335 feature = "serde",
336 derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
337)]
338#[repr(u32)]
339pub enum AccessorIndicesComponentType {
340 UnsignedByte = gl_const::UNSIGNED_BYTE,
341 UnsignedShort = gl_const::UNSIGNED_SHORT,
342 UnsignedInt = gl_const::UNSIGNED_INT,
343}
344
345#[derive(Clone, Debug)]
346#[cfg_attr(
347 feature = "serde",
348 derive(serde::Serialize, serde::Deserialize),
349 serde(rename_all = "camelCase")
350)]
351#[repr(C)]
352pub struct Animation {
353 pub channels: Vec<AnimationChannel>,
354 pub samplers: Vec<AnimationSampler>,
355 #[cfg(feature = "gltf-name")]
356 #[cfg_attr(
357 feature = "serde",
358 serde(default),
359 serde(skip_serializing_if = "String::is_empty")
360 )]
361 pub name: String,
362 #[cfg(feature = "gltf-extras")]
363 #[cfg_attr(
364 feature = "serde",
365 serde(default),
366 serde(skip_serializing_if = "serde_json::Value::is_null")
367 )]
368 pub extras: Extras,
369 #[cfg(feature = "gltf-extensions")]
370 #[cfg_attr(
371 feature = "serde",
372 serde(default),
373 serde(skip_serializing_if = "Option::is_none")
374 )]
375 pub extensions: Option<Extensions>,
376}
377
378#[derive(Clone, Debug)]
379#[cfg_attr(
380 feature = "serde",
381 derive(serde::Serialize, serde::Deserialize),
382 serde(rename_all = "camelCase")
383)]
384#[repr(C)]
385pub struct AnimationChannel {
386 pub sampler: Id,
387 pub target: AnimationChannelTarget,
388 #[cfg(feature = "gltf-extras")]
389 #[cfg_attr(
390 feature = "serde",
391 serde(default),
392 serde(skip_serializing_if = "serde_json::Value::is_null")
393 )]
394 pub extras: Extras,
395 #[cfg(feature = "gltf-extensions")]
396 #[cfg_attr(
397 feature = "serde",
398 serde(default),
399 serde(skip_serializing_if = "Option::is_none")
400 )]
401 pub extensions: Option<Extensions>,
402}
403
404#[derive(Clone, Debug)]
405#[cfg_attr(
406 feature = "serde",
407 derive(serde::Serialize, serde::Deserialize),
408 serde(rename_all = "camelCase")
409)]
410#[repr(C)]
411pub struct AnimationChannelTarget {
412 pub node: Id,
413 pub path: NodePath,
414 #[cfg(feature = "gltf-extras")]
415 #[cfg_attr(
416 feature = "serde",
417 serde(default),
418 serde(skip_serializing_if = "serde_json::Value::is_null")
419 )]
420 pub extras: Extras,
421 #[cfg(feature = "gltf-extensions")]
422 #[cfg_attr(
423 feature = "serde",
424 serde(default),
425 serde(skip_serializing_if = "Option::is_none")
426 )]
427 pub extensions: Option<Extensions>,
428}
429
430#[derive(Clone, Copy, Debug)]
431#[cfg_attr(
432 feature = "serde",
433 derive(serde::Serialize, serde::Deserialize),
434 serde(rename_all = "lowercase")
435)]
436#[repr(u32)]
437pub enum NodePath {
438 Weights,
439 Translation,
440 Rotation,
441 Scale,
442}
443
444#[derive(Clone, Debug)]
445#[cfg_attr(
446 feature = "serde",
447 derive(serde::Serialize, serde::Deserialize),
448 serde(rename_all = "camelCase")
449)]
450#[repr(C)]
451pub struct AnimationSampler {
452 pub input: Id,
453 pub output: Id,
454 pub interpolation: Interpolation,
455 #[cfg(feature = "gltf-extras")]
456 #[cfg_attr(
457 feature = "serde",
458 serde(default),
459 serde(skip_serializing_if = "serde_json::Value::is_null")
460 )]
461 pub extras: Extras,
462 #[cfg(feature = "gltf-extensions")]
463 #[cfg_attr(
464 feature = "serde",
465 serde(default),
466 serde(skip_serializing_if = "Option::is_none")
467 )]
468 pub extensions: Option<Extensions>,
469}
470
471#[derive(Clone, Copy, Debug)]
472#[cfg_attr(
473 feature = "serde",
474 derive(serde::Serialize, serde::Deserialize),
475 serde(rename_all = "UPPERCASE")
476)]
477#[repr(u32)]
478pub enum Interpolation {
479 Linear,
480 Step,
481 Cubicspline,
482}
483
484#[derive(Clone, Debug)]
485#[cfg_attr(
486 feature = "serde",
487 derive(serde::Serialize, serde::Deserialize),
488 serde(rename_all = "camelCase")
489)]
490#[repr(C)]
491pub struct Buffer {
492 #[cfg_attr(
493 feature = "serde",
494 serde(default),
495 serde(skip_serializing_if = "String::is_empty")
496 )]
497 pub uri: String,
498 pub byte_length: Size,
499 #[cfg(feature = "gltf-name")]
500 #[cfg_attr(
501 feature = "serde",
502 serde(default),
503 serde(skip_serializing_if = "String::is_empty")
504 )]
505 pub name: String,
506 #[cfg(feature = "gltf-extras")]
507 #[cfg_attr(
508 feature = "serde",
509 serde(default),
510 serde(skip_serializing_if = "serde_json::Value::is_null")
511 )]
512 pub extras: Extras,
513 #[cfg(feature = "gltf-extensions")]
514 #[cfg_attr(
515 feature = "serde",
516 serde(default),
517 serde(skip_serializing_if = "Option::is_none")
518 )]
519 pub extensions: Option<Extensions>,
520}
521
522#[derive(Clone, Debug, Default)]
523#[cfg_attr(
524 feature = "serde",
525 derive(serde::Serialize, serde::Deserialize),
526 serde(rename_all = "camelCase"),
527 serde(default)
528)]
529#[repr(C)]
530pub struct BufferView {
531 pub buffer: Id,
532 pub byte_offset: Size,
533 pub byte_length: Size,
534 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_zero"))]
535 pub byte_stride: Size,
536 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
537 pub target: Option<BufferViewTarget>,
538 #[cfg(feature = "gltf-name")]
539 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
540 pub name: String,
541 #[cfg(feature = "gltf-extras")]
542 #[cfg_attr(
543 feature = "serde",
544 serde(default),
545 serde(skip_serializing_if = "serde_json::Value::is_null")
546 )]
547 pub extras: Extras,
548 #[cfg(feature = "gltf-extensions")]
549 #[cfg_attr(
550 feature = "serde",
551 serde(default),
552 serde(skip_serializing_if = "Option::is_none")
553 )]
554 pub extensions: Option<Extensions>,
555}
556
557#[derive(Clone, Copy, Debug)]
558#[cfg_attr(
559 feature = "serde",
560 derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
561)]
562#[repr(u32)]
563pub enum BufferViewTarget {
564 Vertex = gl_const::ARRAY_BUFFER,
565 Index = gl_const::ELEMENT_ARRAY_BUFFER,
566}
567
568#[derive(Clone, Debug)]
569#[cfg_attr(
570 feature = "serde",
571 derive(serde::Serialize, serde::Deserialize),
572 serde(rename_all = "camelCase"),
573 serde(tag = "type")
574)]
575#[repr(C)]
576pub enum Camera {
577 Orthographic {
578 orthographic: CameraOrthographic,
579 #[cfg(feature = "gltf-name")]
580 #[cfg_attr(
581 feature = "serde",
582 serde(default),
583 serde(skip_serializing_if = "String::is_empty")
584 )]
585 name: String,
586 #[cfg(feature = "gltf-extras")]
587 #[cfg_attr(
588 feature = "serde",
589 serde(default),
590 serde(skip_serializing_if = "serde_json::Value::is_null")
591 )]
592 extras: Extras,
593 #[cfg(feature = "gltf-extensions")]
594 #[cfg_attr(
595 feature = "serde",
596 serde(default),
597 serde(skip_serializing_if = "Option::is_none")
598 )]
599 extensions: Option<Extensions>,
600 },
601 Perspective {
602 perspective: CameraPerspective,
603 #[cfg(feature = "gltf-name")]
604 #[cfg_attr(
605 feature = "serde",
606 serde(default),
607 serde(skip_serializing_if = "String::is_empty")
608 )]
609 name: String,
610 #[cfg(feature = "gltf-extras")]
611 #[cfg_attr(
612 feature = "serde",
613 serde(default),
614 serde(skip_serializing_if = "serde_json::Value::is_null")
615 )]
616 extras: Extras,
617 #[cfg(feature = "gltf-extensions")]
618 #[cfg_attr(
619 feature = "serde",
620 serde(default),
621 serde(skip_serializing_if = "Option::is_none")
622 )]
623 extensions: Option<Extensions>,
624 },
625}
626
627#[derive(Clone, Debug)]
628#[cfg_attr(
629 feature = "serde",
630 derive(serde::Serialize, serde::Deserialize),
631 serde(rename_all = "camelCase")
632)]
633#[repr(C)]
634pub struct CameraOrthographic {
635 pub xmag: Float,
636 pub ymag: Float,
637 pub zfar: Float,
638 pub znear: Float,
639 #[cfg(feature = "gltf-extras")]
640 #[cfg_attr(
641 feature = "serde",
642 serde(default),
643 serde(skip_serializing_if = "serde_json::Value::is_null")
644 )]
645 pub extras: Extras,
646 #[cfg(feature = "gltf-extensions")]
647 #[cfg_attr(
648 feature = "serde",
649 serde(default),
650 serde(skip_serializing_if = "Option::is_none")
651 )]
652 pub extensions: Option<Extensions>,
653}
654
655#[derive(Clone, Debug)]
656#[cfg_attr(
657 feature = "serde",
658 derive(serde::Serialize, serde::Deserialize),
659 serde(rename_all = "camelCase"),
660 serde(default)
661)]
662#[repr(C)]
663pub struct CameraPerspective {
664 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
665 pub aspect_ratio: Option<Float>,
666 pub yfov: Float,
667 pub zfar: Float,
668 pub znear: Float,
669 #[cfg(feature = "gltf-extras")]
670 #[cfg_attr(
671 feature = "serde",
672 serde(default),
673 serde(skip_serializing_if = "serde_json::Value::is_null")
674 )]
675 pub extras: Extras,
676 #[cfg(feature = "gltf-extensions")]
677 #[cfg_attr(
678 feature = "serde",
679 serde(default),
680 serde(skip_serializing_if = "Option::is_none")
681 )]
682 pub extensions: Option<Extensions>,
683}
684
685impl Default for CameraPerspective {
686 fn default() -> Self {
687 Self {
688 aspect_ratio: None,
689 yfov: 0.,
690 zfar: Float::INFINITY,
691 znear: 0.,
692 #[cfg(feature = "gltf-extras")]
693 extras: Default::default(),
694 #[cfg(feature = "gltf-extensions")]
695 extensions: Default::default(),
696 }
697 }
698}
699
700#[derive(Clone, Debug, Default)]
701#[cfg_attr(
702 feature = "serde",
703 derive(serde::Serialize, serde::Deserialize),
704 serde(rename_all = "camelCase"),
705 serde(default)
706)]
707#[repr(C)]
708pub struct Image {
709 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
710 pub uri: String,
711 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
712 pub mime_type: String,
713 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
714 pub buffer_view: Option<Id>,
715 #[cfg(feature = "gltf-name")]
716 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
717 pub name: String,
718 #[cfg(feature = "gltf-extras")]
719 #[cfg_attr(
720 feature = "serde",
721 serde(default),
722 serde(skip_serializing_if = "serde_json::Value::is_null")
723 )]
724 pub extras: Extras,
725 #[cfg(feature = "gltf-extensions")]
726 #[cfg_attr(
727 feature = "serde",
728 serde(default),
729 serde(skip_serializing_if = "Option::is_none")
730 )]
731 pub extensions: Option<Extensions>,
732}
733
734#[derive(Clone, Debug)]
735#[cfg_attr(
736 feature = "serde",
737 derive(serde::Serialize, serde::Deserialize),
738 serde(rename_all = "camelCase"),
739 serde(default)
740)]
741#[repr(C)]
742pub struct Material {
743 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
744 pub pbr_metallic_roughness: Option<PbrMetallicRoughness>,
745 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
746 pub normal_texture: Option<NormalTextureInfo>,
747 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
748 pub occlusion_texture: Option<OcclusionTextureInfo>,
749 pub emissive_factor: [Float; 3],
750 pub alpha_mode: AlphaMode,
751 pub alpha_cutoff: Float,
752 pub double_sided: bool,
753 #[cfg(feature = "gltf-name")]
754 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
755 pub name: String,
756 #[cfg(feature = "gltf-extras")]
757 #[cfg_attr(
758 feature = "serde",
759 serde(default),
760 serde(skip_serializing_if = "serde_json::Value::is_null")
761 )]
762 pub extras: Extras,
763 #[cfg(feature = "gltf-extensions")]
764 #[cfg_attr(
765 feature = "serde",
766 serde(default),
767 serde(skip_serializing_if = "Option::is_none")
768 )]
769 pub extensions: Option<Extensions>,
770}
771
772impl Default for Material {
773 fn default() -> Self {
774 Self {
775 pbr_metallic_roughness: None,
776 normal_texture: None,
777 occlusion_texture: None,
778 emissive_factor: [0., 0., 0.],
779 alpha_mode: Default::default(),
780 alpha_cutoff: 0.5,
781 double_sided: false,
782 #[cfg(feature = "gltf-name")]
783 name: Default::default(),
784 #[cfg(feature = "gltf-extras")]
785 extras: Default::default(),
786 #[cfg(feature = "gltf-extensions")]
787 extensions: Default::default(),
788 }
789 }
790}
791
792#[derive(Clone, Debug)]
793#[cfg_attr(
794 feature = "serde",
795 derive(serde::Serialize, serde::Deserialize),
796 serde(rename_all = "camelCase"),
797 serde(default)
798)]
799#[repr(C)]
800pub struct PbrMetallicRoughness {
801 pub base_color_factor: [Float; 4],
802 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
803 pub base_color_texture: Option<TextureInfo>,
804 pub metallic_factor: Float,
805 pub roughness_factor: Float,
806 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
807 pub metallic_roughness_texture: Option<TextureInfo>,
808 #[cfg(feature = "gltf-extras")]
809 #[cfg_attr(
810 feature = "serde",
811 serde(default),
812 serde(skip_serializing_if = "serde_json::Value::is_null")
813 )]
814 pub extras: Extras,
815 #[cfg(feature = "gltf-extensions")]
816 #[cfg_attr(
817 feature = "serde",
818 serde(default),
819 serde(skip_serializing_if = "Option::is_none")
820 )]
821 pub extensions: Option<Extensions>,
822}
823
824impl Default for PbrMetallicRoughness {
825 fn default() -> Self {
826 Self {
827 base_color_factor: [1., 1., 1., 1.],
828 base_color_texture: None,
829 metallic_factor: 1.,
830 roughness_factor: 1.,
831 metallic_roughness_texture: None,
832 #[cfg(feature = "gltf-extras")]
833 extras: Default::default(),
834 #[cfg(feature = "gltf-extensions")]
835 extensions: Default::default(),
836 }
837 }
838}
839
840#[derive(Clone, Debug, Default)]
841#[cfg_attr(
842 feature = "serde",
843 derive(serde::Serialize, serde::Deserialize),
844 serde(rename_all = "camelCase"),
845 serde(default)
846)]
847#[repr(C)]
848pub struct TextureInfo {
849 pub index: Id,
850 pub tex_coord: Size,
851 #[cfg(feature = "gltf-extras")]
852 #[cfg_attr(
853 feature = "serde",
854 serde(default),
855 serde(skip_serializing_if = "serde_json::Value::is_null")
856 )]
857 pub extras: Extras,
858 #[cfg(feature = "gltf-extensions")]
859 #[cfg_attr(
860 feature = "serde",
861 serde(default),
862 serde(skip_serializing_if = "Option::is_none")
863 )]
864 pub extensions: Option<Extensions>,
865}
866
867#[derive(Clone, Debug)]
868#[cfg_attr(
869 feature = "serde",
870 derive(serde::Serialize, serde::Deserialize),
871 serde(rename_all = "camelCase"),
872 serde(default)
873)]
874#[repr(C)]
875pub struct NormalTextureInfo {
876 pub index: Id,
877 pub tex_coord: Size,
878 pub scale: Float,
879 #[cfg(feature = "gltf-extras")]
880 #[cfg_attr(
881 feature = "serde",
882 serde(default),
883 serde(skip_serializing_if = "serde_json::Value::is_null")
884 )]
885 pub extras: Extras,
886 #[cfg(feature = "gltf-extensions")]
887 #[cfg_attr(
888 feature = "serde",
889 serde(default),
890 serde(skip_serializing_if = "Option::is_none")
891 )]
892 pub extensions: Option<Extensions>,
893}
894
895impl Default for NormalTextureInfo {
896 fn default() -> Self {
897 Self {
898 index: 0,
899 tex_coord: 0,
900 scale: 1.,
901 #[cfg(feature = "gltf-extras")]
902 extras: Default::default(),
903 #[cfg(feature = "gltf-extensions")]
904 extensions: Default::default(),
905 }
906 }
907}
908
909#[derive(Clone, Debug)]
910#[cfg_attr(
911 feature = "serde",
912 derive(serde::Serialize, serde::Deserialize),
913 serde(rename_all = "camelCase"),
914 serde(default)
915)]
916#[repr(C)]
917pub struct OcclusionTextureInfo {
918 pub index: Id,
919 pub tex_coord: Size,
920 pub strength: Float,
921 #[cfg(feature = "gltf-extras")]
922 #[cfg_attr(
923 feature = "serde",
924 serde(default),
925 serde(skip_serializing_if = "serde_json::Value::is_null")
926 )]
927 pub extras: Extras,
928 #[cfg(feature = "gltf-extensions")]
929 #[cfg_attr(
930 feature = "serde",
931 serde(default),
932 serde(skip_serializing_if = "Option::is_none")
933 )]
934 pub extensions: Option<Extensions>,
935}
936
937impl Default for OcclusionTextureInfo {
938 fn default() -> Self {
939 Self {
940 index: 0,
941 tex_coord: 0,
942 strength: 1.,
943 #[cfg(feature = "gltf-extras")]
944 extras: Default::default(),
945 #[cfg(feature = "gltf-extensions")]
946 extensions: Default::default(),
947 }
948 }
949}
950
951#[derive(Clone, Copy, Debug)]
952#[cfg_attr(
953 feature = "serde",
954 derive(serde::Serialize, serde::Deserialize),
955 serde(rename_all = "UPPERCASE")
956)]
957#[repr(u32)]
958pub enum AlphaMode {
959 Opaque,
960 Mask,
961 Blend,
962}
963
964impl Default for AlphaMode {
965 fn default() -> Self {
966 Self::Opaque
967 }
968}
969
970#[derive(Clone, Debug)]
971#[cfg_attr(
972 feature = "serde",
973 derive(serde::Serialize, serde::Deserialize),
974 serde(rename_all = "camelCase")
975)]
976#[repr(C)]
977pub struct Mesh {
978 pub primitives: Vec<MeshPrimitive>,
979 #[cfg_attr(
980 feature = "serde",
981 serde(default),
982 serde(skip_serializing_if = "Vec::is_empty")
983 )]
984 pub weights: Vec<Float>,
985 #[cfg(feature = "gltf-name")]
986 #[cfg_attr(
987 feature = "serde",
988 serde(default),
989 serde(skip_serializing_if = "String::is_empty")
990 )]
991 pub name: String,
992 #[cfg(feature = "gltf-extras")]
993 #[cfg_attr(
994 feature = "serde",
995 serde(default),
996 serde(skip_serializing_if = "serde_json::Value::is_null")
997 )]
998 pub extras: Extras,
999 #[cfg(feature = "gltf-extensions")]
1000 #[cfg_attr(
1001 feature = "serde",
1002 serde(default),
1003 serde(skip_serializing_if = "Option::is_none")
1004 )]
1005 pub extensions: Option<Extensions>,
1006}
1007
1008#[derive(Clone, Debug)]
1009#[cfg_attr(
1010 feature = "serde",
1011 derive(serde::Serialize, serde::Deserialize),
1012 serde(rename_all = "camelCase")
1013)]
1014#[repr(C)]
1015pub struct MeshPrimitive {
1016 pub attributes: Map<String, Id>,
1017 #[cfg_attr(
1018 feature = "serde",
1019 serde(default),
1020 serde(skip_serializing_if = "Option::is_none")
1021 )]
1022 pub indices: Option<Id>,
1023 #[cfg_attr(
1024 feature = "serde",
1025 serde(default),
1026 serde(skip_serializing_if = "Option::is_none")
1027 )]
1028 pub material: Option<Id>,
1029 #[cfg_attr(feature = "serde", serde(default))]
1030 pub mode: PrimitiveTopology,
1031 #[cfg_attr(
1032 feature = "serde",
1033 serde(default),
1034 serde(skip_serializing_if = "Vec::is_empty")
1035 )]
1036 pub targets: Vec<Map<String, Id>>,
1037 #[cfg(feature = "gltf-extras")]
1038 #[cfg_attr(
1039 feature = "serde",
1040 serde(default),
1041 serde(skip_serializing_if = "serde_json::Value::is_null")
1042 )]
1043 pub extras: Extras,
1044 #[cfg(feature = "gltf-extensions")]
1045 #[cfg_attr(
1046 feature = "serde",
1047 serde(default),
1048 serde(skip_serializing_if = "Option::is_none")
1049 )]
1050 pub extensions: Option<Extensions>,
1051}
1052
1053#[derive(Clone, Debug, Default)]
1054#[cfg_attr(
1055 feature = "serde",
1056 derive(serde::Serialize, serde::Deserialize),
1057 serde(rename_all = "camelCase"),
1058 serde(default)
1059)]
1060#[repr(C)]
1061pub struct Node {
1062 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1063 pub camera: Option<Id>,
1064 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
1065 pub children: Vec<Id>,
1066 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1067 pub skin: Option<Id>,
1068 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1069 pub matrix: Option<[Float; 16]>,
1070 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1071 pub mesh: Option<Id>,
1072 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1073 pub rotation: Option<[Float; 4]>,
1074 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1075 pub scale: Option<[Float; 3]>,
1076 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1077 pub translation: Option<[Float; 3]>,
1078 #[cfg_attr(
1079 feature = "serde",
1080 serde(default),
1081 serde(skip_serializing_if = "Vec::is_empty")
1082 )]
1083 pub weights: Vec<Float>,
1084 #[cfg(feature = "gltf-name")]
1085 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
1086 pub name: String,
1087 #[cfg(feature = "gltf-extras")]
1088 #[cfg_attr(
1089 feature = "serde",
1090 serde(default),
1091 serde(skip_serializing_if = "serde_json::Value::is_null")
1092 )]
1093 pub extras: Extras,
1094 #[cfg(feature = "gltf-extensions")]
1095 #[cfg_attr(
1096 feature = "serde",
1097 serde(default),
1098 serde(skip_serializing_if = "Option::is_none")
1099 )]
1100 pub extensions: Option<Extensions>,
1101}
1102
1103#[derive(Clone, Debug)]
1104#[cfg_attr(
1105 feature = "serde",
1106 derive(serde::Serialize, serde::Deserialize),
1107 serde(rename_all = "camelCase"),
1108 serde(default)
1109)]
1110#[repr(C)]
1111pub struct Sampler {
1112 #[cfg_attr(
1113 feature = "serde",
1114 serde(default),
1115 serde(skip_serializing_if = "Option::is_none")
1116 )]
1117 pub mag_filter: Option<FilterMode>,
1118 #[cfg_attr(
1119 feature = "serde",
1120 serde(default),
1121 serde(skip_serializing_if = "Option::is_none")
1122 )]
1123 pub min_filter: Option<MinFilterMode>,
1124 pub wrap_s: AddressMode,
1125 pub wrap_t: AddressMode,
1126 #[cfg(feature = "gltf-name")]
1127 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
1128 pub name: String,
1129 #[cfg(feature = "gltf-extras")]
1130 #[cfg_attr(
1131 feature = "serde",
1132 serde(default),
1133 serde(skip_serializing_if = "serde_json::Value::is_null")
1134 )]
1135 pub extras: Extras,
1136 #[cfg(feature = "gltf-extensions")]
1137 #[cfg_attr(
1138 feature = "serde",
1139 serde(default),
1140 serde(skip_serializing_if = "Option::is_none")
1141 )]
1142 pub extensions: Option<Extensions>,
1143}
1144
1145impl Default for Sampler {
1146 fn default() -> Self {
1147 Self {
1148 mag_filter: None,
1149 min_filter: None,
1150 wrap_s: AddressMode::Repeat,
1151 wrap_t: AddressMode::Repeat,
1152 #[cfg(feature = "gltf-name")]
1153 name: Default::default(),
1154 #[cfg(feature = "gltf-extras")]
1155 extras: Default::default(),
1156 #[cfg(feature = "gltf-extensions")]
1157 extensions: Default::default(),
1158 }
1159 }
1160}
1161
1162#[derive(Clone, Copy, Debug)]
1163#[cfg_attr(
1164 feature = "serde",
1165 derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
1166)]
1167#[repr(u32)]
1168pub enum MinFilterMode {
1169 Nearest = gl_const::NEAREST,
1170 Linear = gl_const::LINEAR,
1171 NearestMipmapNearest = gl_const::NEAREST_MIPMAP_NEAREST,
1172 NearestMipmapLinear = gl_const::NEAREST_MIPMAP_LINEAR,
1173 LinearMipmapNearest = gl_const::LINEAR_MIPMAP_NEAREST,
1174 LinearMipmapLinear = gl_const::LINEAR_MIPMAP_LINEAR,
1175}
1176
1177impl Default for MinFilterMode {
1178 fn default() -> Self {
1179 Self::Nearest
1180 }
1181}
1182
1183#[derive(Clone, Debug, Default)]
1184#[cfg_attr(
1185 feature = "serde",
1186 derive(serde::Serialize, serde::Deserialize),
1187 serde(rename_all = "camelCase"),
1188 serde(default)
1189)]
1190#[repr(C)]
1191pub struct Scene {
1192 pub nodes: Vec<Id>,
1193 #[cfg(feature = "gltf-name")]
1194 #[cfg_attr(
1195 feature = "serde",
1196 serde(default),
1197 serde(skip_serializing_if = "String::is_empty")
1198 )]
1199 pub name: String,
1200 #[cfg(feature = "gltf-extras")]
1201 #[cfg_attr(
1202 feature = "serde",
1203 serde(default),
1204 serde(skip_serializing_if = "serde_json::Value::is_null")
1205 )]
1206 pub extras: Extras,
1207 #[cfg(feature = "gltf-extensions")]
1208 #[cfg_attr(
1209 feature = "serde",
1210 serde(default),
1211 serde(skip_serializing_if = "Option::is_none")
1212 )]
1213 pub extensions: Option<Extensions>,
1214}
1215
1216#[derive(Clone, Debug)]
1217#[cfg_attr(
1218 feature = "serde",
1219 derive(serde::Serialize, serde::Deserialize),
1220 serde(rename_all = "camelCase")
1221)]
1222#[repr(C)]
1223pub struct Skin {
1224 #[cfg_attr(
1225 feature = "serde",
1226 serde(default),
1227 serde(skip_serializing_if = "Option::is_none")
1228 )]
1229 pub inverse_bind_matrices: Option<Id>,
1230 #[cfg_attr(
1231 feature = "serde",
1232 serde(default),
1233 serde(skip_serializing_if = "Option::is_none")
1234 )]
1235 pub skeleton: Option<Id>,
1236 pub joints: Vec<Id>,
1237 #[cfg(feature = "gltf-name")]
1238 #[cfg_attr(
1239 feature = "serde",
1240 serde(default),
1241 serde(skip_serializing_if = "String::is_empty")
1242 )]
1243 pub name: String,
1244 #[cfg(feature = "gltf-extras")]
1245 #[cfg_attr(
1246 feature = "serde",
1247 serde(default),
1248 serde(skip_serializing_if = "serde_json::Value::is_null")
1249 )]
1250 pub extras: Extras,
1251 #[cfg(feature = "gltf-extensions")]
1252 #[cfg_attr(
1253 feature = "serde",
1254 serde(default),
1255 serde(skip_serializing_if = "Option::is_none")
1256 )]
1257 pub extensions: Option<Extensions>,
1258}
1259
1260#[derive(Clone, Debug, Default)]
1261#[cfg_attr(
1262 feature = "serde",
1263 derive(serde::Serialize, serde::Deserialize),
1264 serde(rename_all = "camelCase"),
1265 serde(default)
1266)]
1267#[repr(C)]
1268pub struct Texture {
1269 #[cfg_attr(
1270 feature = "serde",
1271 serde(default),
1272 serde(skip_serializing_if = "Option::is_none")
1273 )]
1274 pub sampler: Option<Id>,
1275 #[cfg_attr(
1276 feature = "serde",
1277 serde(default),
1278 serde(skip_serializing_if = "Option::is_none")
1279 )]
1280 pub source: Option<Id>,
1281 #[cfg(feature = "gltf-name")]
1282 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
1283 pub name: String,
1284 #[cfg(feature = "gltf-extras")]
1285 #[cfg_attr(
1286 feature = "serde",
1287 serde(default),
1288 serde(skip_serializing_if = "serde_json::Value::is_null")
1289 )]
1290 pub extras: Extras,
1291 #[cfg(feature = "gltf-extensions")]
1292 #[cfg_attr(
1293 feature = "serde",
1294 serde(default),
1295 serde(skip_serializing_if = "Option::is_none")
1296 )]
1297 pub extensions: Option<Extensions>,
1298}
1299
1300#[cfg(feature = "serde")]
1302#[inline]
1303fn is_zero(size: &Size) -> bool {
1304 *size == 0
1305}
1306
1307#[cfg(feature = "serde")]
1309#[inline]
1310fn is_false(b: &bool) -> bool {
1311 !*b
1312}