mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-18 07:35:19 +00:00
Simplify BVH joints representation
This commit is contained in:
+10
-10
@@ -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]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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>,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user