Take collision groups into account for ray-casting.

This commit is contained in:
Crozet Sébastien
2020-10-27 14:29:58 +01:00
parent 5a5ba9cf59
commit b4d322a6ca
2 changed files with 35 additions and 21 deletions

View File

@@ -1,5 +1,7 @@
use crate::dynamics::RigidBodySet; use crate::dynamics::RigidBodySet;
use crate::geometry::{Collider, ColliderHandle, ColliderSet, Ray, RayIntersection, WQuadtree}; use crate::geometry::{
Collider, ColliderHandle, ColliderSet, InteractionGroups, Ray, RayIntersection, WQuadtree,
};
/// A pipeline for performing queries on all the colliders of a scene. /// A pipeline for performing queries on all the colliders of a scene.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
@@ -59,6 +61,7 @@ impl QueryPipeline {
colliders: &'a ColliderSet, colliders: &'a ColliderSet,
ray: &Ray, ray: &Ray,
max_toi: f32, max_toi: f32,
groups: InteractionGroups,
) -> Option<(ColliderHandle, &'a Collider, RayIntersection)> { ) -> Option<(ColliderHandle, &'a Collider, RayIntersection)> {
// TODO: avoid allocation? // TODO: avoid allocation?
let mut inter = Vec::new(); let mut inter = Vec::new();
@@ -69,14 +72,17 @@ impl QueryPipeline {
for handle in inter { for handle in inter {
let collider = &colliders[handle]; let collider = &colliders[handle];
if let Some(inter) = if collider.collision_groups.test(groups) {
collider if let Some(inter) = collider.shape().toi_and_normal_with_ray(
.shape() collider.position(),
.toi_and_normal_with_ray(collider.position(), ray, max_toi, true) ray,
{ max_toi,
if inter.toi < best { true,
best = inter.toi; ) {
result = Some((handle, collider, inter)); if inter.toi < best {
best = inter.toi;
result = Some((handle, collider, inter));
}
} }
} }
} }
@@ -99,6 +105,7 @@ impl QueryPipeline {
colliders: &'a ColliderSet, colliders: &'a ColliderSet,
ray: &Ray, ray: &Ray,
max_toi: f32, max_toi: f32,
groups: InteractionGroups,
mut callback: impl FnMut(ColliderHandle, &'a Collider, RayIntersection) -> bool, mut callback: impl FnMut(ColliderHandle, &'a Collider, RayIntersection) -> bool,
) { ) {
// TODO: avoid allocation? // TODO: avoid allocation?
@@ -107,13 +114,17 @@ impl QueryPipeline {
for handle in inter { for handle in inter {
let collider = &colliders[handle]; let collider = &colliders[handle];
if let Some(inter) =
collider if collider.collision_groups.test(groups) {
.shape() if let Some(inter) = collider.shape().toi_and_normal_with_ray(
.toi_and_normal_with_ray(collider.position(), ray, max_toi, true) collider.position(),
{ ray,
if !callback(handle, collider, inter) { max_toi,
return; true,
) {
if !callback(handle, collider, inter) {
return;
}
} }
} }
} }

View File

@@ -24,7 +24,8 @@ use rapier::dynamics::{
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
use rapier::geometry::Ray; use rapier::geometry::Ray;
use rapier::geometry::{ use rapier::geometry::{
BroadPhase, ColliderHandle, ColliderSet, ContactEvent, NarrowPhase, ProximityEvent, BroadPhase, ColliderHandle, ColliderSet, ContactEvent, InteractionGroups, NarrowPhase,
ProximityEvent,
}; };
use rapier::math::Vector; use rapier::math::Vector;
use rapier::pipeline::{ChannelEventCollector, PhysicsPipeline, QueryPipeline}; use rapier::pipeline::{ChannelEventCollector, PhysicsPipeline, QueryPipeline};
@@ -1188,10 +1189,12 @@ impl Testbed {
.camera() .camera()
.unproject(&self.cursor_pos, &na::convert(size)); .unproject(&self.cursor_pos, &na::convert(size));
let ray = Ray::new(pos, dir); let ray = Ray::new(pos, dir);
let hit = self let hit = self.physics.query_pipeline.cast_ray(
.physics &self.physics.colliders,
.query_pipeline &ray,
.cast_ray(&self.physics.colliders, &ray, f32::MAX); f32::MAX,
InteractionGroups::all(),
);
if let Some((_, collider, _)) = hit { if let Some((_, collider, _)) = hit {
if self.physics.bodies[collider.parent()].is_dynamic() { if self.physics.bodies[collider.parent()].is_dynamic() {