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}