mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-17 00:13:17 +00:00
WIP asset loader for BVH files
This commit is contained in:
Generated
+1
@@ -3706,6 +3706,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"serde_json",
|
||||
"studio-bvh",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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"]
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
@@ -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
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user