mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-17 00:13:17 +00:00
[BREAKING] BVH now loads into AnimationClips
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user