#![deny(missing_docs, trivial_casts, unsafe_code, unstable_features, unused_import_braces,
unused_qualifications)]
extern crate cgmath;
extern crate collision;
#[cfg(feature = "ecs")]
extern crate shrev;
#[cfg(feature = "ecs")]
extern crate specs;
#[cfg(test)]
#[macro_use]
extern crate approx;
#[cfg(feature = "eders")]
#[macro_use]
extern crate serde;
pub mod collide;
pub mod physics;
#[cfg(feature = "ecs")]
pub mod ecs;
use cgmath::BaseFloat;
use cgmath::prelude::*;
use collision::prelude::*;
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))]
pub struct NextFrame<T> {
pub value: T,
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))]
pub struct BodyPose<P, R> {
dirty: bool,
position: P,
rotation: R,
inverse_rotation: R,
}
impl<P, R> BodyPose<P, R>
where
P: EuclideanSpace,
P::Scalar: BaseFloat,
R: Rotation<P>,
{
pub fn new(position: P, rotation: R) -> Self {
Self {
dirty: true,
position,
inverse_rotation: rotation.invert(),
rotation,
}
}
pub fn set_rotation(&mut self, rotation: R) {
self.rotation = rotation;
self.inverse_rotation = self.rotation.invert();
self.dirty = true;
}
pub fn set_position(&mut self, position: P) {
self.position = position;
self.dirty = true;
}
pub fn position(&self) -> &P {
&self.position
}
pub fn rotation(&self) -> &R {
&self.rotation
}
pub fn clear(&mut self) {
self.dirty = false;
}
}
impl<P, R> Transform<P> for BodyPose<P, R>
where
P: EuclideanSpace,
P::Scalar: BaseFloat,
R: Rotation<P>,
{
fn one() -> Self {
Self::new(P::origin(), R::one())
}
fn look_at(eye: P, center: P, up: P::Diff) -> Self {
let rot = R::look_at(center - eye, up);
let disp = rot.rotate_vector(P::origin() - eye);
Self::new(P::from_vec(disp), rot)
}
fn transform_vector(&self, vec: P::Diff) -> P::Diff {
self.rotation.rotate_vector(vec)
}
fn transform_point(&self, point: P) -> P {
self.rotation.rotate_point(point) + self.position.to_vec()
}
fn concat(&self, other: &Self) -> Self {
Self::new(
self.position + self.rotation.rotate_point(other.position).to_vec(),
self.rotation * other.rotation,
)
}
fn inverse_transform(&self) -> Option<Self> {
Some(Self::new(
self.rotation.rotate_point(self.position) * -P::Scalar::one(),
self.inverse_rotation,
))
}
fn inverse_transform_vector(&self, vec: P::Diff) -> Option<P::Diff> {
Some(self.inverse_rotation.rotate_vector(vec))
}
}
impl<P, R> TranslationInterpolate<P::Scalar> for BodyPose<P, R>
where
P: EuclideanSpace,
P::Scalar: BaseFloat,
P::Diff: VectorSpace + InnerSpace,
R: Rotation<P> + Clone,
{
fn translation_interpolate(&self, other: &Self, amount: P::Scalar) -> Self {
BodyPose::new(
P::from_vec(self.position.to_vec().lerp(other.position.to_vec(), amount)),
other.rotation.clone(),
)
}
}
impl<P, R> Interpolate<P::Scalar> for BodyPose<P, R>
where
P: EuclideanSpace,
P::Scalar: BaseFloat,
P::Diff: VectorSpace + InnerSpace,
R: Rotation<P> + Interpolate<P::Scalar>,
{
fn interpolate(&self, other: &Self, amount: P::Scalar) -> Self {
BodyPose::new(
P::from_vec(self.position.to_vec().lerp(other.position.to_vec(), amount)),
self.rotation.interpolate(&other.rotation, amount),
)
}
}