Browse Source

Merge pull request #39084 from madmiraal/backport-37314

[3.2] Better damping implementation for Bullet rigid bodies
Rémi Verschelde 5 years ago
parent
commit
44a516986d

+ 2 - 0
modules/bullet/SCsub

@@ -203,6 +203,8 @@ if env["builtin_bullet"]:
     # if env['target'] == "debug" or env['target'] == "release_debug":
     #     env_bullet.Append(CPPDEFINES=['BT_DEBUG'])
 
+    env_bullet.Append(CPPDEFINES=["BT_USE_OLD_DAMPING_METHOD"])
+
     env_thirdparty = env_bullet.Clone()
     env_thirdparty.disable_warnings()
     env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)

+ 20 - 20
modules/bullet/rigid_body_bullet.cpp

@@ -503,15 +503,18 @@ void RigidBodyBullet::set_param(PhysicsServer::BodyParameter p_param, real_t p_v
 		}
 		case PhysicsServer::BODY_PARAM_LINEAR_DAMP:
 			linearDamp = p_value;
-			btBody->setDamping(linearDamp, angularDamp);
+			// Mark for updating total linear damping.
+			scratch_space_override_modificator();
 			break;
 		case PhysicsServer::BODY_PARAM_ANGULAR_DAMP:
 			angularDamp = p_value;
-			btBody->setDamping(linearDamp, angularDamp);
+			// Mark for updating total angular damping.
+			scratch_space_override_modificator();
 			break;
 		case PhysicsServer::BODY_PARAM_GRAVITY_SCALE:
 			gravity_scale = p_value;
-			/// The Bullet gravity will be is set by reload_space_override_modificator
+			// The Bullet gravity will be is set by reload_space_override_modificator.
+			// Mark for updating total gravity scale.
 			scratch_space_override_modificator();
 			break;
 		default:
