veloren/voxygen/src/anim/src/lib.rs

172 lines
5.1 KiB
Rust
Raw Normal View History

2020-06-17 07:49:14 +00:00
#[cfg(all(feature = "be-dyn-lib", feature = "use-dyn-lib"))]
compile_error!("Can't use both \"be-dyn-lib\" and \"use-dyn-lib\" features at once");
pub mod biped_large;
pub mod bird_medium;
pub mod bird_small;
pub mod character;
pub mod critter;
pub mod dragon;
#[cfg(feature = "use-dyn-lib")] pub mod dyn_lib;
pub mod fish_medium;
pub mod fish_small;
pub mod fixture;
pub mod golem;
pub mod object;
pub mod quadruped_medium;
pub mod quadruped_small;
#[cfg(feature = "use-dyn-lib")]
pub use dyn_lib::init;
#[cfg(feature = "use-dyn-lib")]
use std::ffi::CStr;
2020-06-17 07:49:14 +00:00
use vek::*;
// TODO: replace with inner type everywhere
pub struct FigureBoneData(pub Mat4<f32>);
impl FigureBoneData {
pub fn new(mat: Mat4<f32>) -> Self { Self(mat) }
pub fn default() -> Self { Self(Mat4::identity()) }
}
#[derive(Copy, Clone, Debug)]
pub struct Bone {
pub offset: Vec3<f32>,
pub ori: Quaternion<f32>,
pub scale: Vec3<f32>,
}
impl Default for Bone {
fn default() -> Self {
Self {
offset: Vec3::zero(),
ori: Quaternion::identity(),
scale: Vec3::broadcast(1.0 / 11.0),
}
}
}
impl Bone {
pub fn compute_base_matrix(&self) -> Mat4<f32> {
Mat4::<f32>::translation_3d(self.offset)
* Mat4::scaling_3d(self.scale)
* Mat4::from(self.ori)
}
/// Change the current bone to be more like `target`.
fn interpolate(&mut self, target: &Bone, dt: f32) {
// TODO: Make configurable.
let factor = (15.0 * dt).min(1.0);
self.offset += (target.offset - self.offset) * factor;
self.ori = vek::Slerp::slerp(self.ori, target.ori, factor);
self.scale += (target.scale - self.scale) * factor;
}
}
pub trait Skeleton: Send + Sync + 'static {
type Attr;
#[cfg(feature = "use-dyn-lib")]
2020-06-19 03:33:30 +00:00
const COMPUTE_FN: &'static [u8];
2020-06-17 07:49:14 +00:00
fn bone_count(&self) -> usize { 16 }
2020-06-19 03:33:30 +00:00
fn compute_matrices_inner(&self) -> ([FigureBoneData; 16], Vec3<f32>);
2020-06-17 07:49:14 +00:00
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
#[cfg(not(feature = "use-dyn-lib"))]
{
Self::compute_matrices_inner(self)
}
#[cfg(feature = "use-dyn-lib")]
{
let lock = dyn_lib::LIB.lock().unwrap();
let lib = &lock.as_ref().unwrap().lib;
let compute_fn: libloading::Symbol<fn(&Self) -> ([FigureBoneData; 16], Vec3<f32>)> =
unsafe { lib.get(Self::COMPUTE_FN) }.unwrap_or_else(|err| {
panic!(
"Trying to use: {} but had error: {:?}",
CStr::from_bytes_with_nul(Self::COMPUTE_FN)
.map(CStr::to_str)
.unwrap()
.unwrap(),
err
)
});
2020-06-17 07:49:14 +00:00
compute_fn(self)
}
}
/// Change the current skeleton to be more like `target`.
fn interpolate(&mut self, target: &Self, dt: f32);
}
pub trait Animation {
type Skeleton: Skeleton;
type Dependency;
#[cfg(feature = "use-dyn-lib")]
2020-06-19 03:33:30 +00:00
const UPDATE_FN: &'static [u8];
2020-06-17 07:49:14 +00:00
/// Returns a new skeleton that is generated by the animation.
2020-06-19 03:33:30 +00:00
fn update_skeleton_inner(
_skeleton: &Self::Skeleton,
_dependency: Self::Dependency,
_anim_time: f64,
_rate: &mut f32,
_skeleton_attr: &<<Self as Animation>::Skeleton as Skeleton>::Attr,
) -> Self::Skeleton;
/// Calls `update_skeleton_inner` either directly or via `libloading` to
/// produce generate the new skeleton.
2020-06-17 07:49:14 +00:00
fn update_skeleton(
skeleton: &Self::Skeleton,
dependency: Self::Dependency,
anim_time: f64,
rate: &mut f32,
skeleton_attr: &<<Self as Animation>::Skeleton as Skeleton>::Attr,
) -> Self::Skeleton {
#[cfg(not(feature = "use-dyn-lib"))]
{
Self::update_skeleton_inner(skeleton, dependency, anim_time, rate, skeleton_attr)
}
#[cfg(feature = "use-dyn-lib")]
{
let lock = dyn_lib::LIB.lock().unwrap();
let lib = &lock.as_ref().unwrap().lib;
let update_fn: libloading::Symbol<
fn(
&Self::Skeleton,
Self::Dependency,
f64,
&mut f32,
&<Self::Skeleton as Skeleton>::Attr,
) -> Self::Skeleton,
> = unsafe {
//let start = std::time::Instant::now();
// Overhead of 0.5-5 us (could use hashmap to mitigate if this is an issue)
let f = lib.get(Self::UPDATE_FN);
2020-06-17 07:49:14 +00:00
//println!("{}", start.elapsed().as_nanos());
f
}
.unwrap_or_else(|err| {
panic!(
"Trying to use: {} but had error: {:?}",
CStr::from_bytes_with_nul(Self::UPDATE_FN)
.map(CStr::to_str)
.unwrap()
.unwrap(),
err
)
});
2020-06-17 07:49:14 +00:00
update_fn(skeleton, dependency, anim_time, rate, skeleton_attr)
}
}
}