@@ -150,6 +150,10 @@ struct RigidBodySlot2D {
150150struct ColliderSlot2D {
151151 /// The handle to the Rapier collider stored in the `ColliderSet`.
152152 rapier_handle : ColliderHandle ,
153+ /// The parent rigid body slot index that owns this collider.
154+ parent_slot_index : u32 ,
155+ /// The parent rigid body slot generation that owns this collider.
156+ parent_slot_generation : u32 ,
153157 /// A monotonically increasing counter used to validate stale handles.
154158 generation : u32 ,
155159}
@@ -620,6 +624,85 @@ impl PhysicsBackend2D {
620624 . is_ok ( ) ;
621625 }
622626
627+ /// Returns all rigid bodies whose colliders contain the provided point.
628+ ///
629+ /// # Arguments
630+ /// - `point`: The world-space point to test.
631+ ///
632+ /// # Returns
633+ /// Returns backend rigid body slot pairs for each matching collider.
634+ pub fn query_point_2d ( & self , point : [ f32 ; 2 ] ) -> Vec < ( u32 , u32 ) > {
635+ if validate_position ( point[ 0 ] , point[ 1 ] ) . is_err ( ) {
636+ return Vec :: new ( ) ;
637+ }
638+
639+ let point = Vector :: new ( point[ 0 ] , point[ 1 ] ) ;
640+ let mut body_slots = Vec :: new ( ) ;
641+
642+ for ( collider_handle, collider) in self . colliders . iter ( ) {
643+ if !collider. shape ( ) . contains_point ( collider. position ( ) , point) {
644+ continue ;
645+ }
646+
647+ let Some ( body_slot) =
648+ self . query_hit_to_parent_body_slot_2d ( collider_handle)
649+ else {
650+ continue ;
651+ } ;
652+
653+ body_slots. push ( body_slot) ;
654+ }
655+
656+ return body_slots;
657+ }
658+
659+ /// Returns all rigid bodies whose colliders overlap the provided AABB.
660+ ///
661+ /// # Arguments
662+ /// - `min`: The minimum world-space corner of the query box.
663+ /// - `max`: The maximum world-space corner of the query box.
664+ ///
665+ /// # Returns
666+ /// Returns backend rigid body slot pairs for each matching collider.
667+ pub fn query_aabb_2d ( & self , min : [ f32 ; 2 ] , max : [ f32 ; 2 ] ) -> Vec < ( u32 , u32 ) > {
668+ if validate_position ( min[ 0 ] , min[ 1 ] ) . is_err ( )
669+ || validate_position ( max[ 0 ] , max[ 1 ] ) . is_err ( )
670+ {
671+ return Vec :: new ( ) ;
672+ }
673+
674+ let half_extents =
675+ Vector :: new ( ( max[ 0 ] - min[ 0 ] ) * 0.5 , ( max[ 1 ] - min[ 1 ] ) * 0.5 ) ;
676+ let center = Vector :: new ( ( min[ 0 ] + max[ 0 ] ) * 0.5 , ( min[ 1 ] + max[ 1 ] ) * 0.5 ) ;
677+ let query_shape = Cuboid :: new ( half_extents) ;
678+ let query_pose = Pose :: from_translation ( center) ;
679+ let query_dispatcher = self . narrow_phase . query_dispatcher ( ) ;
680+ let mut body_slots = Vec :: new ( ) ;
681+
682+ for ( collider_handle, collider) in self . colliders . iter ( ) {
683+ let shape_to_collider = query_pose. inv_mul ( collider. position ( ) ) ;
684+ let intersects = query_dispatcher. intersection_test (
685+ & shape_to_collider,
686+ & query_shape,
687+ collider. shape ( ) ,
688+ ) ;
689+
690+ if intersects != Ok ( true ) {
691+ continue ;
692+ }
693+
694+ let Some ( body_slot) =
695+ self . query_hit_to_parent_body_slot_2d ( collider_handle)
696+ else {
697+ continue ;
698+ } ;
699+
700+ body_slots. push ( body_slot) ;
701+ }
702+
703+ return body_slots;
704+ }
705+
623706 /// Sets the current position for the referenced body.
624707 ///
625708 /// # Arguments
@@ -1101,6 +1184,8 @@ impl PhysicsBackend2D {
11011184 let slot_generation = 1 ;
11021185 self . collider_slots_2d . push ( ColliderSlot2D {
11031186 rapier_handle,
1187+ parent_slot_index,
1188+ parent_slot_generation,
11041189 generation : slot_generation,
11051190 } ) ;
11061191
@@ -1222,10 +1307,41 @@ impl PhysicsBackend2D {
12221307 self . colliders. get( slot. rapier_handle) . is_some( ) ,
12231308 "collider slot references missing Rapier collider"
12241309 ) ;
1310+ debug_assert ! (
1311+ self
1312+ . rigid_body_slot_2d(
1313+ slot. parent_slot_index,
1314+ slot. parent_slot_generation
1315+ )
1316+ . is_ok( ) ,
1317+ "collider slot references missing parent rigid body slot"
1318+ ) ;
12251319 }
12261320
12271321 return ;
12281322 }
1323+ /// Resolves a query hit collider back to its owning rigid body slot.
1324+ ///
1325+ /// # Arguments
1326+ /// - `collider_handle`: The Rapier collider handle returned by a query.
1327+ ///
1328+ /// # Returns
1329+ /// Returns the owning backend rigid body slot pair when the collider slot is
1330+ /// still tracked by the backend.
1331+ fn query_hit_to_parent_body_slot_2d (
1332+ & self ,
1333+ collider_handle : ColliderHandle ,
1334+ ) -> Option < ( u32 , u32 ) > {
1335+ let collider_slot = self
1336+ . collider_slots_2d
1337+ . iter ( )
1338+ . find ( |slot| slot. rapier_handle == collider_handle) ?;
1339+
1340+ return Some ( (
1341+ collider_slot. parent_slot_index ,
1342+ collider_slot. parent_slot_generation ,
1343+ ) ) ;
1344+ }
12291345}
12301346
12311347/// Builds a Rapier rigid body builder with `lambda-rs` invariants applied.
0 commit comments