@@ -902,21 +905,20 @@ void RigidBodyBullet::on_exit_area(AreaBullet *p_area) {
 }
 
 void RigidBodyBullet::reload_space_override_modificator() {
-
 	// Make sure that kinematic bodies have their total gravity calculated
 	if (!is_active() && PhysicsServer::BODY_MODE_KINEMATIC != mode)
 		return;
 
-	Vector3 newGravity(space->get_gravity_direction() * space->get_gravity_magnitude());
-	real_t newLinearDamp(linearDamp);
-	real_t newAngularDamp(angularDamp);
+	Vector3 newGravity(0.0, 0.0, 0.0);
+	real_t newLinearDamp = MAX(0.0, linearDamp);
+	real_t newAngularDamp = MAX(0.0, angularDamp);
 
 	AreaBullet *currentArea;
 	// Variable used to calculate new gravity for gravity point areas, it is pointed by currentGravity pointer
 	Vector3 support_gravity(0, 0, 0);
 
-	int countCombined(0);
-	for (int i = areaWhereIamCount - 1; 0 <= i; --i) {
+	bool stopped = false;
+	for (int i = areaWhereIamCount - 1; (0 <= i) && !stopped; --i) {
 
 		currentArea = areasWhereIam[i];
 
@@ -965,7 +967,6 @@ void RigidBodyBullet::reload_space_override_modificator() {
 				newGravity += support_gravity;
 				newLinearDamp += currentArea->get_spOv_linearDamp();
 				newAngularDamp += currentArea->get_spOv_angularDamp();
-				++countCombined;
 				break;
 			case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE:
 				/// This area adds its gravity/damp values to whatever has been calculated
@@ -974,32 +975,31 @@ void RigidBodyBullet::reload_space_override_modificator() {
 				newGravity += support_gravity;
 				newLinearDamp += currentArea->get_spOv_linearDamp();
 				newAngularDamp += currentArea->get_spOv_angularDamp();
-				++countCombined;
-				goto endAreasCycle;
+				stopped = true;
+				break;
 			case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE:
 				/// This area replaces any gravity/damp, even the default one, and
 				/// stops taking into account the rest of the areas.
 				newGravity = support_gravity;
 				newLinearDamp = currentArea->get_spOv_linearDamp();
 				newAngularDamp = currentArea->get_spOv_angularDamp();
-				countCombined = 1;
-				goto endAreasCycle;
+				stopped = true;
+				break;
 			case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE_COMBINE:
 				/// This area replaces any gravity/damp calculated so far, but keeps
 				/// calculating the rest of the areas, down to the default one.
 				newGravity = support_gravity;
 				newLinearDamp = currentArea->get_spOv_linearDamp();
 				newAngularDamp = currentArea->get_spOv_angularDamp();
-				countCombined = 1;
 				break;
 		}
 	}
-endAreasCycle:
 
-	if (1 < countCombined) {
-		newGravity /= countCombined;
-		newLinearDamp /= countCombined;
-		newAngularDamp /= countCombined;
+	// Add default gravity and damping from space.
+	if (!stopped) {
+		newGravity += space->get_gravity_direction() * space->get_gravity_magnitude();
+		newLinearDamp += space->get_linear_damp();
+		newAngularDamp += space->get_angular_damp();
 	}
 
 	btVector3 newBtGravity;

+ 8 - 2
modules/bullet/space_bullet.cpp

@@ -353,6 +353,8 @@ SpaceBullet::SpaceBullet() :
 		godotFilterCallback(NULL),
 		gravityDirection(0, -1, 0),
 		gravityMagnitude(10),
+		linear_damp(0.0),
+		angular_damp(0.0),
 		contactDebugCount(0),
 		delta_time(0.) {
 
@@ -390,8 +392,11 @@ void SpaceBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant
 			update_gravity();
 			break;
 		case PhysicsServer::AREA_PARAM_LINEAR_DAMP:
+			linear_damp = p_value;
+			break;
 		case PhysicsServer::AREA_PARAM_ANGULAR_DAMP:
-			break; // No damp
+			angular_damp = p_value;
+			break;
 		case PhysicsServer::AREA_PARAM_PRIORITY:
 			// Priority is always 0, the lower
 			break;
@@ -412,8 +417,9 @@ Variant SpaceBullet::get_param(PhysicsServer::AreaParameter p_param) {
 		case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR:
 			return gravityDirection;
 		case PhysicsServer::AREA_PARAM_LINEAR_DAMP:
+			return linear_damp;
 		case PhysicsServer::AREA_PARAM_ANGULAR_DAMP:
-			return 0; // No damp
+			return angular_damp;
 		case PhysicsServer::AREA_PARAM_PRIORITY:
 			return 0; // Priority is always 0, the lower
 		case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT:

+ 6 - 0
modules/bullet/space_bullet.h

@@ -108,6 +108,9 @@ class SpaceBullet : public RIDBullet {
 	Vector3 gravityDirection;
 	real_t gravityMagnitude;
 
+	real_t linear_damp;
+	real_t angular_damp;
+
 	Vector<AreaBullet *> areas;
 
 	Vector<Vector3> contactDebug;
@@ -177,6 +180,9 @@ public:
 
 	void update_gravity();
 
+	real_t get_linear_damp() const { return linear_damp; }
+	real_t get_angular_damp() const { return angular_damp; }
+
 	bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes);
 	int test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer::SeparationResult *r_results, int p_result_max, float p_margin);
 

+ 34 - 0
thirdparty/bullet/0001-old-damping-def.patch

@@ -0,0 +1,34 @@
+diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
+index 9e8705b001..f1b50b39c8 100644
+--- a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
++++ b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
+@@ -136,8 +136,13 @@ void btRigidBody::setGravity(const btVector3& acceleration)
+ 
+ void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
+ {
+-	m_linearDamping = btClamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+-	m_angularDamping = btClamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
++#ifdef BT_USE_OLD_DAMPING_METHOD
++	m_linearDamping = btMax(lin_damping, btScalar(0.0));
++	m_angularDamping = btMax(ang_damping, btScalar(0.0));
++#else
++	m_linearDamping = btClamped(lin_damping, btScalar(0.0), btScalar(1.0));
++	m_angularDamping = btClamped(ang_damping, btScalar(0.0), btScalar(1.0));
++#endif
+ }
+ 
+ ///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
+@@ -146,10 +151,9 @@ void btRigidBody::applyDamping(btScalar timeStep)
+ 	//On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
+ 	//todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
+ 
+-//#define USE_OLD_DAMPING_METHOD 1
+-#ifdef USE_OLD_DAMPING_METHOD
+-	m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+-	m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
++#ifdef BT_USE_OLD_DAMPING_METHOD
++	m_linearVelocity *= btMax((btScalar(1.0) - timeStep * m_linearDamping), btScalar(0.0));
++	m_angularVelocity *= btMax((btScalar(1.0) - timeStep * m_angularDamping), btScalar(0.0));
+ #else
+ 	m_linearVelocity *= btPow(btScalar(1) - m_linearDamping, timeStep);
+ 	m_angularVelocity *= btPow(btScalar(1) - m_angularDamping, timeStep);

+ 10 - 6
thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp

@@ -136,8 +136,13 @@ void btRigidBody::setGravity(const btVector3& acceleration)
 
 void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
 {
-	m_linearDamping = btClamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
-	m_angularDamping = btClamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+#ifdef BT_USE_OLD_DAMPING_METHOD
+	m_linearDamping = btMax(lin_damping, btScalar(0.0));
+	m_angularDamping = btMax(ang_damping, btScalar(0.0));
+#else
+	m_linearDamping = btClamped(lin_damping, btScalar(0.0), btScalar(1.0));
+	m_angularDamping = btClamped(ang_damping, btScalar(0.0), btScalar(1.0));
+#endif
 }
 
 ///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
@@ -146,10 +151,9 @@ void btRigidBody::applyDamping(btScalar timeStep)
 	//On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
 	//todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
 
-//#define USE_OLD_DAMPING_METHOD 1
-#ifdef USE_OLD_DAMPING_METHOD
-	m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
-	m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+#ifdef BT_USE_OLD_DAMPING_METHOD
+	m_linearVelocity *= btMax((btScalar(1.0) - timeStep * m_linearDamping), btScalar(0.0));
+	m_angularVelocity *= btMax((btScalar(1.0) - timeStep * m_angularDamping), btScalar(0.0));
 #else
 	m_linearVelocity *= btPow(btScalar(1) - m_linearDamping, timeStep);
 	m_angularVelocity *= btPow(btScalar(1) - m_angularDamping, timeStep);