Merge pull request #47266 from nekomatata/solver-kinematic-bug-fix-3.4
[3.4] Fix GodotPhysics solver with kinematic body set to report contacts
This commit is contained in:
commit
d5a0b2e8bf
|
@ -211,11 +211,21 @@ real_t combine_friction(BodySW *A, BodySW *B) {
|
|||
|
||||
bool BodyPairSW::setup(real_t p_step) {
|
||||
//cannot collide
|
||||
if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) {
|
||||
if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) {
|
||||
collided = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool report_contacts_only = false;
|
||||
if ((A->get_mode() <= PhysicsServer::BODY_MODE_KINEMATIC) && (B->get_mode() <= PhysicsServer::BODY_MODE_KINEMATIC)) {
|
||||
if ((A->get_max_contacts_reported() > 0) || (B->get_max_contacts_reported() > 0)) {
|
||||
report_contacts_only = true;
|
||||
} else {
|
||||
collided = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
offset_B = B->get_transform().get_origin() - A->get_transform().get_origin();
|
||||
|
||||
validate_contacts();
|
||||
|
@ -274,12 +284,9 @@ bool BodyPairSW::setup(real_t p_step) {
|
|||
real_t depth = c.normal.dot(global_A - global_B);
|
||||
|
||||
if (depth <= 0) {
|
||||
c.active = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
c.active = true;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
if (space->is_debugging_contacts()) {
|
||||
|
@ -303,6 +310,11 @@ bool BodyPairSW::setup(real_t p_step) {
|
|||
B->add_contact(global_B, c.normal, depth, shape_B, global_A, shape_A, A->get_instance_id(), A->get_self(), crB);
|
||||
}
|
||||
|
||||
if (report_contacts_only) {
|
||||
collided = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
c.active = true;
|
||||
|
||||
// Precompute normal mass, tangent mass, and bias.
|
||||
|
|
|
@ -221,11 +221,21 @@ real_t combine_friction(Body2DSW *A, Body2DSW *B) {
|
|||
|
||||
bool BodyPair2DSW::setup(real_t p_step) {
|
||||
//cannot collide
|
||||
if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) {
|
||||
if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) {
|
||||
collided = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool report_contacts_only = false;
|
||||
if ((A->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC) && (B->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC)) {
|
||||
if ((A->get_max_contacts_reported() > 0) || (B->get_max_contacts_reported() > 0)) {
|
||||
report_contacts_only = true;
|
||||
} else {
|
||||
collided = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//use local A coordinates to avoid numerical issues on collision detection
|
||||
offset_B = B->get_transform().get_origin() - A->get_transform().get_origin();
|
||||
|
||||
|
@ -344,6 +354,7 @@ bool BodyPair2DSW::setup(real_t p_step) {
|
|||
|
||||
for (int i = 0; i < contact_count; i++) {
|
||||
Contact &c = contacts[i];
|
||||
c.active = false;
|
||||
|
||||
Vector2 global_A = xform_Au.xform(c.local_A);
|
||||
Vector2 global_B = xform_Bu.xform(c.local_B);
|
||||
|
@ -351,45 +362,36 @@ bool BodyPair2DSW::setup(real_t p_step) {
|
|||
real_t depth = c.normal.dot(global_A - global_B);
|
||||
|
||||
if (depth <= 0 || !c.reused) {
|
||||
c.active = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
c.active = true;
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (space->is_debugging_contacts()) {
|
||||
space->add_debug_contact(global_A + offset_A);
|
||||
space->add_debug_contact(global_B + offset_A);
|
||||
}
|
||||
#endif
|
||||
int gather_A = A->can_report_contacts();
|
||||
int gather_B = B->can_report_contacts();
|
||||
|
||||
c.rA = global_A;
|
||||
c.rB = global_B - offset_B;
|
||||
|
||||
if (gather_A | gather_B) {
|
||||
//Vector2 crB( -B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x );
|
||||
|
||||
global_A += offset_A;
|
||||
global_B += offset_A;
|
||||
|
||||
if (gather_A) {
|
||||
if (A->can_report_contacts()) {
|
||||
Vector2 crB(-B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x);
|
||||
A->add_contact(global_A, -c.normal, depth, shape_A, global_B, shape_B, B->get_instance_id(), B->get_self(), crB + B->get_linear_velocity());
|
||||
}
|
||||
if (gather_B) {
|
||||
Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x);
|
||||
B->add_contact(global_B, c.normal, depth, shape_B, global_A, shape_A, A->get_instance_id(), A->get_self(), crA + A->get_linear_velocity());
|
||||
}
|
||||
A->add_contact(global_A + offset_A, -c.normal, depth, shape_A, global_B + offset_A, shape_B, B->get_instance_id(), B->get_self(), crB + B->get_linear_velocity());
|
||||
}
|
||||
|
||||
if ((A->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC)) {
|
||||
c.active = false;
|
||||
if (B->can_report_contacts()) {
|
||||
Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x);
|
||||
B->add_contact(global_B + offset_A, c.normal, depth, shape_B, global_A + offset_A, shape_A, A->get_instance_id(), A->get_self(), crA + A->get_linear_velocity());
|
||||
}
|
||||
|
||||
if (report_contacts_only) {
|
||||
collided = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
c.active = true;
|
||||
|
||||
// Precompute normal mass, tangent mass, and bias.
|
||||
real_t rnA = c.rA.dot(c.normal);
|
||||
real_t rnB = c.rB.dot(c.normal);
|
||||
|
|
Loading…
Reference in New Issue