diff options
| author | Crozet Sébastien <developer@crozet.re> | 2020-09-21 17:26:57 +0200 |
|---|---|---|
| committer | Crozet Sébastien <developer@crozet.re> | 2020-09-28 15:27:25 +0200 |
| commit | 2dda0e5ce48ed0d93b4b0fa3098ba08f59a50a0a (patch) | |
| tree | eca54e0187df75a70ee461a987e23cc02ff4c653 /src/geometry/waabb.rs | |
| parent | 7b8e322446ffa36e3f47078e23eb61ef423175dc (diff) | |
| download | rapier-2dda0e5ce48ed0d93b4b0fa3098ba08f59a50a0a.tar.gz rapier-2dda0e5ce48ed0d93b4b0fa3098ba08f59a50a0a.tar.bz2 rapier-2dda0e5ce48ed0d93b4b0fa3098ba08f59a50a0a.zip | |
Complete the WQuadtree construction and ray-cast.
Diffstat (limited to 'src/geometry/waabb.rs')
| -rw-r--r-- | src/geometry/waabb.rs | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/src/geometry/waabb.rs b/src/geometry/waabb.rs index 702b5aa..0664a50 100644 --- a/src/geometry/waabb.rs +++ b/src/geometry/waabb.rs @@ -1,7 +1,10 @@ +use crate::geometry::Ray; #[cfg(feature = "serde-serialize")] use crate::math::DIM; -use crate::math::{Point, SIMD_WIDTH}; +use crate::math::{Point, Vector, SIMD_WIDTH}; +use crate::utils; use ncollide::bounding_volume::AABB; +use num::{One, Zero}; #[cfg(feature = "simd-is-enabled")] use { crate::math::{SimdBool, SimdFloat}, @@ -10,6 +13,29 @@ use { #[derive(Debug, Copy, Clone)] #[cfg(feature = "simd-is-enabled")] +pub(crate) struct WRay { + pub origin: Point<SimdFloat>, + pub dir: Vector<SimdFloat>, +} + +impl WRay { + pub fn splat(ray: Ray) -> Self { + Self { + origin: Point::splat(ray.origin), + dir: Vector::splat(ray.dir), + } + } +} + +#[derive(Debug, Copy, Clone)] +#[cfg(not(feature = "simd-is-enabled"))] +pub(crate) struct WRay { + pub origin: [Point<f32>; SIMD_WIDTH], + pub dir: [Vector<f32>; SIMD_WIDTH], +} + +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "simd-is-enabled")] pub(crate) struct WAABB { pub mins: Point<SimdFloat>, pub maxs: Point<SimdFloat>, @@ -124,6 +150,42 @@ impl WAABB { } } + pub fn intersects_ray(&self, ray: &WRay, max_toi: SimdFloat) -> SimdBool { + let _0 = SimdFloat::zero(); + let _1 = SimdFloat::one(); + let _infinity = SimdFloat::splat(f32::MAX); + + let mut hit = SimdBool::splat(true); + let mut tmin = SimdFloat::zero(); + let mut tmax = max_toi; + + // TODO: could this be optimized more considering we really just need a boolean answer? + for i in 0usize..DIM { + let is_not_zero = ray.dir[i].simd_ne(_0); + let is_zero_test = + (ray.origin[i].simd_ge(self.mins[i]) & ray.origin[i].simd_le(self.maxs[i])); + let is_not_zero_test = { + let denom = _1 / ray.dir[i]; + let mut inter_with_near_plane = + ((self.mins[i] - ray.origin[i]) * denom).select(is_not_zero, -_infinity); + let mut inter_with_far_plane = + ((self.maxs[i] - ray.origin[i]) * denom).select(is_not_zero, _infinity); + + let gt = inter_with_near_plane.simd_gt(inter_with_far_plane); + utils::simd_swap(gt, &mut inter_with_near_plane, &mut inter_with_far_plane); + + tmin = tmin.simd_max(inter_with_near_plane); + tmax = tmax.simd_min(inter_with_far_plane); + + tmin.simd_le(tmax) + }; + + hit = hit & is_not_zero_test.select(is_not_zero, is_zero_test); + } + + hit + } + #[cfg(feature = "dim2")] pub fn intersects_lanewise(&self, other: &WAABB) -> SimdBool { self.mins.x.simd_le(other.maxs.x) |
