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
+158 -105
View File
@@ -13,13 +13,14 @@ use bevy::{
utils::hashbrown::HashMap,
};
use bevy_inspector_egui::egui::TextBuffer;
use bevy_mod_picking::prelude::EntityEvent;
use bevy_rapier3d::parry::transformation;
use studio_bvh::{frames::Frame, joint};
mod error;
mod loader;
use crate::scene::SceneState;
use crate::{debug::print_mat3, scene::SceneState};
use self::loader::BvhLoader;
@@ -31,7 +32,10 @@ impl Plugin for BvhPlugin {
.register_asset_loader(BvhLoader)
.add_systems(Update, animate_bvh.run_if(in_state(SceneState::Active)))
.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,
frame: usize,
#[reflect(ignore)]
retarget: Option<RetargetMap>,
#[reflect(ignore)]
timer: Timer,
#[reflect(ignore)]
last_frame: usize,
@@ -99,49 +105,51 @@ fn apply_frame<T: ReadOnlyWorldQuery>(
return;
};
let joint_data = bvh_file
.get_joint(joint_entity.joint.0)
.expect("Invalid BVH format: the joint index is out of bounds");
if let Some(joint) = joint_entity.joint {
let joint_data = bvh_file
.get_joint(joint.0)
.expect("Invalid BVH format: the joint index is out of bounds");
//new Positions and rotations
let mut new_pos = joint_entity.transform.translation;
let mut new_rot: Vec3 = joint_entity
.transform
.rotation
.to_euler(EulerRot::ZXY)
.into();
//new Positions and rotations
let mut new_pos = joint_entity.transform.translation;
let mut new_rot: Vec3 = joint_entity
.transform
.rotation
.to_euler(EulerRot::ZXY)
.into();
for channel in joint_data.channels() {
// info!("Channel {}: {:?} : {}", channel.motion_index(), channel.channel_type(), frame.as_slice()[channel.motion_index()]);
match channel.channel_type() {
studio_bvh::ChannelType::PositionX => {
new_pos.x = frame.as_slice()[channel.motion_index()]
}
studio_bvh::ChannelType::PositionY => {
new_pos.y = frame.as_slice()[channel.motion_index()]
}
studio_bvh::ChannelType::PositionZ => {
new_pos.z = frame.as_slice()[channel.motion_index()]
}
studio_bvh::ChannelType::RotationX => {
new_rot.x = frame.as_slice()[channel.motion_index()]
}
studio_bvh::ChannelType::RotationY => {
new_rot.y = frame.as_slice()[channel.motion_index()]
}
studio_bvh::ChannelType::RotationZ => {
new_rot.z = frame.as_slice()[channel.motion_index()]
for channel in joint_data.channels() {
// info!("Channel {}: {:?} : {}", channel.motion_index(), channel.channel_type(), frame.as_slice()[channel.motion_index()]);
match channel.channel_type() {
studio_bvh::ChannelType::PositionX => {
new_pos.x = frame.as_slice()[channel.motion_index()]
}
studio_bvh::ChannelType::PositionY => {
new_pos.y = frame.as_slice()[channel.motion_index()]
}
studio_bvh::ChannelType::PositionZ => {
new_pos.z = frame.as_slice()[channel.motion_index()]
}
studio_bvh::ChannelType::RotationX => {
new_rot.x = frame.as_slice()[channel.motion_index()]
}
studio_bvh::ChannelType::RotationY => {
new_rot.y = frame.as_slice()[channel.motion_index()]
}
studio_bvh::ChannelType::RotationZ => {
new_rot.z = frame.as_slice()[channel.motion_index()]
}
}
}
}
joint_entity.transform.translation = new_pos;
joint_entity.transform.rotation = Quat::from_euler(
EulerRot::ZXY,
new_rot.z.to_radians(),
new_rot.x.to_radians(),
new_rot.y.to_radians(),
);
joint_entity.transform.translation = new_pos;
joint_entity.transform.rotation = Quat::from_euler(
EulerRot::ZXY,
new_rot.z.to_radians(),
new_rot.x.to_radians(),
new_rot.y.to_radians(),
);
}
if joint_entity.children.is_some() {
let children = joint_entity
@@ -171,10 +179,9 @@ pub struct BvhJoint(usize);
#[derive(Debug, WorldQuery)]
#[world_query(mutable)]
pub struct JointQuery {
pub name: &'static Name,
pub joint: &'static BvhJoint,
pub transform: &'static mut Transform,
pub joint: Option<&'static BvhJoint>,
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")
};
if let Some((skinned_model, RetargetMap)) = self.3 {
let entity = world
.query::<&Children>()
.get(world, skinned_model)
.unwrap();
if let Some((skinned_model, retarget_map)) = self.3 {
world.entity_mut(skinned_model).insert((
BvhAnim {
bvh: self.1,
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 {
let entity = world.spawn_empty().id();
spawn_bvh_recursive(world, &entity, root);
@@ -279,23 +298,112 @@ impl Command for SpawnBvhCommand {
frame: 0,
last_frame: 0,
should_play: true,
retarget: None,
timer: Timer::from_seconds(
bvh.0.frame_time().as_secs_f32(),
TimerMode::Repeating,
),
},
SpatialBundle::from_transform(self.2),
Name::new("BVH Skeliton"),
Name::new("BVH Anim"),
))
.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
//==============================================================================
#[derive(Debug)]
pub struct RetargetMap {
pub map: HashMap<String, String>,
}
@@ -375,58 +483,3 @@ impl RetargetMap {
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,
(move |mut cmd: Commands, mut ew: EventWriter<LoadSceneEvent>| {
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(
@@ -96,8 +96,6 @@ pub fn init(viewport_size: ViewportSize) {
// )
;
#[cfg(feature = "wasm")]
wasm::initialize();
+13 -5
View File
@@ -43,8 +43,8 @@ impl Plugin for ScenePlugin {
init_scene_loading,
tick_scene_loading.run_if(in_state(SceneState::Loading)),
tick_scene_spawning.run_if(in_state(SceneState::Spawning)),
).in_set(SceneSpawnerSystem)
)
.in_set(SceneSpawnerSystem),
)
.add_systems(
OnEnter(SceneState::Loading),
@@ -158,11 +158,19 @@ fn spawn_test_bvh(
mut commands: Commands,
mut er_bvh_events: EventReader<AssetEvent<Bvh>>,
r_bvh: Res<TestBvh>,
mut asset_server : ResMut<AssetServer>
mut asset_server: ResMut<AssetServer>,
) {
for event in er_bvh_events.read() {
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() {
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
if let Some(active_scene_path) =