aboutsummaryrefslogtreecommitdiff
path: root/src/dynamics/ccd/ccd_solver.rs
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2021-06-02 17:15:46 +0200
committerGitHub <noreply@github.com>2021-06-02 17:15:46 +0200
commit6ba1c9dec184adcba2c68cc1851dc05587fd0bf0 (patch)
treeb672cfc4db1d2f426dad931d77098ecb4a600358 /src/dynamics/ccd/ccd_solver.rs
parent3bac79ecacdeaa18de19127b7a6c82cbfab29d14 (diff)
parentbde6657287cd32a801abb996322c520673406418 (diff)
downloadrapier-6ba1c9dec184adcba2c68cc1851dc05587fd0bf0.tar.gz
rapier-6ba1c9dec184adcba2c68cc1851dc05587fd0bf0.tar.bz2
rapier-6ba1c9dec184adcba2c68cc1851dc05587fd0bf0.zip
Merge pull request #196 from dimforge/api_changes
More API changes
Diffstat (limited to 'src/dynamics/ccd/ccd_solver.rs')
-rw-r--r--src/dynamics/ccd/ccd_solver.rs97
1 files changed, 65 insertions, 32 deletions
diff --git a/src/dynamics/ccd/ccd_solver.rs b/src/dynamics/ccd/ccd_solver.rs
index b348283..7e95f08 100644
--- a/src/dynamics/ccd/ccd_solver.rs
+++ b/src/dynamics/ccd/ccd_solver.rs
@@ -10,6 +10,7 @@ use crate::geometry::{
use crate::math::Real;
use crate::parry::utils::SortedPair;
use crate::pipeline::{EventHandler, QueryPipeline, QueryPipelineMode};
+use crate::prelude::{ActiveEvents, ColliderFlags};
use parry::query::{DefaultQueryDispatcher, QueryDispatcher};
use parry::utils::hashmap::HashMap;
use std::collections::BinaryHeap;
@@ -66,7 +67,7 @@ impl CCDSolver {
&RigidBodyCcd,
&RigidBodyMassProps,
) = bodies.index_bundle(handle.0);
- let local_com = &mprops.mass_properties.local_com;
+ let local_com = &mprops.local_mprops.local_com;
let min_toi = (ccd.ccd_thickness
* 0.15
@@ -139,7 +140,8 @@ impl CCDSolver {
Colliders: ComponentSetOption<ColliderParent>
+ ComponentSet<ColliderPosition>
+ ComponentSet<ColliderShape>
- + ComponentSet<ColliderType>,
+ + ComponentSet<ColliderType>
+ + ComponentSet<ColliderFlags>,
{
// Update the query pipeline.
self.query_pipeline.update_with_mode(
@@ -200,16 +202,21 @@ impl CCDSolver {
{
let co_parent1: Option<&ColliderParent> = colliders.get(ch1.0);
let co_parent2: Option<&ColliderParent> = colliders.get(ch2.0);
- let c1: (_, _, _) = colliders.index_bundle(ch1.0);
- let c2: (_, _, _) = colliders.index_bundle(ch2.0);
+ let c1: (_, _, _, &ColliderFlags) = colliders.index_bundle(ch1.0);
+ let c2: (_, _, _, &ColliderFlags) = colliders.index_bundle(ch2.0);
let co_type1: &ColliderType = colliders.index(ch1.0);
let co_type2: &ColliderType = colliders.index(ch1.0);
let bh1 = co_parent1.map(|p| p.handle);
let bh2 = co_parent2.map(|p| p.handle);
- if bh1 == bh2 || (co_type1.is_sensor() || co_type2.is_sensor()) {
- // Ignore self-intersection and sensors.
+ // Ignore self-intersection and sensors and apply collision groups filter.
+ if bh1 == bh2 // Ignore self-intersection.
+ || (co_type1.is_sensor() || co_type2.is_sensor()) // Ignore sensors.
+ || !c1.3.collision_groups.test(c2.3.collision_groups) // Apply collision groups.
+ || !c1.3.solver_groups.test(c2.3.solver_groups)
+ // Apply solver groups.
+ {
return true;
}
@@ -225,8 +232,8 @@ impl CCDSolver {
self.query_pipeline.query_dispatcher(),
*ch1,
*ch2,
- (c1.0, c1.1, c1.2, co_parent1),
- (c2.0, c2.1, c2.2, co_parent2),
+ (c1.0, c1.1, c1.2, c1.3, co_parent1),
+ (c2.0, c2.1, c2.2, c2.3, co_parent2),
Some((rb_pos1, rb_vels1, rb_mprops1, rb_ccd1)),
b2,
None,
@@ -272,7 +279,9 @@ impl CCDSolver {
Colliders: ComponentSetOption<ColliderParent>
+ ComponentSet<ColliderPosition>
+ ComponentSet<ColliderShape>
- + ComponentSet<ColliderType>,
+ + ComponentSet<ColliderType>
+ + ComponentSet<ColliderFlags>
+ + ComponentSet<ColliderFlags>,
{
let mut frozen = HashMap::<_, Real>::default();
let mut all_toi = BinaryHeap::new();
@@ -334,14 +343,15 @@ impl CCDSolver {
{
let co_parent1: Option<&ColliderParent> = colliders.get(ch1.0);
let co_parent2: Option<&ColliderParent> = colliders.get(ch2.0);
- let c1: (_, _, _) = colliders.index_bundle(ch1.0);
- let c2: (_, _, _) = colliders.index_bundle(ch2.0);
+ let c1: (_, _, _, &ColliderFlags) = colliders.index_bundle(ch1.0);
+ let c2: (_, _, _, &ColliderFlags) = colliders.index_bundle(ch2.0);
let bh1 = co_parent1.map(|p| p.handle);
let bh2 = co_parent2.map(|p| p.handle);
- if bh1 == bh2 {
- // Ignore self-intersection.
+ // Ignore self-intersections and apply groups filter.
+ if bh1 == bh2 || !c1.3.collision_groups.test(c2.3.collision_groups)
+ {
return true;
}
@@ -358,8 +368,8 @@ impl CCDSolver {
self.query_pipeline.query_dispatcher(),
*ch1,
*ch2,
- (c1.0, c1.1, c1.2, co_parent1),
- (c2.0, c2.1, c2.2, co_parent2),
+ (c1.0, c1.1, c1.2, c1.3, co_parent1),
+ (c2.0, c2.1, c2.2, c2.3, co_parent2),
b1,
b2,
None,
@@ -398,7 +408,7 @@ impl CCDSolver {
// NOTE: all static bodies (and kinematic bodies?) should be considered as "frozen", this
// may avoid some resweeps.
- let mut intersections_to_check = vec![];
+ let mut pseudo_intersections_to_check = vec![];
while let Some(toi) = all_toi.pop() {
assert!(toi.toi <= dt);
@@ -420,7 +430,7 @@ impl CCDSolver {
continue;
}
- if toi.is_intersection_test {
+ if toi.is_pseudo_intersection_test {
// NOTE: this test is redundant with the previous `if !should_freeze && ...`
// but let's keep it to avoid tricky regressions if we end up swapping both
// `if` for some reasons in the future.
@@ -428,7 +438,7 @@ impl CCDSolver {
// This is only an intersection so we don't have to freeze and there is no
// need to resweep. However we will need to see if we have to generate
// intersection events, so push the TOI for further testing.
- intersections_to_check.push(toi);
+ pseudo_intersections_to_check.push(toi);
}
continue;
}
@@ -460,14 +470,14 @@ impl CCDSolver {
.colliders_with_aabb_intersecting_aabb(&aabb, |ch2| {
let co_parent1: Option<&ColliderParent> = colliders.get(ch1.0);
let co_parent2: Option<&ColliderParent> = colliders.get(ch2.0);
- let c1: (_, _, _) = colliders.index_bundle(ch1.0);
- let c2: (_, _, _) = colliders.index_bundle(ch2.0);
+ let c1: (_, _, _, &ColliderFlags) = colliders.index_bundle(ch1.0);
+ let c2: (_, _, _, &ColliderFlags) = colliders.index_bundle(ch2.0);
let bh1 = co_parent1.map(|p| p.handle);
let bh2 = co_parent2.map(|p| p.handle);
- if bh1 == bh2 {
- // Ignore self-intersection.
+ // Ignore self-intersection and apply groups filter.
+ if bh1 == bh2 || !c1.3.collision_groups.test(c2.3.collision_groups) {
return true;
}
@@ -496,8 +506,8 @@ impl CCDSolver {
self.query_pipeline.query_dispatcher(),
*ch1,
*ch2,
- (c1.0, c1.1, c1.2, co_parent1),
- (c2.0, c2.1, c2.2, co_parent2),
+ (c1.0, c1.1, c1.2, c1.3, co_parent1),
+ (c2.0, c2.1, c2.2, c2.3, co_parent2),
b1,
b2,
frozen1.copied(),
@@ -514,7 +524,7 @@ impl CCDSolver {
}
}
- for toi in intersections_to_check {
+ for toi in pseudo_intersections_to_check {
// See if the intersection is still active once the bodies
// reach their final positions.
// - If the intersection is still active, don't report it yet. It will be
@@ -522,10 +532,29 @@ impl CCDSolver {
// - If the intersection isn't active anymore, and it wasn't intersecting
// before, then we need to generate one interaction-start and one interaction-stop
// events because it will never be detected by the narrow-phase because of tunneling.
- let (co_pos1, co_shape1): (&ColliderPosition, &ColliderShape) =
- colliders.index_bundle(toi.c1.0);
- let (co_pos2, co_shape2): (&ColliderPosition, &ColliderShape) =
- colliders.index_bundle(toi.c2.0);
+ let (co_type1, co_pos1, co_shape1, co_flags1): (
+ &ColliderType,
+ &ColliderPosition,
+ &ColliderShape,
+ &ColliderFlags,
+ ) = colliders.index_bundle(toi.c1.0);
+ let (co_type2, co_pos2, co_shape2, co_flags2): (
+ &ColliderType,
+ &ColliderPosition,
+ &ColliderShape,
+ &ColliderFlags,
+ ) = colliders.index_bundle(toi.c2.0);
+
+ if !co_type1.is_sensor() && !co_type2.is_sensor() {
+ // TODO: this happens if we found a TOI between two non-sensor
+ // colliders with mismatching solver_flags. It is not clear
+ // what we should do in this case: we could report a
+ // contact started/contact stopped event for example. But in
+ // that case, what contact pair should be pass to these events?
+ // For now we just ignore this special case. Let's wait for an actual
+ // use-case to come up before we determine what we want to do here.
+ continue;
+ }
let co_next_pos1 = if let Some(b1) = toi.b1 {
let co_parent1: &ColliderParent = colliders.get(toi.c1.0).unwrap();
@@ -535,7 +564,7 @@ impl CCDSolver {
&RigidBodyMassProps,
) = bodies.index_bundle(b1.0);
- let local_com1 = &rb_mprops1.mass_properties.local_com;
+ let local_com1 = &rb_mprops1.local_mprops.local_com;
let frozen1 = frozen.get(&b1);
let pos1 = frozen1
.map(|t| rb_vels1.integrate(*t, &rb_pos1.position, local_com1))
@@ -553,7 +582,7 @@ impl CCDSolver {
&RigidBodyMassProps,
) = bodies.index_bundle(b2.0);
- let local_com2 = &rb_mprops2.mass_properties.local_com;
+ let local_com2 = &rb_mprops2.local_mprops.local_com;
let frozen2 = frozen.get(&b2);
let pos2 = frozen2
.map(|t| rb_vels2.integrate(*t, &rb_pos2.position, local_com2))
@@ -575,7 +604,11 @@ impl CCDSolver {
.intersection_test(&next_coll_pos12, co_shape1.as_ref(), co_shape2.as_ref())
.unwrap_or(false);
- if !intersect_before && !intersect_after {
+ if !intersect_before
+ && !intersect_after
+ && (co_flags1.active_events | co_flags2.active_events)
+ .contains(ActiveEvents::INTERSECTION_EVENTS)
+ {
// Emit one intersection-started and one intersection-stopped event.
events.handle_intersection_event(IntersectionEvent::new(toi.c1, toi.c2, true));
events.handle_intersection_event(IntersectionEvent::new(toi.c1, toi.c2, false));