scene_queries_shape_casting
Shape-casting (aka. sweep tests) is the big brother of ray-casting. The only difference with ray-cast is that instead of being a point travelling along a straight line, we have a complete shape travelling along a straight line. This is typically used for character controllers in games to determine by how much the player can move before it hits the environment.
Just like ray-casting, it is possible to control the behavior of the shape-casting like limiting the distance
travelled by the shape cast, and ignoring some colliders. See the details about the max_toi
and
filter
arguments in the ray-casting section.
There is only one shape-casting method: QueryPipeline::cast_shape
RapierContext::cast_shape
World.castShape
QueryPipeline::cast_ray
RapierContext::cast_ray
World.castRay
ray.origin
) and
the linear velocity the shape is travelling at (this is analog to ray.dir
):
- Example 2D
- Example 3D
let shape = Cuboid::new(vector![1.0, 2.0]);
let shape_pos = Isometry::new(vector![0.0, 1.0], 0.8);
let shape_vel = vector![0.1, 0.4];
let filter = QueryFilter::default();
let options = ShapeCastOptions {
max_time_of_impact: 4.0,
target_distance: 0.0,
stop_at_penetration: false,
compute_impact_geometry_on_penetration: false,
};
if let Some((handle, hit)) = query_pipeline.cast_shape(rigid_body_set,
collider_set, &shape_pos, &shape_vel, &shape, options, filter
) {
// The first collider hit has the handle `handle`. The `hit` is a
// structure containing details about the hit configuration.
println!("Hit the collider {:?} with the configuration: {:?}", handle, hit);
}
let shape = Cuboid::new(vector![1.0, 2.0, 3.0]);
let shape_pos = Isometry::new(vector![0.0, 1.0, 0.0], vector![0.2, 0.7, 0.1]);
let shape_vel = vector![0.1, 0.4, 0.2];
let max_toi = 4.0;
let filter = QueryFilter::default();
let options = ShapeCastOptions {
max_time_of_impact: 4.0,
target_distance: 0.0,
stop_at_penetration: false,
compute_impact_geometry_on_penetration: false,
};
if let Some((handle, hit)) = query_pipeline.cast_shape(
rigid_body_set, &collider_set, &shape_pos, &shape_vel, &shape, options, filter
) {
// The first collider hit has the handle `handle`. The `hit` is a
// structure containing details about the hit configuration.
println!("Hit the collider {:?} with the configuration: {:?}", handle, hit);
}
- Example 2D
- Example 3D
/* Cast a shape inside of a system. */
fn cast_shape(rapier_context: Res<RapierContext>) {
let shape = Collider::cuboid(1.0, 2.0);
let shape_pos = Vec2::new(1.0, 2.0);
let shape_rot = 0.8;
let shape_vel = Vec2::new(0.1, 0.4);
let filter = QueryFilter::default();
let options = ShapeCastOptions {
max_time_of_impact: 4.0,
target_distance: 0.0,
stop_at_penetration: false,
compute_impact_geometry_on_penetration: false,
};
if let Some((entity, hit)) =
rapier_context.cast_shape(shape_pos, shape_rot, shape_vel, &shape, options, filter)
{
// The first collider hit has the entity `entity`. The `hit` is a
// structure containing details about the hit configuration.
println!(
"Hit the entity {:?} with the configuration: {:?}",
entity, hit
);
}
}
/* Cast a shape inside of a system. */
fn cast_shape(rapier_context: Res<RapierContext>) {
let shape = Collider::cuboid(1.0, 2.0, 3.0);
let shape_pos = Vec3::new(1.0, 2.0, 3.0);
let shape_rot = Quat::from_rotation_z(0.8);
let shape_vel = Vec3::new(0.1, 0.4, 0.2);
let filter = QueryFilter::default();
let options = ShapeCastOptions {
max_time_of_impact: 4.0,
target_distance: 0.0,
stop_at_penetration: false,
compute_impact_geometry_on_penetration: false,
};
if let Some((entity, hit)) =
rapier_context.cast_shape(shape_pos, shape_rot, shape_vel, &shape, options, filter)
{
// The first collider hit has the entity `entity`. The `hit` is a
// structure containing details about the hit configuration.
println!(
"Hit the entity {:?} with the configuration: {:?}",
entity, hit
);
}
}
- Example 2D
- Example 3D
let shapePos = { x: 0.0, y: 1.0 };
let shapeRot = 0.2;
let shapeVel = { x: 0.1, y: 0.4 };
let shape = new RAPIER.Cuboid(1.0, 2.0);
let targetDistance = 0.0;
let maxToi = 4.0;
// Optional parameters:
let stopAtPenetration = true;
let filterFlags = QueryFilterFlags.EXCLUDE_DYNAMIC;
let filterGroups = 0x000b0001;
let filterExcludeCollider = collider;
let filterExcludeRigidBody = rigidBody;
let hit = world.castShape(shapePos, shapeRot, shapeVel, shape, targetDistance, maxToi,
stopAtPenetration, filterFlags, filterGroups, filterExcludeCollider, filterExcludeRigidBody);
if (hit != null) {
// The first collider hit has the handle `handle`. The `hit` is a
// structure containing details about the hit configuration.
console.log("Hit the collider", hit.collider, "at time", hit.time_of_impact);
}
let shapePos = { x: 0.0, y: 1.0, z: 0.0 };
let shapeRot = { w: 1.0, x: 0.0, y: 0.0, z: 0.0 };
let shapeVel = { x: 0.1, y: 0.4, z: 1.0 };
let shape = new RAPIER.Cuboid(1.0, 2.0, 3.0);
let targetDistance = 0.0;
let maxToi = 4.0;
// Optional parameters:
let stopAtPenetration = true;
let filterFlags = QueryFilterFlags.EXCLUDE_DYNAMIC;
let filterGroups = 0x000b0001;
let filterExcludeCollider = collider;
let filterExcludeRigidBody = rigidBody;
let hit = world.castShape(shapePos, shapeRot, shapeVel, shape, targetDistance, maxToi,
stopAtPenetration, filterFlags, filterGroups, filterExcludeCollider, filterExcludeRigidBody);
if (hit != null) {
// The first collider hit has the handle `handle`. The `hit` is a
// structure containing details about the hit configuration.
console.log("Hit the collider", hit.collider, "at time", hit.time_of_impact);
}
The result of the shape-casting includes the handle of the first collider being hit, as well as detailed information about the geometry of the hit:
hit.toi
: indicates the time of impact between the shape and the collider hit. This means that after travelling a distance ofshape_vel * hit.toi
the collider and the cast shape are exactly touching. IfshapeVel * hit.toi
hit.toi == 0.0
then the shape is already intersecting a collider at its initial position.hit.witness1
: indicates the contact point when the cast shape and the collider are touching, expressed in the local-space of the collider hit by the shape.hit.witness2
: indicates the contact point when the cast shape and the collider are touching, expressed in the local-space of the cast shape.hit.normal1
: indicates the normal at the contact pointhit.witness1
, expressed in the local-space of the collider hit by the shape.hit.normal2
: indicates the normal at the contact pointhit.witness2
, expressed in the local-space of the cast shape.