enigma_3d/
object.rs

1use std::collections::HashMap;
2use std::vec::Vec;
3use glium::Display;
4use glium::glutin::surface::WindowSurface;
5use crate::geometry::{BoneTransforms, BoundingBox, Vertex};
6use nalgebra::{Vector3, Matrix4, Translation3, UnitQuaternion, Point3};
7use crate::{animation, debug_geo, geometry, smart_format};
8use uuid::Uuid;
9
10
11use std::fs::File;
12use std::io::BufReader;
13use glium::uniforms::UniformBuffer;
14use nalgebra_glm::normalize;
15use obj::{load_obj, Obj};
16use serde::{Deserialize, Serialize};
17use crate::animation::{AnimationState, MAX_BONES};
18use crate::logging::{EnigmaError, EnigmaMessage, EnigmaWarning};
19
20pub struct ObjectInstance {
21    pub vertex_buffers: Vec<(glium::vertex::VertexBufferAny, usize)>,
22    pub index_buffers: Vec<glium::IndexBuffer<u32>>,
23    pub instance_matrices: Vec<[[f32; 4]; 4]>,
24    pub instance_attributes: glium::VertexBuffer<geometry::InstanceAttribute>,
25}
26
27#[derive(Serialize, Deserialize, Clone)]
28pub struct ObjectSerializer {
29    pub name: String,
30    pub transform: TransformSerializer,
31    collision: bool,
32    shapes: Vec<Shape>,
33    materials: Vec<String>,
34    unique_id: String,
35    cloned_id: String,
36    animations: HashMap<String, animation::AnimationSerializer>,
37    skeleton: Option<animation::SkeletonSerializer>,
38}
39
40pub struct Object {
41    pub name: String,
42    pub transform: Transform,
43    collision: bool,
44    shapes: Vec<Shape>,
45    materials: Vec<Uuid>,
46    bounding_box: Option<geometry::BoundingBox>,
47    unique_id: Uuid,
48    cloned_id: Uuid,
49    animations: HashMap<String, animation::Animation>,
50    skeleton: Option<animation::Skeleton>,
51    current_animation: Option<AnimationState>,
52}
53
54impl Clone for Object {
55    fn clone(&self) -> Self {
56        //creating new object
57        let mut new_object = Object::new(Some(self.name.clone()));
58
59        //setting transform for new object
60        new_object.transform.set_position(self.transform.get_position().into());
61        new_object.transform.set_rotation(self.transform.get_rotation().into());
62        new_object.transform.set_scale(self.transform.get_scale().into());
63
64        //cloning shapes
65        for shape in self.shapes.iter() {
66            let mut new_shape = Shape::new();
67            new_shape.vertices = shape.vertices.clone();
68            new_shape.indices = shape.indices.clone();
69            new_shape.material_index = shape.material_index;
70            new_object.add_shape(new_shape);
71        }
72
73        //cloning materials
74        new_object.materials = self.materials.clone();
75
76        new_object.bounding_box = self.bounding_box.clone();
77        new_object.unique_id = Uuid::new_v4();
78        new_object.cloned_id = self.unique_id;
79        new_object.animations = self.animations.clone();
80        new_object.skeleton = self.skeleton.clone();
81        new_object
82    }
83}
84
85#[derive(Serialize, Deserialize)]
86pub struct Shape {
87    pub vertices: Vec<Vertex>,
88    pub indices: Vec<u32>,
89    pub material_index: usize,
90}
91
92impl Clone for Shape {
93    fn clone(&self) -> Self {
94        Shape {
95            vertices: self.vertices.clone(),
96            indices: self.indices.clone(),
97            material_index: self.material_index,
98        }
99    }
100}
101
102impl Shape {
103    pub fn new() -> Self {
104        Shape {
105            vertices: Vec::new(),
106            indices: Vec::new(),
107            material_index: 0,
108        }
109    }
110
111    pub fn from_vertices_indices(vertices: Vec<Vertex>, indices: Vec<u32>) -> Self {
112        Shape {
113            vertices,
114            indices,
115            material_index: 0,
116        }
117    }
118
119    pub fn default() -> Self {
120        let triangle = debug_geo::TRIANGLE;
121        let mut shape = Shape::new();
122        shape.vertices = triangle.to_vec();
123        for i in 0..triangle.iter().len() {
124            shape.indices.push(i as u32);
125        }
126        shape
127    }
128
129    pub fn get_vertex_buffer(&self, display: Display<WindowSurface>) -> glium::VertexBuffer<Vertex> {
130        glium::VertexBuffer::new(&display, &self.vertices).unwrap()
131    }
132
133    pub fn get_index_buffer(&self, display: Display<WindowSurface>) -> glium::IndexBuffer<u32> {
134        glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList, &self.indices).unwrap()
135    }
136
137    pub fn set_material_from_object_list(&mut self, material_index: usize) {
138        self.material_index = material_index;
139    }
140}
141
142impl ObjectInstance {
143    pub fn new(display: &Display<WindowSurface>) -> Self {
144        Self {
145            vertex_buffers: Vec::new(),
146            index_buffers: Vec::new(),
147            instance_matrices: Vec::new(),
148            instance_attributes: glium::vertex::VertexBuffer::dynamic(display, &Vec::new()).expect("Building ObjectInstance, Per Instance Attribute could not be created"),
149        }
150    }
151
152    pub fn set_vertex_buffers(&mut self, buffers: Vec<(glium::vertex::VertexBufferAny, usize)>) {
153        self.vertex_buffers = buffers;
154    }
155
156    pub fn set_index_buffers(&mut self, buffers: Vec<glium::IndexBuffer<u32>>) {
157        self.index_buffers = buffers;
158    }
159
160    pub fn add_instance(&mut self, instance: [[f32; 4]; 4]) {
161        self.instance_matrices.push(instance);
162    }
163}
164
165impl Object {
166    pub fn new(name: Option<String>) -> Self {
167        let uuid = Uuid::new_v4();
168        let mut object = Object {
169            name: name.unwrap_or_else(|| String::from("Object")),
170            transform: Transform::new(),
171            shapes: Vec::new(),
172            materials: Vec::new(),
173            bounding_box: None,
174            unique_id: uuid,
175            cloned_id: uuid,
176            collision: true,
177            animations: HashMap::new(),
178            skeleton: None,
179            current_animation: None,
180        };
181        object.calculate_bounding_box();
182        object
183    }
184
185    pub fn to_serializer(&self) -> ObjectSerializer {
186        let name = self.name.clone();
187        let transform = self.transform.to_serializer();
188        let mut animations = HashMap::new();
189        for (n, a) in &self.animations {
190            animations.insert(n.to_string(), a.to_serializer());
191        }
192        let shapes = self.shapes.clone();
193        let materials = self.materials.iter().map(|x| x.to_string()).collect();
194        let unique_id = self.unique_id.to_string();
195        let cloned_id = self.cloned_id.to_string();
196        ObjectSerializer {
197            name,
198            transform,
199            shapes,
200            materials,
201            unique_id,
202            cloned_id,
203            collision: self.collision,
204            animations,
205            skeleton: match &self.skeleton {
206                Some(skeleton) => Some(skeleton.to_serializer()),
207                None => None
208            },
209        }
210    }
211
212    pub fn from_serializer(serializer: ObjectSerializer) -> Self {
213        let mut object = Object::new(Some(serializer.name));
214        object.transform = Transform::from_serializer(serializer.transform);
215        object.shapes = serializer.shapes;
216        for mat in serializer.materials {
217            object.add_material(Uuid::parse_str(mat.as_str()).expect("failed to parse material uuid"));
218        }
219        object.unique_id = uuid::Uuid::parse_str(serializer.unique_id.as_str()).unwrap();
220        object.cloned_id = uuid::Uuid::parse_str(serializer.cloned_id.as_str()).unwrap();
221        object.collision = serializer.collision;
222        object.calculate_bounding_box();
223
224        let mut animations = HashMap::new();
225        for (n, s) in serializer.animations {
226            let anim = animation::Animation::from_serializer(s);
227            animations.insert(n, anim);
228        }
229        object.animations = animations;
230        object.skeleton = match serializer.skeleton {
231            Some(s) => Some(animation::Skeleton::from_serializer(s)),
232            None => None
233        };
234        object
235    }
236
237    pub fn set_collision(&mut self, collision: bool) {
238        self.collision = collision;
239    }
240
241    pub fn get_collision(&self) -> &bool {
242        &self.collision
243    }
244
245    pub fn get_unique_id(&self) -> Uuid {
246        self.unique_id
247    }
248
249    pub fn get_instance_id(&self) -> Uuid {
250        self.cloned_id
251    }
252
253    pub fn break_instance(&mut self) {
254        self.cloned_id = self.unique_id;
255    }
256
257    fn calculate_bounding_box(&mut self) -> BoundingBox {
258        let mut min_x = f32::INFINITY;
259        let mut min_y = f32::INFINITY;
260        let mut min_z = f32::INFINITY;
261        let mut max_x = f32::NEG_INFINITY;
262        let mut max_y = f32::NEG_INFINITY;
263        let mut max_z = f32::NEG_INFINITY;
264
265        for shape in self.get_shapes().iter() {
266            for vertex in shape.vertices.iter() {
267                min_x = min_x.min(vertex.position[0]);
268                min_y = min_y.min(vertex.position[1]);
269                min_z = min_z.min(vertex.position[2]);
270                max_x = max_x.max(vertex.position[0]);
271                max_y = max_y.max(vertex.position[1]);
272                max_z = max_z.max(vertex.position[2]);
273            }
274        }
275
276        let min_point = Point3::new(min_x, min_y, min_z);
277        let max_point = Point3::new(max_x, max_y, max_z);
278
279        let center = Point3::new(
280            (min_point.x + max_point.x) / 2.0,
281            (min_point.y + max_point.y) / 2.0,
282            (min_point.z + max_point.z) / 2.0,
283        );
284        self.transform.update();
285        let transformed_center = self.transform.matrix.transform_point(&center);
286        let transformed_width = (max_x - min_x) * self.transform.get_scale().x;
287        let transformed_height = (max_y - min_y) * self.transform.get_scale().y;
288        let transformed_depth = (max_z - min_z) * self.transform.get_scale().z;
289
290        let aabb = BoundingBox {
291            center: Vector3::from([transformed_center.x, transformed_center.y, transformed_center.z]),
292            width: transformed_width,
293            height: transformed_height,
294            depth: transformed_depth,
295        };
296        self.bounding_box = Some(aabb);
297        aabb
298    }
299
300    pub fn default() -> Self {
301        let mut object = Object::new(None);
302        object.add_shape(Shape::default());
303        object
304    }
305
306    fn update_animation_internal(&mut self, delta_time: f32) {
307        if let Some(anim_state) = &mut self.current_animation {
308            if let Some(animation) = self.animations.get(&anim_state.name) {
309                anim_state.time += delta_time * anim_state.speed;
310                if anim_state.time > animation.duration {
311                    if anim_state.looping {
312                        anim_state.time %= animation.duration;
313                    } else {
314                        anim_state.time = animation.duration;
315                    }
316                }
317            }
318        }
319    }
320
321    pub fn has_skeletal_animation(&self) -> bool {
322        self.skeleton.is_some() && !self.animations.is_empty()
323    }
324
325    #[allow(unreachable_code)]
326    pub fn get_bone_transform_buffer(&self, display: &Display<WindowSurface>) -> UniformBuffer<BoneTransforms> {
327        let bone_transform_data = BoneTransforms {
328            bone_transforms: [[[1.0; 4]; 4]; MAX_BONES],
329        };
330        // temporary returning empty buffer. skeletal meshes are not working in this version so no need to do calculations
331        return UniformBuffer::new(display, bone_transform_data).expect("Failed to create BoneTransform Buffer");
332
333        if let (Some(skeleton), Some(anim_state)) = (&self.skeleton, &self.current_animation) {
334            if let Some(animation) = self.animations.get(anim_state.name.as_str()) {
335                let mut global_transforms = vec![Matrix4::identity(); skeleton.bones.len()];
336
337                for (i, bone) in skeleton.bones.iter().enumerate() {
338                    let local_transform = self.interpolate_keyframes(animation, i, anim_state.time);
339                    let parent_transform: Matrix4<f32> = bone.parent_id
340                        .map(|id| global_transforms[id])
341                        .unwrap_or_else(Matrix4::identity);
342
343                    global_transforms[i] = parent_transform * local_transform;
344                    let final_transform: Matrix4<f32> = global_transforms[i] * bone.inverse_bind_pose;
345
346                    bone_transform_data.bone_transforms[i] = final_transform.into();
347
348                    EnigmaWarning::new(Some(smart_format!("Bone {}: {}", i, final_transform).as_str()), true).log();
349                }
350            }
351        }
352
353        UniformBuffer::new(display, bone_transform_data).expect("Failed to create BoneTransform Buffer")
354    }
355
356    fn interpolate_keyframes(&self, animation: &animation::Animation, bone_id: usize, time: f32) -> Matrix4<f32> {
357        if let Some(channel) = animation.channels.iter().find(|c| c.bone_id == bone_id) {
358            let mut prev_keyframe = &channel.keyframes[0];
359            let mut next_keyframe = prev_keyframe;
360
361            for keyframe in &channel.keyframes {
362                if keyframe.time > time {
363                    next_keyframe = keyframe;
364                    break;
365                }
366                prev_keyframe = keyframe;
367            }
368
369            let t = (time - prev_keyframe.time) / (next_keyframe.time - prev_keyframe.time);
370
371            match (&prev_keyframe.transform, &next_keyframe.transform) {
372                (animation::AnimationTransform::Translation(prev), animation::AnimationTransform::Translation(next)) => {
373                    let interpolated = Vector3::new(
374                        prev[0] + (next[0] - prev[0]) * t,
375                        prev[1] + (next[1] - prev[1]) * t,
376                        prev[2] + (next[2] - prev[2]) * t,
377                    );
378                    Matrix4::new_translation(&interpolated)
379                }
380                (animation::AnimationTransform::Rotation(prev), animation::AnimationTransform::Rotation(next)) => {
381                    let prev_quat = UnitQuaternion::from_quaternion(nalgebra::Quaternion::new(prev[3], prev[0], prev[1], prev[2]));
382                    let next_quat = UnitQuaternion::from_quaternion(nalgebra::Quaternion::new(next[3], next[0], next[1], next[2]));
383                    prev_quat.slerp(&next_quat, t).to_homogeneous()
384                }
385                (animation::AnimationTransform::Scale(prev), animation::AnimationTransform::Scale(next)) => {
386                    let interpolated = Vector3::new(
387                        prev[0] + (next[0] - prev[0]) * t,
388                        prev[1] + (next[1] - prev[1]) * t,
389                        prev[2] + (next[2] - prev[2]) * t,
390                    );
391                    Matrix4::new_nonuniform_scaling(&interpolated)
392                }
393                _ => Matrix4::identity(),
394            }
395        } else {
396            Matrix4::identity()
397        }
398    }
399
400    pub fn play_animation(&mut self, name: &str, looping: bool) {
401        if let Some(_) = self.animations.get(name) {
402            self.current_animation = Some(AnimationState {
403                name: name.to_string(),
404                time: 0.0,
405                speed: 1.0,
406                looping,
407            });
408        }
409    }
410
411    pub fn stop_animation(&mut self) {
412        self.current_animation = None;
413    }
414
415    pub fn get_current_animation(&self) -> &Option<AnimationState> {
416        &self.current_animation
417    }
418
419    pub fn update(&mut self, delta_time: f32) {
420        self.transform.update();
421        if self.skeleton.is_some() && self.current_animation.is_some() {
422            self.update_animation_internal(delta_time);
423        }
424    }
425
426    pub fn get_closest_lights(&self, lights: &Vec<crate::light::Light>) -> Vec<crate::light::Light> {
427        let mut closest_lights = Vec::new();
428
429        //collect the four closest lights to the object
430        for light in lights.iter() {
431            let light_pos = light.position;
432            let object_pos = self.transform.get_position();
433            let distance = (Vector3::from(light_pos) - object_pos).magnitude();
434            if closest_lights.len() < 4 {
435                closest_lights.push((light.clone(), distance));
436            } else {
437                let mut max_distance = 0.0;
438                let mut max_index = 0;
439                for (index, (_, distance)) in closest_lights.iter().enumerate() {
440                    if *distance > max_distance {
441                        max_distance = *distance;
442                        max_index = index;
443                    }
444                }
445                if distance < max_distance {
446                    closest_lights[max_index] = (light.clone(), distance.clone());
447                }
448            }
449        }
450        closest_lights.iter().map(|(light, _)| light.clone()).collect()
451    }
452
453    pub fn add_shape(&mut self, shape: Shape) {
454        self.shapes.push(shape);
455    }
456
457    pub fn get_vertex_buffers(&self, display: &Display<WindowSurface>) -> Vec<(glium::vertex::VertexBufferAny, usize)> {
458        let shapes = self.get_shapes();
459        let mut buffer = Vec::new();
460        for shape in shapes.iter() {
461            let vertex: glium::vertex::VertexBufferAny = glium::VertexBuffer::new(display, &shape.vertices).unwrap().into();
462            buffer.push((vertex, shape.material_index));
463        }
464        buffer
465    }
466
467    pub fn get_index_buffers(&self, display: &Display<WindowSurface>) -> Vec<glium::IndexBuffer<u32>> {
468        let shapes = self.get_shapes();
469        let mut buffer = Vec::new();
470        for shape in shapes.iter() {
471            let index = glium::IndexBuffer::new(display, glium::index::PrimitiveType::TrianglesList, &shape.indices).unwrap();
472            buffer.push(index);
473        }
474        buffer
475    }
476    pub fn get_bounding_box(&mut self) -> BoundingBox {
477        self.calculate_bounding_box()
478    }
479
480    pub fn get_materials(&self) -> &Vec<Uuid> {
481        &self.materials
482    }
483
484    pub fn get_materials_mut(&mut self) -> &mut Vec<Uuid> {
485        &mut self.materials
486    }
487
488    pub fn add_material(&mut self, material: Uuid) {
489        self.materials.push(material);
490    }
491
492    pub fn get_shapes(&self) -> &Vec<Shape> {
493        &self.shapes
494    }
495
496    pub fn get_shapes_mut(&mut self) -> &mut Vec<Shape> {
497        &mut self.shapes
498    }
499
500    pub fn get_name(&self) -> &String {
501        &self.name
502    }
503
504    pub fn set_name(&mut self, name: String) {
505        self.name = name;
506    }
507
508    pub fn get_animations(&self) -> &HashMap<String, animation::Animation> {
509        &self.animations
510    }
511    pub fn get_animations_mut(&mut self) -> &mut HashMap<String, animation::Animation> {
512        &mut self.animations
513    }
514
515    pub fn get_skeleton(&self) -> &Option<animation::Skeleton> {
516        &self.skeleton
517    }
518
519    pub fn get_skeleton_mut(&mut self) -> &mut Option<animation::Skeleton> {
520        &mut self.skeleton
521    }
522
523    pub fn try_fix_object(&mut self) -> Result<EnigmaMessage, EnigmaError> {
524        let mut errors = EnigmaError::new(None, true);
525        if let Some(skeleton) = &mut self.skeleton {
526            match skeleton.try_fix() {
527                Ok(_) => {},
528                Err(e) => errors.merge(e),
529            }
530        }
531
532        if !errors.is_empty() {
533            Err(errors)
534        } else {
535            Ok(EnigmaMessage::new(Some(&smart_format!("Nothing to Repair on Object {:?}", self.get_name())), true))
536        }
537    }
538
539    pub fn load_from_obj(path: &str) -> Self {
540        let input = BufReader::new(File::open(path).expect("Failed to open file"));
541        let obj: Obj = load_obj(input).unwrap();
542        let mut vertices = Vec::new();
543        let mut indices = Vec::new();
544        for vert in obj.vertices.iter() {
545            let vertex = geometry::Vertex { position: vert.position, color: [1.0, 1.0, 1.0], texcoord: [0.0, 0.0], normal: vert.normal, bone_indices: [0, 0, 0, 0], bone_weights: [0.0, 0.0, 0.0, 0.0] };
546            vertices.push(vertex);
547        }
548        for index in obj.indices.iter() {
549            indices.push((*index).into());
550        }
551
552        let shape = Shape::from_vertices_indices(vertices, indices);
553        let mut object = Object::new(obj.name);
554        object.add_shape(shape);
555        object
556    }
557
558    pub fn load_from_gltf_resource(data: &[u8], rig_scale_multiplier: Option<f32>) -> Self {
559        let (gltf, buffers, images) = gltf::import_slice(data).expect("Failed to import gltf file"); // gltf::import(path).expect("Failed to import gltf file");
560        let object = Object::new(Some(String::from("INTERNAL ENIGMA RESOURCE")));
561        Object::load_from_gltf_internal((gltf, buffers, images), object, rig_scale_multiplier.unwrap_or_else(|| 1.0f32))
562    }
563
564    pub fn load_from_gltf(path: &str, rig_scale_multiplier: Option<f32>) -> Self {
565        let (gltf, buffers, images) = gltf::import(path).expect("Failed to import gltf file");
566        let object = Object::new(Some(String::from(path)));
567        Object::load_from_gltf_internal((gltf, buffers, images), object, rig_scale_multiplier.unwrap_or_else(|| 1.0f32))
568    }
569
570    fn load_from_gltf_internal(content: (gltf::Document, Vec<gltf::buffer::Data>, Vec<gltf::image::Data>), mut object: Object, rig_scale_multiplier: f32) -> Self {
571        let (gltf, buffers, _images) = content;
572        for mesh in gltf.meshes() {
573            let mut vertices = Vec::new();
574            let mut indices = Vec::new();
575            for primitive in mesh.primitives() {
576                let reader = primitive.reader(|buffer| buffers.get(buffer.index()).map(|data| &data[..]));
577
578                let positions = reader.read_positions().unwrap();
579                let normals = reader.read_normals().unwrap();
580                let tex_coords = reader.read_tex_coords(0).unwrap().into_f32();
581                let prim_indices = reader.read_indices().unwrap().into_u32();
582
583                // Read skinning data
584                let joints = reader.read_joints(0).map(|j| j.into_u16());
585                let weights = reader.read_weights(0).map(|w| w.into_f32());
586
587                let mut flipped_tex_coords: Vec<[f32; 2]> = Vec::new();
588                for mut tex_coord in tex_coords.into_iter() {
589                    tex_coord[1] = 1.0 - tex_coord[1];
590                    flipped_tex_coords.push(tex_coord);
591                }
592
593                let mut joint_data = joints.map(|j| j.map(|arr| [arr[0] as u32, arr[1] as u32, arr[2] as u32, arr[3] as u32]));
594                let mut weight_data = weights;
595
596                for ((position, normal), tex_coord) in positions.zip(normals).zip(flipped_tex_coords) {
597                    let bone_indices = joint_data.as_mut().and_then(|j| j.next()).unwrap_or([0; 4]);
598                    let bone_weight = weight_data.as_mut().and_then(|w| w.next()).unwrap_or([0.0; 4]);
599                    let vertex = Vertex {
600                        position,
601                        texcoord: tex_coord,
602                        color: [1.0, 1.0, 1.0],
603                        normal,
604                        bone_indices,
605                        bone_weights: bone_weight,
606                    };
607                    vertices.push(vertex);
608                }
609
610                indices.extend(prim_indices);
611            }
612            let shape = Shape::from_vertices_indices(vertices, indices);
613            object.add_shape(shape);
614        }
615
616        if let Some(skin) = gltf.skins().next() {
617            let skeleton = Object::load_skeleton_internal(&gltf, &skin, &buffers, rig_scale_multiplier);
618            match skeleton.validate() {
619                Err(e) => e.log(),
620                Ok(_) => ()
621            }
622            object.skeleton = Some(skeleton)
623
624        }
625        let animations = gltf.animations();
626        for (i, animation) in animations.enumerate() {
627            let loaded_anim = Object::load_animation_internal(&animation, &buffers, i, 1.);
628            object.animations.insert(loaded_anim.name.clone(), loaded_anim);
629        }
630        object
631    }
632
633    fn load_skeleton_internal(document: &gltf::Document, skin: &gltf::Skin, buffers: &[gltf::buffer::Data], multiplier: f32) -> animation::Skeleton {
634        let reader = skin.reader(|buffer| Some(&buffers[buffer.index()]));
635
636        // Get joints from the skin
637        let joints: Vec<gltf::Node> = skin.joints().collect();
638
639        // Read inverse bind matrices
640        let mut inverse_bind_matrices: Vec<Matrix4<f32>> = reader.read_inverse_bind_matrices()
641            .map(|iter| iter.map(Matrix4::from).collect())
642            .unwrap_or_else(|| vec![Matrix4::identity(); joints.len()]);
643
644        // apply scale multiplier
645        inverse_bind_matrices = inverse_bind_matrices.iter_mut().map(|x| *x * multiplier).collect();
646
647        // Create a map of child to parent relationships
648        let mut parent_map = HashMap::new();
649        for node in document.nodes() {
650            for child in node.children() {
651                parent_map.insert(child.index(), node.index());
652            }
653        }
654
655        let bones = joints.into_iter().enumerate().zip(inverse_bind_matrices).map(|((id, joint), ibm)| {
656            animation::Bone {
657                name: joint.name().unwrap_or("").to_string(),
658                id,
659                parent_id: parent_map.get(&joint.index()).cloned(),
660                inverse_bind_pose: ibm,
661            }
662        }).collect();
663
664        animation::Skeleton { bones }
665    }
666
667    fn load_animation_internal(anim: &gltf::Animation, buffers: &[gltf::buffer::Data], padding: usize, multiplier: f32) -> animation::Animation {
668        let mut channels = Vec::new();
669        let mut duration: f32 = 0.0;
670        let name = match anim.name() {
671            Some(n) => n.to_string(),
672            None => format!("animation_{}", padding)
673        };
674        for channel in anim.channels() {
675            let reader = channel.reader(|buffer| Some(&buffers[buffer.index()]));
676            let bone_id = channel.target().node().index();
677            let mut keyframes = Vec::new();
678            if let (Some(times), Some(outputs)) = (reader.read_inputs(), reader.read_outputs()) {
679                let times: Vec<f32> = times.collect();
680                // Update max_time
681                if let Some(&channel_duration) = times.iter().max_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)) {
682                    duration = duration.max(channel_duration);
683                }
684                match outputs {
685                    gltf::animation::util::ReadOutputs::Translations(translations) => {
686                        for (i, translation) in translations.enumerate() {
687                            let translation = Vector3::from(translation);
688                            keyframes.push(animation::AnimationKeyframe {
689                                time: times[i],
690                                transform: animation::AnimationTransform::Translation((translation * multiplier).into()),
691                            });
692                        }
693                    }
694                    gltf::animation::util::ReadOutputs::Rotations(rotations) => {
695                        for (i, rotation) in rotations.into_f32().enumerate() {
696                            let rotation = UnitQuaternion::from_quaternion(
697                                nalgebra::Quaternion::new(rotation[3], rotation[0], rotation[1], rotation[2])
698                            );
699                            keyframes.push(animation::AnimationKeyframe {
700                                time: times[i],
701                                transform: animation::AnimationTransform::Rotation([rotation[0], rotation[1], rotation[2], rotation[3]]),
702                            });
703                        }
704                    }
705                    gltf::animation::util::ReadOutputs::Scales(scales) => {
706                        for (i, scale) in scales.enumerate() {
707                            let scale = Vector3::from(scale);
708                            keyframes.push(animation::AnimationKeyframe {
709                                time: times[i],
710                                transform: animation::AnimationTransform::Scale((scale * multiplier).into()),
711                            });
712                        }
713                    }
714                    gltf::animation::util::ReadOutputs::MorphTargetWeights(_) => {
715                        // Handle morph target weights if needed
716                        // For now, we'll just ignore these
717                    }
718                }
719            }
720
721            if !keyframes.is_empty() {
722                channels.push(animation::AnimationChannel { bone_id, keyframes });
723            }
724        }
725
726        animation::Animation {
727            name,
728            duration,
729            channels,
730        }
731    }
732}
733
734#[derive(Serialize, Deserialize, Clone)]
735pub struct TransformSerializer {
736    position: [f32; 3],
737    rotation: [f32; 3],
738    scale: [f32; 3],
739}
740
741#[derive(Copy, Clone)]
742pub struct Transform {
743    pub position: Vector3<f32>,
744    pub rotation: Vector3<f32>,
745    // radian angles
746    pub scale: Vector3<f32>,
747    pub matrix: Matrix4<f32>,
748}
749
750impl Transform {
751    pub fn new() -> Self {
752        Transform {
753            position: Vector3::new(0.0, 0.0, 0.0),
754            rotation: Vector3::new(0.0, 0.0, 0.0),
755            scale: Vector3::new(1.0, 1.0, 1.0),
756            matrix: Matrix4::identity(),
757        }
758    }
759
760    pub fn forward(&self) -> Vector3<f32> {
761        // return the forward vector of the transform with positive z being forward
762        let rotation = UnitQuaternion::from_euler_angles(self.rotation.x, self.rotation.y, self.rotation.z);
763        let forward = rotation * Vector3::new(0.0, 0.0, 1.0);
764        normalize(&forward)
765    }
766
767    pub fn left(&self) -> Vector3<f32> {
768        // return the left vector of the transform with positive x being left
769        let rotation = UnitQuaternion::from_euler_angles(self.rotation.x, self.rotation.y, self.rotation.z);
770        let left = rotation * Vector3::new(-1.0, 0.0, 0.0);
771        normalize(&left)
772    }
773
774    pub fn up(&self) -> Vector3<f32> {
775        // return the up vector of the transform with positive y being up
776        let rotation = UnitQuaternion::from_euler_angles(self.rotation.x, self.rotation.y, self.rotation.z);
777        let up = rotation * Vector3::new(0.0, 1.0, 0.0);
778        normalize(&up)
779    }
780
781    pub fn from_serializer(serializer: TransformSerializer) -> Self {
782        let mut t = Transform::new();
783        t.set_position(serializer.position);
784        t.set_rotation(serializer.rotation);
785        t.set_scale(serializer.scale);
786        t
787    }
788
789    pub fn to_serializer(&self) -> TransformSerializer {
790        TransformSerializer {
791            position: self.get_position().into(),
792            rotation: self.get_rotation().into(),
793            scale: self.get_scale().into(),
794        }
795    }
796
797    pub fn update(&mut self) {
798        let scale_matrix = Matrix4::new_nonuniform_scaling(&self.scale);
799        let rotation_matrix = UnitQuaternion::from_euler_angles(self.rotation.x, self.rotation.y, self.rotation.z).to_homogeneous();
800        let translation_matrix = Translation3::from(self.position).to_homogeneous();
801        // Scale, then rotate, then translate
802        self.matrix = translation_matrix * rotation_matrix * scale_matrix;
803    }
804
805
806    pub fn set_position(&mut self, position: [f32; 3]) {
807        self.position = Vector3::from(position);
808    }
809
810    pub fn get_position(&self) -> Vector3<f32> {
811        self.position.clone()
812    }
813
814    pub fn set_rotation(&mut self, rotation: [f32; 3]) {
815        let radians = rotation.iter().map(|x| x.to_radians()).collect::<Vec<f32>>();
816        self.rotation = Vector3::from([radians[0], radians[1], radians[2]]);
817    }
818
819    pub fn rotate(&mut self, rotation: [f32; 3]) {
820        let cur_r = self.get_rotation();
821        let additive_rotation = [cur_r.x + rotation[0], cur_r.y + rotation[1], cur_r.z + rotation[2]];
822        let radians = additive_rotation.iter().map(|x| x.to_radians()).collect::<Vec<f32>>();
823        self.rotation = Vector3::from([radians[0], radians[1], radians[2]]);
824    }
825
826    pub fn move_dir_array(&mut self, position: [f32; 3]) {
827        let cur_p = self.get_position();
828        let additive_position = [cur_p.x + position[0], cur_p.y + position[1], cur_p.z + position[2]];
829        self.position = Vector3::from(additive_position);
830    }
831
832    pub fn move_dir_vector(&mut self, direction: Vector3<f32>) {
833        self.position += direction;
834    }
835
836    pub fn get_rotation(&self) -> Vector3<f32> {
837        let x = self.rotation.x.to_degrees();
838        let y = self.rotation.y.to_degrees();
839        let z = self.rotation.z.to_degrees();
840        Vector3::from([x, y, z])
841    }
842
843    pub fn set_scale(&mut self, scale: [f32; 3]) {
844        self.scale = Vector3::from(scale);
845    }
846
847    pub fn get_scale(&self) -> Vector3<f32> {
848        self.scale.clone()
849    }
850
851    pub fn get_matrix(&mut self) -> [[f32; 4]; 4] {
852        self.update();
853        self.matrix.into()
854    }
855
856    pub fn get_matrix_object(&mut self) -> Matrix4<f32> {
857        self.update();
858        self.matrix
859    }
860
861    pub fn lerp(&self, other: &Self, t: f32) -> Self {
862        let position = self.get_position().lerp(&other.get_position(), t);
863        let scale = self.get_scale().lerp(&other.get_scale(), t);
864        let rotation = self.get_rotation().slerp(&other.get_rotation(), t);
865
866        let mut result = Self::new();
867        result.set_position(position.into());
868        result.set_scale(scale.into());
869        result.set_rotation(rotation.into());
870        result
871    }
872}