use serde::Serialize;
use crate::FArray;
use crate::{Float, QArray, Quaternion, SqMatrix4, Transform, Vector};
#[derive(Clone, Copy, Debug)] pub struct FQArrayTrans<F>
where
F: Float + Serialize,
FArray<F, 4>: Vector<F, 4>,
QArray<F>: Quaternion<F>,
{
quat: QArray<F>,
trans_scale: [F; 4],
}
macro_rules! fqarray_basic_traits {
{ $f:ty, $ty:ty } => {
impl std::default::Default for $ty
{
fn default() -> Self {
use num_traits::{One, Zero};
Self {
quat: QArray::default(),
trans_scale: [<$f>::zero(), <$f>
::zero(), <$f>::zero(), <$f>::one()]
}
}
}
impl std::fmt::Display for $ty
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"trans[+({},{},{}) rot{} *{}]",
self.trans_scale[0],
self.trans_scale[1],
self.trans_scale[2],
self.quat,
self.trans_scale[3],
)
}
}
}
}
macro_rules! fqarray_transform_trait {
{ $f:ty, $v:ty, $q:ty, $ty:ty } => {
impl Transform<$f, $v, $q> for $ty
{
fn of_trs(t: $v, r: $q, s: $f) -> Self {
Self {
quat: r,
trans_scale: [t[0], t[1], t[2], s],
}
}
fn scale(&self) -> $f {
self.trans_scale[3]
}
fn translation(&self) -> $v {
[
self.trans_scale[0],
self.trans_scale[1],
self.trans_scale[2],
]
.into()
}
fn rotation(&self) -> QArray<$f> {
self.quat
}
fn inverse(&self) -> Self {
use num_traits::{Float, One};
let scale = self.trans_scale[3];
if scale.abs() < <$f>::epsilon() {
Self::default()
} else {
let scale = <$f>::one() / scale;
let trans: $v = [
self.trans_scale[0],
self.trans_scale[1],
self.trans_scale[2],
]
.into();
let iquat = self.quat.conjugate();
let trans = iquat.apply3(&trans);
let trans = trans * -scale;
Self::of_trs(trans, iquat, scale)
}
}
fn invert(&mut self) {
*self = self.inverse();
}
fn as_mat<M: SqMatrix4<$f>>(&self) -> M {
let mut m = M::default();
self.quat.set_rotation4(&mut m);
m *= self.trans_scale[3];
m[3] = self.trans_scale[0];
m[7] = self.trans_scale[1];
m[11] = self.trans_scale[2];
m
}
}
}
}
macro_rules! fqarray_traits {
{ $f:ty, $v:ty, $q:ty, $ty:ty } => {
fqarray_basic_traits! {$f, $ty}
fqarray_transform_trait! {$f, $v, $q, $ty}
}
}
fqarray_traits! {f32, FArray<f32,3>, QArray<f32>, FQArrayTrans<f32>}
fqarray_traits! {f64, FArray<f64,3>, QArray<f64>, FQArrayTrans<f64>}