Commit: c5c2883ce039a35945282b770ad77f461cdf05ad
Author: Sybren A. Stüvel
Date:   Thu Jun 18 14:43:30 2015 +0200
Branches: master
https://developer.blender.org/rBc5c2883ce039a35945282b770ad77f461cdf05ad

BGE Fix: apply velocity clamping on every physics subtick

This patch uses the Bullet "internal tick callback" functionality to
ensure that velocity clamping is performed after every physics update.
This makes a difference when physics subticks > 1, as in that case the
too-high velocity could have impacted the simulation.

This patch follows the examples at [1] and [2]; the latter example
also explains that the way we limit velocity in the BGE (before this
patch) is wrong.

[1] http://bulletphysics.org/mediawiki-1.5.8/index.php/Simulation_Tick_Callbacks
[2] 
http://www.bulletphysics.org/mediawiki-1.5.8/index.php/Code_Snippets#I_want_to_cap_the_speed_of_my_spaceship;

Reviewed by: panzergame

Differential Revision: https://developer.blender.org/D1364

===================================================================

M       source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
M       source/gameengine/Physics/Bullet/CcdPhysicsController.h
M       source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
M       source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h

===================================================================

diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp 
b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index 4fd1f10..4306d6d 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -697,6 +697,24 @@ CcdPhysicsController::~CcdPhysicsController()
        }
 }
 
+void CcdPhysicsController::SimulationTick(float timestep)
+{
+       btRigidBody *body = GetRigidBody();
+       if (!body && body->isStaticObject())
+               return;
+
+       // Clamp linear velocity
+       if (m_cci.m_clamp_vel_max > 0.0f || m_cci.m_clamp_vel_min > 0.0f) {
+               const btVector3 &linvel = body->getLinearVelocity();
+               btScalar len = linvel.length();
+
+               if (m_cci.m_clamp_vel_max > 0.0f && len > m_cci.m_clamp_vel_max)
+                       body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max 
/ len));
+               else if (m_cci.m_clamp_vel_min > 0.0f && !btFuzzyZero(len) && 
len < m_cci.m_clamp_vel_min)
+                       body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min 
/ len));
+       }
+}
+
 
 /**
  * SynchronizeMotionStates ynchronizes dynas, kinematic and deformable 
entities (and do 'late binding')
@@ -732,19 +750,6 @@ bool               
CcdPhysicsController::SynchronizeMotionStates(float time)
 
        if (body && !body->isStaticObject())
        {
-               
-               if ((m_cci.m_clamp_vel_max>0.0) || (m_cci.m_clamp_vel_min>0.0))
-               {
-                       const btVector3& linvel = body->getLinearVelocity();
-                       float len= linvel.length();
-                       
-                       if ((m_cci.m_clamp_vel_max>0.0) && (len > 
m_cci.m_clamp_vel_max))
-                                       body->setLinearVelocity(linvel * 
(m_cci.m_clamp_vel_max / len));
-                       
-                       else if ((m_cci.m_clamp_vel_min>0.0) && 
btFuzzyZero(len)==0 && (len < m_cci.m_clamp_vel_min))
-                               body->setLinearVelocity(linvel * 
(m_cci.m_clamp_vel_min / len));
-               }
-               
                const btTransform& xform = body->getCenterOfMassTransform();
                const btMatrix3x3& worldOri = xform.getBasis();
                const btVector3& worldPos = xform.getOrigin();
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h 
b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index b1d3876..2a15b61 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -579,6 +579,13 @@ protected:
                 * SynchronizeMotionStates ynchronizes dynas, kinematic and 
deformable entities (and do 'late binding')
                 */
                virtual bool            SynchronizeMotionStates(float time);
+
+               /**
+                * Called for every physics simulation step. Use this method for
+                * things like limiting linear and angular velocity.
+                */
+               void SimulationTick(float timestep);
+
                /**
                 * WriteMotionStateToDynamics ynchronizes dynas, kinematic and 
deformable entities (and do 'late binding')
                 */
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp 
b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index 89c8c12..14a19fd 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -452,6 +452,7 @@ m_scalingPropagated(false)
        SetSolverType(1);//issues with quickstep and memory allocations
 //     m_dynamicsWorld = new 
btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
        m_dynamicsWorld = new 
btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
+       
m_dynamicsWorld->setInternalTickCallback(&CcdPhysicsEnvironment::StaticSimulationSubtickCallback,
 this);
        //m_dynamicsWorld->getSolverInfo().m_linearSlop = 0.01f;
        //m_dynamicsWorld->getSolverInfo().m_solverMode=        
SOLVER_USE_WARMSTARTING +       SOLVER_USE_2_FRICTION_DIRECTIONS +      
SOLVER_RANDMIZE_ORDER + SOLVER_USE_FRICTION_WARMSTARTING;
 
@@ -677,6 +678,22 @@ void CcdPhysicsEnvironment::DebugDrawWorld()
                        m_dynamicsWorld->debugDrawWorld();
 }
 
+void CcdPhysicsEnvironment::StaticSimulationSubtickCallback(btDynamicsWorld 
*world, btScalar timeStep)
+{
+       // Get the pointer to the CcdPhysicsEnvironment associated with this 
Bullet world.
+       CcdPhysicsEnvironment *this_ = 
static_cast<CcdPhysicsEnvironment*>(world->getWorldUserInfo());
+       this_->SimulationSubtickCallback(timeStep);
+}
+
+void CcdPhysicsEnvironment::SimulationSubtickCallback(btScalar timeStep)
+{
+       std::set<CcdPhysicsController*>::iterator it;
+
+       for (it = m_controllers.begin(); it != m_controllers.end(); it++) {
+               (*it)->SimulationTick(timeStep);
+       }
+}
+
 bool   CcdPhysicsEnvironment::ProceedDeltaTime(double curTime,float 
timeStep,float interval)
 {
        std::set<CcdPhysicsController*>::iterator it;
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h 
b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
index e198847..d681298 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
@@ -52,6 +52,7 @@ class btBroadphaseInterface;
 struct btDbvtBroadphase;
 class btOverlappingPairCache;
 class btIDebugDraw;
+class btDynamicsWorld;
 class PHY_IVehicle;
 class CcdOverlapFilterCallBack;
 class CcdShapeConstructionInfo;
@@ -129,6 +130,14 @@ protected:
                /// Perform an integration step of duration 'timeStep'.
                virtual bool            ProceedDeltaTime(double curTime,float 
timeStep,float interval);
 
+               /**
+                * Called by Bullet for every physical simulation (sub)tick.
+                * Our constructor registers this callback to Bullet, which 
stores a pointer to 'this' in
+                * the btDynamicsWorld::getWorldUserInfo() pointer.
+                */
+               static void StaticSimulationSubtickCallback(btDynamicsWorld 
*world, btScalar timeStep);
+               void SimulationSubtickCallback(btScalar timeStep);
+
                virtual void            DebugDrawWorld();
 //             virtual bool            proceedDeltaTimeOneStep(float timeStep);

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to