Simplify BVH joints representation

This commit is contained in:
Danny McGee
2023-12-21 18:21:46 -05:00
parent 197f936785
commit 1bfb81f13d
4 changed files with 51 additions and 39 deletions
+10 -10
View File
@@ -17,7 +17,7 @@ pub type Offset = [f32; 3];
/// Internal representation of a joint. /// Internal representation of a joint.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub(crate) enum JointData { pub enum JointData {
/// Root of the skeletal heirarchy. /// Root of the skeletal heirarchy.
Root { Root {
/// Name of the root `Joint`. /// Name of the root `Joint`.
@@ -44,17 +44,17 @@ pub(crate) enum JointData {
impl JointData { impl JointData {
#[inline] #[inline]
pub(crate) const fn is_root(&self) -> bool { pub const fn is_root(&self) -> bool {
matches!(*self, JointData::Root { .. }) matches!(*self, JointData::Root { .. })
} }
#[inline] #[inline]
pub(crate) const fn is_child(&self) -> bool { pub const fn is_child(&self) -> bool {
matches!(*self, JointData::Child { .. }) matches!(*self, JointData::Child { .. })
} }
#[inline] #[inline]
pub(crate) fn name(&self) -> &[u8] { pub fn name(&self) -> &[u8] {
let name = match *self { let name = match *self {
JointData::Root { ref name, .. } | JointData::Child { ref name, .. } => name, JointData::Root { ref name, .. } | JointData::Child { ref name, .. } => name,
}; };
@@ -63,7 +63,7 @@ impl JointData {
} }
#[inline] #[inline]
pub(crate) fn name_str(&self) -> Result<&str, Utf8Error> { pub fn name_str(&self) -> Result<&str, Utf8Error> {
let name = match *self { let name = match *self {
JointData::Root { ref name, .. } => name, JointData::Root { ref name, .. } => name,
JointData::Child { ref name, .. } => name, JointData::Child { ref name, .. } => name,
@@ -73,14 +73,14 @@ impl JointData {
} }
#[inline] #[inline]
pub(crate) const fn offset(&self) -> &Offset { pub const fn offset(&self) -> &Offset {
match *self { match *self {
JointData::Child { ref offset, .. } | JointData::Root { ref offset, .. } => offset, JointData::Child { ref offset, .. } | JointData::Root { ref offset, .. } => offset,
} }
} }
#[inline] #[inline]
pub(crate) const fn end_site(&self) -> Option<&Offset> { pub const fn end_site(&self) -> Option<&Offset> {
match *self { match *self {
JointData::Child { JointData::Child {
ref end_site_offset, ref end_site_offset,
@@ -220,7 +220,7 @@ pub(crate) type JointNameInner = SmallVec<[u8; mem::size_of::<String>()]>;
/// Wrapper struct for the `Joint` name type. /// Wrapper struct for the `Joint` name type.
#[derive(Clone, Default, Eq, Hash, Ord)] #[derive(Clone, Default, Eq, Hash, Ord)]
pub(crate) struct JointName(pub(crate) JointNameInner); pub struct JointName(pub(crate) JointNameInner);
impl JointName { impl JointName {
#[inline] #[inline]
@@ -365,7 +365,7 @@ impl fmt::Display for JointName {
/// Data private to joints. /// Data private to joints.
#[doc(hidden)] #[doc(hidden)]
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq)]
pub(crate) struct JointPrivateData { pub struct JointPrivateData {
/// Index of this `Joint` in the array. /// Index of this `Joint` in the array.
pub(crate) self_index: usize, pub(crate) self_index: usize,
/// The parent index in the array of `JointPrivateData`s in the `Bvh`. /// 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`. /// Access a read-only view of the internal data of the `Joint`.
#[inline] #[inline]
pub(crate) const fn data(&self) -> &JointData { pub const fn data(&self) -> &JointData {
&self.joints[self.index] &self.joints[self.index]
} }
} }
+2 -2
View File
@@ -192,7 +192,7 @@ mod parse;
use crate::{ use crate::{
errors::{LoadError, ParseChannelError}, errors::{LoadError, ParseChannelError},
frames::{FrameCursor, Frames, FramesMut}, frames::{FrameCursor, Frames, FramesMut},
joint::{JointData, Offset}, joint::Offset,
}; };
use bstr::{ use bstr::{
io::{BufReadExt, ByteLines}, io::{BufReadExt, ByteLines},
@@ -217,7 +217,7 @@ pub mod frames {
pub use crate::frame_iter::{Frame, FrameIndex, FrameMut, Frames, FramesMut}; 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)] #[doc(hidden)]
pub use macros::BvhLiteralBuilder; pub use macros::BvhLiteralBuilder;
+34 -23
View File
@@ -1,7 +1,7 @@
use bevy::{ use bevy::{
asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext}, asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext},
prelude::*, prelude::*,
utils::{BoxedFuture, HashMap}, utils::BoxedFuture,
}; };
use super::{ use super::{
@@ -21,35 +21,21 @@ impl AssetLoader for BvhLoader {
&'a self, &'a self,
reader: &'a mut Reader, reader: &'a mut Reader,
_settings: &'a Self::Settings, _settings: &'a Self::Settings,
cx: &'a mut LoadContext, _cx: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> { ) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
Box::pin(async move { Box::pin(async move {
let mut buf = vec![]; let mut buf = vec![];
reader.read_to_end(&mut buf).await.anyhow()?; reader.read_to_end(&mut buf).await.anyhow()?;
// FIXME: This is algorithmically terrible
let bvh = studio_bvh::from_bytes(&buf).anyhow()?; let bvh = studio_bvh::from_bytes(&buf).anyhow()?;
let all_joints = bvh.joints().map(|j| j.data().clone()).collect::<Vec<_>>();
let joints = all_joints
.iter()
.map(|joint| joint.clone().into_bvh_joint(&all_joints))
.collect();
let mut joints = Vec::<Handle<BvhJoint>>::new(); Ok(Bvh { joints })
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,
})
}) })
} }
@@ -57,3 +43,28 @@ impl AssetLoader for BvhLoader {
&["bvh"] &["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(),
}
}
}
+5 -4
View File
@@ -1,4 +1,4 @@
use bevy::{prelude::*, utils::HashMap}; use bevy::prelude::*;
mod error; mod error;
mod loader; mod loader;
@@ -17,13 +17,14 @@ impl Plugin for BvhPlugin {
#[derive(Asset, TypePath, Debug)] #[derive(Asset, TypePath, Debug)]
pub struct Bvh { pub struct Bvh {
pub joints: Vec<Handle<BvhJoint>>, pub joints: Vec<BvhJoint>,
pub named_joints: HashMap<String, Handle<BvhJoint>>,
} }
#[derive(Asset, TypePath, Debug, Clone)] #[derive(Asset, TypePath, Debug, Clone)]
pub struct BvhJoint { pub struct BvhJoint {
pub parent: Option<Handle<BvhJoint>>, pub name: String,
/// Local transform /// Local transform
pub transform: Transform, pub transform: Transform,
/// Direct children of this joint
pub children: Vec<BvhJoint>,
} }