From 8f0f2bf4ef6cc0430933c019ad72fc1774f4f804 Mon Sep 17 00:00:00 2001 From: Marcel Admiraal Date: Wed, 27 May 2020 17:50:24 +0100 Subject: [PATCH 1/2] Better damping implementation for Bullet rigid bodies --- modules/bullet/rigid_body_bullet.cpp | 40 ++++++++++++++-------------- modules/bullet/space_bullet.cpp | 10 +++++-- modules/bullet/space_bullet.h | 6 +++++ 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 16a8cf8ede7..7109d61f764 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/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; diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index fb317f6eb37..aabcaeaa208 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -342,6 +342,8 @@ SpaceBullet::SpaceBullet() : godotFilterCallback(NULL), gravityDirection(0, -1, 0), gravityMagnitude(10), + linear_damp(0.0), + angular_damp(0.0), contactDebugCount(0), delta_time(0.) { @@ -379,8 +381,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; @@ -401,8 +406,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: diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index 32372f16305..4b01ed9220f 100644 --- a/modules/bullet/space_bullet.h +++ b/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 areas; Vector 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); From 5d8b0649be6c3f8e32103cb4c4e00c70679ab3fd Mon Sep 17 00:00:00 2001 From: Marcel Admiraal Date: Wed, 27 May 2020 17:50:49 +0100 Subject: [PATCH 2/2] Apply old method for linear & angular damping in Bullet, in order to make it easier to tweak and consistent with Godot Physics. Include patch applied to Bullet master to enable dampings greater than 1. --- modules/bullet/SCsub | 2 ++ thirdparty/bullet/0001-old-damping-def.patch | 34 +++++++++++++++++++ .../BulletDynamics/Dynamics/btRigidBody.cpp | 16 +++++---- 3 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 thirdparty/bullet/0001-old-damping-def.patch diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub index 02d0a31a699..8d4e3cf819e 100644 --- a/modules/bullet/SCsub +++ b/modules/bullet/SCsub @@ -208,6 +208,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) diff --git a/thirdparty/bullet/0001-old-damping-def.patch b/thirdparty/bullet/0001-old-damping-def.patch new file mode 100644 index 00000000000..4c4c4c35ed2 --- /dev/null +++ b/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); diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp index 9e8705b001a..f1b50b39c82 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);