1#![allow(clippy::question_mark)]
39
40pub mod extensions;
41#[cfg(feature = "primitive_reader")]
43pub mod primitive_reader;
44
45use nanoserde::DeJson;
46use std::fmt::Debug;
47
48pub trait Extensions: DeJson {
49 type RootExtensions: DeJson + Default + Debug + Clone;
50 type TextureExtensions: DeJson + Default + Debug + Clone;
51 type TextureInfoExtensions: DeJson + Default + Debug + Clone;
52 type MaterialExtensions: DeJson + Default + Debug + Clone;
53 type BufferExtensions: DeJson + Default + Debug + Clone;
54 type NodeExtensions: DeJson + Default + Debug + Clone;
55 type NodeExtras: DeJson + Default + Debug + Clone;
56 type BufferViewExtensions: DeJson + Default + Debug + Clone;
57}
58
59impl Extensions for () {
60 type RootExtensions = ();
61 type TextureExtensions = ();
62 type TextureInfoExtensions = ();
63 type MaterialExtensions = ();
64 type BufferExtensions = ();
65 type NodeExtensions = ();
66 type NodeExtras = ();
67 type BufferViewExtensions = ();
68}
69
70#[derive(Debug, DeJson)]
72pub struct Gltf<E: Extensions> {
73 #[nserde(default)]
74 pub images: Vec<Image>,
75 #[nserde(default)]
76 pub textures: Vec<Texture<E>>,
77 #[nserde(default)]
78 pub materials: Vec<Material<E>>,
79 #[nserde(default)]
80 pub buffers: Vec<Buffer<E>>,
81 #[nserde(rename = "bufferViews")]
82 #[nserde(default)]
83 pub buffer_views: Vec<BufferView<E>>,
84 #[nserde(default)]
85 pub accessors: Vec<Accessor>,
86 #[nserde(default)]
87 pub meshes: Vec<Mesh>,
88 #[nserde(default)]
89 pub animations: Vec<Animation>,
90 #[nserde(default)]
91 pub nodes: Vec<Node<E>>,
92 #[nserde(default)]
93 pub skins: Vec<Skin>,
94 #[nserde(default)]
95 pub samplers: Vec<Sampler>,
96 #[nserde(default)]
97 pub cameras: Vec<Camera>,
98 #[nserde(default)]
99 pub extensions: E::RootExtensions,
100 #[nserde(default)]
101 pub scenes: Vec<Scene>,
102 #[nserde(default)]
103 pub scene: usize,
104}
105
106impl<E: Extensions> Gltf<E> {
107 pub fn from_bytes(bytes: &[u8]) -> Result<(Self, Option<&[u8]>), nanoserde::DeJsonErr> {
111 if !bytes.starts_with(b"glTF") {
113 return Ok((Self::from_json_bytes(bytes)?, None));
114 }
115
116 let json_chunk_length = u32::from_le_bytes(bytes[12..16].try_into().unwrap());
120
121 let json_chunk_end = 20 + json_chunk_length as usize;
122
123 let json_chunk_bytes = &bytes[20..20 + json_chunk_length as usize];
124
125 let json = Self::from_json_bytes(json_chunk_bytes)?;
126
127 let binary_buffer = if bytes.len() != json_chunk_end {
128 Some(&bytes[json_chunk_end + 8..])
129 } else {
130 None
131 };
132
133 Ok((json, binary_buffer))
134 }
135
136 pub fn from_json_bytes(bytes: &[u8]) -> Result<Self, nanoserde::DeJsonErr> {
137 match std::str::from_utf8(bytes) {
138 Ok(string) => Self::from_json_string(string),
139 Err(error) => Err(nanoserde::DeJsonState::default().err_parse(&error.to_string())),
140 }
141 }
142
143 pub fn from_json_string(string: &str) -> Result<Self, nanoserde::DeJsonErr> {
144 Self::deserialize_json(string)
145 }
146}
147
148#[derive(Debug, DeJson)]
149pub struct Skin {
150 #[nserde(rename = "inverseBindMatrices")]
151 pub inverse_bind_matrices: Option<usize>,
152 pub skeleton: Option<usize>,
153 pub joints: Vec<usize>,
154 #[cfg(feature = "names")]
155 pub name: Option<String>,
156}
157
158#[derive(Debug, DeJson)]
159pub struct Animation {
160 pub channels: Vec<Channel>,
161 pub samplers: Vec<AnimationSampler>,
162 #[cfg(feature = "names")]
163 pub name: Option<String>,
164}
165
166#[derive(Debug, DeJson)]
167pub struct Channel {
168 pub sampler: usize,
169 pub target: Target,
170}
171
172#[derive(Debug, DeJson)]
173pub struct Target {
174 pub node: Option<usize>,
175 pub path: TargetPath,
176}
177
178#[derive(Debug, DeJson)]
179pub struct AnimationSampler {
180 pub input: usize,
181 #[nserde(default)]
182 pub interpolation: Interpolation,
183 pub output: usize,
184}
185
186#[derive(Debug, DeJson, Clone, Copy)]
187pub enum Interpolation {
188 #[nserde(rename = "LINEAR")]
189 Linear,
190 #[nserde(rename = "STEP")]
191 Step,
192 #[nserde(rename = "CUBICSPLINE")]
193 CubicSpline,
194}
195
196impl Default for Interpolation {
197 fn default() -> Self {
198 Self::Linear
199 }
200}
201
202#[derive(Debug, DeJson)]
203pub enum TargetPath {
204 #[nserde(rename = "translation")]
205 Translation,
206 #[nserde(rename = "rotation")]
207 Rotation,
208 #[nserde(rename = "scale")]
209 Scale,
210 #[nserde(rename = "weights")]
211 Weights,
212}
213
214#[derive(Debug, DeJson)]
215pub struct Buffer<E: Extensions> {
216 pub uri: Option<String>,
217 #[nserde(rename = "byteLength")]
218 pub byte_length: usize,
219 #[cfg(feature = "names")]
220 pub name: Option<String>,
221 #[nserde(default)]
222 pub extensions: E::BufferExtensions,
223}
224
225#[derive(Debug, DeJson)]
226pub struct Node<E: Extensions> {
227 pub camera: Option<usize>,
228 #[nserde(default)]
229 pub children: Vec<usize>,
230 pub skin: Option<usize>,
231 pub matrix: Option<[f32; 16]>,
232 pub mesh: Option<usize>,
233 pub rotation: Option<[f32; 4]>,
234 pub scale: Option<[f32; 3]>,
235 pub translation: Option<[f32; 3]>,
236 #[cfg(feature = "names")]
237 pub name: Option<String>,
238 #[nserde(default)]
239 pub extensions: E::NodeExtensions,
240 #[nserde(default)]
241 pub extras: E::NodeExtras,
242}
243
244impl<E: Extensions> Node<E> {
245 pub fn transform(&self) -> NodeTransform {
246 match self.matrix {
247 Some(matrix) => match (self.translation, self.rotation, self.scale) {
248 (Some(translation), Some(rotation), Some(scale)) => NodeTransform::Set {
250 translation,
251 rotation,
252 scale,
253 },
254 _ => NodeTransform::Matrix(matrix),
255 },
256 None => {
257 let translation = self.translation.unwrap_or([0.0; 3]);
258 let rotation = self.rotation.unwrap_or([0.0, 0.0, 0.0, 1.0]);
259 let scale = self.scale.unwrap_or([1.0; 3]);
260 NodeTransform::Set {
261 translation,
262 rotation,
263 scale,
264 }
265 }
266 }
267 }
268}
269
270pub enum NodeTransform {
271 Matrix([f32; 16]),
272 Set {
273 translation: [f32; 3],
274 rotation: [f32; 4],
275 scale: [f32; 3],
276 },
277}
278
279#[derive(Debug, DeJson)]
280pub struct Mesh {
281 pub primitives: Vec<Primitive>,
282 pub weights: Option<Vec<f32>>,
283 #[cfg(feature = "names")]
284 pub name: Option<String>,
285}
286
287#[derive(Debug, DeJson)]
288pub struct Primitive {
289 pub attributes: Attributes,
290 pub indices: Option<usize>,
291 pub material: Option<usize>,
292 #[nserde(default)]
293 pub mode: PrimitiveMode,
294 pub targets: Option<Vec<Attributes>>,
295}
296
297#[derive(Debug, Clone, Copy, PartialEq, Eq)]
298pub enum PrimitiveMode {
299 Points,
300 Lines,
301 LineLoop,
302 LineStrip,
303 Triangles,
304 TriangleStrip,
305 TriangleFan,
306}
307
308impl Default for PrimitiveMode {
309 fn default() -> Self {
310 Self::Triangles
311 }
312}
313
314impl DeJson for PrimitiveMode {
315 fn de_json(
316 state: &mut nanoserde::DeJsonState,
317 input: &mut core::str::Chars,
318 ) -> Result<Self, nanoserde::DeJsonErr> {
319 let ty = match &state.tok {
320 nanoserde::DeJsonTok::U64(ty) => match ty {
321 0 => Self::Points,
322 1 => Self::Lines,
323 2 => Self::LineLoop,
324 3 => Self::LineStrip,
325 4 => Self::Triangles,
326 5 => Self::TriangleStrip,
327 6 => Self::TriangleFan,
328 _ => return Err(state.err_range(&ty.to_string())),
329 },
330 _ => return Err(state.err_token("U64")),
331 };
332
333 state.next_tok(input)?;
334
335 Ok(ty)
336 }
337}
338
339#[derive(Debug, DeJson)]
340pub struct Attributes {
341 #[nserde(rename = "POSITION")]
342 pub position: Option<usize>,
343 #[nserde(rename = "TANGENT")]
344 pub tangent: Option<usize>,
345 #[nserde(rename = "NORMAL")]
346 pub normal: Option<usize>,
347 #[nserde(rename = "TEXCOORD_0")]
348 pub texcoord_0: Option<usize>,
349 #[nserde(rename = "TEXCOORD_1")]
350 pub texcoord_1: Option<usize>,
351 #[nserde(rename = "JOINTS_0")]
352 pub joints_0: Option<usize>,
353 #[nserde(rename = "WEIGHTS_0")]
354 pub weights_0: Option<usize>,
355}
356
357#[derive(Debug, DeJson, Clone)]
358pub struct Image {
359 pub uri: Option<String>,
360 #[nserde(rename = "mimeType")]
361 pub mime_type: Option<String>,
362 #[nserde(rename = "bufferView")]
363 pub buffer_view: Option<usize>,
364 #[cfg(feature = "names")]
365 pub name: Option<String>,
366}
367
368#[derive(Debug, DeJson)]
369pub struct Texture<E: Extensions> {
370 pub sampler: Option<usize>,
371 pub source: Option<usize>,
372 #[cfg(feature = "names")]
373 pub name: Option<String>,
374 #[nserde(default)]
375 pub extensions: E::TextureExtensions,
376}
377
378#[derive(Debug, DeJson)]
379pub struct BufferView<E: Extensions> {
380 pub buffer: usize,
381 #[nserde(rename = "byteOffset")]
382 #[nserde(default)]
383 pub byte_offset: usize,
384 #[nserde(rename = "byteLength")]
385 pub byte_length: usize,
386 #[nserde(rename = "byteStride")]
387 pub byte_stride: Option<usize>,
388 #[cfg(feature = "names")]
389 pub name: Option<String>,
390 #[nserde(default)]
391 pub extensions: E::BufferViewExtensions,
392}
393
394#[derive(Debug, DeJson)]
395pub struct Accessor {
396 #[nserde(rename = "bufferView")]
397 pub buffer_view: Option<usize>,
398 #[nserde(rename = "byteOffset")]
399 #[nserde(default)]
400 pub byte_offset: usize,
401 #[nserde(rename = "componentType")]
402 pub component_type: ComponentType,
403 #[nserde(default)]
404 pub normalized: bool,
405 pub count: usize,
406 #[nserde(rename = "type")]
407 pub accessor_type: AccessorType,
408 pub sparse: Option<Sparse>,
409 pub min: Option<Vec<f32>>,
411 pub max: Option<Vec<f32>>,
412 #[cfg(feature = "names")]
413 pub name: Option<String>,
414}
415
416impl Accessor {
417 pub fn byte_length<E: Extensions>(&self, buffer_view: &BufferView<E>) -> usize {
418 self.count
419 * buffer_view.byte_stride.unwrap_or_else(|| {
420 self.component_type.byte_size() * self.accessor_type.num_components()
421 })
422 }
423}
424
425#[derive(Debug, DeJson)]
426pub struct Sparse {
427 pub count: usize,
428 pub indices: SparseIndices,
429 pub values: SparseValues,
430}
431
432#[derive(Debug, DeJson)]
433pub struct SparseIndices {
434 #[nserde(rename = "bufferView")]
435 pub buffer_view: usize,
436 #[nserde(rename = "byteOffset")]
437 #[nserde(default)]
438 pub byte_offset: usize,
439 #[nserde(rename = "componentType")]
440 pub component_type: ComponentType,
441}
442
443#[derive(Debug, DeJson)]
444pub struct SparseValues {
445 #[nserde(rename = "bufferView")]
446 pub buffer_view: usize,
447 #[nserde(rename = "byteOffset")]
448 #[nserde(default)]
449 pub byte_offset: usize,
450}
451
452#[derive(Debug, Clone, Copy, PartialEq, Eq)]
453pub enum ComponentType {
454 UnsignedByte,
455 Byte,
456 UnsignedShort,
457 Short,
458 UnsignedInt,
459 Float,
460}
461
462impl ComponentType {
463 pub fn byte_size(&self) -> usize {
464 match self {
465 Self::UnsignedByte | Self::Byte => 1,
466 Self::UnsignedShort | Self::Short => 2,
467 Self::UnsignedInt | Self::Float => 4,
468 }
469 }
470}
471
472impl DeJson for ComponentType {
473 fn de_json(
474 state: &mut nanoserde::DeJsonState,
475 input: &mut core::str::Chars,
476 ) -> Result<Self, nanoserde::DeJsonErr> {
477 let ty = match &state.tok {
478 nanoserde::DeJsonTok::U64(ty) => match ty {
479 5120 => Self::Byte,
480 5121 => Self::UnsignedByte,
481 5122 => Self::Short,
482 5123 => Self::UnsignedShort,
483 5125 => Self::UnsignedInt,
484 5126 => Self::Float,
485 _ => return Err(state.err_range(&ty.to_string())),
486 },
487 _ => return Err(state.err_token("U64")),
488 };
489
490 state.next_tok(input)?;
491
492 Ok(ty)
493 }
494}
495
496#[derive(Debug, DeJson, PartialEq, Clone, Copy)]
497pub enum AccessorType {
498 #[nserde(rename = "SCALAR")]
499 Scalar,
500 #[nserde(rename = "VEC2")]
501 Vec2,
502 #[nserde(rename = "VEC3")]
503 Vec3,
504 #[nserde(rename = "VEC4")]
505 Vec4,
506 #[nserde(rename = "MAT2")]
507 Mat2,
508 #[nserde(rename = "MAT3")]
509 Mat3,
510 #[nserde(rename = "MAT4")]
511 Mat4,
512}
513
514impl AccessorType {
515 pub fn num_components(&self) -> usize {
516 match self {
517 Self::Scalar => 1,
518 Self::Vec2 => 2,
519 Self::Vec3 => 3,
520 Self::Vec4 | Self::Mat2 => 4,
521 Self::Mat3 => 9,
522 Self::Mat4 => 16,
523 }
524 }
525}
526
527#[derive(Debug, DeJson, Clone)]
528pub struct Material<E: Extensions> {
529 #[nserde(rename = "pbrMetallicRoughness")]
530 #[nserde(default)]
531 pub pbr_metallic_roughness: PbrMetallicRoughness<E>,
532 #[nserde(rename = "normalTexture")]
533 pub normal_texture: Option<NormalTextureInfo<E>>,
534 #[nserde(rename = "occlusionTexture")]
535 pub occlusion_texture: Option<OcclusionTextureInfo<E>>,
536 #[nserde(rename = "emissiveTexture")]
537 pub emissive_texture: Option<TextureInfo<E>>,
538 #[nserde(rename = "emissiveFactor")]
539 #[nserde(default)]
540 pub emissive_factor: [f32; 3],
541 #[nserde(rename = "alphaMode")]
542 #[nserde(default)]
543 pub alpha_mode: AlphaMode,
544 #[nserde(rename = "alphaCutoff")]
545 #[nserde(default = "0.5")]
546 pub alpha_cutoff: f32,
547 #[nserde(rename = "doubleSided")]
548 #[nserde(default)]
549 pub double_sided: bool,
550 #[cfg(feature = "names")]
551 pub name: Option<String>,
552 #[nserde(default)]
553 pub extensions: E::MaterialExtensions,
554}
555
556#[derive(Debug, DeJson, Clone, Copy)]
557pub enum AlphaMode {
558 #[nserde(rename = "OPAQUE")]
559 Opaque,
560 #[nserde(rename = "MASK")]
561 Mask,
562 #[nserde(rename = "BLEND")]
563 Blend,
564}
565
566impl Default for AlphaMode {
567 fn default() -> Self {
568 Self::Opaque
569 }
570}
571
572#[derive(Debug, DeJson, Clone)]
573pub struct PbrMetallicRoughness<E: Extensions> {
574 #[nserde(rename = "baseColorFactor")]
575 #[nserde(default = "[1.0, 1.0, 1.0, 1.0]")]
576 pub base_color_factor: [f32; 4],
577 #[nserde(rename = "baseColorTexture")]
578 pub base_color_texture: Option<TextureInfo<E>>,
579 #[nserde(rename = "metallicFactor")]
580 #[nserde(default = "1.0")]
581 pub metallic_factor: f32,
582 #[nserde(rename = "roughnessFactor")]
583 #[nserde(default = "1.0")]
584 pub roughness_factor: f32,
585 #[nserde(rename = "metallicRoughnessTexture")]
586 pub metallic_roughness_texture: Option<TextureInfo<E>>,
587}
588
589impl<E: Extensions> Default for PbrMetallicRoughness<E> {
590 fn default() -> Self {
591 Self {
592 base_color_factor: [1.0; 4],
593 base_color_texture: None,
594 metallic_factor: 1.0,
595 roughness_factor: 1.0,
596 metallic_roughness_texture: None,
597 }
598 }
599}
600
601#[derive(Debug, DeJson, Clone)]
602pub struct TextureInfo<E: Extensions> {
603 pub index: usize,
604 #[nserde(rename = "texCoord")]
605 #[nserde(default)]
606 pub tex_coord: usize,
607 #[nserde(default)]
608 pub extensions: E::TextureInfoExtensions,
609}
610
611#[derive(Debug, DeJson, Clone)]
612pub struct NormalTextureInfo<E: Extensions> {
613 pub index: usize,
614 #[nserde(rename = "texCoord")]
615 #[nserde(default)]
616 pub tex_coord: usize,
617 #[nserde(default = "1.0")]
618 pub scale: f32,
619 #[nserde(default)]
620 pub extensions: E::TextureInfoExtensions,
621}
622
623#[derive(Debug, DeJson, Clone)]
624pub struct OcclusionTextureInfo<E: Extensions> {
625 pub index: usize,
626 #[nserde(rename = "texCoord")]
627 #[nserde(default)]
628 pub tex_coord: usize,
629 #[nserde(default = "1.0")]
630 pub strength: f32,
631 #[nserde(default)]
632 pub extensions: E::TextureInfoExtensions,
633}
634
635#[derive(Debug, DeJson)]
636pub struct Sampler {
637 #[nserde(rename = "magFilter")]
638 pub mag_filter: Option<FilterMode>,
639 #[nserde(rename = "minFilter")]
640 pub min_filter: Option<MinFilter>,
641 #[nserde(rename = "wrapS")]
642 #[nserde(default)]
643 pub wrap_s: SamplerWrap,
644 #[nserde(rename = "wrapT")]
645 #[nserde(default)]
646 pub wrap_t: SamplerWrap,
647 #[cfg(feature = "names")]
648 pub name: Option<String>,
649}
650
651#[derive(Debug)]
652pub enum FilterMode {
653 Nearest,
654 Linear,
655}
656
657impl DeJson for FilterMode {
658 fn de_json(
659 state: &mut nanoserde::DeJsonState,
660 input: &mut core::str::Chars,
661 ) -> Result<Self, nanoserde::DeJsonErr> {
662 let ty = match &state.tok {
663 nanoserde::DeJsonTok::U64(ty) => match ty {
664 9728 => Self::Nearest,
665 9729 => Self::Linear,
666 _ => return Err(state.err_range(&ty.to_string())),
667 },
668 _ => return Err(state.err_token("U64")),
669 };
670
671 state.next_tok(input)?;
672
673 Ok(ty)
674 }
675}
676
677#[derive(Debug)]
678pub struct MinFilter {
679 pub mode: FilterMode,
680 pub mipmap: Option<FilterMode>,
681}
682
683impl DeJson for MinFilter {
684 fn de_json(
685 state: &mut nanoserde::DeJsonState,
686 input: &mut core::str::Chars,
687 ) -> Result<Self, nanoserde::DeJsonErr> {
688 let ty = match &state.tok {
689 nanoserde::DeJsonTok::U64(ty) => match ty {
690 9728 => Self {
691 mode: FilterMode::Nearest,
692 mipmap: None,
693 },
694 9729 => Self {
695 mode: FilterMode::Linear,
696 mipmap: None,
697 },
698 9984 => Self {
699 mode: FilterMode::Nearest,
700 mipmap: Some(FilterMode::Nearest),
701 },
702 9985 => Self {
703 mode: FilterMode::Linear,
704 mipmap: Some(FilterMode::Nearest),
705 },
706 9986 => Self {
707 mode: FilterMode::Nearest,
708 mipmap: Some(FilterMode::Linear),
709 },
710 9987 => Self {
711 mode: FilterMode::Linear,
712 mipmap: Some(FilterMode::Linear),
713 },
714 _ => return Err(state.err_range(&ty.to_string())),
715 },
716 _ => return Err(state.err_token("U64")),
717 };
718
719 state.next_tok(input)?;
720
721 Ok(ty)
722 }
723}
724
725#[derive(Debug)]
726pub enum SamplerWrap {
727 ClampToEdge,
728 MirroredRepeat,
729 Repeat,
730}
731
732impl DeJson for SamplerWrap {
733 fn de_json(
734 state: &mut nanoserde::DeJsonState,
735 input: &mut core::str::Chars,
736 ) -> Result<Self, nanoserde::DeJsonErr> {
737 let ty = match &state.tok {
738 nanoserde::DeJsonTok::U64(ty) => match ty {
739 33071 => Self::ClampToEdge,
740 33648 => Self::MirroredRepeat,
741 10497 => Self::Repeat,
742 _ => return Err(state.err_range(&ty.to_string())),
743 },
744 _ => return Err(state.err_token("U64")),
745 };
746
747 state.next_tok(input)?;
748
749 Ok(ty)
750 }
751}
752
753impl Default for SamplerWrap {
754 fn default() -> Self {
755 Self::Repeat
756 }
757}
758
759#[derive(Debug, DeJson)]
760pub struct Camera {
761 pub perspective: Option<CameraPerspective>,
762 pub orthographic: Option<CameraOrthographic>,
763 #[nserde(rename = "type")]
764 pub ty: CameraType,
765 #[cfg(feature = "names")]
766 pub name: Option<String>,
767}
768
769#[derive(Debug, DeJson)]
770pub struct CameraPerspective {
771 pub yfov: f32,
772 pub znear: f32,
773 pub zfar: Option<f32>,
774 #[nserde(rename = "aspectRatio")]
775 pub aspect_ratio: Option<f32>,
776}
777
778#[derive(Debug, DeJson, Clone, Copy)]
779pub struct CameraOrthographic {
780 pub xmag: f32,
781 pub ymag: f32,
782 pub zfar: f32,
783 pub znear: f32,
784}
785
786#[derive(Debug, DeJson)]
787pub enum CameraType {
788 #[nserde(rename = "perspective")]
789 Perspective,
790 #[nserde(rename = "orthographic")]
791 Orthographic,
792}
793
794#[derive(Debug, DeJson, Clone)]
795pub struct Scene {
796 pub nodes: Vec<usize>,
797 #[cfg(feature = "names")]
798 pub name: Option<String>,
799}
800
801pub mod default_extensions {
802 use crate::extensions;
803 use nanoserde::DeJson;
804
805 #[derive(Debug, Default, Clone, Copy, DeJson)]
806 pub struct Extensions;
807
808 impl super::Extensions for Extensions {
809 type RootExtensions = RootExtensions;
810 type TextureExtensions = TextureExtensions;
811 type TextureInfoExtensions = TextureInfoExtensions;
812 type MaterialExtensions = MaterialExtensions<Self>;
813 type BufferExtensions = BufferExtensions;
814 type NodeExtensions = NodeExtensions;
815 type NodeExtras = NodeExtras;
816 type BufferViewExtensions = BufferViewExtensions;
817 }
818
819 #[derive(Debug, DeJson, Default, Clone)]
820 pub struct RootExtensions {
821 #[nserde(rename = "KHR_lights_punctual")]
822 pub khr_lights_punctual: Option<extensions::KhrLightsPunctual>,
823 }
824
825 #[derive(Debug, DeJson, Default, Clone)]
826 pub struct BufferExtensions {
827 #[nserde(rename = "EXT_meshopt_compression")]
828 pub ext_meshopt_compression: Option<extensions::ExtMeshoptCompressionBuffer>,
829 }
830
831 #[derive(Debug, DeJson, Default, Clone)]
832 pub struct NodeExtensions {
833 #[nserde(rename = "EXT_mesh_gpu_instancing")]
834 pub ext_mesh_gpu_instancing: Option<extensions::ExtMeshGpuInstancing>,
835 #[nserde(rename = "MSFT_lod")]
836 pub msft_lod: Option<extensions::MsftLod>,
837 }
838
839 #[derive(Debug, DeJson, Default, Clone)]
840 pub struct NodeExtras {
841 #[nserde(rename = "MSFT_screencoverage")]
842 pub msft_screencoverage: Option<Vec<f32>>,
843 }
844
845 #[derive(Debug, Default, DeJson, Clone)]
846 pub struct TextureExtensions {
847 #[nserde(rename = "KHR_texture_basisu")]
848 pub khr_texture_basisu: Option<extensions::KhrTextureBasisu>,
849 }
850
851 #[derive(Debug, DeJson, Default, Clone)]
852 pub struct BufferViewExtensions {
853 #[nserde(rename = "EXT_meshopt_compression")]
854 pub ext_meshopt_compression: Option<extensions::ExtMeshoptCompression>,
855 }
856
857 #[derive(Debug, DeJson, Default, Clone)]
858 pub struct MaterialExtensions<E: super::Extensions> {
859 #[nserde(rename = "KHR_materials_sheen")]
860 pub khr_materials_sheen: Option<extensions::KhrMaterialsSheen<E>>,
861 #[nserde(rename = "KHR_materials_emissive_strength")]
862 pub khr_materials_emissive_strength: Option<extensions::KhrMaterialsEmissiveStrength>,
863 #[nserde(rename = "KHR_materials_unlit")]
864 pub khr_materials_unlit: Option<extensions::KhrMaterialsUnlit>,
865 #[nserde(rename = "KHR_materials_ior")]
866 pub khr_materials_ior: Option<extensions::KhrMaterialsIor>,
867 #[nserde(rename = "KHR_materials_specular")]
868 pub khr_materials_specular: Option<extensions::KhrMaterialsSpecular<E>>,
869 #[nserde(rename = "KHR_materials_transmission")]
870 pub khr_materials_transmission: Option<extensions::KhrMaterialsTransmission<E>>,
871 }
872
873 #[derive(Debug, DeJson, Default, Clone, Copy)]
874 pub struct TextureInfoExtensions {
875 #[nserde(rename = "KHR_texture_transform")]
876 pub khr_texture_transform: Option<extensions::KhrTextureTransform>,
877 }
878}