Stablized bvh representation

This commit is contained in:
Brooks Palin
2023-12-29 11:33:17 -07:00
parent 5164e85ff5
commit 744fd75192
6 changed files with 820 additions and 111 deletions
+39 -37
View File
@@ -6,7 +6,7 @@ use bevy::{
use super::{
error::{Anyhow, Error},
Bvh, BvhJoint,
Bvh,
};
#[derive(Default)]
@@ -26,22 +26,24 @@ impl AssetLoader for BvhLoader {
Box::pin(async move {
let mut buf = vec![];
reader.read_to_end(&mut buf).await.anyhow()?;
let bvh = studio_bvh::from_bytes(&buf).anyhow()?;
// FIXME: This is algorithmically terrible
let bvh = studio_bvh::from_bytes(&buf).anyhow()?;
let all_joints = bvh.joints().map(|j| j.data().clone()).collect::<Vec<_>>();
let joints = bvh
.joints()
.filter_map(|joint| {
if joint.is_root() {
Some(joint.data().clone().into_bvh_joint(&all_joints))
} else {
None
}
})
.collect();
// let all_joints = bvh.joints().map(|j| j.data().clone()).collect::<Vec<_>>();
// let joints = bvh
// .joints()
// .filter_map(|joint| {
// if joint.is_root() {
// Some(joint.data().clone().into_bvh_joint(&all_joints))
// } else {
// None
// }
// })
// .collect();
Ok(Bvh { joints })
// bvh.frame_cursor().
Ok(Bvh(bvh))
})
}
@@ -50,27 +52,27 @@ impl AssetLoader for BvhLoader {
}
}
trait IntoBvhJoint: Sized {
fn into_bvh_joint(self, data: &[Self]) -> BvhJoint;
}
// trait IntoBvhJoint: Sized {
// fn into_bvh_joint(self, data: &[Self]) -> BvhJoint;
// }
impl IntoBvhJoint for studio_bvh::JointData {
fn into_bvh_joint(self, data: &[Self]) -> BvhJoint {
BvhJoint {
name: String::from_utf8_lossy(self.name()).into(),
transform: Transform::from_translation((*self.offset()).into()),
children: data
.iter()
.filter_map(|joint| {
joint.parent_index().and_then(|idx| {
if idx == self.index() {
Some(joint.clone().into_bvh_joint(data))
} else {
None
}
})
})
.collect(),
}
}
}
// impl IntoBvhJoint for studio_bvh::JointData {
// fn into_bvh_joint(self, data: &[Self]) -> BvhJoint {
// BvhJoint {
// name: String::from_utf8_lossy(self.name()).into(),
// transform: Transform::from_translation((*self.offset()).into()),
// children: data
// .iter()
// .filter_map(|joint| {
// joint.parent_index().and_then(|idx| {
// if idx == self.index() {
// Some(joint.clone().into_bvh_joint(data))
// } else {
// None
// }
// })
// })
// .collect(),
// }
// }
// }
+115 -12
View File
@@ -1,4 +1,5 @@
use bevy::prelude::*;
use bevy::{prelude::*, ecs::system::{Command, EntityCommands}, asset::AsyncReadExt};
use studio_bvh::joint;
mod error;
mod loader;
@@ -10,21 +11,123 @@ pub struct BvhPlugin;
impl Plugin for BvhPlugin {
fn build(&self, app: &mut App) {
app.init_asset::<Bvh>()
.init_asset::<BvhJoint>()
.register_asset_loader(BvhLoader);
}
}
#[derive(Asset, TypePath, Debug)]
pub struct Bvh {
pub joints: Vec<BvhJoint>,
//==============================================================================
// Bvh Asset
//==============================================================================
#[derive(Clone, Debug, Default, Asset, TypePath)]
pub struct Bvh(studio_bvh::Bvh);
//==============================================================================
// Bvh Anim Component
//==============================================================================
#[derive(Component, Debug)]
pub struct BvhAnim {
pub bvh : Handle<Bvh>,
pub frame : usize,
}
#[derive(Asset, TypePath, Debug, Clone)]
pub struct BvhJoint {
pub name: String,
/// Local transform
pub transform: Transform,
/// Direct children of this joint
pub children: Vec<BvhJoint>,
//==============================================================================
// Bvh Anim Component
//==============================================================================
#[derive(Debug, Component)]
pub struct BvhJoint;
//==============================================================================
// Commands Plugin
//==============================================================================
pub trait CommandsSpawnBvhExt {
fn spawn_bvh(&mut self, asset : &Handle<Bvh>) -> Entity;
fn spawn_bvh_with_transform(&mut self, asset : &Handle<Bvh>, transform : Transform) -> Entity;
}
impl <'w, 's> CommandsSpawnBvhExt for Commands<'w, 's> {
fn spawn_bvh(&mut self, asset : &Handle<Bvh>) -> Entity {
let entity = self.spawn_empty().id();
self.add(SpawnBvhCommand(entity, 1.0, asset.clone()));
self.entity(entity).insert(BvhAnim {
bvh : asset.clone(),
frame : 0,
});
entity
}
fn spawn_bvh_with_transform(&mut self, asset : &Handle<Bvh>, transform : Transform) -> Entity {
let entity = self.spawn_empty().id();
self.add(SpawnBvhCommand(entity, 1.0, asset.clone()));
self.entity(entity).insert((
BvhAnim {
bvh : asset.clone(),
frame : 0,
},
transform
));
entity
}
}
pub struct SpawnBvhCommand(Entity, f32, Handle<Bvh>);
impl Command for SpawnBvhCommand {
fn apply(self, world: &mut World) {
let bvh = {
let Some(bvh) = world.get_resource::<Assets<Bvh>>().unwrap().get(self.2)
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") };
spawn_bvh_recursive(world, &self.0, root);
}
}
//==============================================================================
// Utility Functions
//==============================================================================
// fn spawn_bvh(commands : &mut Commands, asset : Handle<Bvh>, assets : &Res<Assets<Bvh>>) -> Option<Entity> {
// let Some(root) = bvh.0.root_joint()
// else { return None; };
// let tree = spawn_bvh_recursive(commands, &bvh.0, root);
// // commands.entity(tree).insert(BvhAnim {
// // bvh : bvh.id(),
// // frame : 0,
// // }
// // Some()
// }
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,
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]);
};
}
+24 -2
View File
@@ -2,13 +2,14 @@ use std::fmt;
use bevy::{prelude::*, window::PrimaryWindow};
use bevy_inspector_egui::quick::WorldInspectorPlugin;
use bevy_mod_picking::debug::DebugPickingMode;
use bevy_mod_picking::debug::{DebugPickingMode, self};
use bevy_rapier3d::na::Quaternion;
use crate::{
camera_controller::{CameraController, CameraMotionSystem},
input::{Action, InputAction, Lifecycle},
scene::SkeletalJoint,
MainCamera,
MainCamera, bvh::BvhJoint,
};
#[derive(Resource, Deref, DerefMut)]
@@ -36,6 +37,7 @@ impl Plugin for DebugPlugin {
.add_systems(
Update,
(
debug_bvh_model,
toggle_debug_mode,
update_debug_picking_mode.run_if(resource_changed::<DebugMode>()),
update_gizmo_line_thickness,
@@ -47,6 +49,26 @@ impl Plugin for DebugPlugin {
}
}
fn debug_bvh_model(
mut gizmos: Gizmos,
bvh_joints : Query<(&GlobalTransform, Option<&Children>), With<BvhJoint>>,
debug_mode : Res<DebugMode>,
) {
if debug_mode.0 {
for (transform, children) in bvh_joints.iter() {
gizmos.sphere(transform.translation(), Quat::IDENTITY, 0.01, Color::TEAL);
if let Some(children) = children {
for child in children.iter() {
if let Ok((child_transform, _)) = bvh_joints.get(child.clone()) {
gizmos.line(transform.translation(), child_transform.translation(), Color::RED);
}
}
}
}
}
}
fn toggle_debug_mode(mut input: EventReader<InputAction>, mut r_debug: ResMut<DebugMode>) {
if input
.read()
+36 -34
View File
@@ -17,7 +17,7 @@ use bevy::{
use wasm_bindgen::prelude::wasm_bindgen;
use crate::{
bvh::{Bvh, BvhJoint},
bvh::{Bvh, BvhJoint, CommandsSpawnBvhExt},
camera_controller::{CameraController, CameraControllerBundle},
debug::DebugPoint,
math::{Combinable, Extrema},
@@ -155,52 +155,54 @@ fn initialize(mut cmd: Commands, r_assets: Res<AssetServer>) {
// TODO
fn spawn_test_bvh(
mut cmd: Commands,
mut commands: Commands,
mut er_bvh_events: EventReader<AssetEvent<Bvh>>,
r_bvh: Res<TestBvh>,
ra_bvh: Res<Assets<Bvh>>,
) {
for event in er_bvh_events.read() {
if matches!(event, AssetEvent::LoadedWithDependencies { .. }) {
let bvh = ra_bvh.get(&**r_bvh).unwrap();
for joint in bvh.joints.iter() {
let scale = Vec3::splat(0.01);
let offset = vec3(0., 0.849, -0.024);
commands.spawn_bvh_with_transform(&r_bvh.0, Transform::from_scale(Vec3::splat(0.01)).with_translation(Vec3::new(0., 0.849, -0.024)));
let mut parent = cmd.spawn((
Name::new("BVH Skeleton"),
SpatialBundle::from_transform(Transform {
rotation: default(),
translation: offset,
scale,
}),
));
let parent_ent = parent.id();
info!("SPAWNED BVH")
// let bvh = ra_bvh.get(&**r_bvh).unwrap();
// for joint in bvh.joints.iter() {
// let scale = Vec3::splat(0.01);
// let offset = vec3(0., 0.849, -0.024);
spawn_joint(parent.commands(), joint, Some(parent_ent));
}
// let mut parent = cmd.spawn((
// Name::new("BVH Skeleton"),
// SpatialBundle::from_transform(Transform {
// rotation: default(),
// translation: offset,
// scale,
// }),
// ));
// let parent_ent = parent.id();
// spawn_joint(parent.commands(), joint, Some(parent_ent));
// }
}
}
}
// TODO
fn spawn_joint(cmd: &mut Commands, joint: &BvhJoint, parent: Option<Entity>) {
let mut spawned = cmd.spawn((
Name::new(joint.name.clone()),
SpatialBundle::from_transform(joint.transform),
SceneElement,
SkeletalJoint(Color::CYAN),
));
let spawned_ent = spawned.id();
// // TODO
// fn spawn_joint(cmd: &mut Commands, joint: &BvhJoint, parent: Option<Entity>) {
// let mut spawned = cmd.spawn((
// Name::new(joint.name.clone()),
// SpatialBundle::from_transform(joint.transform),
// SceneElement,
// SkeletalJoint(Color::CYAN),
// ));
// let spawned_ent = spawned.id();
if let Some(parent) = parent {
spawned.set_parent(parent);
}
// if let Some(parent) = parent {
// spawned.set_parent(parent);
// }
for child in joint.children.iter() {
spawn_joint(spawned.commands(), child, Some(spawned_ent));
}
}
// for child in joint.children.iter() {
// spawn_joint(spawned.commands(), child, Some(spawned_ent));
// }
// }
fn init_scene_loading(
mut cmd: Commands,