use std::ops::{Add, Mul, Neg, Sub};
use mat4;
use num_traits::{Float, One, Zero};
use specs::{Component, DenseVecStorage, FlaggedStorage};
#[derive(Debug, Serialize, Deserialize)]
pub struct Transform3D<T> {
pub position: [T; 3],
pub scale: [T; 3],
pub rotation: [T; 4],
}
impl<T> Component for Transform3D<T>
where
T: 'static + Sync + Send,
{
type Storage = FlaggedStorage<Self, DenseVecStorage<Self>>;
}
impl<T> Default for Transform3D<T>
where
T: Zero + One,
{
#[inline(always)]
fn default() -> Self {
Self::new(
[T::zero(), T::zero(), T::zero()],
[T::one(), T::one(), T::one()],
[T::zero(), T::zero(), T::zero(), T::one()],
)
}
}
impl<T> Transform3D<T>
where
T: Zero + One,
{
#[inline(always)]
pub fn new(position: [T; 3], scale: [T; 3], rotation: [T; 4]) -> Self {
Transform3D {
position: position,
scale: scale,
rotation: rotation,
}
}
#[inline]
pub fn with_position(mut self, position: [T; 3]) -> Self {
self.position = position;
self
}
#[inline]
pub fn with_scale(mut self, scale: [T; 3]) -> Self {
self.scale = scale;
self
}
#[inline]
pub fn with_rotation(mut self, rotation: [T; 4]) -> Self {
self.rotation = rotation;
self
}
#[inline]
pub fn set_position(&mut self, position: [T; 3]) -> &mut Self {
self.position = position;
self
}
#[inline]
pub fn set_scale(&mut self, scale: [T; 3]) -> &mut Self {
self.scale = scale;
self
}
#[inline]
pub fn set_rotation(&mut self, rotation: [T; 4]) -> &mut Self {
self.rotation = rotation;
self
}
#[inline(always)]
pub fn matrix(&self) -> [T; 16]
where
T: Float,
for<'a, 'b> &'a T: Mul<&'b T, Output = T>
+ Neg<Output = T>
+ Add<&'b T, Output = T>
+ Sub<&'b T, Output = T>,
{
let mut matrix = mat4::new_identity();
mat4::compose(&mut matrix, &self.position, &self.scale, &self.rotation);
matrix
}
}