feat: changed some QueryPipeline API to be more library friendly (#863)

This commit is contained in:
Thierry Berger
2025-07-24 16:21:55 +02:00
committed by GitHub
parent 626512911b
commit 0f5b4a4d88
6 changed files with 22 additions and 25 deletions

View File

@@ -53,7 +53,7 @@ pub fn init_world(testbed: &mut Testbed) {
); );
for intersection in query_pipeline.intersect_shape( for intersection in query_pipeline.intersect_shape(
&Isometry::translation(slow_time.cos() * 10.0, slow_time.sin() * 10.0), Isometry::translation(slow_time.cos() * 10.0, slow_time.sin() * 10.0),
&Ball::new(rad / 2.0), &Ball::new(rad / 2.0),
) { ) {
if let Some(graphics) = graphics.as_deref_mut() { if let Some(graphics) = graphics.as_deref_mut() {

View File

@@ -140,7 +140,7 @@ fn update_kinematic_controller(
let Some(broad_phase) = phx.broad_phase.downcast_ref::<BroadPhaseBvh>() else { let Some(broad_phase) = phx.broad_phase.downcast_ref::<BroadPhaseBvh>() else {
return; return;
}; };
let query_pipeline = broad_phase.as_query_pipeline_mut( let mut query_pipeline = broad_phase.as_query_pipeline_mut(
phx.narrow_phase.query_dispatcher(), phx.narrow_phase.query_dispatcher(),
&mut phx.bodies, &mut phx.bodies,
&mut phx.colliders, &mut phx.colliders,
@@ -165,7 +165,7 @@ fn update_kinematic_controller(
controller.solve_character_collision_impulses( controller.solve_character_collision_impulses(
phx.integration_parameters.dt, phx.integration_parameters.dt,
query_pipeline, &mut query_pipeline,
&*character_shape, &*character_shape,
character_mass, character_mass,
&*collisions, &*collisions,

View File

@@ -150,7 +150,7 @@ fn update_kinematic_controller(
let Some(broad_phase) = phx.broad_phase.downcast_ref::<BroadPhaseBvh>() else { let Some(broad_phase) = phx.broad_phase.downcast_ref::<BroadPhaseBvh>() else {
return; return;
}; };
let query_pipeline = broad_phase.as_query_pipeline_mut( let mut query_pipeline = broad_phase.as_query_pipeline_mut(
phx.narrow_phase.query_dispatcher(), phx.narrow_phase.query_dispatcher(),
&mut phx.bodies, &mut phx.bodies,
&mut phx.colliders, &mut phx.colliders,
@@ -175,7 +175,7 @@ fn update_kinematic_controller(
controller.solve_character_collision_impulses( controller.solve_character_collision_impulses(
phx.integration_parameters.dt, phx.integration_parameters.dt,
query_pipeline, &mut query_pipeline,
&*character_shape, &*character_shape,
character_mass, character_mass,
&*collisions, &*collisions,

View File

@@ -423,7 +423,7 @@ impl KinematicCharacterController {
let mut grounded = false; let mut grounded = false;
'outer: for (_, collider) in queries.intersect_aabb_conservative(&character_aabb) { 'outer: for (_, collider) in queries.intersect_aabb_conservative(character_aabb) {
manifolds.clear(); manifolds.clear();
let pos12 = character_pos.inv_mul(collider.position()); let pos12 = character_pos.inv_mul(collider.position());
let _ = dispatcher.contact_manifolds( let _ = dispatcher.contact_manifolds(
@@ -770,7 +770,7 @@ impl KinematicCharacterController {
pub fn solve_character_collision_impulses<'a>( pub fn solve_character_collision_impulses<'a>(
&self, &self,
dt: Real, dt: Real,
mut queries: QueryPipelineMut, queries: &mut QueryPipelineMut,
character_shape: &dyn Shape, character_shape: &dyn Shape,
character_mass: Real, character_mass: Real,
collisions: impl IntoIterator<Item = &'a CharacterCollision>, collisions: impl IntoIterator<Item = &'a CharacterCollision>,
@@ -778,7 +778,7 @@ impl KinematicCharacterController {
for collision in collisions { for collision in collisions {
self.solve_single_character_collision_impulse( self.solve_single_character_collision_impulse(
dt, dt,
&mut queries, queries,
character_shape, character_shape,
character_mass, character_mass,
collision, collision,
@@ -813,10 +813,7 @@ impl KinematicCharacterController {
.compute_aabb(&collision.character_pos) .compute_aabb(&collision.character_pos)
.loosened(prediction); .loosened(prediction);
for (_, collider) in queries for (_, collider) in queries.as_ref().intersect_aabb_conservative(character_aabb) {
.as_ref()
.intersect_aabb_conservative(&character_aabb)
{
if let Some(parent) = collider.parent { if let Some(parent) = collider.parent {
if let Some(body) = queries.bodies.get(parent.handle) { if let Some(body) = queries.bodies.get(parent.handle) {
if body.is_dynamic() { if body.is_dynamic() {

View File

@@ -168,7 +168,7 @@ impl CCDSolver {
.shape .shape
.compute_swept_aabb(&co1.pos, &predicted_collider_pos1); .compute_swept_aabb(&co1.pos, &predicted_collider_pos1);
for (ch2, _) in query_pipeline.intersect_aabb_conservative(&aabb1) { for (ch2, _) in query_pipeline.intersect_aabb_conservative(aabb1) {
if *ch1 == ch2 { if *ch1 == ch2 {
// Ignore self-intersection. // Ignore self-intersection.
continue; continue;
@@ -301,7 +301,7 @@ impl CCDSolver {
.shape .shape
.compute_swept_aabb(&co1.pos, &predicted_collider_pos1); .compute_swept_aabb(&co1.pos, &predicted_collider_pos1);
for (ch2, _) in query_pipeline.intersect_aabb_conservative(&aabb1) { for (ch2, _) in query_pipeline.intersect_aabb_conservative(aabb1) {
if *ch1 == ch2 { if *ch1 == ch2 {
// Ignore self-intersection. // Ignore self-intersection.
continue; continue;
@@ -433,7 +433,7 @@ impl CCDSolver {
let co_next_pos1 = rb1.pos.next_position * co1_parent.pos_wrt_parent; let co_next_pos1 = rb1.pos.next_position * co1_parent.pos_wrt_parent;
let aabb = co1.shape.compute_swept_aabb(&co1.pos, &co_next_pos1); let aabb = co1.shape.compute_swept_aabb(&co1.pos, &co_next_pos1);
for (ch2, _) in query_pipeline.intersect_aabb_conservative(&aabb) { for (ch2, _) in query_pipeline.intersect_aabb_conservative(aabb) {
let co2 = &colliders[ch2]; let co2 = &colliders[ch2];
let bh1 = co1.parent.map(|p| p.handle); let bh1 = co1.parent.map(|p| p.handle);

View File

@@ -211,19 +211,19 @@ impl<'a> QueryPipeline<'a> {
#[profiling::function] #[profiling::function]
pub fn intersect_ray( pub fn intersect_ray(
&'a self, &'a self,
ray: &'a Ray, ray: Ray,
max_toi: Real, max_toi: Real,
solid: bool, solid: bool,
) -> impl Iterator<Item = (ColliderHandle, &'a Collider, RayIntersection)> + 'a { ) -> impl Iterator<Item = (ColliderHandle, &'a Collider, RayIntersection)> + 'a {
// TODO: add this to CompositeShapeRef? // TODO: add this to CompositeShapeRef?
self.bvh self.bvh
.leaves(move |node: &BvhNode| node.aabb().intersects_local_ray(ray, max_toi)) .leaves(move |node: &BvhNode| node.aabb().intersects_local_ray(&ray, max_toi))
.filter_map(move |leaf| { .filter_map(move |leaf| {
let (co, co_handle) = self.colliders.get_unknown_gen(leaf)?; let (co, co_handle) = self.colliders.get_unknown_gen(leaf)?;
if self.filter.test(self.bodies, co_handle, co) { if self.filter.test(self.bodies, co_handle, co) {
if let Some(intersection) = if let Some(intersection) =
co.shape co.shape
.cast_ray_and_get_normal(co.position(), ray, max_toi, solid) .cast_ray_and_get_normal(co.position(), &ray, max_toi, solid)
{ {
return Some((co_handle, co, intersection)); return Some((co_handle, co, intersection));
} }
@@ -259,15 +259,15 @@ impl<'a> QueryPipeline<'a> {
#[profiling::function] #[profiling::function]
pub fn intersect_point( pub fn intersect_point(
&'a self, &'a self,
point: &'a Point<Real>, point: Point<Real>,
) -> impl Iterator<Item = (ColliderHandle, &'a Collider)> + 'a { ) -> impl Iterator<Item = (ColliderHandle, &'a Collider)> + 'a {
// TODO: add to CompositeShapeRef? // TODO: add to CompositeShapeRef?
self.bvh self.bvh
.leaves(move |node: &BvhNode| node.aabb().contains_local_point(point)) .leaves(move |node: &BvhNode| node.aabb().contains_local_point(&point))
.filter_map(move |leaf| { .filter_map(move |leaf| {
let (co, co_handle) = self.colliders.get_unknown_gen(leaf)?; let (co, co_handle) = self.colliders.get_unknown_gen(leaf)?;
if self.filter.test(self.bodies, co_handle, co) if self.filter.test(self.bodies, co_handle, co)
&& co.shape.contains_point(co.position(), point) && co.shape.contains_point(co.position(), &point)
{ {
return Some((co_handle, co)); return Some((co_handle, co));
} }
@@ -299,11 +299,11 @@ impl<'a> QueryPipeline<'a> {
#[profiling::function] #[profiling::function]
pub fn intersect_aabb_conservative( pub fn intersect_aabb_conservative(
&'a self, &'a self,
aabb: &'a Aabb, aabb: Aabb,
) -> impl Iterator<Item = (ColliderHandle, &'a Collider)> + 'a { ) -> impl Iterator<Item = (ColliderHandle, &'a Collider)> + 'a {
// TODO: add to ColliderRef? // TODO: add to ColliderRef?
self.bvh self.bvh
.leaves(move |node: &BvhNode| node.aabb().intersects(aabb)) .leaves(move |node: &BvhNode| node.aabb().intersects(&aabb))
.filter_map(move |leaf| { .filter_map(move |leaf| {
let (co, co_handle) = self.colliders.get_unknown_gen(leaf)?; let (co, co_handle) = self.colliders.get_unknown_gen(leaf)?;
// NOTE: do **not** recompute and check the latest collider AABB. // NOTE: do **not** recompute and check the latest collider AABB.
@@ -388,11 +388,11 @@ impl<'a> QueryPipeline<'a> {
#[profiling::function] #[profiling::function]
pub fn intersect_shape( pub fn intersect_shape(
&'a self, &'a self,
shape_pos: &'a Isometry<Real>, shape_pos: Isometry<Real>,
shape: &'a dyn Shape, shape: &'a dyn Shape,
) -> impl Iterator<Item = (ColliderHandle, &'a Collider)> + 'a { ) -> impl Iterator<Item = (ColliderHandle, &'a Collider)> + 'a {
// TODO: add this to CompositeShapeRef? // TODO: add this to CompositeShapeRef?
let shape_aabb = shape.compute_aabb(shape_pos); let shape_aabb = shape.compute_aabb(&shape_pos);
self.bvh self.bvh
.leaves(move |node: &BvhNode| node.aabb().intersects(&shape_aabb)) .leaves(move |node: &BvhNode| node.aabb().intersects(&shape_aabb))
.filter_map(move |leaf| { .filter_map(move |leaf| {