diff options
-rw-r--r-- | source/blender/blenkernel/BKE_rigidbody.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/rigidbody.c | 37 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 17 |
3 files changed, 41 insertions, 14 deletions
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h index 12779a697b6..bab961bcbd2 100644 --- a/source/blender/blenkernel/BKE_rigidbody.h +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -91,6 +91,7 @@ void BKE_rigidbody_remove_constraint(struct Scene *scene, struct Object *ob); 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__ */ diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index d3a457ac2ed..025522fad25 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -1220,10 +1220,10 @@ void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) /* ------------------ */ -/* 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 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) 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,12 +1246,27 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) cache->last_exact = 0; cache->flag &= ~PTCACHE_REDO_NEEDED; } - 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); +} + +/* 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; } /* make sure we don't go out of cache frame range */ else if (ctime > endframe) { diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 83b2648ee50..9479e3e2e0e 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1090,6 +1090,15 @@ static void scene_flag_rbw_recursive(Scene *scene) 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 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen * 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 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) { 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); |