(data: &[u8])
| 766 | } |
| 767 | |
| 768 | fn load_gltf_animation(data: &[u8]) -> Option<ModelAnimation> { |
| 769 | let gltf = gltf::Gltf::from_slice(data).ok()?; |
| 770 | |
| 771 | // Get buffer data |
| 772 | let mut buffer_data: Vec<Vec<u8>> = Vec::new(); |
| 773 | for buffer in gltf.buffers() { |
| 774 | match buffer.source() { |
| 775 | gltf::buffer::Source::Bin => { |
| 776 | if let Some(blob) = gltf.blob.as_ref() { |
| 777 | buffer_data.push(blob.clone()); |
| 778 | } |
| 779 | } |
| 780 | gltf::buffer::Source::Uri(uri) => { |
| 781 | if let Some(encoded) = uri.strip_prefix("data:application/octet-stream;base64,") { |
| 782 | let mut decoded = Vec::new(); |
| 783 | let _ = base64_decode(encoded, &mut decoded); |
| 784 | buffer_data.push(decoded); |
| 785 | } else { |
| 786 | buffer_data.push(Vec::new()); |
| 787 | } |
| 788 | } |
| 789 | } |
| 790 | } |
| 791 | |
| 792 | // Parse skeleton from the first skin |
| 793 | let skeleton = if let Some(skin) = gltf.skins().next() { |
| 794 | let joints_nodes: Vec<_> = skin.joints().collect(); |
| 795 | let joint_count = joints_nodes.len(); |
| 796 | |
| 797 | // Build a mapping from node index to joint index |
| 798 | let mut node_to_joint = std::collections::HashMap::new(); |
| 799 | for (ji, node) in joints_nodes.iter().enumerate() { |
| 800 | node_to_joint.insert(node.index(), ji); |
| 801 | } |
| 802 | |
| 803 | // Read inverse bind matrices |
| 804 | let ibm_data = if let Some(accessor) = skin.inverse_bind_matrices() { |
| 805 | read_accessor_f32(&gltf, &buffer_data, &accessor) |
| 806 | } else { |
| 807 | let mut default_ibm = Vec::with_capacity(joint_count * 16); |
| 808 | for _ in 0..joint_count { |
| 809 | default_ibm.extend_from_slice(&[ |
| 810 | 1.0, 0.0, 0.0, 0.0, |
| 811 | 0.0, 1.0, 0.0, 0.0, |
| 812 | 0.0, 0.0, 1.0, 0.0, |
| 813 | 0.0, 0.0, 0.0, 1.0, |
| 814 | ]); |
| 815 | } |
| 816 | default_ibm |
| 817 | }; |
| 818 | |
| 819 | let mut joints = Vec::with_capacity(joint_count); |
| 820 | let mut root_joints = Vec::new(); |
| 821 | |
| 822 | for (ji, node) in joints_nodes.iter().enumerate() { |
| 823 | let mut ibm = [[0.0f32; 4]; 4]; |
| 824 | let base = ji * 16; |
| 825 | if base + 16 <= ibm_data.len() { |
no test coverage detected