mirror of
https://github.com/godotengine/godot.git
synced 2025-02-05 10:23:20 +00:00
Fix GodotPhysics solver with kinematic body set to report contacts
In 3D, collision is disabled between kinematic/static bodies when contacts are generated only to report them. In 2D, this case was already fixed but the code is cleaned to make it easier to follow.
This commit is contained in:
parent
01851defb5
commit
c5d2404a13
@ -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() <= PhysicsServer2D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer2D::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() <= PhysicsServer2D::BODY_MODE_KINEMATIC) && (B->get_mode() <= PhysicsServer2D::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;
|
||||
}
|
||||
}
|
||||
|
||||
if (A->is_shape_set_as_disabled(shape_A) || B->is_shape_set_as_disabled(shape_B)) {
|
||||
collided = false;
|
||||
return false;
|
||||
@ -350,51 +360,44 @@ 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);
|
||||
|
||||
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) {
|
||||
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());
|
||||
}
|
||||
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 + 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() <= PhysicsServer2D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer2D::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);
|
||||
|
@ -211,11 +211,21 @@ real_t combine_friction(Body3DSW *A, Body3DSW *B) {
|
||||
|
||||
bool BodyPair3DSW::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() <= PhysicsServer3D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer3D::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() <= PhysicsServer3D::BODY_MODE_KINEMATIC) && (B->get_mode() <= PhysicsServer3D::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;
|
||||
}
|
||||
}
|
||||
|
||||
if (A->is_shape_set_as_disabled(shape_A) || B->is_shape_set_as_disabled(shape_B)) {
|
||||
collided = false;
|
||||
return false;
|
||||
@ -279,12 +289,9 @@ bool BodyPair3DSW::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()) {
|
||||
@ -308,6 +315,11 @@ bool BodyPair3DSW::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.
|
||||
|
Loading…
Reference in New Issue
Block a user