Skip to content

Commit

Permalink
feat: shape-cast naming changes (#199)
Browse files Browse the repository at this point in the history
* feat!: various renamin of shape-casting related struct/methods

* chore: update changelog

* feat: re-export ShapeCastOptions from the query module

* feat: add a way to retrieve/modify the heightfield flags

* fix compilation of tests

* chore: a few internal renamings
  • Loading branch information
sebcrozet committed May 5, 2024
1 parent dfa638c commit 266bccb
Show file tree
Hide file tree
Showing 53 changed files with 978 additions and 832 deletions.
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
# Change Log

## unreleased

### Added

- Add `ShapeCastOptions` that includes two new options for (linear) shape-casting.
`ShapeCastOptions::target_distance` which will return a hit as soon as the moving
shapes are closer than this distance; and `compute_impact_geometry_on_penetration`
which forces the calculation of proper witness points and normals even if the shapes
are initially intersecting (`time_of_impact == 0.0`).

### Modified

This version modifies many names related to shape-casting:

- Renamed `TOI` to `ShapeCastHit`.
- Renamed `TOIStatus` to `ShapeCastStatus`.
- Rename `RayIntersection::toi` to `RayIntersection::time_of_impact`.
- More generally, all occurrences of the word `toi` have been replaced by `time_of_impact`
for better clarity.
- Rename `query::time_of_impact` to `query::cast_shapes`. More generally, all the
functions prefixed with `time_of_impact_` (e.g. `time_of_impact_ball_ball`) are
now prefixed with `cast_shapes_` (e.g. `cast_shapes_ball_ball`).
- Rename `QueryDispatcher::time_of_impact` to `QueryDispatcher::cast_shapes`.
- The (linear) shape-casting functions like `query::cast_shapes` (previously named
`query::time_of_impact) now take a `ShapeCastOptions` instead of the `max_toi` and
`stop_at_penetration` arguments.
- Rename `query::nonlinear_time_of_impact` to `query::cast_shapes_nonlinear`.
- Rename `QueryDispatcher::nonlinear_time_of_impact` to `QueryDispatcher::cast_sahpes_nonlinear`.
- Rename `NonlinearTOIMode` to `NonlinearShapeCastMode`, and `NonlinearTOIMode::DirectionalTOI` to
`NonlinearShapeCastMode::Directional`.
- Rename `TimeOfImpactStatus::Penetrating` to `ShapeCastStatus::PenetratingOrWithinTargetDist`.

## v0.14.0

### Modified
Expand Down
23 changes: 10 additions & 13 deletions crates/parry2d/examples/time_of_impact_query2d.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
extern crate nalgebra as na;

use na::{Isometry2, Vector2};
use parry2d::math::Real;
use parry2d::query;
use parry2d::query::ShapeCastOptions;
use parry2d::shape::{Ball, Cuboid};

fn main() {
Expand All @@ -20,42 +20,39 @@ fn main() {
let ball_vel1 = Vector2::new(2.0, 2.0);
let ball_vel2 = Vector2::new(-0.5, -0.5);

let toi_intersecting = query::time_of_impact(
let toi_intersecting = query::cast_shapes(
&ball_pos_intersecting,
&ball_vel1,
&ball,
&cuboid_pos,
&box_vel1,
&cuboid,
Real::MAX,
true,
ShapeCastOptions::default(),
)
.unwrap();
let toi_will_touch = query::time_of_impact(
let toi_will_touch = query::cast_shapes(
&ball_pos_will_touch,
&ball_vel2,
&ball,
&cuboid_pos,
&box_vel2,
&cuboid,
Real::MAX,
true,
ShapeCastOptions::default(),
)
.unwrap();
let toi_wont_touch = query::time_of_impact(
let toi_wont_touch = query::cast_shapes(
&ball_pos_wont_touch,
&ball_vel1,
&ball,
&cuboid_pos,
&box_vel1,
&cuboid,
Real::MAX,
true,
ShapeCastOptions::default(),
)
.unwrap();

assert_eq!(toi_intersecting.map(|toi| toi.toi), Some(0.0));
assert_eq!(toi_intersecting.map(|hit| hit.time_of_impact), Some(0.0));
println!("Toi: {:?}", toi_will_touch);
assert!(toi_will_touch.is_some() && toi_will_touch.unwrap().toi > 0.0);
assert_eq!(toi_wont_touch.map(|toi| toi.toi), None);
assert!(toi_will_touch.is_some() && toi_will_touch.unwrap().time_of_impact > 0.0);
assert_eq!(toi_wont_touch.map(|hit| hit.time_of_impact), None);
}
6 changes: 3 additions & 3 deletions crates/parry2d/tests/geometry/ball_ball_toi.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Issue #35

use na::{self, Isometry2, Vector2};
use parry2d::math::Real;
use parry2d::query;
use parry2d::query::details::ShapeCastOptions;
use parry2d::shape::Ball;

#[test]
Expand All @@ -13,7 +13,7 @@ fn test_ball_ball_toi() {
let v1 = Vector2::new(0.0, 10.0);
let v2 = Vector2::zeros();

let cast = query::time_of_impact(&m1, &v1, &b, &m2, &v2, &b, Real::MAX, true).unwrap();
let cast = query::cast_shapes(&m1, &v1, &b, &m2, &v2, &b, ShapeCastOptions::default()).unwrap();

assert_eq!(cast.unwrap().toi, 0.9);
assert_eq!(cast.unwrap().time_of_impact, 0.9);
}
6 changes: 3 additions & 3 deletions crates/parry2d/tests/geometry/ray_cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ fn raycast_starting_outside_of_triangle() {
.cast_local_ray_and_get_normal(&ray, std::f32::MAX, true)
.expect("No intersection");

assert_ne!(intersect.toi, 0.0);
assert_ne!(intersect.time_of_impact, 0.0);
}

#[test]
Expand All @@ -117,7 +117,7 @@ fn raycast_starting_inside_of_triangle() {
.cast_local_ray_and_get_normal(&ray, std::f32::MAX, true)
.expect("No intersection");

assert_eq!(intersect.toi, 0.0);
assert_eq!(intersect.time_of_impact, 0.0);
}

#[test]
Expand All @@ -132,7 +132,7 @@ fn raycast_starting_on_edge_of_triangle() {
.cast_local_ray_and_get_normal(&ray, std::f32::MAX, true)
.expect("No intersection");

assert_eq!(intersect.toi, 0.0);
assert_eq!(intersect.time_of_impact, 0.0);
}

/// Ray Target
Expand Down
56 changes: 25 additions & 31 deletions crates/parry2d/tests/geometry/time_of_impact2.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use na::{self, Isometry2, Point2, Vector2};
use parry2d::math::Real;
use parry2d::query;
use parry2d::query::details::ShapeCastOptions;
use parry2d::shape::{Ball, Cuboid, Polyline, Segment};

#[test]
Expand All @@ -19,46 +20,43 @@ fn ball_cuboid_toi() {
let ball_vel1 = Vector2::new(2.0, 2.0);
let ball_vel2 = Vector2::new(-0.5, -0.5);

let toi_intersecting = query::time_of_impact(
let toi_intersecting = query::cast_shapes(
&ball_pos_intersecting,
&ball_vel1,
&ball,
&cuboid_pos,
&cuboid_vel1,
&cuboid,
Real::MAX,
true,
ShapeCastOptions::default(),
)
.unwrap();
let toi_will_touch = query::time_of_impact(
let toi_will_touch = query::cast_shapes(
&ball_pos_will_touch,
&ball_vel2,
&ball,
&cuboid_pos,
&cuboid_vel2,
&cuboid,
Real::MAX,
true,
ShapeCastOptions::default(),
)
.unwrap();
let toi_wont_touch = query::time_of_impact(
let toi_wont_touch = query::cast_shapes(
&ball_pos_wont_touch,
&ball_vel2,
&ball,
&cuboid_pos,
&cuboid_vel1,
&cuboid,
Real::MAX,
true,
ShapeCastOptions::default(),
)
.unwrap();

assert_eq!(toi_intersecting.map(|toi| toi.toi), Some(0.0));
assert_eq!(toi_intersecting.map(|hit| hit.time_of_impact), Some(0.0));
assert!(relative_eq!(
toi_will_touch.unwrap().toi,
toi_will_touch.unwrap().time_of_impact,
((2.0 as Real).sqrt() - 1.0) / (ball_vel2 - cuboid_vel2).norm()
));
assert_eq!(toi_wont_touch.map(|toi| toi.toi), None);
assert_eq!(toi_wont_touch.map(|hit| hit.time_of_impact), None);
}

#[test]
Expand All @@ -72,22 +70,21 @@ fn cuboid_cuboid_toi_issue_214() {
let vel1 = Vector2::new(1.0, 0.0);
let vel2 = Vector2::new(0.0, 0.0);

let toi = query::time_of_impact(
let hit = query::cast_shapes(
&pos1,
&vel1,
&shape1,
&pos2,
&vel2,
&shape2,
Real::MAX,
true,
ShapeCastOptions::default(),
)
.unwrap();
assert!(toi.is_some());
assert!(hit.is_some());
}

#[test]
fn time_of_impact_should_return_toi_for_ball_and_rotated_polyline() {
fn cast_shapes_should_return_toi_for_ball_and_rotated_polyline() {
let ball_isometry = Isometry2::identity();
let ball_velocity = Vector2::new(1.0, 0.0);
let ball = Ball::new(0.5);
Expand All @@ -104,23 +101,22 @@ fn time_of_impact_should_return_toi_for_ball_and_rotated_polyline() {
Point2::new(1.0, 0.99999994)
);

let toi = query::time_of_impact(
let hit = query::cast_shapes(
&ball_isometry,
&ball_velocity,
&ball,
&polyline_isometry,
&polyline_velocity,
&polyline,
1.0,
true,
ShapeCastOptions::with_max_time_of_impact(1.0),
)
.unwrap();

assert_eq!(toi.unwrap().toi, 0.5);
assert_eq!(hit.unwrap().time_of_impact, 0.5);
}

#[test]
fn time_of_impact_should_return_toi_for_ball_and_rotated_segment() {
fn cast_shapes_should_return_toi_for_ball_and_rotated_segment() {
let ball_isometry = Isometry2::identity();
let ball_velocity = Vector2::new(1.0, 0.0);
let ball = Ball::new(0.5);
Expand All @@ -137,23 +133,22 @@ fn time_of_impact_should_return_toi_for_ball_and_rotated_segment() {
Point2::new(1.0, 0.99999994)
);

let toi = query::time_of_impact(
let hit = query::cast_shapes(
&ball_isometry,
&ball_velocity,
&ball,
&segment_isometry,
&segment_velocity,
&segment,
1.0,
true,
ShapeCastOptions::with_max_time_of_impact(1.0),
)
.unwrap();

assert_eq!(toi.unwrap().toi, 0.49999994);
assert_eq!(hit.unwrap().time_of_impact, 0.49999994);
}

#[test]
fn time_of_impact_should_return_toi_for_rotated_segment_and_ball() {
fn cast_shapes_should_return_toi_for_rotated_segment_and_ball() {
let ball_isometry = Isometry2::identity();
let ball_velocity = Vector2::new(1.0, 0.0);
let ball = Ball::new(0.5);
Expand All @@ -170,17 +165,16 @@ fn time_of_impact_should_return_toi_for_rotated_segment_and_ball() {
Point2::new(1.0, 0.99999994)
);

let toi = query::time_of_impact(
let hit = query::cast_shapes(
&segment_isometry,
&segment_velocity,
&segment,
&ball_isometry,
&ball_velocity,
&ball,
1.0,
true,
ShapeCastOptions::with_max_time_of_impact(1.0),
)
.unwrap();

assert_eq!(toi.unwrap().toi, 0.5);
assert_eq!(hit.unwrap().time_of_impact, 0.5);
}

0 comments on commit 266bccb

Please sign in to comment.