[Bf-blender-cvs] [53069d4] hair_system: Extended RigidBodyWorld stepping function with a tick callback.

Lukas Tönne noreply at git.blender.org
Thu Jul 31 19:08:10 CEST 2014


Commit: 53069d44cfe434b08209820dc4d566829d5cf0bb
Author: Lukas Tönne
Date:   Thu Jul 31 16:38:34 2014 +0200
Branches: hair_system
https://developer.blender.org/rB53069d44cfe434b08209820dc4d566829d5cf0bb

Extended RigidBodyWorld stepping function with a tick callback.

This will allow hooking other simulations (e.g. hair) into the Bullet
time step loop to enable sync'ed stepping of Bullet and other solvers
for accurate collision response.

This means that more solvers have to become global (instead of object-
based), but that was a design goal anyway for reasons of avoiding
dependency issues.

The Bullet time step will have to be run more generally if there are
other simulations. In particular it should still be executed even when
rigid bodies are cached, because the collision info may be needed. In
case of cached rigid bodies it would probably be sufficient to make them
all kinematic bodies, so that no calculation takes place for the rigid
bodies themselves, while their collision shapes are still available and
interpolated between cache frames.

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

M	intern/rigidbody/RBI_api.h
M	intern/rigidbody/rb_bullet_api.cpp
M	source/blender/blenkernel/BKE_rigidbody.h
M	source/blender/blenkernel/intern/rigidbody.c
M	source/blender/blenkernel/intern/scene.c

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

diff --git a/intern/rigidbody/RBI_api.h b/intern/rigidbody/RBI_api.h
index 688ca91..47e12f6 100644
--- a/intern/rigidbody/RBI_api.h
+++ b/intern/rigidbody/RBI_api.h
@@ -66,6 +66,9 @@ typedef struct rbMeshData rbMeshData;
 /* Constraint */
 typedef struct rbConstraint rbConstraint;
 
+/* Callback type for handling simulation ticks */
+typedef void (*rbSimulationTickCallback)(void *userdata, float timestep);
+
 /* ********************************** */
 /* Dynamics World Methods */
 
@@ -92,7 +95,8 @@ void RB_dworld_set_split_impulse(rbDynamicsWorld *world, int split_impulse);
 /* Simulation ----------------------- */
 
 /* Step the simulation by the desired amount (in seconds) with extra controls on substep sizes and maximum substeps */
-void RB_dworld_step_simulation(rbDynamicsWorld *world, float timeStep, int maxSubSteps, float timeSubStep);
+void RB_dworld_step_simulation(rbDynamicsWorld *world, float timeStep, int maxSubSteps, float timeSubStep,
+                               rbSimulationTickCallback cb, void *userdata, bool is_pre_tick);
 
 /* Export -------------------------- */
 
diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp
index 17bb381..5d194a7 100644
--- a/intern/rigidbody/rb_bullet_api.cpp
+++ b/intern/rigidbody/rb_bullet_api.cpp
@@ -213,9 +213,32 @@ void RB_dworld_set_split_impulse(rbDynamicsWorld *world, int split_impulse)
 
 /* Simulation ----------------------- */
 
-void RB_dworld_step_simulation(rbDynamicsWorld *world, float timeStep, int maxSubSteps, float timeSubStep)
+struct rbSimulationTickData {
+	rbSimulationTickData(rbSimulationTickCallback cb, void *userdata) : cb(cb), userdata(userdata) {}
+	
+	rbSimulationTickCallback cb;
+	void *userdata;
+};
+
+/* wrapper for our own callback type */
+static void rb_simulation_step_cb(btDynamicsWorld *world, btScalar timestep)
+{
+	rbSimulationTickData *data = (rbSimulationTickData *)world->getWorldUserInfo();
+	data->cb(data->userdata, timestep);
+}
+
+void RB_dworld_step_simulation(rbDynamicsWorld *world, float timeStep, int maxSubSteps, float timeSubStep,
+                               rbSimulationTickCallback cb, void *userdata, bool is_pre_tick)
 {
+	/* set the tick callback */
+	rbSimulationTickData data(cb, userdata);
+	world->dynamicsWorld->setInternalTickCallback(rb_simulation_step_cb, (void *)(&data), is_pre_tick);
+	
+	/* perform actual time step */
 	world->dynamicsWorld->stepSimulation(timeStep, maxSubSteps, timeSubStep);
+	
+	/* clean up */
+	world->dynamicsWorld->setWorldUserInfo(NULL);
 }
 
 /* Export -------------------------- */
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index c946f3a..7c0da86 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -97,6 +97,6 @@ void BKE_rigidbody_sync_transforms(struct RigidBodyWorld *rbw, struct Object *ob
 bool BKE_rigidbody_check_sim_running(struct RigidBodyWorld *rbw, float ctime);
 void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw);
 void BKE_rigidbody_rebuild_world(struct Scene *scene, float ctime);
