Browse Source

Merge pull request #32641 from nekomatata/change-collision-layer

Fixed RigidBody stuttering when changing collision layer/mask
Rémi Verschelde 5 years ago
parent
commit
26bbb26738

+ 8 - 4
modules/bullet/collision_object_bullet.h

@@ -167,14 +167,18 @@ public:
 	_FORCE_INLINE_ const VSet<RID> &get_exceptions() const { return exceptions; }
 
 	_FORCE_INLINE_ void set_collision_layer(uint32_t p_layer) {
-		collisionLayer = p_layer;
-		on_collision_filters_change();
+		if (collisionLayer != p_layer) {
+			collisionLayer = p_layer;
+			on_collision_filters_change();
+		}
 	}
 	_FORCE_INLINE_ uint32_t get_collision_layer() const { return collisionLayer; }
 
 	_FORCE_INLINE_ void set_collision_mask(uint32_t p_mask) {
-		collisionMask = p_mask;
-		on_collision_filters_change();
+		if (collisionMask != p_mask) {
+			collisionMask = p_mask;
+			on_collision_filters_change();
+		}
 	}
 	_FORCE_INLINE_ uint32_t get_collision_mask() const { return collisionMask; }
 

+ 2 - 0
modules/bullet/rigid_body_bullet.cpp

@@ -411,6 +411,8 @@ void RigidBodyBullet::on_collision_filters_change() {
 	if (space) {
 		space->reload_collision_filters(this);
 	}
+
+	set_activation_state(true);
 }
 
 void RigidBodyBullet::on_collision_checker_start() {

+ 15 - 6
modules/bullet/space_bullet.cpp

@@ -42,6 +42,7 @@
 #include "servers/physics_server.h"
 #include "soft_body_bullet.h"
 
+#include <BulletCollision/BroadphaseCollision/btBroadphaseProxy.h>
 #include <BulletCollision/CollisionDispatch/btCollisionObject.h>
 #include <BulletCollision/CollisionDispatch/btGhostObject.h>
 #include <BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h>
@@ -459,9 +460,13 @@ void SpaceBullet::remove_area(AreaBullet *p_area) {
 }
 
 void SpaceBullet::reload_collision_filters(AreaBullet *p_area) {
-	// This is necessary to change collision filter
-	dynamicsWorld->removeCollisionObject(p_area->get_bt_ghost());
-	dynamicsWorld->addCollisionObject(p_area->get_bt_ghost(), p_area->get_collision_layer(), p_area->get_collision_mask());
+	btGhostObject *ghost_object = p_area->get_bt_ghost();
+
+	btBroadphaseProxy *ghost_proxy = ghost_object->getBroadphaseHandle();
+	ghost_proxy->m_collisionFilterGroup = p_area->get_collision_layer();
+	ghost_proxy->m_collisionFilterMask = p_area->get_collision_mask();
+
+	dynamicsWorld->refreshBroadphaseProxy(ghost_object);
 }
 
 void SpaceBullet::add_rigid_body(RigidBodyBullet *p_body) {
@@ -482,9 +487,13 @@ void SpaceBullet::remove_rigid_body(RigidBodyBullet *p_body) {
 }
 
 void SpaceBullet::reload_collision_filters(RigidBodyBullet *p_body) {
-	// This is necessary to change collision filter
-	remove_rigid_body(p_body);
-	add_rigid_body(p_body);
+	btRigidBody *rigid_body = p_body->get_bt_rigid_body();
+
+	btBroadphaseProxy *body_proxy = rigid_body->getBroadphaseProxy();
+	body_proxy->m_collisionFilterGroup = p_body->get_collision_layer();
+	body_proxy->m_collisionFilterMask = p_body->get_collision_mask();
+
+	dynamicsWorld->refreshBroadphaseProxy(rigid_body);
 }
 
 void SpaceBullet::add_soft_body(SoftBodyBullet *p_body) {