diff --git a/studio/src/anim/retargeting.rs b/studio/src/anim/retargeting.rs index d0d51fc..4e95b31 100644 --- a/studio/src/anim/retargeting.rs +++ b/studio/src/anim/retargeting.rs @@ -412,6 +412,12 @@ impl RetargetMap { ("mixamorig:LeftFoot", "DEF-foot.L"), ("mixamorig:LeftToeBase", "DEF-toe.L"), ]; + + ///This is a percentage total of the retargeting coverage + pub fn coverage(&self, names : impl IntoIterator) -> f32 { + let matches = names.into_iter().filter(|n| self.src_to_tgt.contains_key(n)).count(); + matches as f32 / self.src_to_tgt.len() as f32 + } } impl Default for RetargetMap { diff --git a/studio/src/bvh/loader.rs b/studio/src/bvh/loader.rs index 2b4b14f..a5f4d32 100644 --- a/studio/src/bvh/loader.rs +++ b/studio/src/bvh/loader.rs @@ -1,7 +1,9 @@ use bevy::{ - asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext}, - utils::BoxedFuture, + animation::{AnimationClip, EntityPath, Keyframes, VariableCurve}, asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext}, core::Name, math::{Quat, Vec3}, utils::BoxedFuture }; +use studio_bvh::Joint; + +use crate::anim::RetargetMap; use super::{ error::{Anyhow, Error}, @@ -12,7 +14,7 @@ use super::{ pub struct BvhLoader; impl AssetLoader for BvhLoader { - type Asset = Bvh; + type Asset = AnimationClip; type Settings = (); type Error = Error; @@ -26,8 +28,51 @@ impl AssetLoader for BvhLoader { let mut buf = vec![]; reader.read_to_end(&mut buf).await.anyhow()?; let bvh = studio_bvh::from_bytes(&buf).anyhow()?; + + let mut anim_clip = AnimationClip::default(); + + for joint in bvh.joints() { + let path = get_entity_path(&joint, &RetargetMap::default()); + let mut timestamps = Vec::new(); + let mut motions = Vec::new(); + let mut rotations = Vec::new(); + for (index, frame) in bvh.frames().enumerate() { + timestamps.push(index as f32 * bvh.frame_time().as_secs_f32()); + let mut frame_pos = Vec3::ZERO; + let mut frame_rot = Vec3::ZERO; + for channel in joint.channels() { + let target = match channel.channel_type() { + studio_bvh::ChannelType::PositionX => &mut frame_pos.x, + studio_bvh::ChannelType::PositionY => &mut frame_pos.y, + studio_bvh::ChannelType::PositionZ => &mut frame_pos.z, + studio_bvh::ChannelType::RotationX => &mut frame_rot.x, + studio_bvh::ChannelType::RotationY => &mut frame_rot.y, + studio_bvh::ChannelType::RotationZ => &mut frame_rot.z, + }; + + *target = frame[channel.motion_index()]; + } + + motions.push(frame_pos); + rotations.push(Quat::from_euler(bevy::math::EulerRot::ZXY, frame_rot.x, frame_rot.y, frame_rot.z)); + } + + if joint.is_root() { + let motion_curve = VariableCurve { + keyframe_timestamps: timestamps.clone(), + keyframes: Keyframes::Translation(motions), + }; + anim_clip.add_curve_to_path(path.clone(), motion_curve); + } + + let rotation_curve = VariableCurve { + keyframe_timestamps: timestamps, + keyframes: Keyframes::Rotation(rotations), + }; + anim_clip.add_curve_to_path(path, rotation_curve); + } - Ok(Bvh(bvh)) + Ok(anim_clip) }) } @@ -35,3 +80,18 @@ impl AssetLoader for BvhLoader { &["bvh"] } } + +pub fn get_entity_path(current_joint : &Joint, retarget_map : &RetargetMap) -> EntityPath { + let name = String::from_utf8_lossy(current_joint.name()).to_string(); + let name = retarget_map.src_to_tgt.get(&name).unwrap_or(&name).clone(); + + if let Some(parent) = current_joint.parent() { + let mut path = get_entity_path(&parent, retarget_map); + path.parts.push(Name::new(name)); + path + } else { + let mut path = EntityPath::default(); + path.parts.push(Name::new(name)); + path + } +} diff --git a/studio/src/bvh/mod.rs b/studio/src/bvh/mod.rs index fc50fe1..91b746b 100644 --- a/studio/src/bvh/mod.rs +++ b/studio/src/bvh/mod.rs @@ -45,7 +45,7 @@ impl Plugin for BvhPlugin { // TODO: Rename & reorganize #[derive(Resource, Deref, DerefMut)] -pub struct TestBvh(pub Handle); +pub struct TestBvh(pub Handle); // TODO: Rename & reorganize fn spawn_test_bvh( @@ -55,6 +55,9 @@ fn spawn_test_bvh( ) { for event in er_bvh_events.read() { if matches!(event, AssetEvent::LoadedWithDependencies { .. }) { + + + let ent = cmd.spawn_bvh_with_transform( &r_bvh.0, Transform::from_scale(Vec3::splat(0.06))