-void BKE_rigidbody_do_simulation(struct Scene *scene, float ctime);
+bool BKE_rigidbody_do_simulation(struct Scene *scene, float ctime, void (*tickcb)(void *tickdata, float timestep), void *tickdata);
 
 #endif /* __BKE_RIGIDBODY_H__ */
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 3d61b0b..5356354 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -1515,7 +1515,7 @@ void BKE_rigidbody_rebuild_world(Scene *scene, float ctime)
 }
 
 /* Run RigidBody simulation for the specified physics world */
-void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
+bool BKE_rigidbody_do_simulation(Scene *scene, float ctime, void (*tickcb)(void *tickdata, float timestep), void *tickdata)
 {
 	float timestep;
 	RigidBodyWorld *rbw = scene->rigidbody_world;
@@ -1529,7 +1529,7 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
 
 	if (ctime <= startframe) {
 		rbw->ltime = startframe;
-		return;
+		return true; /* is ok, just nothing to simulate before the start frame */
 	}
 	/* make sure we don't go out of cache frame range */
 	else if (ctime > endframe) {
@@ -1538,7 +1538,7 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
 
 	/* don't try to run the simulation if we don't have a world yet but allow reading baked cache */
 	if (rbw->physics_world == NULL && !(cache->flag & PTCACHE_BAKED))
-		return;
+		return false;
 	else if (rbw->objects == NULL)
 		rigidbody_update_ob_array(rbw);
 
@@ -1547,7 +1547,11 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
 	if (BKE_ptcache_read(&pid, ctime)) {
 		BKE_ptcache_validate(cache, (int)ctime);
 		rbw->ltime = ctime;
-		return;
+		/* XXX TODO run the stepping loop anyway, but then set all rigid bodies
+		 * to animated and interpolate cached data!
+		 * The collision info may still be needed for other solvers
+		 */
+		return true;
 	}
 
 	/* advance simulation, we can only step one frame forward */
@@ -1563,7 +1567,8 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
 		/* calculate how much time elapsed since last step in seconds */
 		timestep = 1.0f / (float)FPS * (ctime - rbw->ltime) * rbw->time_scale;
 		/* step simulation by the requested timestep, steps per second are adjusted to take time scale into account */
-		RB_dworld_step_simulation(rbw->physics_world, timestep, INT_MAX, 1.0f / (float)rbw->steps_per_second * min_ff(rbw->time_scale, 1.0f));
+		RB_dworld_step_simulation(rbw->physics_world, timestep, INT_MAX, 1.0f / (float)rbw->steps_per_second * min_ff(rbw->time_scale, 1.0f),
+		                          tickcb, tickdata, false);
 
 		rigidbody_update_simulation_post_step(rbw);
 
@@ -1573,6 +1578,8 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
 
 		rbw->ltime = ctime;
 	}
+	
+	return true;
 }
 /* ************************************** */
 
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 18a4081..b24ab63 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -1249,13 +1249,31 @@ static void scene_rebuild_rbw_recursive(Scene *scene, float ctime)
 		BKE_rigidbody_rebuild_world(scene, ctime);
 }
 
+static void scene_tick(void *vscene, float timestep)
+{
+}
+
+/* fallback implementation for global simulation solvers,
+ * in case Bullet time stepping is not available.
+ */
+static void scene_do_simulation_step(Scene *scene, float ctime)
+{
+	// XXX TODO !!
+}
+
 static void scene_do_rb_simulation_recursive(Scene *scene, float ctime)
 {
 	if (scene->set)
 		scene_do_rb_simulation_recursive(scene->set, ctime);
 
-	if (BKE_scene_check_rigidbody_active(scene))
-		BKE_rigidbody_do_simulation(scene, ctime);
+	{
+		bool stepped = false;
+		if (BKE_scene_check_rigidbody_active(scene))
+			stepped |= BKE_rigidbody_do_simulation(scene, ctime, scene_tick, scene);
+	
+		if (!stepped)
+			scene_do_simulation_step(scene, ctime);
+	}
 }
 
 /* Used to visualize CPU threads activity during threaded object update,




More information about the Bf-blender-cvs mailing list