WIP asset loader for BVH files

This commit is contained in:
Danny McGee
2023-12-20 20:38:16 -05:00
parent 6606e5fb5b
commit 197f936785
7 changed files with 157 additions and 1 deletions
Generated
+1
View File
@@ -3706,6 +3706,7 @@ dependencies = [
"serde",
"serde-wasm-bindgen",
"serde_json",
"studio-bvh",
"wasm-bindgen",
"web-sys",
]
+2
View File
@@ -13,6 +13,7 @@ name = "studio-standalone"
path = "src/main.rs"
[dependencies]
anyhow = { workspace = true }
bevy-inspector-egui = "0.21.0"
bevy_mod_raycast = "0.16.0"
bevy_rapier3d = "0.23.0"
@@ -24,6 +25,7 @@ parking_lot = "0.12.1"
serde = { version = "1.0.192", optional = true }
serde-wasm-bindgen = { version = "0.6.1", optional = true }
serde_json = { version = "1.0.108", optional = true }
studio-bvh = { path = "../studio-bvh" }
wasm-bindgen = "0.2.84"
web-sys = { version = "0.3.65", optional = true, features = [
"CustomEvent",
+38
View File
@@ -0,0 +1,38 @@
use core::fmt;
use anyhow::anyhow;
use bevy::prelude::Deref;
#[derive(Debug, Deref)]
pub struct Error(pub anyhow::Error);
impl From<anyhow::Error> for Error {
fn from(value: anyhow::Error) -> Self {
Self(value)
}
}
pub trait Anyhow<T> {
fn anyhow(self) -> anyhow::Result<T>;
}
impl<T, E> Anyhow<T> for Result<T, E>
where
E: std::error::Error,
{
fn anyhow(self) -> anyhow::Result<T> {
self.map_err(|err| anyhow!("{err}"))
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.0.source()
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", **self)
}
}
+59
View File
@@ -0,0 +1,59 @@
use bevy::{
asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext},
prelude::*,
utils::{BoxedFuture, HashMap},
};
use super::{
error::{Anyhow, Error},
Bvh, BvhJoint,
};
#[derive(Default)]
pub struct BvhLoader;
impl AssetLoader for BvhLoader {
type Asset = Bvh;
type Settings = ();
type Error = Error;
fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a Self::Settings,
cx: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
Box::pin(async move {
let mut buf = vec![];
reader.read_to_end(&mut buf).await.anyhow()?;
let bvh = studio_bvh::from_bytes(&buf).anyhow()?;
let mut joints = Vec::<Handle<BvhJoint>>::new();
let mut named_joints = HashMap::new();
for (idx, joint) in bvh.joints().enumerate() {
let label = format!("Joint{idx}");
let asset = BvhJoint {
transform: Transform::from_translation((*joint.offset()).into()),
parent: joint.parent_index().map(|idx| joints[idx].clone()),
};
let handle = cx.add_labeled_asset(label, asset);
joints.push(handle.clone());
let name = String::from_utf8_lossy(joint.name()).to_string();
named_joints.insert(name, handle);
}
Ok(Bvh {
joints,
named_joints,
})
})
}
fn extensions(&self) -> &[&str] {
&["bvh"]
}
}
+29
View File
@@ -0,0 +1,29 @@
use bevy::{prelude::*, utils::HashMap};
mod error;
mod loader;
use self::loader::BvhLoader;
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<Handle<BvhJoint>>,
pub named_joints: HashMap<String, Handle<BvhJoint>>,
}
#[derive(Asset, TypePath, Debug, Clone)]
pub struct BvhJoint {
pub parent: Option<Handle<BvhJoint>>,
/// Local transform
pub transform: Transform,
}
+3
View File
@@ -6,6 +6,7 @@ use bevy_mod_picking::DefaultPickingPlugins;
#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;
mod bvh;
mod camera_controller;
mod debug;
mod design_system;
@@ -20,6 +21,7 @@ mod viewport;
mod world_grid;
use crate::{
bvh::BvhPlugin,
camera_controller::CameraControllerPlugin,
debug::DebugPlugin,
input::StudioInputPlugin,
@@ -134,6 +136,7 @@ pub fn start_viewer(
SkyboxPlugin,
UiLayerPlugin,
WorldGridPlugin,
BvhPlugin, // TODO: Alphabetize these plugins
))
.add_systems(
Startup,
+25 -1
View File
@@ -17,6 +17,7 @@ use bevy::{
use wasm_bindgen::prelude::wasm_bindgen;
use crate::{
bvh::Bvh,
camera_controller::{CameraController, CameraControllerBundle},
debug::DebugPoint,
math::{Combinable, Extrema},
@@ -38,6 +39,7 @@ impl Plugin for ScenePlugin {
.add_systems(
Update,
(
spawn_test_bvh, // TODO
init_scene_loading,
tick_scene_loading.run_if(in_state(SceneState::Loading)),
tick_scene_spawning.run_if(in_state(SceneState::Spawning)),
@@ -113,10 +115,14 @@ pub struct SkeletalJoint;
#[derive(Component)]
pub struct SceneRoot;
fn initialize(mut cmd: Commands) {
#[derive(Resource, Deref, DerefMut)]
struct TestBvh(Handle<Bvh>); // TODO
fn initialize(mut cmd: Commands, r_assets: Res<AssetServer>) {
// Camera, graphics settings
let focus = Vec3::ZERO;
let camera_xform = Transform::from_xyz(-2.5, 4.5, 5.0).looking_at(focus, Vec3::Y);
cmd.spawn((
Name::new("Main Camera"),
MainCamera,
@@ -142,6 +148,24 @@ fn initialize(mut cmd: Commands) {
},
Fxaa::default(),
));
// TODO
cmd.insert_resource(TestBvh(r_assets.load("mocap/scott.bvh")));
}
// TODO
fn spawn_test_bvh(
mut _cmd: 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();
info!("{bvh:#?}");
}
}
}
fn init_scene_loading(