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;
|
|
|
|
|
2020-06-18 06:45:49 +00:00
|
|
|
#[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>)> =
|
2020-06-18 06:45:49 +00:00
|
|
|
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)
|
2020-06-18 06:45:49 +00:00
|
|
|
let f = lib.get(Self::UPDATE_FN);
|
2020-06-17 07:49:14 +00:00
|
|
|
//println!("{}", start.elapsed().as_nanos());
|
|
|
|
f
|
2020-06-18 06:45:49 +00:00
|
|
|
}
|
|
|
|
.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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|