|
@@ -246,13 +246,22 @@ bool JoltContactListener3D::_try_evaluate_area_overlap(const JPH::Body &p_body1,
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
- auto evaluate = [&](const auto &p_area, const auto &p_object, const JPH::SubShapeIDPair &p_shape_pair) {
|
|
|
|
|
|
+ auto has_shifted = [](const JoltShapedObject3D &p_object, const JPH::SubShapeID &p_sub_shape_id) {
|
|
|
|
+ return p_object.get_previous_jolt_shape() != nullptr && p_object.get_jolt_shape()->GetSubShapeUserData(p_sub_shape_id) != p_object.get_previous_jolt_shape()->GetSubShapeUserData(p_sub_shape_id);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ auto evaluate = [&](const JoltArea3D &p_area, const auto &p_object, const JPH::SubShapeIDPair &p_shape_pair) {
|
|
const MutexLock write_lock(write_mutex);
|
|
const MutexLock write_lock(write_mutex);
|
|
|
|
|
|
if (p_area.can_monitor(p_object)) {
|
|
if (p_area.can_monitor(p_object)) {
|
|
if (!area_overlaps.has(p_shape_pair)) {
|
|
if (!area_overlaps.has(p_shape_pair)) {
|
|
area_overlaps.insert(p_shape_pair);
|
|
area_overlaps.insert(p_shape_pair);
|
|
area_enters.insert(p_shape_pair);
|
|
area_enters.insert(p_shape_pair);
|
|
|
|
+ } else if (has_shifted(p_area, p_shape_pair.GetSubShapeID1()) || has_shifted(p_object, p_shape_pair.GetSubShapeID2())) {
|
|
|
|
+ // A shape has taken on the `JPH::SubShapeID` value of another shape, likely because of the other shape having been replaced or moved
|
|
|
|
+ // in some way, so we force the area to refresh its internal mappings by exiting and entering this shape pair.
|
|
|
|
+ area_exits.insert(p_shape_pair);
|
|
|
|
+ area_enters.insert(p_shape_pair);
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
if (area_overlaps.erase(p_shape_pair)) {
|
|
if (area_overlaps.erase(p_shape_pair)) {
|
|
@@ -456,32 +465,6 @@ void JoltContactListener3D::_flush_area_enters() {
|
|
area_enters.clear();
|
|
area_enters.clear();
|
|
}
|
|
}
|
|
|
|
|
|
-void JoltContactListener3D::_flush_area_shifts() {
|
|
|
|
- for (const JPH::SubShapeIDPair &shape_pair : area_overlaps) {
|
|
|
|
- auto is_shifted = [&](const JPH::BodyID &p_body_id, const JPH::SubShapeID &p_sub_shape_id) {
|
|
|
|
- const JoltShapedObject3D *object = space->try_get_shaped(p_body_id);
|
|
|
|
- ERR_FAIL_NULL_V(object, false);
|
|
|
|
-
|
|
|
|
- if (object->get_previous_jolt_shape() == nullptr) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- const JPH::Shape ¤t_shape = *object->get_jolt_shape();
|
|
|
|
- const JPH::Shape &previous_shape = *object->get_previous_jolt_shape();
|
|
|
|
-
|
|
|
|
- const uint32_t current_id = (uint32_t)current_shape.GetSubShapeUserData(p_sub_shape_id);
|
|
|
|
- const uint32_t previous_id = (uint32_t)previous_shape.GetSubShapeUserData(p_sub_shape_id);
|
|
|
|
-
|
|
|
|
- return current_id != previous_id;
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- if (is_shifted(shape_pair.GetBody1ID(), shape_pair.GetSubShapeID1()) || is_shifted(shape_pair.GetBody2ID(), shape_pair.GetSubShapeID2())) {
|
|
|
|
- area_enters.insert(shape_pair);
|
|
|
|
- area_exits.insert(shape_pair);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
void JoltContactListener3D::_flush_area_exits() {
|
|
void JoltContactListener3D::_flush_area_exits() {
|
|
for (const JPH::SubShapeIDPair &shape_pair : area_exits) {
|
|
for (const JPH::SubShapeIDPair &shape_pair : area_exits) {
|
|
const JPH::BodyID &body_id1 = shape_pair.GetBody1ID();
|
|
const JPH::BodyID &body_id1 = shape_pair.GetBody1ID();
|
|
@@ -523,7 +506,6 @@ void JoltContactListener3D::pre_step() {
|
|
|
|
|
|
void JoltContactListener3D::post_step() {
|
|
void JoltContactListener3D::post_step() {
|
|
_flush_contacts();
|
|
_flush_contacts();
|
|
- _flush_area_shifts();
|
|
|
|
_flush_area_exits();
|
|
_flush_area_exits();
|
|
_flush_area_enters();
|
|
_flush_area_enters();
|
|
}
|
|
}
|