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