[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [54990] trunk/blender/source/blender/ blenkernel: rigidbody: Fix inconsistency with world rebuilding

Sergej Reich sergej.reich at googlemail.com
Sun Mar 3 07:09:45 CET 2013


Revision: 54990
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=54990
Author:   sergof
Date:     2013-03-03 06:09:45 +0000 (Sun, 03 Mar 2013)
Log Message:
-----------
rigidbody: Fix inconsistency with world rebuilding

The rigid body world could be rebuilt on start frame and one frame after
start frame. The latter was necessary sice animation playback usually
doesn't start at start frame.
This lead to different simulations depending on which frame the
simulaton was rebuilt when animation was involved.

Now we only rebuild the world on start frame.
This is actually tricky to do since, as mentioned above, animation
playback starts on second frame. To work around this we rebuild the
world before the actual update.
The alternative would be to rebuld the world on every simulation change
(like the other simulations do it) but this is an expensive operation
and would be too slow.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_rigidbody.h
    trunk/blender/source/blender/blenkernel/intern/rigidbody.c
    trunk/blender/source/blender/blenkernel/intern/scene.c

Modified: trunk/blender/source/blender/blenkernel/BKE_rigidbody.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_rigidbody.h	2013-03-03 06:00:01 UTC (rev 54989)
+++ trunk/blender/source/blender/blenkernel/BKE_rigidbody.h	2013-03-03 06:09:45 UTC (rev 54990)
@@ -91,6 +91,7 @@
 void BKE_rigidbody_aftertrans_update(struct Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle);
 void BKE_rigidbody_sync_transforms(struct RigidBodyWorld *rbw, struct Object *ob, 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);
 
 #endif /* __BKE_RIGIDBODY_H__ */

Modified: trunk/blender/source/blender/blenkernel/intern/rigidbody.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/rigidbody.c	2013-03-03 06:00:01 UTC (rev 54989)
+++ trunk/blender/source/blender/blenkernel/intern/rigidbody.c	2013-03-03 06:09:45 UTC (rev 54990)
@@ -1220,10 +1220,10 @@
 
 /* ------------------ */
 
-/* Run RigidBody simulation for the specified physics world */
-void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
+/* Rebuild rigid body world */
+/* NOTE: this needs to be called before frame update to work correctly */
+void BKE_rigidbody_rebuild_world(Scene *scene, float ctime)
 {
-	float timestep;
 	RigidBodyWorld *rbw = scene->rigidbody_world;
 	PointCache *cache;
 	PTCacheID pid;
@@ -1233,16 +1233,12 @@
 	BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL);
 	cache = rbw->pointcache;
 
-	rbw->flag &= ~RBW_FLAG_FRAME_UPDATE;
-
 	/* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */
 	if (rbw->physics_world == NULL || rbw->numbodies != BLI_countlist(&rbw->group->gobject)) {
 		cache->flag |= PTCACHE_OUTDATED;
 	}
 
-	if (ctime <= startframe) {
-		rbw->ltime = startframe;
-		/* reset and rebuild simulation if necessary */
+	if (ctime <= startframe + 1 && rbw->ltime == startframe) {
 		if (cache->flag & PTCACHE_OUTDATED) {
 			BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
 			rigidbody_update_simulation(scene, rbw, true);
@@ -1250,13 +1246,28 @@
 			cache->last_exact = 0;
 			cache->flag &= ~PTCACHE_REDO_NEEDED;
 		}
+	}
+}
+
+/* Run RigidBody simulation for the specified physics world */
+void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
+{
+	float timestep;
+	RigidBodyWorld *rbw = scene->rigidbody_world;
+	PointCache *cache;
+	PTCacheID pid;
+	int startframe, endframe;
+
+	BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw);
+	BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL);
+	cache = rbw->pointcache;
+
+	rbw->flag &= ~RBW_FLAG_FRAME_UPDATE;
+
+	if (ctime <= startframe) {
+		rbw->ltime = startframe;
 		return;
 	}
-	/* rebuild world if it's outdated on second frame */
-	else if (ctime == startframe + 1 && rbw->ltime == startframe && cache->flag & PTCACHE_OUTDATED) {
-		BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
-		rigidbody_update_simulation(scene, rbw, true);
-	}
 	/* make sure we don't go out of cache frame range */
 	else if (ctime > endframe) {
 		ctime = endframe;

Modified: trunk/blender/source/blender/blenkernel/intern/scene.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/scene.c	2013-03-03 06:00:01 UTC (rev 54989)
+++ trunk/blender/source/blender/blenkernel/intern/scene.c	2013-03-03 06:09:45 UTC (rev 54990)
@@ -1090,6 +1090,15 @@
 		scene->rigidbody_world->flag |= RBW_FLAG_FRAME_UPDATE;
 }
 
+static void scene_rebuild_rbw_recursive(Scene *scene, float ctime)
+{
+	if (scene->set)
+		scene_rebuild_rbw_recursive(scene->set, ctime);
+
+	if (BKE_scene_check_rigidbody_active(scene))
+		BKE_rigidbody_rebuild_world(scene, ctime);
+}
+
 static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scene_parent)
 {
 	Base *base;
@@ -1112,7 +1121,7 @@
 		 * as that is the active scene controlling all timing in file at the moment
 		 */
 		float ctime = BKE_scene_frame_get(scene_parent);
-		
+
 		/* however, "scene" contains the rigidbody world needed for eval... */
 		BKE_rigidbody_do_simulation(scene, ctime);
 	}
@@ -1195,6 +1204,12 @@
 {
 	float ctime = BKE_scene_frame_get(sce);
 	Scene *sce_iter;
+	
+	/* rebuild rigid body worlds before doing the actual frame update
+	 * this needs to be done on start frame but animation playback usually starts one frame later
+	 * we need to do it here to avoid rebuilding the world on every simulation change, which can be very expensive
+	 */
+	scene_rebuild_rbw_recursive(sce, ctime);
 
 	/* keep this first */
 	BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_PRE);




More information about the Bf-blender-cvs mailing list