From 1bfb81f13dcc7fe163fec86691d0b0fdfd2a8bac Mon Sep 17 00:00:00 2001 From: Danny McGee Date: Thu, 21 Dec 2023 18:21:46 -0500 Subject: [PATCH] Simplify BVH joints representation --- studio-bvh/src/joint.rs | 20 +++++++------- studio-bvh/src/lib.rs | 4 +-- studio/src/bvh/loader.rs | 57 ++++++++++++++++++++++++---------------- studio/src/bvh/mod.rs | 9 ++++--- 4 files changed, 51 insertions(+), 39 deletions(-) diff --git a/studio-bvh/src/joint.rs b/studio-bvh/src/joint.rs index 4d12ca6..b0612de 100644 --- a/studio-bvh/src/joint.rs +++ b/studio-bvh/src/joint.rs @@ -17,7 +17,7 @@ pub type Offset = [f32; 3]; /// Internal representation of a joint. #[derive(Clone, Debug, PartialEq)] -pub(crate) enum JointData { +pub enum JointData { /// Root of the skeletal heirarchy. Root { /// Name of the root `Joint`. @@ -44,17 +44,17 @@ pub(crate) enum JointData { impl JointData { #[inline] - pub(crate) const fn is_root(&self) -> bool { + pub const fn is_root(&self) -> bool { matches!(*self, JointData::Root { .. }) } #[inline] - pub(crate) const fn is_child(&self) -> bool { + pub const fn is_child(&self) -> bool { matches!(*self, JointData::Child { .. }) } #[inline] - pub(crate) fn name(&self) -> &[u8] { + pub fn name(&self) -> &[u8] { let name = match *self { JointData::Root { ref name, .. } | JointData::Child { ref name, .. } => name, }; @@ -63,7 +63,7 @@ impl JointData { } #[inline] - pub(crate) fn name_str(&self) -> Result<&str, Utf8Error> { + pub fn name_str(&self) -> Result<&str, Utf8Error> { let name = match *self { JointData::Root { ref name, .. } => name, JointData::Child { ref name, .. } => name, @@ -73,14 +73,14 @@ impl JointData { } #[inline] - pub(crate) const fn offset(&self) -> &Offset { + pub const fn offset(&self) -> &Offset { match *self { JointData::Child { ref offset, .. } | JointData::Root { ref offset, .. } => offset, } } #[inline] - pub(crate) const fn end_site(&self) -> Option<&Offset> { + pub const fn end_site(&self) -> Option<&Offset> { match *self { JointData::Child { ref end_site_offset, @@ -220,7 +220,7 @@ pub(crate) type JointNameInner = SmallVec<[u8; mem::size_of::()]>; /// Wrapper struct for the `Joint` name type. #[derive(Clone, Default, Eq, Hash, Ord)] -pub(crate) struct JointName(pub(crate) JointNameInner); +pub struct JointName(pub(crate) JointNameInner); impl JointName { #[inline] @@ -365,7 +365,7 @@ impl fmt::Display for JointName { /// Data private to joints. #[doc(hidden)] #[derive(Clone, Eq, PartialEq)] -pub(crate) struct JointPrivateData { +pub struct JointPrivateData { /// Index of this `Joint` in the array. pub(crate) self_index: usize, /// The parent index in the array of `JointPrivateData`s in the `Bvh`. @@ -805,7 +805,7 @@ impl Joint<'_> { /// Access a read-only view of the internal data of the `Joint`. #[inline] - pub(crate) const fn data(&self) -> &JointData { + pub const fn data(&self) -> &JointData { &self.joints[self.index] } } diff --git a/studio-bvh/src/lib.rs b/studio-bvh/src/lib.rs index 0b8b1c0..d413d90 100644 --- a/studio-bvh/src/lib.rs +++ b/studio-bvh/src/lib.rs @@ -192,7 +192,7 @@ mod parse; use crate::{ errors::{LoadError, ParseChannelError}, frames::{FrameCursor, Frames, FramesMut}, - joint::{JointData, Offset}, + joint::Offset, }; use bstr::{ io::{BufReadExt, ByteLines}, @@ -217,7 +217,7 @@ pub mod frames { pub use crate::frame_iter::{Frame, FrameIndex, FrameMut, Frames, FramesMut}; } -pub use joint::{Joint, JointMut, Joints, JointsMut}; +pub use joint::{Joint, JointData, JointMut, Joints, JointsMut}; #[doc(hidden)] pub use macros::BvhLiteralBuilder; diff --git a/studio/src/bvh/loader.rs b/studio/src/bvh/loader.rs index 82efd4e..4565dee 100644 --- a/studio/src/bvh/loader.rs +++ b/studio/src/bvh/loader.rs @@ -1,7 +1,7 @@ use bevy::{ asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext}, prelude::*, - utils::{BoxedFuture, HashMap}, + utils::BoxedFuture, }; use super::{ @@ -21,35 +21,21 @@ impl AssetLoader for BvhLoader { &'a self, reader: &'a mut Reader, _settings: &'a Self::Settings, - cx: &'a mut LoadContext, + _cx: &'a mut LoadContext, ) -> BoxedFuture<'a, Result> { Box::pin(async move { let mut buf = vec![]; reader.read_to_end(&mut buf).await.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::>(); + let joints = all_joints + .iter() + .map(|joint| joint.clone().into_bvh_joint(&all_joints)) + .collect(); - let mut joints = Vec::>::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, - }) + Ok(Bvh { joints }) }) } @@ -57,3 +43,28 @@ impl AssetLoader for BvhLoader { &["bvh"] } } + +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(), + } + } +} diff --git a/studio/src/bvh/mod.rs b/studio/src/bvh/mod.rs index 1938d7f..7753a97 100644 --- a/studio/src/bvh/mod.rs +++ b/studio/src/bvh/mod.rs @@ -1,4 +1,4 @@ -use bevy::{prelude::*, utils::HashMap}; +use bevy::prelude::*; mod error; mod loader; @@ -17,13 +17,14 @@ impl Plugin for BvhPlugin { #[derive(Asset, TypePath, Debug)] pub struct Bvh { - pub joints: Vec>, - pub named_joints: HashMap>, + pub joints: Vec, } #[derive(Asset, TypePath, Debug, Clone)] pub struct BvhJoint { - pub parent: Option>, + pub name: String, /// Local transform pub transform: Transform, + /// Direct children of this joint + pub children: Vec, }