checkpoint

This commit is contained in:
Brooks Palin
2024-01-10 14:00:16 -07:00
parent f0a8588273
commit d30b790fa0
5 changed files with 172 additions and 113 deletions
Binary file not shown.
Binary file not shown.
+158 -105
View File
@@ -13,13 +13,14 @@ use bevy::{
utils::hashbrown::HashMap, utils::hashbrown::HashMap,
}; };
use bevy_inspector_egui::egui::TextBuffer; use bevy_inspector_egui::egui::TextBuffer;
use bevy_mod_picking::prelude::EntityEvent;
use bevy_rapier3d::parry::transformation; use bevy_rapier3d::parry::transformation;
use studio_bvh::{frames::Frame, joint}; use studio_bvh::{frames::Frame, joint};
mod error; mod error;
mod loader; mod loader;
use crate::scene::SceneState; use crate::{debug::print_mat3, scene::SceneState};
use self::loader::BvhLoader; use self::loader::BvhLoader;
@@ -31,7 +32,10 @@ impl Plugin for BvhPlugin {
.register_asset_loader(BvhLoader) .register_asset_loader(BvhLoader)
.add_systems(Update, animate_bvh.run_if(in_state(SceneState::Active))) .add_systems(Update, animate_bvh.run_if(in_state(SceneState::Active)))
.register_type::<BvhJoint>() .register_type::<BvhJoint>()
.register_type::<BvhAnim>(); .register_type::<BvhAnim>()
//Events
.add_event::<UpdateBVHAnim>()
.add_systems(PreUpdate, update_bvh_anim);
} }
} }
@@ -49,6 +53,8 @@ pub struct BvhAnim {
should_play: bool, should_play: bool,
frame: usize, frame: usize,
#[reflect(ignore)] #[reflect(ignore)]
retarget: Option<RetargetMap>,
#[reflect(ignore)]
timer: Timer, timer: Timer,
#[reflect(ignore)] #[reflect(ignore)]
last_frame: usize, last_frame: usize,
@@ -99,49 +105,51 @@ fn apply_frame<T: ReadOnlyWorldQuery>(
return; return;
}; };
let joint_data = bvh_file if let Some(joint) = joint_entity.joint {
.get_joint(joint_entity.joint.0) let joint_data = bvh_file
.expect("Invalid BVH format: the joint index is out of bounds"); .get_joint(joint.0)
.expect("Invalid BVH format: the joint index is out of bounds");
//new Positions and rotations //new Positions and rotations
let mut new_pos = joint_entity.transform.translation; let mut new_pos = joint_entity.transform.translation;
let mut new_rot: Vec3 = joint_entity let mut new_rot: Vec3 = joint_entity
.transform .transform
.rotation .rotation
.to_euler(EulerRot::ZXY) .to_euler(EulerRot::ZXY)
.into(); .into();
for channel in joint_data.channels() { for channel in joint_data.channels() {
// info!("Channel {}: {:?} : {}", channel.motion_index(), channel.channel_type(), frame.as_slice()[channel.motion_index()]); // info!("Channel {}: {:?} : {}", channel.motion_index(), channel.channel_type(), frame.as_slice()[channel.motion_index()]);
match channel.channel_type() { match channel.channel_type() {
studio_bvh::ChannelType::PositionX => { studio_bvh::ChannelType::PositionX => {
new_pos.x = frame.as_slice()[channel.motion_index()] new_pos.x = frame.as_slice()[channel.motion_index()]
} }
studio_bvh::ChannelType::PositionY => { studio_bvh::ChannelType::PositionY => {
new_pos.y = frame.as_slice()[channel.motion_index()] new_pos.y = frame.as_slice()[channel.motion_index()]
} }
studio_bvh::ChannelType::PositionZ => { studio_bvh::ChannelType::PositionZ => {
new_pos.z = frame.as_slice()[channel.motion_index()] new_pos.z = frame.as_slice()[channel.motion_index()]
} }
studio_bvh::ChannelType::RotationX => { studio_bvh::ChannelType::RotationX => {
new_rot.x = frame.as_slice()[channel.motion_index()] new_rot.x = frame.as_slice()[channel.motion_index()]
} }
studio_bvh::ChannelType::RotationY => { studio_bvh::ChannelType::RotationY => {
new_rot.y = frame.as_slice()[channel.motion_index()] new_rot.y = frame.as_slice()[channel.motion_index()]
} }
studio_bvh::ChannelType::RotationZ => { studio_bvh::ChannelType::RotationZ => {
new_rot.z = frame.as_slice()[channel.motion_index()] new_rot.z = frame.as_slice()[channel.motion_index()]
}
} }
} }
}
joint_entity.transform.translation = new_pos; joint_entity.transform.translation = new_pos;
joint_entity.transform.rotation = Quat::from_euler( joint_entity.transform.rotation = Quat::from_euler(
EulerRot::ZXY, EulerRot::ZXY,
new_rot.z.to_radians(), new_rot.z.to_radians(),
new_rot.x.to_radians(), new_rot.x.to_radians(),
new_rot.y.to_radians(), new_rot.y.to_radians(),
); );
}
if joint_entity.children.is_some() { if joint_entity.children.is_some() {
let children = joint_entity let children = joint_entity
@@ -171,10 +179,9 @@ pub struct BvhJoint(usize);
#[derive(Debug, WorldQuery)] #[derive(Debug, WorldQuery)]
#[world_query(mutable)] #[world_query(mutable)]
pub struct JointQuery { pub struct JointQuery {
pub name: &'static Name, pub joint: Option<&'static BvhJoint>,
pub joint: &'static BvhJoint,
pub transform: &'static mut Transform,
pub children: Option<&'static mut Children>, pub children: Option<&'static mut Children>,
pub transform: &'static mut Transform,
} }
//============================================================================== //==============================================================================
@@ -261,13 +268,25 @@ impl Command for SpawnBvhCommand {
panic!("Could not create the BVH entity because the bvh file has no root joint") panic!("Could not create the BVH entity because the bvh file has no root joint")
}; };
if let Some((skinned_model, RetargetMap)) = self.3 { if let Some((skinned_model, retarget_map)) = self.3 {
let entity = world world.entity_mut(skinned_model).insert((
.query::<&Children>() BvhAnim {
.get(world, skinned_model) bvh: self.1,
.unwrap(); frame: 0,
last_frame: 0,
retarget: Some(retarget_map),
should_play: true,
timer: Timer::from_seconds(
bvh.0.frame_time().as_secs_f32(),
TimerMode::Repeating,
),
},
Name::new("BVH Anim"),
));
println!("Entity: {:?}", entity); world.send_event(UpdateBVHAnim {
entity: skinned_model,
});
} else { } else {
let entity = world.spawn_empty().id(); let entity = world.spawn_empty().id();
spawn_bvh_recursive(world, &entity, root); spawn_bvh_recursive(world, &entity, root);
@@ -279,23 +298,112 @@ impl Command for SpawnBvhCommand {
frame: 0, frame: 0,
last_frame: 0, last_frame: 0,
should_play: true, should_play: true,
retarget: None,
timer: Timer::from_seconds( timer: Timer::from_seconds(
bvh.0.frame_time().as_secs_f32(), bvh.0.frame_time().as_secs_f32(),
TimerMode::Repeating, TimerMode::Repeating,
), ),
}, },
SpatialBundle::from_transform(self.2), SpatialBundle::from_transform(self.2),
Name::new("BVH Skeliton"), Name::new("BVH Anim"),
)) ))
.add_child(entity); .add_child(entity);
} }
} }
} }
//==============================================================================
// Update BVH anim Event Functions
//==============================================================================
#[derive(Event)]
pub struct UpdateBVHAnim {
pub entity: Entity,
}
fn update_bvh_anim(
mut commands: Commands,
mut bvh_anims: Query<(Entity, &BvhAnim, Option<&Children>)>,
mut update_events: EventReader<UpdateBVHAnim>,
bvh_assets: Res<Assets<Bvh>>,
) {
for event in update_events.read() {
// println!("Updating BVHs");
// println!("{:?} | {:?}", event.entity, bvh_anims.single().0);
// for anim in bvh_anims.iter() {
// println!("Children {:?}", anim);
// };
if let Ok(bvh_anim) = bvh_anims.get(event.entity) {
let Some(bvh) = bvh_assets.get(bvh_anim.1.bvh.id()) else {
continue;
};
};
}
}
fn update_bvh_recursive(current_node: Entity, commands: &mut Commands, bvh_anim: &Bvh) {}
//==============================================================================
// Utility Functions
//==============================================================================
fn spawn_bvh_recursive(world: &mut World, entity: &Entity, joint: studio_bvh::Joint) {
let offset = joint.data().offset();
let transform = Transform::from_xyz(offset[0], offset[1], offset[2]);
// Save the name of the joint
let name = String::from_utf8_lossy(joint.data().name()).to_string();
world.entity_mut(*entity).insert((
SpatialBundle::from_transform(transform),
BvhJoint(joint.data().index()),
Name::new(name),
));
for child in joint.children() {
let mut child_entity = world.spawn_empty().id();
spawn_bvh_recursive(world, &child_entity, child);
world.entity_mut(*entity).push_children(&[child_entity]);
}
}
// fn locate_rig(world: &mut World, current_entity: Entity) -> Option<Entity> {
// let Ok(query) = world
// .query::<(Option<&Children>, Option<&Name>)>()
// .get(world, current_entity)
// else {
// return None;
// };
// if let Some(name) = query.1 {
// println!("Name: {}", name.as_str());
// if name.as_str() == "Rig" {
// return Some(current_entity);
// }
// }
// let children = if let Some(children) = query.0 {
// children.iter().map(|x| x.clone()).collect::<Vec<_>>()
// } else {
// return None;
// };
// for child in children.iter() {
// println!("Child: {:?}", child);
// if let Some(entity) = locate_rig(world, *child) {
// return Some(entity);
// }
// }
// None
// }
//============================================================================== //==============================================================================
// RetargetMap // RetargetMap
//============================================================================== //==============================================================================
#[derive(Debug)]
pub struct RetargetMap { pub struct RetargetMap {
pub map: HashMap<String, String>, pub map: HashMap<String, String>,
} }
@@ -375,58 +483,3 @@ impl RetargetMap {
false false
} }
} }
//==============================================================================
// Utility Functions
//==============================================================================
fn spawn_bvh_recursive(world: &mut World, entity: &Entity, joint: studio_bvh::Joint) {
let offset = joint.data().offset();
let transform = Transform::from_xyz(offset[0], offset[1], offset[2]);
// Save the name of the joint
let name = String::from_utf8_lossy(joint.data().name()).to_string();
world.entity_mut(*entity).insert((
SpatialBundle::from_transform(transform),
BvhJoint(joint.data().index()),
Name::new(name),
));
for child in joint.children() {
let mut child_entity = world.spawn_empty().id();
spawn_bvh_recursive(world, &child_entity, child);
world.entity_mut(*entity).push_children(&[child_entity]);
}
}
fn locate_rig(world: &mut World, current_entity: Entity) -> Option<Entity> {
let Ok(query) = world
.query::<(Option<&Children>, Option<&Name>)>()
.get(world, current_entity)
else {
return None;
};
if let Some(name) = query.1 {
println!("Name: {}", name.as_str());
if name.as_str() == "Rig" {
return Some(current_entity);
}
}
let children = if let Some(children) = query.0 {
children.iter().map(|x| x.clone()).collect::<Vec<_>>()
} else {
return None;
};
for child in children.iter() {
println!("Child: {:?}", child);
if let Some(entity) = locate_rig(world, *child) {
return Some(entity);
}
}
None
}
+1 -3
View File
@@ -87,7 +87,7 @@ pub fn init(viewport_size: ViewportSize) {
Startup, Startup,
(move |mut cmd: Commands, mut ew: EventWriter<LoadSceneEvent>| { (move |mut cmd: Commands, mut ew: EventWriter<LoadSceneEvent>| {
cmd.insert_resource(SkyboxId("gum_trees_4k".to_string())); cmd.insert_resource(SkyboxId("gum_trees_4k".to_string()));
ew.send(LoadSceneEvent("base-human-female".to_string())); ew.send(LoadSceneEvent("Alien".to_string()));
}) })
) )
// .add_systems( // .add_systems(
@@ -96,8 +96,6 @@ pub fn init(viewport_size: ViewportSize) {
// ) // )
; ;
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
wasm::initialize(); wasm::initialize();
+13 -5
View File
@@ -43,8 +43,8 @@ impl Plugin for ScenePlugin {
init_scene_loading, init_scene_loading,
tick_scene_loading.run_if(in_state(SceneState::Loading)), tick_scene_loading.run_if(in_state(SceneState::Loading)),
tick_scene_spawning.run_if(in_state(SceneState::Spawning)), tick_scene_spawning.run_if(in_state(SceneState::Spawning)),
).in_set(SceneSpawnerSystem) )
.in_set(SceneSpawnerSystem),
) )
.add_systems( .add_systems(
OnEnter(SceneState::Loading), OnEnter(SceneState::Loading),
@@ -158,11 +158,19 @@ fn spawn_test_bvh(
mut commands: Commands, mut commands: Commands,
mut er_bvh_events: EventReader<AssetEvent<Bvh>>, mut er_bvh_events: EventReader<AssetEvent<Bvh>>,
r_bvh: Res<TestBvh>, r_bvh: Res<TestBvh>,
mut asset_server : ResMut<AssetServer> mut asset_server: ResMut<AssetServer>,
) { ) {
for event in er_bvh_events.read() { for event in er_bvh_events.read() {
if matches!(event, AssetEvent::LoadedWithDependencies { .. }) { if matches!(event, AssetEvent::LoadedWithDependencies { .. }) {
commands.spawn_skined_bvh_with_transform(&r_bvh.0, asset_server.load("gltf/base-human-female.gltf#Scene0"), RetargetMap::mocap_to_rigify(), Transform::from_scale(Vec3::splat(1.0)).with_translation(Vec3::new(0., 1.0, -0.024))); commands.spawn_skined_bvh_with_transform(
&r_bvh.0,
asset_server.load("gltf/base-human-female.gltf#Scene0"),
RetargetMap::mocap_to_rigify(),
Transform::from_scale(Vec3::splat(1.0))
.with_translation(Vec3::new(0., 1.0, -0.024)),
);
commands.spawn_bvh_with_transform(&r_bvh.0, Transform::from_xyz(0.0, 1.0, -0.024));
} }
} }
} }
@@ -176,7 +184,7 @@ fn init_scene_loading(
) { ) {
if let Some(id) = er.read().last() { if let Some(id) = er.read().last() {
let name = &**id; let name = &**id;
let path = format!("gltf/{name}.gltf"); let path = format!("gltf/{name}.glb");
// Avoid trying to re-load this scene if it's already active // Avoid trying to re-load this scene if it's already active
if let Some(active_scene_path) = if let Some(active_scene_path) =