use glam_det::nums::*;
use glam_det::{Mat3x4, Point3, Point3x4, Vec3, Vec3x4};
use super::BatchesReductionContext;
use crate::collision_tasks::ShapeWideTester;
use crate::convex_contact_manifold::Convex4ContactManifoldWide;
use crate::traits::{
CollisionCallBack, CollisionPairWide, ContactContext, ContactManifoldWide, Orientation,
OrientationWide, PairWide, PairWideTest, WritePairWide,
};
use crate::{ConvexContactManifold, ShapeContainer};
pub trait CollisionTask<const N: usize> {
type TPairWide: CollisionPairWide
+ Default
+ PairWide
+ WritePairWide<4>
+ WritePairWide<3>
+ WritePairWide<2>
+ WritePairWide<1>;
fn need_flip() -> bool;
#[inline]
fn flip(pair_wide: &mut Self::TPairWide, manifold_wide: &mut Convex4ContactManifoldWide) {
let mut offset_b = *pair_wide.offset_b();
ContactManifoldWide::<ConvexContactManifold>::apply_flip_mask(
manifold_wide,
N,
&mut offset_b,
pair_wide.flip_mask(),
);
pair_wide.set_offset_b(offset_b);
}
#[inline]
fn collision_wide<const PAIR_COUNT: usize>(
reduction_callback: &mut BatchesReductionContext,
collision_callback: &mut dyn CollisionCallBack,
pair_wide: &mut Self::TPairWide,
manifold_wide: &mut Convex4ContactManifoldWide,
container: Option<&ShapeContainer>,
) where
ShapeWideTester: PairWideTest<
<Self::TPairWide as CollisionPairWide>::TShapeWideA,
<Self::TPairWide as CollisionPairWide>::TShapeWideB,
>,
{
let a_wide = pair_wide.shape_a();
let b_wide = pair_wide.shape_b();
let speculative_margin = *pair_wide.speculative_margin();
let offset_b = pair_wide.offset_b();
let contact_context = ContactContext {
orientation_a: pair_wide.orientation_a(),
orientation_b: pair_wide.orientation_b(),
offset_b,
speculative_margin,
pair_count: PAIR_COUNT,
complex_shape_container: container,
};
let need_reset_manifold = <ShapeWideTester as PairWideTest<
<Self::TPairWide as CollisionPairWide>::TShapeWideA,
<Self::TPairWide as CollisionPairWide>::TShapeWideB,
>>::should_reset_manifold_before_test();
if need_reset_manifold {
manifold_wide.reset(N);
}
<ShapeWideTester as PairWideTest<
<Self::TPairWide as CollisionPairWide>::TShapeWideA,
<Self::TPairWide as CollisionPairWide>::TShapeWideB,
>>::test(a_wide, b_wide, &contact_context, manifold_wide);
if Self::need_flip() {
Self::flip(pair_wide, manifold_wide);
}
let mut manifold = ConvexContactManifold::default();
let reduction_ids = pair_wide.reduction_id();
let reduction_id_array = reduction_ids.as_ref();
for (index, reduction_id) in reduction_id_array.iter().enumerate().take(PAIR_COUNT) {
ContactManifoldWide::<ConvexContactManifold>::get_manifold(
manifold_wide,
index,
N,
pair_wide.offset_b(),
&mut manifold,
);
reduction_callback.on_pair_complete(*reduction_id, &manifold, collision_callback);
}
}
fn execute_batch(
pairs: &[<Self::TPairWide as PairWide>::TPair],
reduction_callback: &mut BatchesReductionContext,
collision_callback: &mut dyn CollisionCallBack,
container: Option<&ShapeContainer>,
) where
ShapeWideTester: PairWideTest<
<Self::TPairWide as CollisionPairWide>::TShapeWideA,
<Self::TPairWide as CollisionPairWide>::TShapeWideB,
>,
{
let lanes = i32x4::lanes();
let mut pair_wide = Self::TPairWide::default();
let mut manifold_wide = Convex4ContactManifoldWide::default();
let iter = &mut pairs.iter();
let wide_pair_full_wide_count = pairs.len() / lanes;
for _ in 0..wide_pair_full_wide_count {
let pair_0 = iter.next().unwrap();
let pair_1 = iter.next().unwrap();
let pair_2 = iter.next().unwrap();
let pair_3 = iter.next().unwrap();
pair_wide.write_wide([pair_0, pair_1, pair_2, pair_3]);
Self::collision_wide::<4>(
reduction_callback,
collision_callback,
&mut pair_wide,
&mut manifold_wide,
container,
);
}
match pairs.len() % lanes {
3 => {
let mut iter = iter.take(3);
let pair_0 = iter.next().unwrap();
let pair_1 = iter.next().unwrap();
let pair_2 = iter.next().unwrap();
pair_wide.write_wide([pair_0, pair_1, pair_2]);
Self::collision_wide::<3>(
reduction_callback,
collision_callback,
&mut pair_wide,
&mut manifold_wide,
container,
);
}
2 => {
let mut iter = iter.take(2);
let pair_0 = iter.next().unwrap();
let pair_1 = iter.next().unwrap();
pair_wide.write_wide([pair_0, pair_1]);
Self::collision_wide::<2>(
reduction_callback,
collision_callback,
&mut pair_wide,
&mut manifold_wide,
container,
);
}
1 => {
let mut iter = iter.take(1);
let pair_0 = iter.next().unwrap();
pair_wide.write_wide([pair_0]);
Self::collision_wide::<1>(
reduction_callback,
collision_callback,
&mut pair_wide,
&mut manifold_wide,
container,
);
}
0 => {}
_ => unreachable!(),
}
}
}
pub trait TransformativeWide {
type Orientation: OrientationWide;
fn offset(&self) -> Vec3x4;
fn orientation(&self) -> &Self::Orientation;
#[allow(unused)]
#[inline]
fn transform_point(&self, point: Point3x4) -> Point3x4 {
let result = self.orientation().mul_vec3(point.as_vec3x4()) + self.offset();
Point3x4::from_vec3x4(result)
}
#[allow(unused)]
#[inline]
fn inverse_transform_point(&self, point: Point3x4) -> Point3x4 {
let offset = self.orientation().inverse_mul_vec3(-self.offset());
let point = self.orientation().inverse_mul_vec3(point.as_vec3x4());
Point3x4::from_vec3x4(offset + point)
}
}
pub(super) trait Transformative {
type Orientation: Orientation;
fn offset(&self) -> Vec3;
fn orientation(&self) -> &Self::Orientation;
#[inline]
fn transform_point(&self, point: Point3) -> Point3 {
let result = self.orientation().mul_vec3(point.as_vec3()) + self.offset();
Point3::from_vec3(result)
}
#[allow(unused)]
#[inline]
fn inverse_transform_point(&self, point: Point3) -> Point3 {
let offset = self.orientation().inverse_mul_vec3(-self.offset());
let point = self.orientation().inverse_mul_vec3(point.as_vec3());
Point3::from_vec3(offset + point)
}
}
#[derive(Clone, Copy)]
pub enum Axis {
X = 0,
Y = 1,
Z = 2,
}
pub trait AxisInfo {
fn x_axis(&self) -> Vec3x4;
fn y_axis(&self) -> Vec3x4;
fn z_axis(&self) -> Vec3x4;
#[inline]
fn axis(&self, index: Axis) -> Vec3x4 {
match index {
Axis::X => self.x_axis(),
Axis::Y => self.y_axis(),
Axis::Z => self.z_axis(),
}
}
}
pub struct TransformWide<'a, T> {
pub offset: Vec3x4,
pub orientation: &'a T,
}
impl<'a, T> TransformWide<'a, T> {
#[inline]
pub fn new(offset: Vec3x4, orientation: &'a T) -> Self {
Self {
offset,
orientation,
}
}
}
impl<'a, T> TransformativeWide for TransformWide<'a, T>
where
T: OrientationWide,
{
type Orientation = T;
#[inline]
fn offset(&self) -> Vec3x4 {
self.offset
}
#[inline]
fn orientation(&self) -> &Self::Orientation {
self.orientation
}
}
pub(crate) struct Transform<'a, T> {
pub offset: Vec3,
pub orientation: &'a T,
}
impl<'a, T> Transform<'a, T> {
#[inline]
pub fn new(offset: Vec3, orientation: &'a T) -> Self {
Self {
offset,
orientation,
}
}
}
impl<'a, T> Transformative for Transform<'a, T>
where
T: Orientation,
{
type Orientation = T;
#[inline]
fn offset(&self) -> Vec3 {
self.offset
}
#[inline]
fn orientation(&self) -> &Self::Orientation {
self.orientation
}
}
impl<'a> AxisInfo for TransformWide<'a, Mat3x4> {
#[inline]
fn x_axis(&self) -> Vec3x4 {
self.orientation.x_axis
}
#[inline]
fn y_axis(&self) -> Vec3x4 {
self.orientation.y_axis
}
#[inline]
fn z_axis(&self) -> Vec3x4 {
self.orientation.z_axis
}
}
impl AxisInfo for Mat3x4 {
#[inline]
fn x_axis(&self) -> Vec3x4 {
self.x_axis
}
#[inline]
fn y_axis(&self) -> Vec3x4 {
self.y_axis
}
#[inline]
fn z_axis(&self) -> Vec3x4 {
self.z_axis
}
}