Handle test body motion with 0 margin

Margin needs to have a high enough value for test body motion to work
properly (separate using the margin, move without then gather rest info
with the margin again).

Fixes issues with test motion returning no collision in some cases with
margin equal to 0.

(cherry picked from commit 0c354047e1)
This commit is contained in:
PouleyKetchoupp 2021-12-09 10:52:27 -07:00 committed by Rémi Verschelde
parent 2025648d6d
commit e11662ad77
No known key found for this signature in database
GPG key ID: C3336907360768E1
2 changed files with 28 additions and 16 deletions

View file

@ -34,6 +34,7 @@
#include "core/project_settings.h"
#include "physics_server_sw.h"
#define TEST_MOTION_MARGIN_MIN_VALUE 0.0001
#define TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR 0.05
_FORCE_INLINE_ static bool _can_collide_with(CollisionObjectSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
@ -434,10 +435,12 @@ bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_
ShapeSW *shape = static_cast<PhysicsServerSW *>(PhysicsServer::get_singleton())->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape, 0);
real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
real_t margin = MAX(p_margin, TEST_MOTION_MARGIN_MIN_VALUE);
real_t min_contact_depth = margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
AABB aabb = p_shape_xform.xform(shape->get_aabb());
aabb = aabb.grow(p_margin);
aabb = aabb.grow(margin);
int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
@ -461,7 +464,7 @@ bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_
rcd.object = col_obj;
rcd.shape = shape_idx;
bool sc = CollisionSolverSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin);
bool sc = CollisionSolverSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, margin);
if (!sc) {
continue;
}
@ -730,6 +733,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
r_result->collider_id = 0;
r_result->collider_shape = 0;
}
AABB body_aabb;
bool shapes_found = false;
@ -755,11 +759,13 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
return false;
}
real_t margin = MAX(p_margin, TEST_MOTION_MARGIN_MIN_VALUE);
// Undo the currently transform the physics server is aware of and apply the provided one
body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb));
body_aabb = body_aabb.grow(p_margin);
body_aabb = body_aabb.grow(margin);
real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
real_t min_contact_depth = margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
float motion_length = p_motion.length();
Vector3 motion_normal = p_motion / motion_length;
@ -813,7 +819,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
}
}
if (CollisionSolverSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) {
if (CollisionSolverSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, margin)) {
collided = cbk.amount > 0;
}
}
@ -1036,7 +1042,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
rcd.object = col_obj;
rcd.shape = shape_idx;
rcd.local_shape = j;
bool sc = CollisionSolverSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin);
bool sc = CollisionSolverSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, margin);
if (!sc) {
continue;
}

View file

@ -35,6 +35,7 @@
#include "core/pair.h"
#include "physics_2d_server_sw.h"
#define TEST_MOTION_MARGIN_MIN_VALUE 0.0001
#define TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR 0.05
_FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
@ -438,11 +439,13 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_sh
Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape, 0);
real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
real_t margin = MAX(p_margin, TEST_MOTION_MARGIN_MIN_VALUE);
real_t min_contact_depth = margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
Rect2 aabb = p_shape_xform.xform(shape->get_aabb());
aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion
aabb = aabb.grow(p_margin);
aabb = aabb.grow(margin);
int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results);
@ -468,7 +471,7 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_sh
rcd.object = col_obj;
rcd.shape = shape_idx;
rcd.local_shape = 0;
bool sc = CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, nullptr, p_margin);
bool sc = CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, nullptr, margin);
if (!sc) {
continue;
}
@ -729,6 +732,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
r_result->collider_id = 0;
r_result->collider_shape = 0;
}
Rect2 body_aabb;
bool shapes_found = false;
@ -758,15 +762,17 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
return false;
}
real_t margin = MAX(p_margin, TEST_MOTION_MARGIN_MIN_VALUE);
// Undo the currently transform the physics server is aware of and apply the provided one
body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb));
body_aabb = body_aabb.grow(p_margin);
body_aabb = body_aabb.grow(margin);
static const int max_excluded_shape_pairs = 32;
ExcludedShapeSW excluded_shape_pairs[max_excluded_shape_pairs];
int excluded_shape_pair_count = 0;
real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
real_t min_contact_depth = margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR;
float motion_length = p_motion.length();
Vector2 motion_normal = p_motion / motion_length;
@ -829,7 +835,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
float owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
cbk.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work
cbk.valid_depth = MAX(owc_margin, margin); //user specified, but never less than actual margin or it won't work
cbk.invalid_by_dir = 0;
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
@ -854,7 +860,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
bool did_collide = false;
Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, p_margin)) {
if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, margin)) {
did_collide = cbk.passed > current_passed; //more passed, so collision actually existed
}
@ -1133,7 +1139,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
rcd.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
float owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
rcd.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work
rcd.valid_depth = MAX(owc_margin, margin); //user specified, but never less than actual margin or it won't work
if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) {
const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
@ -1155,7 +1161,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
rcd.object = col_obj;
rcd.shape = shape_idx;
rcd.local_shape = j;
bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, nullptr, p_margin);
bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, nullptr, margin);
if (!sc) {
continue;
}