scene_queries_intersection_test
Intersection tests will find all the colliders with a shape intersecting a given shape. This can be useful for, e.g., selecting all the objects that intersect a given area. There are two kind of intersection tests:
- The exact intersection test
QueryPipeline::intersect_shapeRapierContext::intersect_shapeWorld.intersectionsWithShaper3IntersectShape searches for all the colliders with shapes intersecting the given shape.QueryPipeline.intersect_shape - The approximate intersection test
QueryPipeline::intersect_aabb_conservativeRapierContext::intersect_aabb_conservativeWorld.collidersWithAabbIntersectingAabbr3IntersectAabbConservative searches for all the colliders with an AABB intersecting the given AABB. This does not check if the actual shapes of these colliders intersect the AABB.QueryPipeline.intersect_aabb_conservativeNote that the AABB taken into account is the one currently stored in the BVH of the broad-phase: it isn't recomputed from the latest collider positions. Note that the AABB taken into account is the one currently stored in the BVH of the broad-phase (updated by each simulation step): it isn't recomputed from the latest collider positions. Note that the AABB taken into account is the one currently stored in the BVH of the broad-phase (updated by each call to r3Step): it isn't recomputed from the latest collider positions.Note that the AABB taken into account is the one currently stored in the BVH of the broad-phase (updated by each call to PhysicsWorld.step): it isn't recomputed from the latest collider positions.
See the ray-casting section for details about intersection tests between a ray and the colliders on the scene. And see the point projection section for details about the intersection test between the colliders and a point.
- Example 2D
- Example 3D
let shape = Cuboid::new(Vector::new(1.0, 2.0));
let shape_pos = Pose::new(Vector::new(0.0, 1.0), 0.2);
let filter = QueryFilter::default();
let query_pipeline = world.query_pipeline_with_filter(filter);
for (handle, _) in query_pipeline.intersect_shape(shape_pos, &shape) {
println!("The collider {:?} intersects our shape.", handle);
}
let aabb = Aabb::new(Vector::new(-1.0, -2.0), Vector::new(1.0, 2.0));
for (handle, _) in query_pipeline.intersect_aabb_conservative(aabb) {
println!("The collider {:?} has an AABB intersecting our test AABB", handle);
}
let shape = Cuboid::new(Vector::new(1.0, 2.0, 3.0));
let shape_pos = Pose::new(Vector::new(0.0, 1.0, 0.0), Vector::new(0.2, 0.7, 0.1));
let filter = QueryFilter::default();
let query_pipeline = world.query_pipeline_with_filter(filter);
for (handle, _) in query_pipeline.intersect_shape(shape_pos, &shape) {
println!("The collider {:?} intersects our shape.", handle);
}
let aabb = Aabb::new(Vector::new(-1.0, -2.0, -3.0), Vector::new(1.0, 2.0, 3.0));
for (handle, _) in query_pipeline.intersect_aabb_conservative(aabb) {
println!("The collider {:?} has an AABB intersecting our test AABB", handle);
}
- Example 2D
- Example 3D
/* Test intersections inside of a system. */
fn test_intersections(rapier_context: ReadRapierContext) {
let rapier_context = rapier_context.single().unwrap();
let shape = Collider::cuboid(1.0, 2.0);
let shape_pos = Vec2::new(0.0, 1.0);
let shape_rot = 0.8;
let filter = QueryFilter::default();
rapier_context.intersect_shape(shape_pos, shape_rot, &shape, filter, |entity, _collider| {
println!("The entity {:?} intersects our shape.", entity);
true // Return `false` instead if we want to stop searching for other colliders intersecting our shape.
});
let aabb = Aabb2d::new(Vec2::new(-1.0, -2.0), Vec2::new(1.0, 2.0));
rapier_context.intersect_aabb_conservative(aabb, filter, |entity, _collider| {
println!(
"The entity {:?} has an AABB intersecting our test AABB",
entity
);
true // Return `false` instead if we want to stop searching for other colliders with an intersecting AABB.
});
}
/* Test intersections inside of a system. */
fn test_intersections(rapier_context: ReadRapierContext) {
let rapier_context = rapier_context.single().unwrap();
let shape = Collider::cuboid(1.0, 2.0, 3.0);
let shape_pos = Vec3::new(0.0, 1.0, 2.0);
let shape_rot = Quat::from_rotation_z(0.8);
let filter = QueryFilter::default();
rapier_context.intersect_shape(shape_pos, shape_rot, &shape, filter, |entity, _collider| {
println!("The entity {:?} intersects our shape.", entity);
true // Return `false` instead if we want to stop searching for other colliders intersecting our shape.
});
let aabb = Aabb3d::new(Vec3::new(-1.0, -2.0, -3.0), Vec3::new(1.0, 2.0, 3.0));
rapier_context.intersect_aabb_conservative(aabb, filter, |entity, _collider| {
println!(
"The entity {:?} has an AABB intersecting our test AABB",
entity
);
true // Return `false` instead if we want to stop searching for other colliders with an intersecting AABB.
});
}
The closures given to these methods are called with the entity of each collider found, as well as its Rapier collider
(rapier::geometry::Collider), and can return false to stop the search. The AABB to test is given as a Bevy
Aabb2d in 2D, or Aabb3d in 3D.
- Example 2D
- Example 3D
let shape = new RAPIER.Cuboid(1.0, 2.0);
let shapePos = { x: 1.0, y: 2.0 };
let shapeRot = 0.1;
world.intersectionsWithShape(shapePos, shapeRot, shape, (handle) => {
console.log("The collider", handle, "intersects our shape.");
return true; // Return `false` instead if we want to stop searching for other colliders that contain this point.
});
let aabbCenter = { x: -1.0, y: -2.0 };
let aabbHalfExtents = { x: 0.5, y: 0.6 };
world.collidersWithAabbIntersectingAabb(aabbCenter, aabbHalfExtents, (handle) => {
console.log("The collider", handle, "has an AABB intersecting our test AABB");
return true; // Return `false` instead if we want to stop searching for other colliders that contain this point.
});
let shape = new RAPIER.Cuboid(1.0, 2.0, 3.0);
let shapePos = { x: 1.0, y: 2.0, z: 3.0 };
let shapeRot = { w: 1.0, x: 0.0, y: 0.0, z: 0.0 };
world.intersectionsWithShape(shapePos, shapeRot, shape, (handle) => {
console.log("The collider", handle, "intersects our shape.");
return true; // Return `false` instead if we want to stop searching for other colliders that contain this point.
});
let aabbCenter = { x: -1.0, y: -2.0, z: -3.0 };
let aabbHalfExtents = { x: 0.5, y: 0.6, z: 0.5 };
world.collidersWithAabbIntersectingAabb(aabbCenter, aabbHalfExtents, (handle) => {
console.log("The collider", handle, "has an AABB intersecting our test AABB");
return true; // Return `false` instead if we want to stop searching for other colliders that contain this point.
});
- Example 2D
- Example 3D
R2SharedShape *shape = r2CuboidSharedShape(r2Vector(1.0, 2.0));
R2Pose shape_pos = r2Pose(r2Vector(0.0, 1.0), r2Rotation(0.2));
R2QueryOptions options = r2DefaultQueryOptions();
// Get the number of colliders intersecting the shape, then copy their handles.
size_t count = r2IntersectShape(world, &options, shape_pos, shape, NULL, 0);
R2ColliderHandle *handles = malloc(count * sizeof(*handles));
count = r2IntersectShape(world, &options, shape_pos, shape, handles, count);
for (size_t i = 0; i < count; i++) {
printf("The collider %u intersects our shape.\n", handles[i].index);
}
free(handles);
r2FreeSharedShape(shape);
R2Aabb aabb = {r2Vector(-1.0, -2.0), r2Vector(1.0, 2.0)};
count = r2IntersectAabbConservative(world, &options, aabb, NULL, 0);
handles = malloc(count * sizeof(*handles));
count = r2IntersectAabbConservative(world, &options, aabb, handles, count);
for (size_t i = 0; i < count; i++) {
printf("The collider %u has an AABB intersecting our test AABB.\n", handles[i].index);
}
free(handles);
R3SharedShape *shape = r3CuboidSharedShape(r3Vector(1.0, 2.0, 3.0));
// The rotation is given as a scaled axis, i.e., an axis multiplied by the angle.
R3Vector scaled_axis = r3Vector(0.2, 0.7, 0.1);
R3Pose shape_pos = r3Pose(r3Vector(0.0, 1.0, 0.0),
r3RotationFromAxisAngle(scaled_axis, r3VectorLength(scaled_axis)));
R3QueryOptions options = r3DefaultQueryOptions();
// Get the number of colliders intersecting the shape, then copy their handles.
size_t count = r3IntersectShape(world, &options, shape_pos, shape, NULL, 0);
R3ColliderHandle *handles = malloc(count * sizeof(*handles));
count = r3IntersectShape(world, &options, shape_pos, shape, handles, count);
for (size_t i = 0; i < count; i++) {
printf("The collider %u intersects our shape.\n", handles[i].index);
}
free(handles);
r3FreeSharedShape(shape);
R3Aabb aabb = {r3Vector(-1.0, -2.0, -3.0), r3Vector(1.0, 2.0, 3.0)};
count = r3IntersectAabbConservative(world, &options, aabb, NULL, 0);
handles = malloc(count * sizeof(*handles));
count = r3IntersectAabbConservative(world, &options, aabb, handles, count);
for (size_t i = 0; i < count; i++) {
printf("The collider %u has an AABB intersecting our test AABB.\n", handles[i].index);
}
free(handles);
Both functions copy the handles of the colliders found into a buffer given by the application, as described at the
beginning of this page. The AABB to test is an R3Aabb, given by its minimum (mins) and maximum (maxs) corners.
shape = rp.SharedShape.cuboid(1.0, 2.0, 3.0)
shape_pos = rp.Isometry3(translation=(0.0, 1.0, 0.0), rotation=rp.rotation_from_angle((0.2, 0.7, 0.1)))
query_filter = rp.QueryFilter()
query_pipeline = world.query_pipeline
def on_shape_intersection(handle):
print(f"The collider {handle} intersects our shape.")
return True # Return `False` to stop the search.
query_pipeline.intersect_shape(shape_pos, shape, on_shape_intersection, filter=query_filter)
aabb = rp.Aabb(mins=(-1.0, -2.0, -3.0), maxs=(1.0, 2.0, 3.0))
def on_aabb_intersection(handle):
print(f"The collider {handle} has an AABB intersecting our test AABB.")
return True # Return `False` to stop the search.
query_pipeline.intersect_aabb_conservative(aabb, on_aabb_intersection, filter=query_filter)
Both methods call the given function with the handle of each collider found, until this function returns False. The
AABB to test is an Aabb, given by its minimum (mins) and maximum (maxs) corners. If you only need to know
whether at least one collider has an AABB intersecting the given AABB, QueryPipeline.test_aabb returns this as a
boolean.
It is possible to only apply the scene query to a subsets of the colliders using a query filter