mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-28 08:58:07 +00:00
leaving this branch for posterity
This commit is contained in:
Binary file not shown.
Binary file not shown.
+245
-262
@@ -1,7 +1,7 @@
|
|||||||
use std::backtrace::Backtrace;
|
use std::backtrace::Backtrace;
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
asset::AsyncReadExt,
|
asset::{AsyncReadExt, LoadState},
|
||||||
ecs::{
|
ecs::{
|
||||||
query::{self, ReadOnlyWorldQuery, WorldQuery},
|
query::{self, ReadOnlyWorldQuery, WorldQuery},
|
||||||
system::{Command, EntityCommands, SystemParam},
|
system::{Command, EntityCommands, SystemParam},
|
||||||
@@ -9,7 +9,7 @@ use bevy::{
|
|||||||
gltf::Gltf,
|
gltf::Gltf,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
render::INSTANCE_INDEX_SHADER_HANDLE,
|
render::INSTANCE_INDEX_SHADER_HANDLE,
|
||||||
scene,
|
scene::{self, InstanceId},
|
||||||
transform::commands,
|
transform::commands,
|
||||||
ui::debug::print_ui_layout_tree,
|
ui::debug::print_ui_layout_tree,
|
||||||
utils::hashbrown::HashMap,
|
utils::hashbrown::HashMap,
|
||||||
@@ -17,7 +17,7 @@ use bevy::{
|
|||||||
use bevy_inspector_egui::egui::TextBuffer;
|
use bevy_inspector_egui::egui::TextBuffer;
|
||||||
use bevy_mod_picking::prelude::EntityEvent;
|
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, Bvh as BvhFile};
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod loader;
|
mod loader;
|
||||||
@@ -35,12 +35,15 @@ impl Plugin for BvhPlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.init_asset::<Bvh>()
|
app.init_asset::<Bvh>()
|
||||||
.register_asset_loader(BvhLoader)
|
.register_asset_loader(BvhLoader)
|
||||||
|
.init_resource::<PendingBVHAnims>()
|
||||||
|
.add_systems(PreUpdate, tick_pending_bvh_anims.run_if(in_state(SceneState::Spawning)))
|
||||||
|
|
||||||
.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
|
//Events
|
||||||
.add_event::<UpdateBVHAnim>()
|
;
|
||||||
.add_systems(PreUpdate, update_bvh_anim);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,14 +60,20 @@ pub struct BvhAnim {
|
|||||||
bvh: Handle<Bvh>,
|
bvh: Handle<Bvh>,
|
||||||
should_play: bool,
|
should_play: bool,
|
||||||
frame: usize,
|
frame: usize,
|
||||||
#[reflect(ignore)]
|
// #[reflect(ignore)]
|
||||||
retarget: Option<RetargetMap>,
|
// retarget: Option<RetargetMap>,
|
||||||
#[reflect(ignore)]
|
#[reflect(ignore)]
|
||||||
timer: Timer,
|
timer: Timer,
|
||||||
#[reflect(ignore)]
|
#[reflect(ignore)]
|
||||||
last_frame: usize,
|
last_frame: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BvhAnim {
|
||||||
|
fn new(handle : Handle<Bvh>, bvh : &BvhFile) -> Self {
|
||||||
|
BvhAnim { bvh: handle, should_play: true, frame: 0, timer: Timer::from_seconds(bvh.frame_time().as_secs_f32(), TimerMode::Repeating), last_frame:0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn animate_bvh(
|
pub fn animate_bvh(
|
||||||
mut command: Commands,
|
mut command: Commands,
|
||||||
mut bvh_anims: Query<(Entity, &mut BvhAnim, &mut Transform, &mut Children)>,
|
mut bvh_anims: Query<(Entity, &mut BvhAnim, &mut Transform, &mut Children)>,
|
||||||
@@ -136,13 +145,13 @@ fn apply_frame<T: ReadOnlyWorldQuery>(
|
|||||||
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()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,100 +198,38 @@ pub struct JointQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// Commands Plugin
|
// Unloaded Scenes
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
pub trait CommandsSpawnBvhExt {
|
#[derive(Resource, Default)]
|
||||||
fn spawn_bvh(&mut self, asset: &Handle<Bvh>) -> Entity;
|
pub struct PendingBVHAnims {
|
||||||
|
pub items: Vec<(Entity, InstanceId, Handle<Bvh>, RetargetMap)>,
|
||||||
fn spawn_bvh_with_transform(&mut self, asset: &Handle<Bvh>, transform: Transform) -> Entity;
|
|
||||||
|
|
||||||
fn spawn_skined_bvh_with_transform(
|
|
||||||
&mut self,
|
|
||||||
asset: Handle<Bvh>,
|
|
||||||
scene: Handle<Scene>,
|
|
||||||
retarget_map: RetargetMap,
|
|
||||||
transform: Transform,
|
|
||||||
) -> Entity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'w, 's> CommandsSpawnBvhExt for Commands<'w, 's> {
|
fn tick_pending_bvh_anims(
|
||||||
fn spawn_bvh(&mut self, asset: &Handle<Bvh>) -> Entity {
|
mut commands : Commands,
|
||||||
let entity = self.spawn_empty().id();
|
mut pending_bvh_anims: ResMut<PendingBVHAnims>,
|
||||||
self.add(SpawnBvhCommand(
|
mut next_state : ResMut<NextState<SceneState>>,
|
||||||
entity,
|
named_entities : Query<&Name>,
|
||||||
asset.clone(),
|
scene_spawner: Res<SceneSpawner>,
|
||||||
Transform::default(),
|
asset_server: Res<AssetServer>,
|
||||||
None,
|
bvh_assets: Res<Assets<Bvh>>,
|
||||||
));
|
) {
|
||||||
entity
|
let is_done_loading = |bvh_handle : &Handle<Bvh>, instance_id : &InstanceId| -> bool {
|
||||||
}
|
asset_server.get_load_state(bvh_handle.id()) == Some(LoadState::Loaded) && scene_spawner.instance_is_ready(instance_id.clone())
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
while i < pending_bvh_anims.items.len() {
|
||||||
|
let (parent, instance_id, bvh_handle, retarget_map) = pending_bvh_anims.items.get(i).unwrap();
|
||||||
|
if is_done_loading(bvh_handle, instance_id) {
|
||||||
|
println!("Bvh anim is ready!");
|
||||||
|
|
||||||
fn spawn_bvh_with_transform(&mut self, asset: &Handle<Bvh>, transform: Transform) -> Entity {
|
let bvh = bvh_assets.get(bvh_handle.id()).unwrap();
|
||||||
let entity = self.spawn_empty().id();
|
|
||||||
self.add(SpawnBvhCommand(entity, asset.clone(), transform, None));
|
for entity in scene_spawner.iter_instance_entities(*instance_id) {
|
||||||
entity
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spawn_skined_bvh_with_transform(
|
let Ok(potential_bone_name) = named_entities.get(entity) else {
|
||||||
&mut self,
|
|
||||||
asset: Handle<Bvh>,
|
|
||||||
scene: Handle<Scene>,
|
|
||||||
retarget_map: RetargetMap,
|
|
||||||
transform: Transform,
|
|
||||||
) -> Entity {
|
|
||||||
let entity = self.spawn_empty().id();
|
|
||||||
|
|
||||||
self.add(SpawnBvhCommand(
|
|
||||||
entity,
|
|
||||||
asset,
|
|
||||||
transform,
|
|
||||||
Some((scene, retarget_map)),
|
|
||||||
));
|
|
||||||
entity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SpawnBvhCommand(
|
|
||||||
Entity,
|
|
||||||
Handle<Bvh>,
|
|
||||||
Transform,
|
|
||||||
Option<(Handle<Scene>, RetargetMap)>,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl Command for SpawnBvhCommand {
|
|
||||||
//TODO: This loading process with have to be async eventually.
|
|
||||||
fn apply(self, world: &mut World) {
|
|
||||||
let bvh = {
|
|
||||||
let Some(bvh) = world.get_resource::<Assets<Bvh>>().unwrap().get(&self.1) else {
|
|
||||||
panic!(
|
|
||||||
"Could not create the BVH entity because the bvh file has not been loaded yet"
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
bvh.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(root) = bvh.0.root_joint() else {
|
|
||||||
panic!("Could not create the BVH entity because the bvh file has no root joint")
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some((scene_handle, retarget_map)) = self.3 {
|
|
||||||
println!("Starting Scene Spawn");
|
|
||||||
let mut scene_spawner = SceneSpawner::from_world(world);
|
|
||||||
|
|
||||||
let id = match scene_spawner.spawn_sync(world, scene_handle.id()) {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(err) => {
|
|
||||||
println!("There was an Error: {:?}", err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for entity in scene_spawner.iter_instance_entities(id) {
|
|
||||||
println!("Bone {:?}", entity);
|
|
||||||
|
|
||||||
let Ok(potential_bone_name) = world.query::<&Name>().get(&world, entity) else {
|
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let Some(mapped_bone_name) = retarget_map.map.get(potential_bone_name.as_str())
|
let Some(mapped_bone_name) = retarget_map.map.get(potential_bone_name.as_str())
|
||||||
@@ -295,114 +242,198 @@ impl Command for SpawnBvhCommand {
|
|||||||
|
|
||||||
println!("Bone Index {}", bone_data.index());
|
println!("Bone Index {}", bone_data.index());
|
||||||
|
|
||||||
world.entity_mut(entity).insert(BvhJoint(bone_data.index()));
|
commands.entity(entity).insert(BvhJoint(bone_data.index()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commands.entity(*parent)
|
||||||
|
.insert(SpatialBundle::default())
|
||||||
|
.insert(BvhAnim::new(bvh_handle.clone(), &bvh.0));
|
||||||
|
|
||||||
world.insert_resource(ActiveScene {
|
commands.insert_resource(ActiveScene { instance: instance_id.clone() });
|
||||||
instance: id,
|
|
||||||
source: scene_handle,
|
pending_bvh_anims.items.remove(i);
|
||||||
});
|
|
||||||
|
|
||||||
// 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"),
|
|
||||||
// ));
|
|
||||||
|
|
||||||
// world.send_event(UpdateBVHAnim {
|
|
||||||
// entity: skinned_model,
|
|
||||||
// });
|
|
||||||
} else {
|
} else {
|
||||||
let entity = world.spawn_empty().id();
|
i += 1;
|
||||||
spawn_bvh_recursive(world, &entity, root);
|
|
||||||
world
|
|
||||||
.entity_mut(self.0)
|
|
||||||
.insert((
|
|
||||||
BvhAnim {
|
|
||||||
bvh: self.1,
|
|
||||||
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 Anim"),
|
|
||||||
))
|
|
||||||
.add_child(entity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pending_bvh_anims.items.is_empty() {
|
||||||
|
println!("Moving to Active state.");
|
||||||
|
next_state.set(SceneState::Active);
|
||||||
|
}
|
||||||
|
// for (parent, instance_id, bvh_handle, retarget_map) in pending_bvh_anims.items.iter() {
|
||||||
|
// if let Some(LoadState::Loaded) = asset_server.get_load_state(bvh_handle) {
|
||||||
|
// if scene_spawner.instance_is_ready(*instance_idance_id) {
|
||||||
|
// println!("Bvh anim is ready!");
|
||||||
|
|
||||||
|
// let bvh = bvh_assets.get(bvh_handle.id()).unwrap();
|
||||||
|
// // commands.entity(parent).insert(BvhAnim{ bvh, should_play: todo!(), frame: todo!(), retarget: todo!(), timer: todo!(), last_frame: todo!() })
|
||||||
|
|
||||||
|
// for entity in scene_spawner.iter_instance_entities(*instance_id) {
|
||||||
|
|
||||||
|
// let Ok(potential_bone_name) = named_entities.get(entity) else {
|
||||||
|
// continue;
|
||||||
|
// };
|
||||||
|
// let Some(mapped_bone_name) = retarget_map.map.get(potential_bone_name.as_str())
|
||||||
|
// else {
|
||||||
|
// continue;
|
||||||
|
// };
|
||||||
|
// let Some(bone_data) = bvh.0.get_joint_by_name(&mapped_bone_name) else {
|
||||||
|
// continue;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// println!("Bone Index {}", bone_data.index());
|
||||||
|
|
||||||
|
// commands.entity(entity).insert(BvhJoint(bone_data.index()));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// commands.entity(*parent)
|
||||||
|
// .insert(SpatialBundle::default())
|
||||||
|
// .insert(BvhAnim::new(bvh_handle.clone(), &bvh.0));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Commands Plugin
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
pub trait CommandsSpawnBvhExt {
|
||||||
|
fn spawn_bvh(
|
||||||
|
&mut self,
|
||||||
|
asset: Handle<Bvh>,
|
||||||
|
scene: Handle<Scene>,
|
||||||
|
retarget_map: RetargetMap,
|
||||||
|
transform: Transform,
|
||||||
|
) -> Entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'w, 's> CommandsSpawnBvhExt for Commands<'w, 's> {
|
||||||
|
fn spawn_bvh(
|
||||||
|
&mut self,
|
||||||
|
asset: Handle<Bvh>,
|
||||||
|
scene: Handle<Scene>,
|
||||||
|
retarget_map: RetargetMap,
|
||||||
|
transform: Transform,
|
||||||
|
) -> Entity {
|
||||||
|
let entity = self.spawn_empty().id();
|
||||||
|
|
||||||
|
self.add(SpawnBvhCommand(
|
||||||
|
entity,
|
||||||
|
scene,
|
||||||
|
asset,
|
||||||
|
retarget_map,
|
||||||
|
transform,
|
||||||
|
));
|
||||||
|
entity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SpawnBvhCommand(Entity, Handle<Scene>, Handle<Bvh>, RetargetMap, Transform);
|
||||||
|
|
||||||
|
impl Command for SpawnBvhCommand {
|
||||||
|
//TODO: This loading process with have to be async eventually.
|
||||||
|
fn apply(self, world: &mut World) {
|
||||||
|
// let bvh = {
|
||||||
|
// let Some(bvh) = world.get_resource::<Assets<Bvh>>().unwrap().get(&self.1) else {
|
||||||
|
// panic!(
|
||||||
|
// "Could not create the BVH entity because the bvh file has not been loaded yet"
|
||||||
|
// )
|
||||||
|
// };
|
||||||
|
|
||||||
|
// bvh.clone()
|
||||||
|
// };
|
||||||
|
|
||||||
|
let mut scene_spanwer = world
|
||||||
|
.get_resource_mut::<SceneSpawner>()
|
||||||
|
.expect("The scene spawner has not been initialized.");
|
||||||
|
let scene_id = scene_spanwer.spawn_as_child(self.1, self.0);
|
||||||
|
|
||||||
|
drop(scene_spanwer);
|
||||||
|
|
||||||
|
let mut pending_bvh_scenes = world.get_resource_mut::<PendingBVHAnims>().expect("Pending bvh Resource has not been initialized.");
|
||||||
|
pending_bvh_scenes.items.push((self.0, scene_id, self.2, self.3));
|
||||||
|
|
||||||
|
// let Some(root) = bvh.0.root_joint() else {
|
||||||
|
// panic!("Could not create the BVH entity because the bvh file has no root joint")
|
||||||
|
// };
|
||||||
|
|
||||||
|
// println!("Starting Scene Spawn");
|
||||||
|
// let mut scene_spawner = SceneSpawner::from_world(world);
|
||||||
|
|
||||||
|
// let id = match scene_spawner.spawn_sync(world, scene_handle.id()) {
|
||||||
|
// Ok(val) => val,
|
||||||
|
// Err(err) => {
|
||||||
|
// println!("There was an Error: {:?}", err);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// world.insert_resource(ActiveScene {
|
||||||
|
// instance: id,
|
||||||
|
// source: scene_handle,
|
||||||
|
// });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// Update BVH anim Event Functions
|
// Update BVH anim Event Functions
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#[derive(Event)]
|
// #[derive(Event)]
|
||||||
pub struct UpdateBVHAnim {
|
// pub struct UpdateBVHAnim {
|
||||||
pub entity: Entity,
|
// pub entity: Entity,
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn update_bvh_anim(
|
// fn update_bvh_anim(
|
||||||
mut commands: Commands,
|
// mut commands: Commands,
|
||||||
mut update_events: EventReader<UpdateBVHAnim>,
|
// mut update_events: EventReader<UpdateBVHAnim>,
|
||||||
bvh_anims: Query<(Entity, &BvhAnim, Option<&Children>)>,
|
// bvh_anims: Query<(Entity, &BvhAnim, Option<&Children>)>,
|
||||||
skinned_model_nodes: Query<(&Name, Option<&Children>)>,
|
// skinned_model_nodes: Query<(&Name, Option<&Children>)>,
|
||||||
bvh_assets: Res<Assets<Bvh>>,
|
// bvh_assets: Res<Assets<Bvh>>,
|
||||||
) {
|
// ) {
|
||||||
for event in update_events.read() {
|
// for event in update_events.read() {
|
||||||
// println!("Updating BVHs");
|
// // println!("Updating BVHs");
|
||||||
// println!("{:?} | {:?}", event.entity, bvh_anims.single().0);
|
// // println!("{:?} | {:?}", event.entity, bvh_anims.single().0);
|
||||||
// for anim in bvh_anims.iter() {
|
// // for anim in bvh_anims.iter() {
|
||||||
// println!("Children {:?}", anim);
|
// // println!("Children {:?}", anim);
|
||||||
// };
|
// // };
|
||||||
|
|
||||||
if let Ok(bvh_anim) = bvh_anims.get(event.entity) {
|
// if let Ok(bvh_anim) = bvh_anims.get(event.entity) {
|
||||||
let Some(bvh) = bvh_assets.get(bvh_anim.1.bvh.id()) else {
|
// let Some(bvh) = bvh_assets.get(bvh_anim.1.bvh.id()) else {
|
||||||
continue;
|
// continue;
|
||||||
};
|
// };
|
||||||
|
|
||||||
println!("Children {:?}", bvh_anim.2);
|
// println!("Children {:?}", bvh_anim.2);
|
||||||
|
|
||||||
if let Some(children) = bvh_anim.2 {
|
// if let Some(children) = bvh_anim.2 {
|
||||||
for child in children {
|
// for child in children {
|
||||||
update_bvh_recursive(child, &mut commands, &bvh, &skinned_model_nodes);
|
// update_bvh_recursive(child, &mut commands, &bvh, &skinned_model_nodes);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn update_bvh_recursive(
|
// fn update_bvh_recursive(
|
||||||
current_node: &Entity,
|
// current_node: &Entity,
|
||||||
commands: &mut Commands,
|
// commands: &mut Commands,
|
||||||
bvh_anim: &Bvh,
|
// bvh_anim: &Bvh,
|
||||||
skinned_model_nodes: &Query<(&Name, Option<&Children>)>,
|
// skinned_model_nodes: &Query<(&Name, Option<&Children>)>,
|
||||||
) {
|
// ) {
|
||||||
println!("Called Function");
|
// println!("Called Function");
|
||||||
|
|
||||||
let Ok((current_name, current_children)) = skinned_model_nodes.get(*current_node) else {
|
// let Ok((current_name, current_children)) = skinned_model_nodes.get(*current_node) else {
|
||||||
return;
|
// return;
|
||||||
};
|
// };
|
||||||
|
|
||||||
if let Some(children) = current_children {
|
// if let Some(children) = current_children {
|
||||||
for child in children.iter() {
|
// for child in children.iter() {
|
||||||
update_bvh_recursive(child, commands, bvh_anim, skinned_model_nodes);
|
// update_bvh_recursive(child, commands, bvh_anim, skinned_model_nodes);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// Utility Functions
|
// Utility Functions
|
||||||
@@ -471,75 +502,23 @@ pub struct RetargetMap {
|
|||||||
impl RetargetMap {
|
impl RetargetMap {
|
||||||
pub fn mocap_to_rigify() -> RetargetMap {
|
pub fn mocap_to_rigify() -> RetargetMap {
|
||||||
RetargetMap {
|
RetargetMap {
|
||||||
// map: [
|
|
||||||
// ("hip", "DEF-spine"),
|
|
||||||
// ("abdomen", "DEF-spine.002"),
|
|
||||||
// ("chest", "DEF-spine.003"),
|
|
||||||
// ("neck", "DEF-spine.004"),
|
|
||||||
// ("neck1", "DEF-spine.005"),
|
|
||||||
// ("head", "DEF-spine.006"),
|
|
||||||
// ("rCollar", "DEF-shoulder.R"),
|
|
||||||
// ("rShldr", "DEF-upper_arm.R"),
|
|
||||||
// ("rForeArm", "DEF-forearm.R"),
|
|
||||||
// ("rHand", "DEF-hand.R"),
|
|
||||||
// ("metacarpal1.r", "DEF-palm.01.R"),
|
|
||||||
// ("finger2-1.r", "DEF-f_index.01.R"),
|
|
||||||
// ("finger3-2.r", "DEF-f_middle.02.R"),
|
|
||||||
// ("finger3-3.r", "DEF-f_middle.03.R"),
|
|
||||||
// ("metacarpal3.r", "DEF-palm.03.R"),
|
|
||||||
// ("finger4-1.r", "DEF-f_ring.01.R"),
|
|
||||||
// ("finger4-2.r", "DEF-f_ring.02.R"),
|
|
||||||
// ("finger4-3.r", "DEF-f_ring.03.R"),
|
|
||||||
// ("metacarpal4.r", "DEF-palm.04.R"),
|
|
||||||
// ("finger5-1.r", "DEF-f_pinky.01.R"),
|
|
||||||
// ("finger5-2.r", "DEF-f_pinky.02.R"),
|
|
||||||
// ("finger5-3.r", "DEF-f_pinky.03.R"),
|
|
||||||
// ("rthumb", "DEF-thumb.01.R"),
|
|
||||||
// ("finger1-2.r", "DEF-thumb.02.R"),
|
|
||||||
// ("finger1-3.r", "DEF-thumb.03.R"),
|
|
||||||
// ("rThigh", "DEF-thumb.03.R"),
|
|
||||||
// ("rShin", "DEF-shin.R"),
|
|
||||||
// ("rFoot", "DEF-foot.R"),
|
|
||||||
// ("lCollar", "DEF-shoulder.L"),
|
|
||||||
// ("lShldr", "DEF-upper_arm.L"),
|
|
||||||
// ("lForeArm", "DEF-forearm.L"),
|
|
||||||
// ("lHand", "DEF-hand.L"),
|
|
||||||
// ("metacarpal1.l", "DEF-palm.01.L"),
|
|
||||||
// ("finger2-1.l", "DEF-f_index.01.L"),
|
|
||||||
// ("finger2-2.l", "DEF-f_index.02.L"),
|
|
||||||
// ("finger2-3.l", "DEF-f_index.03.L"),
|
|
||||||
// ("metacarpal2.l", "DEF-palm.02.L"),
|
|
||||||
// ("finger3-1.l", "DEF-f_middle.01.L"),
|
|
||||||
// ("finger3-2.l", "DEF-f_middle.02.L"),
|
|
||||||
// ("finger3-3.l", "DEF-f_middle.03.L"),
|
|
||||||
// ("metacarpal3.l", "DEF-palm.03.L"),
|
|
||||||
// ("finger4-1.l", "DEF-f_ring.01.L"),
|
|
||||||
// ("finger4-2.l", "DEF-f_ring.02.L"),
|
|
||||||
// ("finger4-3.l", "DEF-f_ring.03.L"),
|
|
||||||
// ("metacarpal4.l", "DEF-palm.04.L"),
|
|
||||||
// ("finger5-1.l", "DEF-f_pinky.01.L"),
|
|
||||||
// ("finger5-2.l", "DEF-f_pinky.02.L"),
|
|
||||||
// ("finger5-3.l", "DEF-f_pinky.03.L"),
|
|
||||||
// ("lthumb", "DEF-thumb.01.L"),
|
|
||||||
// ("finger1-2.l", "DEF-thumb.02.L"),
|
|
||||||
// ("finger1-3.l", "DEF-thumb.03.L"),
|
|
||||||
// ("lThigh", "DEF-thigh.L"),
|
|
||||||
// ("lShin", "DEF-shin.L"),
|
|
||||||
// ("lFoot", "DEF-foot.L"),
|
|
||||||
// ]
|
|
||||||
map: [
|
map: [
|
||||||
("DEF-spine", "hip"),
|
("DEF-spine", "LowerBack"),
|
||||||
("DEF-spine.002", "abdomen"),
|
("DEF-spine.002", "abdomen"),
|
||||||
("DEF-spine.003", "chest"),
|
("DEF-spine.003", "chest"),
|
||||||
("DEF-spine.004", "neck"),
|
("DEF-spine.004", "Neck"),
|
||||||
("DEF-spine.005", "neck1"),
|
("DEF-spine.005", "Neck1"),
|
||||||
("DEF-spine.006", "head"),
|
("DEF-spine.006", "Head"),
|
||||||
("DEF-shoulder.R", "rCollar"),
|
("DEF-shoulder.R", "rcollar"),
|
||||||
("DEF-upper_arm.R", "rShldr"),
|
("DEF-upper_arm.R", "rshoulder"),
|
||||||
("DEF-forearm.R", "rForeArm"),
|
("DEF-forearm.R", "relbow"),
|
||||||
("DEF-hand.R", "rHand"),
|
("DEF-hand.R", "rhand"),
|
||||||
("DEF-palm.01.R", "metacarpal1.r"),
|
("DEF-palm.01.R", "metacarpal1.r"),
|
||||||
("DEF-f_index.01.R", "finger2-1.r"),
|
("DEF-f_index.01.R", "finger2-1.r"),
|
||||||
|
("DEF-f_index.02.R", "finger2-2.r"),
|
||||||
|
("DEF-f_index.03.R", "finger2-3.r"),
|
||||||
|
("DEF-palm.02.R", "metacarpal2.r"),
|
||||||
|
("DEF-f_middle.01.R", "finger3-1.r"),
|
||||||
("DEF-f_middle.02.R", "finger3-2.r"),
|
("DEF-f_middle.02.R", "finger3-2.r"),
|
||||||
("DEF-f_middle.03.R", "finger3-3.r"),
|
("DEF-f_middle.03.R", "finger3-3.r"),
|
||||||
("DEF-palm.03.R", "metacarpal3.r"),
|
("DEF-palm.03.R", "metacarpal3.r"),
|
||||||
@@ -553,13 +532,14 @@ impl RetargetMap {
|
|||||||
("DEF-thumb.01.R", "rthumb"),
|
("DEF-thumb.01.R", "rthumb"),
|
||||||
("DEF-thumb.02.R", "finger1-2.r"),
|
("DEF-thumb.02.R", "finger1-2.r"),
|
||||||
("DEF-thumb.03.R", "finger1-3.r"),
|
("DEF-thumb.03.R", "finger1-3.r"),
|
||||||
("DEF-thumb.03.R", "rThigh"),
|
("DEF-thigh.R", "rhip"),
|
||||||
("DEF-shin.R", "rShin"),
|
("DEF-shin.R", "rknee"),
|
||||||
("DEF-foot.R", "rFoot"),
|
("DEF-foot.R", "rfoot"),
|
||||||
("DEF-shoulder.L", "lCollar"),
|
("DEF-toe.R", "RightToeBase"),
|
||||||
("DEF-upper_arm.L", "lShldr"),
|
("DEF-shoulder.L", "lcollar"),
|
||||||
("DEF-forearm.L", "lForeArm"),
|
("DEF-upper_arm.L", "lshoulder"),
|
||||||
("DEF-hand.L", "lHand"),
|
("DEF-forearm.L", "lelbow"),
|
||||||
|
("DEF-hand.L", "lhand"),
|
||||||
("DEF-palm.01.L", "metacarpal1.l"),
|
("DEF-palm.01.L", "metacarpal1.l"),
|
||||||
("DEF-f_index.01.L", "finger2-1.l"),
|
("DEF-f_index.01.L", "finger2-1.l"),
|
||||||
("DEF-f_index.02.L", "finger2-2.l"),
|
("DEF-f_index.02.L", "finger2-2.l"),
|
||||||
@@ -579,9 +559,12 @@ impl RetargetMap {
|
|||||||
("DEF-thumb.01.L", "lthumb"),
|
("DEF-thumb.01.L", "lthumb"),
|
||||||
("DEF-thumb.02.L", "finger1-2.l"),
|
("DEF-thumb.02.L", "finger1-2.l"),
|
||||||
("DEF-thumb.03.L", "finger1-3.l"),
|
("DEF-thumb.03.L", "finger1-3.l"),
|
||||||
("DEF-thigh.L", "lThigh"),
|
("DEF-thigh.L", "lhip"),
|
||||||
("DEF-shin.L", "lShin"),
|
("DEF-shin.L", "lknee"),
|
||||||
("DEF-foot.L", "lFoot"),
|
("DEF-foot.L", "lfoot"),
|
||||||
|
("DEF-toe.L", "LeftToeBase"),
|
||||||
|
("DEF-pelvis.R", "RHipJoint"),
|
||||||
|
("DEF-pelvis.L", "LHipJoint"),
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| (v.0.to_string(), v.1.to_string()))
|
.map(|v| (v.0.to_string(), v.1.to_string()))
|
||||||
|
|||||||
+39
-6
@@ -2,14 +2,15 @@ use std::fmt;
|
|||||||
|
|
||||||
use bevy::{prelude::*, window::PrimaryWindow};
|
use bevy::{prelude::*, window::PrimaryWindow};
|
||||||
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
||||||
use bevy_mod_picking::debug::{DebugPickingMode, self};
|
use bevy_mod_picking::debug::{self, DebugPickingMode};
|
||||||
use bevy_rapier3d::na::Quaternion;
|
use bevy_rapier3d::na::Quaternion;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
bvh::BvhJoint,
|
||||||
camera_controller::{CameraController, CameraMotionSystem},
|
camera_controller::{CameraController, CameraMotionSystem},
|
||||||
input::{Action, InputAction, Lifecycle},
|
input::{Action, InputAction, Lifecycle},
|
||||||
scene::SkeletalJoint,
|
scene::SkeletalJoint,
|
||||||
MainCamera, bvh::BvhJoint,
|
MainCamera,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Resource, Deref, DerefMut)]
|
#[derive(Resource, Deref, DerefMut)]
|
||||||
@@ -51,8 +52,8 @@ impl Plugin for DebugPlugin {
|
|||||||
|
|
||||||
fn debug_bvh_model(
|
fn debug_bvh_model(
|
||||||
mut gizmos: Gizmos,
|
mut gizmos: Gizmos,
|
||||||
bvh_joints : Query<(&GlobalTransform, Option<&Children>), With<BvhJoint>>,
|
bvh_joints: Query<(&GlobalTransform, Option<&Children>), With<BvhJoint>>,
|
||||||
debug_mode : Res<DebugMode>,
|
debug_mode: Res<DebugMode>,
|
||||||
) {
|
) {
|
||||||
if true {
|
if true {
|
||||||
for (transform, children) in bvh_joints.iter() {
|
for (transform, children) in bvh_joints.iter() {
|
||||||
@@ -60,11 +61,35 @@ fn debug_bvh_model(
|
|||||||
|
|
||||||
if let Some(children) = children {
|
if let Some(children) = children {
|
||||||
for child in children.iter() {
|
for child in children.iter() {
|
||||||
if let Ok((child_transform, _)) = bvh_joints.get(child.clone()) {
|
if let Ok((child_transform, _)) = bvh_joints.get(child.clone()) {
|
||||||
gizmos.line(transform.translation(), child_transform.translation(), Color::RED);
|
gizmos.line(
|
||||||
|
transform.translation(),
|
||||||
|
child_transform.translation(),
|
||||||
|
Color::RED,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let local_x = transform.left() * 0.05;
|
||||||
|
let local_y = transform.up() * 0.05;
|
||||||
|
let local_z = transform.forward() * 0.05;
|
||||||
|
|
||||||
|
gizmos.line(
|
||||||
|
transform.translation(),
|
||||||
|
transform.translation() + local_x,
|
||||||
|
Color::RED,
|
||||||
|
);
|
||||||
|
gizmos.line(
|
||||||
|
transform.translation(),
|
||||||
|
transform.translation() + local_y,
|
||||||
|
Color::GREEN,
|
||||||
|
);
|
||||||
|
gizmos.line(
|
||||||
|
transform.translation(),
|
||||||
|
transform.translation() + local_z,
|
||||||
|
Color::BLUE,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,6 +170,14 @@ fn draw_skeletal_joints(
|
|||||||
|
|
||||||
gizmos.sphere(xlation, rotation, joint_radius, joint.0);
|
gizmos.sphere(xlation, rotation, joint_radius, joint.0);
|
||||||
gizmos.line(xlation, parent_xlation, joint.0);
|
gizmos.line(xlation, parent_xlation, joint.0);
|
||||||
|
|
||||||
|
let local_x = world_xform.left() * 0.05;
|
||||||
|
let local_y = world_xform.up() * 0.05;
|
||||||
|
let local_z = world_xform.forward() * 0.05;
|
||||||
|
|
||||||
|
gizmos.line(xlation, xlation + local_x, Color::RED);
|
||||||
|
gizmos.line(xlation, xlation + local_y, Color::GREEN);
|
||||||
|
gizmos.line(xlation, xlation + local_z, Color::BLUE);
|
||||||
} else {
|
} else {
|
||||||
gizmos.sphere(xlation, rotation, 0.01, joint.0);
|
gizmos.sphere(xlation, rotation, 0.01, joint.0);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -1,6 +1,6 @@
|
|||||||
#![allow(clippy::type_complexity, clippy::too_many_arguments)]
|
#![allow(clippy::type_complexity, clippy::too_many_arguments)]
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::{prelude::*, window::close_on_esc};
|
||||||
use bevy_mod_picking::DefaultPickingPlugins;
|
use bevy_mod_picking::DefaultPickingPlugins;
|
||||||
|
|
||||||
#[cfg(feature = "wasm")]
|
#[cfg(feature = "wasm")]
|
||||||
@@ -87,9 +87,10 @@ 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("base_human_female".to_string()));
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
.add_systems(Update, close_on_esc)
|
||||||
// .add_systems(
|
// .add_systems(
|
||||||
// Update,
|
// Update,
|
||||||
// bevy::window::close_on_esc
|
// bevy::window::close_on_esc
|
||||||
|
|||||||
+12
-12
@@ -43,7 +43,7 @@ impl Plugin for ScenePlugin {
|
|||||||
spawn_test_bvh, // TODO
|
spawn_test_bvh, // TODO
|
||||||
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),
|
||||||
)
|
)
|
||||||
@@ -95,7 +95,7 @@ struct PendingScene(pub Handle<Scene>);
|
|||||||
pub struct ActiveScene {
|
pub struct ActiveScene {
|
||||||
#[deref]
|
#[deref]
|
||||||
pub instance: InstanceId,
|
pub instance: InstanceId,
|
||||||
pub source: Handle<Scene>,
|
// pub source: Handle<Scene>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Event, Deref)]
|
#[derive(Event, Deref)]
|
||||||
@@ -151,7 +151,7 @@ fn initialize(mut cmd: Commands, r_assets: Res<AssetServer>) {
|
|||||||
));
|
));
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
cmd.insert_resource(TestBvh(r_assets.load("mocap/scott.bvh")));
|
cmd.insert_resource(TestBvh(r_assets.load("mocap/shuffle.bvh")));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
@@ -185,16 +185,16 @@ 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#Scene0");
|
let path = format!("gltf/{name}.glb#Scene0");
|
||||||
|
|
||||||
// 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) =
|
||||||
r_active_scene.and_then(|scene| scene.source.path().cloned())
|
// r_active_scene.and_then(|scene| scene.source.path().cloned())
|
||||||
{
|
// {
|
||||||
if active_scene_path == AssetPath::parse(&path) {
|
// if active_scene_path == AssetPath::parse(&path) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
cmd.insert_resource(PendingScene(assets.load(path)));
|
cmd.insert_resource(PendingScene(assets.load(path)));
|
||||||
st_next.set(SceneState::Loading);
|
st_next.set(SceneState::Loading);
|
||||||
@@ -230,7 +230,7 @@ fn spawn_next_scene(
|
|||||||
mut r_scene_spawner: ResMut<SceneSpawner>,
|
mut r_scene_spawner: ResMut<SceneSpawner>,
|
||||||
) {
|
) {
|
||||||
println!("Spawning Scene");
|
println!("Spawning Scene");
|
||||||
cmd.spawn_skined_bvh_with_transform(
|
cmd.spawn_bvh(
|
||||||
test_bvh.0.clone(),
|
test_bvh.0.clone(),
|
||||||
r_pending_scene.0.clone(),
|
r_pending_scene.0.clone(),
|
||||||
RetargetMap::mocap_to_rigify(),
|
RetargetMap::mocap_to_rigify(),
|
||||||
|
|||||||
Reference in New Issue
Block a user