[BREAKING] BVH now loads into AnimationClips

This commit is contained in:
Brooks Palin
2024-03-12 00:41:53 -06:00
parent 7d5c490874
commit 5e16a1197d
3 changed files with 74 additions and 5 deletions
+6
View File
@@ -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<Item = String>) -> 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 {
+64 -4
View File
@@ -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
}
}
+4 -1
View File
@@ -45,7 +45,7 @@ impl Plugin for BvhPlugin {
// TODO: Rename & reorganize
#[derive(Resource, Deref, DerefMut)]
pub struct TestBvh(pub Handle<Bvh>);
pub struct TestBvh(pub Handle<AnimationClip>);
// 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))