rustlf/
lib.rs

1use serde::{Serialize, Deserialize};
2use std::collections::HashMap;
3
4#[derive(Debug)]
5pub enum GltfError {
6    Serde(serde_json::Error),
7    Io(std::io::Error),
8    Unloaded(String),
9    Index(usize, usize)
10}
11impl From<std::io::Error> for GltfError {
12    fn from(err: std::io::Error) -> Self { Self::Io(err) }
13}
14impl From<serde_json::Error> for GltfError {
15    fn from(err: serde_json::Error) -> Self { Self::Serde(err) }
16}
17impl std::fmt::Display for GltfError {
18    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
19        match self {
20            Self::Serde(err) => { write!(f, "Serialisation Error: {}", err) },
21            Self::Io(err) => { write!(f, "I/O Error: {}", err) },
22            Self::Unloaded(err) => { write!(f, "No {} loaded in this glTF file.", err) },
23            Self::Index(index, len) => { write!(f, "Index out of bounds: tried to access element {}, only {} elements.", index, len) }
24        }
25    }
26}
27
28#[derive(Serialize, Deserialize)]
29pub struct GltfObj {
30    pub asset: Asset,
31    pub buffers: Option<Vec<Buffer>>,
32    #[serde(rename="bufferViews")]
33    pub buffer_views: Option<Vec<BufferView>>,
34    pub accessors: Option<Vec<Accessor>>,
35    pub animations: Option<Vec<Animation>>,
36    pub materials: Option<Vec<Material>>,
37    pub meshes: Option<Vec<Mesh>>,
38    pub nodes: Option<Vec<Node>>,
39    pub scenes: Option<Vec<Scene>>,
40    pub images: Option<Vec<Image>>,
41    pub samplers: Option<Vec<Sampler>>,
42    pub skins: Option<Vec<Skin>>,
43    pub textures: Option<Vec<Texture>>,
44    pub cameras: Option<Vec<Camera>>,
45}
46impl GltfObj { 
47    pub fn from_file(file: &str) -> Result<Self, GltfError> {
48        let data = std::fs::read_to_string(file)?;
49        Self::from_string(&data)
50    }
51    pub fn from_string(data: &str) -> Result<Self, GltfError> {
52        let g: GltfObj = serde_json::from_str(data)?;
53        Ok(g)
54    }
55    pub fn get_animation(&self, index: u32) -> Result<Animation, GltfError> {
56        if let Some(data) = &self.animations {
57            if let Some(value) = data.get(index as usize) {
58                Ok(value.clone())
59            } else { Err(GltfError::Index(index as usize, data.len())) }
60        } else { Err(GltfError::Unloaded("Animations".to_string())) }
61    }
62    pub fn get_accessor(&self, index: u32) -> Result<Accessor, GltfError> {
63        if let Some(data) = &self.accessors {
64            if let Some(value) = data.get(index as usize) {
65                Ok(value.clone())
66            } else { Err(GltfError::Index(index as usize, data.len())) }
67        } else { Err(GltfError::Unloaded("Accessors".to_string())) }
68    }
69    pub fn get_buffer(&self, index: u32) -> Result<Buffer, GltfError> {
70        if let Some(data) = &self.buffers {
71            if let Some(value) = data.get(index as usize) {
72                Ok(value.clone())
73            } else { Err(GltfError::Index(index as usize, data.len())) }
74        } else { Err(GltfError::Unloaded("Buffers".to_string())) }
75    }
76    pub fn get_buffer_view(&self, index: u32) -> Result<BufferView, GltfError> {
77        if let Some(data) = &self.buffer_views {
78            if let Some(value) = data.get(index as usize) {
79                Ok(value.clone())
80            } else { Err(GltfError::Index(index as usize, data.len())) }
81        } else { Err(GltfError::Unloaded("Buffer Views".to_string())) }
82    }
83    pub fn get_material(&self, index: u32) -> Result<Material, GltfError> {
84        if let Some(data) = &self.materials {
85            if let Some(value) = data.get(index as usize) {
86                Ok(value.clone())
87            } else { Err(GltfError::Index(index as usize, data.len())) }
88        } else { Err(GltfError::Unloaded("Materials".to_string())) }
89    }
90    pub fn get_mesh(&self, index: u32) -> Result<Mesh, GltfError> {
91        if let Some(data) = &self.meshes {
92            if let Some(value) = data.get(index as usize) {
93                Ok(value.clone())
94            } else { Err(GltfError::Index(index as usize, data.len())) }
95        } else { Err(GltfError::Unloaded("Meshes".to_string())) }
96    }
97    pub fn get_node(&self, index: u32) -> Result<Node, GltfError> {
98        if let Some(data) = &self.nodes {
99            if let Some(value) = data.get(index as usize) {
100                Ok(value.clone())
101            } else { Err(GltfError::Index(index as usize, data.len())) }
102        } else { Err(GltfError::Unloaded("Nodes".to_string())) }
103    }
104    pub fn get_scene(&self, index: u32) -> Result<Scene, GltfError> {
105        if let Some(data) = &self.scenes {
106            if let Some(value) = data.get(index as usize) {
107                Ok(value.clone())
108            } else { Err(GltfError::Index(index as usize, data.len())) }
109        } else { Err(GltfError::Unloaded("Scenes".to_string())) }
110    }
111    pub fn get_image(&self, index: u32) -> Result<Image, GltfError> {
112        if let Some(data) = &self.images {
113            if let Some(value) = data.get(index as usize) {
114                Ok(value.clone())
115            } else { Err(GltfError::Index(index as usize, data.len())) }
116        } else { Err(GltfError::Unloaded("Images".to_string())) }
117    }
118    pub fn get_sampler(&self, index: u32) -> Result<Sampler, GltfError> {
119        if let Some(data) = &self.samplers {
120            if let Some(value) = data.get(index as usize) {
121                Ok(value.clone())
122            } else { Err(GltfError::Index(index as usize, data.len())) }
123        } else { Err(GltfError::Unloaded("Samplers".to_string())) }
124    }
125    pub fn get_skin(&self, index: u32) -> Result<Skin, GltfError> {
126        if let Some(data) = &self.skins {
127            if let Some(value) = data.get(index as usize) {
128                Ok(value.clone())
129            } else { Err(GltfError::Index(index as usize, data.len())) }
130        } else { Err(GltfError::Unloaded("Skins".to_string())) }
131    }
132    pub fn get_texture(&self, index: u32) -> Result<Texture, GltfError> {
133        if let Some(data) = &self.textures {
134            if let Some(value) = data.get(index as usize) {
135                Ok(value.clone())
136            } else { Err(GltfError::Index(index as usize, data.len())) }
137        } else { Err(GltfError::Unloaded("Textures".to_string())) }
138    }
139    pub fn get_camera(&self, index: u32) -> Result<Camera, GltfError> {
140        if let Some(data) = &self.cameras {
141            if let Some(value) = data.get(index as usize) {
142                Ok(value.clone())
143            } else { Err(GltfError::Index(index as usize, data.len())) }
144        } else { Err(GltfError::Unloaded("Cameras".to_string())) }
145    }
146}
147#[derive(Serialize, Deserialize, Clone)]
148pub struct Asset {
149    pub version: String,
150    pub generator: Option<String>,
151    pub copyright: Option<String>,
152}
153#[derive(Serialize, Deserialize, Clone)]
154pub struct Accessor {
155    #[serde(rename="bufferView")]
156    pub buffer_view: u32,
157    #[serde(rename="byteOffset")]
158    #[serde(default="Accessor::default_byte_offset")]
159    pub byte_offset: u32,
160    #[serde(rename="componentType")]
161    pub component_type: u32,
162    pub count: u32,
163    #[serde(rename="type")]
164    pub data_type: String,
165}
166impl Accessor {
167    fn default_byte_offset() -> u32 { 0 }
168}
169#[derive(Serialize, Deserialize, Clone)]
170pub struct AnimationSampler {
171    pub input: u32,
172    #[serde(default="AnimationSampler::default_interpolation")]
173    pub interpolation: String,
174    pub output: u32,
175}
176impl AnimationSampler {
177    fn default_interpolation() -> String { "LINEAR".to_string() }
178}
179#[derive(Serialize, Deserialize, Clone)]
180pub struct AnimationChannelTarget {
181    node: Option<u32>,
182    path: String,
183}
184#[derive(Serialize, Deserialize, Clone)]
185pub struct AnimationChannel {
186    sampler: u32,
187    target: u32,
188}
189impl AnimationChannel {}
190#[derive(Serialize, Deserialize, Clone)]
191pub struct Animation {
192    channels: Vec<AnimationChannel>,
193    samplers: Vec<AnimationSampler>,
194}
195impl Animation {}
196#[derive(Serialize, Deserialize, Clone)]
197pub struct Buffer {
198    pub uri: Option<String>,
199    #[serde(rename="byteLength")]
200    pub byte_length: u32,
201    pub name: Option<String>
202}
203#[derive(Serialize, Deserialize, Clone)]
204pub struct BufferView {
205    pub buffer: u32,
206    #[serde(rename="byteOffset")]
207    #[serde(default="BufferView::default_byte_offset")]
208    pub byte_offset: u32,
209    #[serde(rename="byteLength")]
210    pub byte_length: u32,
211    #[serde(rename="byteStride")]
212    pub byte_stride: Option<u32>,
213    pub target: Option<u32>,
214    pub name: Option<String>
215}
216impl BufferView {
217    fn default_byte_offset() -> u32 { 0 }
218}
219#[derive(Serialize, Deserialize, Clone)]
220pub struct CameraOrthographic {
221    pub xmag: f64,
222    pub ymag: f64,
223    pub zfar: f64,
224    pub znear: f64,
225}
226#[derive(Serialize, Deserialize, Clone)]
227pub struct CameraPerspective {
228    #[serde(rename="aspectRatio")]
229    pub aspect_ratio: f64,
230    pub yfov: f64,
231    pub zfar: f64,
232    pub znear: f64,
233}
234#[derive(Serialize, Deserialize, Clone)]
235pub struct Camera {
236    pub orthographic: Option<CameraOrthographic>,
237    pub perspective: Option<CameraPerspective>,
238    #[serde(rename="type")]
239    pub camera_type: String,
240    pub name: Option<String>,
241}
242#[derive(Serialize, Deserialize, Clone)]
243pub struct Image {
244    pub uri: Option<String>,
245    #[serde(rename="mimeType")]
246    pub mime_type: Option<String>,
247    #[serde(rename="bufferView")]
248    pub buffer_view: Option<u32>,
249    pub name: Option<String>,
250}
251#[derive(Serialize, Deserialize, Clone)]
252pub struct TextureInfo {
253    pub index: u32,
254    #[serde(rename="texCoord")]
255    #[serde(default="TextureInfo::default_tex_coord")]
256    pub tex_coord: u32,
257}
258impl TextureInfo {
259    fn default_tex_coord() -> u32 { 0 }
260}
261#[derive(Serialize, Deserialize, Clone)]
262pub struct Pbr {
263    #[serde(rename="baseColorFactor")]
264    #[serde(default="Pbr::default_base_color_factor")]
265    pub base_color_factor: [f64; 4],
266    #[serde(rename="baseColorTexture")]
267    pub base_color_texture: Option<TextureInfo>,
268    #[serde(rename="metallicFactor")]
269    #[serde(default="Pbr::default_metallic_factor")]
270    pub metallic_factor: f64,
271    #[serde(rename="roughnessFactor")]
272    #[serde(default="Pbr::default_roughness_factor")]
273    pub roughness_factor: f64,
274    #[serde(rename="metallicRoughnessTexture")]
275    pub metallic_roughness_texture: Option<TextureInfo>,
276}
277impl Pbr {
278    fn default_base_color_factor() -> [f64; 4] { [1.0, 1.0, 1.0, 1.0] }
279    fn default_metallic_factor() -> f64 { 1.0 }
280    fn default_roughness_factor() -> f64 { 1.0 }
281}
282#[derive(Serialize, Deserialize, Clone)]
283pub struct NormalTexture {
284    pub index: u32,
285    #[serde(rename="texCoord")]
286    #[serde(default="NormalTexture::default_tex_coord")]
287    pub tex_coord: u32,
288    #[serde(default="NormalTexture::default_scale")]
289    pub scale: f64
290}
291impl NormalTexture {
292    fn default_tex_coord() -> u32 { 0 }
293    fn default_scale() -> f64 { 1.0 }
294}
295#[derive(Serialize, Deserialize, Clone)]
296pub struct OcclusionTexture {
297    pub index: u32,
298    #[serde(rename="texCoord")]
299    #[serde(default="OcclusionTexture::default_tex_coord")]
300    pub tex_coord: u32,
301    #[serde(default="OcclusionTexture::default_strength")]
302    pub strength: f64,
303}
304impl OcclusionTexture {
305    fn default_tex_coord() -> u32 { 0 }
306    fn default_strength() -> f64 { 1.0 }
307}
308#[derive(Serialize, Deserialize, Clone)]
309pub struct Material {
310    pub name: Option<String>,
311    #[serde(rename="pbrMetallicRoughness")]
312    pub pbr: Option<Pbr>,
313    #[serde(rename="normalTexture")]
314    pub normal_texture: Option<NormalTexture>,
315    #[serde(rename="occlusionTexture")]
316    pub occlusion_texture: Option<OcclusionTexture>,
317    #[serde(rename="emissiveTexture")]
318    pub emissive_texture: Option<TextureInfo>,
319    #[serde(rename="emissiveFactor")]
320    #[serde(default="Material::default_emissive_factor")]
321    pub emissive_factor: [f32; 3],
322    #[serde(rename="alphaMode")]
323    #[serde(default="Material::default_alpha_mode")]
324    pub alpha_mode: String,
325    #[serde(rename="alphaCutoff")]
326    #[serde(default="Material::default_alpha_cutoff")]
327    pub alpha_cutoff: f64,
328    #[serde(rename="doubleSided")]
329    #[serde(default="Material::default_double_sided")]
330    pub double_sided: bool,
331}
332impl Material {
333    fn default_emissive_factor() -> [f32; 3] { [0.0, 0.0, 0.0] }
334    fn default_alpha_mode() -> String { "OPAQUE".to_string() }
335    fn default_alpha_cutoff() -> f64 { 0.5 }
336    fn default_double_sided() -> bool { false }
337}
338#[derive(Serialize, Deserialize, Clone)]
339pub struct Primitive {
340    pub attributes: HashMap<String, u32>,
341    pub indices: Option<u32>,
342    pub material: Option<u32>,
343    #[serde(default = "Primitive::default_mode")]
344    pub mode: u32,
345}
346impl Primitive {
347    fn default_mode() -> u32 { 4 }
348}
349#[derive(Serialize, Deserialize, Clone)]
350pub struct Mesh {
351    pub primitives: Vec<Primitive>,
352    pub name: Option<String>
353}
354#[derive(Serialize, Deserialize, Clone)]
355pub struct Node {
356    pub camera: Option<u32>,
357    pub children: Option<Vec<u32>>,
358    #[serde(default = "Node::default_matrix")]
359    pub matrix: [f32; 16],
360    pub mesh: Option<u32>,
361    #[serde(default = "Node::default_rotation")]
362    pub rotation: [f32; 4],
363    #[serde(default = "Node::default_scale")]
364    pub scale: [f32; 3],
365    #[serde(default = "Node::default_translation")]
366    pub translation: [f32; 3],
367    pub name: Option<String>
368}
369impl Node {
370    fn default_matrix() -> [f32; 16] {
371        [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]
372    }
373    fn default_rotation() -> [f32; 4] { [0.0, 0.0, 0.0, 1.0] }
374    fn default_scale() -> [f32; 3] { [1.0, 1.0, 1.0] }
375    fn default_translation() -> [f32; 3] { [0.0, 0.0, 0.0] }
376}
377#[derive(Serialize, Deserialize, Clone)]
378pub struct Sampler {
379    #[serde(rename="magFilter")]
380    pub mag_filter: Option<u32>,
381    #[serde(rename="minFilter")]
382    pub min_filter: Option<u32>,
383    #[serde(rename="wrapS")]
384    #[serde(default="Sampler::default_wrap")]
385    pub wrap_s: u32,
386    #[serde(rename="wrapT")]
387    #[serde(default="Sampler::default_wrap")]
388    pub wrap_t: u32,
389}
390impl Sampler {
391    fn default_wrap() -> u32 { 10497 }
392}
393#[derive(Serialize, Deserialize, Clone)]
394pub struct Scene {
395    pub nodes: Option<Vec<u32>>,
396    pub name: Option<String>,
397}
398#[derive(Serialize, Deserialize, Clone)]
399pub struct Skin {
400    #[serde(rename="inverseBindMatrices")]
401    pub inverse_bind_matrices: Option<u32>,
402    pub skeleton: Option<u32>,
403    pub joints: Vec<u32>,
404}
405#[derive(Serialize, Deserialize, Clone)]
406pub struct Texture {
407    pub sampler: Option<u32>,
408    pub source: Option<u32>,
409    pub name: Option<String>,
410}