use na::storage::Storage;
use na::{self, Isometry3, RealField, U6, UnitQuaternion, Vector, Vector3, Vector6};
use std::mem;
use std::ops::{Add, AddAssign, Mul, Sub, SubAssign};
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct Velocity3<N: RealField> {
pub linear: Vector3<N>,
pub angular: Vector3<N>,
}
impl<N: RealField> Velocity3<N> {
#[inline]
pub fn new(linear: Vector3<N>, angular: Vector3<N>) -> Self {
Velocity3 { linear, angular }
}
#[inline]
pub fn new_with_vectors(linear: Vector3<N>, angular: Vector3<N>) -> Self {
Self::new(linear, angular)
}
#[inline]
pub fn angular(wx: N, wy: N, wz: N) -> Self {
Velocity3::new(na::zero(), Vector3::new(wx, wy, wz))
}
#[inline]
pub fn linear(vx: N, vy: N, vz: N) -> Self {
Velocity3::new(Vector3::new(vx, vy, vz), na::zero())
}
pub fn between_positions(start: &Isometry3<N>, end: &Isometry3<N>, time: N) -> Self {
let delta = end / start;
let linear = delta.translation.vector / time;
let angular = delta.rotation.scaled_axis() / time;
Self::new(linear, angular)
}
#[inline]
pub fn zero() -> Self {
Self::new(na::zero(), na::zero())
}
#[inline]
pub fn angular_vector(&self) -> Vector3<N> {
self.angular
}
#[inline]
pub fn as_slice(&self) -> &[N] {
self.as_vector().as_slice()
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [N] {
self.as_vector_mut().as_mut_slice()
}
pub fn as_vector(&self) -> &Vector6<N> {
unsafe { mem::transmute(self) }
}
pub fn as_vector_mut(&mut self) -> &mut Vector6<N> {
unsafe { mem::transmute(self) }
}
#[inline]
pub fn from_vector<S: Storage<N, U6>>(data: &Vector<N, U6, S>) -> Self {
Self::new(
Vector3::new(data[0], data[1], data[2]),
Vector3::new(data[3], data[4], data[5]),
)
}
#[inline]
pub fn from_slice(data: &[N]) -> Self {
Self::new(
Vector3::new(data[0], data[1], data[2]),
Vector3::new(data[3], data[4], data[5]),
)
}
#[inline]
pub fn shift(&self, shift: &Vector3<N>) -> Self {
Self::new(self.linear + self.angular.cross(&shift), self.angular)
}
#[inline]
pub fn transformed(&self, iso: &Isometry3<N>) -> Self {
Self::new(iso * self.linear, iso * self.angular)
}
#[inline]
pub fn rotated(&self, rot: &UnitQuaternion<N>) -> Self {
Self::new(rot * self.linear, rot * self.angular)
}
}
impl<N: RealField> Add<Velocity3<N>> for Velocity3<N> {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
Velocity3::new(self.linear + rhs.linear, self.angular + rhs.angular)
}
}
impl<N: RealField> AddAssign<Velocity3<N>> for Velocity3<N> {
#[inline]
fn add_assign(&mut self, rhs: Self) {
self.linear += rhs.linear;
self.angular += rhs.angular;
}
}
impl<N: RealField> Sub<Velocity3<N>> for Velocity3<N> {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
Velocity3::new(self.linear - rhs.linear, self.angular - rhs.angular)
}
}
impl<N: RealField> SubAssign<Velocity3<N>> for Velocity3<N> {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
self.linear -= rhs.linear;
self.angular -= rhs.angular;
}
}
impl<N: RealField> Mul<N> for Velocity3<N> {
type Output = Self;
#[inline]
fn mul(self, rhs: N) -> Self {
Velocity3::new(self.linear * rhs, self.angular * rhs)
}
}