[Bf-blender-cvs] [adba575] blender-v2.75-release: BGE Fix: apply velocity clamping on every physics subtick

Sybren A. Stüvel noreply at git.blender.org
Mon Jun 29 16:18:27 CEST 2015


Commit: adba5756050b37d4193f16aee35cdc001d2a4adf
Author: Sybren A. Stüvel
Date:   Thu Jun 18 14:43:30 2015 +0200
Branches: blender-v2.75-release
https://developer.blender.org/rBadba5756050b37d4193f16aee35cdc001d2a4adf

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 8ea2b4f..6fbd786 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 3670d79..cd579de 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;
 
@@ -695,6 +696,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 94aea21..21cbd52 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);




More information about the Bf-blender-cvs mailing list