diff options
Diffstat (limited to 'source/blender/blenkernel/intern/rigidbody.c')
-rw-r--r-- | source/blender/blenkernel/intern/rigidbody.c | 374 |
1 files changed, 205 insertions, 169 deletions
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 502b6a81c76..ab324726812 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -48,25 +48,28 @@ #include "DNA_ID.h" #include "DNA_group_types.h" +#include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_object_force_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" -#include "BKE_cdderivedmesh.h" -#include "BKE_depsgraph.h" +#include "BKE_collection.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" #include "BKE_object.h" #include "BKE_pointcache.h" #include "BKE_rigidbody.h" #include "BKE_scene.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" /* ************************************** */ /* Memory Management */ @@ -93,26 +96,30 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw) if (rbw->physics_world) { /* free physics references, we assume that all physics objects in will have been added to the world */ - GroupObject *go; if (rbw->constraints) { - for (go = rbw->constraints->gobject.first; go; go = go->next) { - if (go->ob && go->ob->rigidbody_constraint) { - RigidBodyCon *rbc = go->ob->rigidbody_constraint; - - if (rbc->physics_constraint) + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, object) + { + if (object->rigidbody_constraint) { + RigidBodyCon *rbc = object->rigidbody_constraint; + if (rbc->physics_constraint) { RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + } } } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } - if (rbw->group) { - for (go = rbw->group->gobject.first; go; go = go->next) { - if (go->ob && go->ob->rigidbody_object) { - RigidBodyOb *rbo = go->ob->rigidbody_object; - if (rbo->physics_object) + if (rbw->group) { + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object) + { + if (object->rigidbody_object) { + RigidBodyOb *rbo = object->rigidbody_object; + if (rbo->physics_object) { RB_dworld_remove_body(rbw->physics_world, rbo->physics_object); + } } } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } /* free dynamics world */ RB_dworld_delete(rbw->physics_world); @@ -229,31 +236,38 @@ RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob, const int UNUSED(f /* Setup Utilities - Validate Sim Instances */ /* get the appropriate DerivedMesh based on rigid body mesh source */ -static DerivedMesh *rigidbody_get_mesh(Object *ob) +static Mesh *rigidbody_get_mesh(Object *ob) { - if (ob->rigidbody_object->mesh_source == RBO_MESH_DEFORM) { - return ob->derivedDeform; - } - else if (ob->rigidbody_object->mesh_source == RBO_MESH_FINAL) { - return ob->derivedFinal; - } - else { - return CDDM_from_mesh(ob->data); - } + switch (ob->rigidbody_object->mesh_source) { + case RBO_MESH_DEFORM: + return ob->runtime.mesh_deform_eval; + case RBO_MESH_FINAL: + return ob->runtime.mesh_eval; + case RBO_MESH_BASE: + /* This mesh may be used for computing looptris, which should be done + * on the original; otherwise every time the CoW is recreated it will + * have to be recomputed. */ + BLI_assert(ob->rigidbody_object->mesh_source == RBO_MESH_BASE); + return DEG_get_original_object(ob)->data; + } + + /* Just return something sensible so that at least Blender won't crash. */ + BLI_assert(!"Unknown mesh source"); + return ob->runtime.mesh_eval; } /* create collision shape of mesh - convex hull */ static rbCollisionShape *rigidbody_get_shape_convexhull_from_mesh(Object *ob, float margin, bool *can_embed) { rbCollisionShape *shape = NULL; - DerivedMesh *dm = NULL; + Mesh *mesh = NULL; MVert *mvert = NULL; int totvert = 0; if (ob->type == OB_MESH && ob->data) { - dm = rigidbody_get_mesh(ob); - mvert = (dm) ? dm->getVertArray(dm) : NULL; - totvert = (dm) ? dm->getNumVerts(dm) : 0; + mesh = rigidbody_get_mesh(ob); + mvert = (mesh) ? mesh->mvert : NULL; + totvert = (mesh) ? mesh->totvert : 0; } else { printf("ERROR: cannot make Convex Hull collision shape for non-Mesh object\n"); @@ -266,9 +280,6 @@ static rbCollisionShape *rigidbody_get_shape_convexhull_from_mesh(Object *ob, fl printf("ERROR: no vertices to define Convex Hull collision shape with\n"); } - if (dm && ob->rigidbody_object->mesh_source == RBO_MESH_BASE) - dm->release(dm); - return shape; } @@ -280,24 +291,24 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob) rbCollisionShape *shape = NULL; if (ob->type == OB_MESH) { - DerivedMesh *dm = NULL; + Mesh *mesh = NULL; MVert *mvert; const MLoopTri *looptri; int totvert; int tottri; const MLoop *mloop; - dm = rigidbody_get_mesh(ob); + mesh = rigidbody_get_mesh(ob); /* ensure mesh validity, then grab data */ - if (dm == NULL) + if (mesh == NULL) return NULL; - mvert = dm->getVertArray(dm); - totvert = dm->getNumVerts(dm); - looptri = dm->getLoopTriArray(dm); - tottri = dm->getNumLoopTri(dm); - mloop = dm->getLoopArray(dm); + mvert = mesh->mvert; + totvert = mesh->totvert; + looptri = BKE_mesh_runtime_looptri_ensure(mesh); + tottri = mesh->runtime.looptris.len; + mloop = mesh->mloop; /* sanity checking - potential case when no data will be present */ if ((totvert == 0) || (tottri == 0)) { @@ -347,11 +358,6 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob) shape = RB_shape_new_gimpact_mesh(mdata); } } - - /* cleanup temp data */ - if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) { - dm->release(dm); - } } else { printf("ERROR: cannot make Triangular Mesh collision shape for non-Mesh object\n"); @@ -514,30 +520,25 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) case RB_SHAPE_TRIMESH: { if (ob->type == OB_MESH) { - DerivedMesh *dm = rigidbody_get_mesh(ob); + Mesh *mesh = rigidbody_get_mesh(ob); MVert *mvert; const MLoopTri *lt = NULL; int totvert, tottri = 0; const MLoop *mloop = NULL; /* ensure mesh validity, then grab data */ - if (dm == NULL) + if (mesh == NULL) return; - mvert = dm->getVertArray(dm); - totvert = dm->getNumVerts(dm); - lt = dm->getLoopTriArray(dm); - tottri = dm->getNumLoopTri(dm); - mloop = dm->getLoopArray(dm); + mvert = mesh->mvert; + totvert = mesh->totvert; + lt = BKE_mesh_runtime_looptri_ensure(mesh); + tottri = mesh->runtime.looptris.len; + mloop = mesh->mloop; if (totvert > 0 && tottri > 0) { BKE_mesh_calc_volume(mvert, totvert, lt, tottri, mloop, &volume, NULL); } - - /* cleanup temp data */ - if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) { - dm->release(dm); - } } else { /* rough estimate from boundbox as fallback */ @@ -597,30 +598,25 @@ void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3]) case RB_SHAPE_TRIMESH: { if (ob->type == OB_MESH) { - DerivedMesh *dm = rigidbody_get_mesh(ob); + Mesh *mesh = rigidbody_get_mesh(ob); MVert *mvert; const MLoopTri *looptri; int totvert, tottri; const MLoop *mloop; /* ensure mesh validity, then grab data */ - if (dm == NULL) + if (mesh == NULL) return; - mvert = dm->getVertArray(dm); - totvert = dm->getNumVerts(dm); - looptri = dm->getLoopTriArray(dm); - tottri = dm->getNumLoopTri(dm); - mloop = dm->getLoopArray(dm); + mvert = mesh->mvert; + totvert = mesh->totvert; + looptri = BKE_mesh_runtime_looptri_ensure(mesh); + tottri = mesh->runtime.looptris.len; + mloop = mesh->mloop; if (totvert > 0 && tottri > 0) { BKE_mesh_calc_volume(mvert, totvert, looptri, tottri, mloop, NULL, r_center); } - - /* cleanup temp data */ - if (ob->rigidbody_object->mesh_source == RBO_MESH_BASE) { - dm->release(dm); - } } break; } @@ -700,7 +696,8 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool /* --------------------- */ -static void rigidbody_constraint_set_limits(RigidBodyCon *rbc, void (*set_limits)(rbConstraint*,int,float,float)) +static void rigidbody_constraint_set_limits( + RigidBodyCon *rbc, void (*set_limits)(rbConstraint *, int, float, float)) { if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) set_limits(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper); @@ -1020,8 +1017,8 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) rbo->lin_sleep_thresh = 0.4f; /* 0.4 is half of Bullet default */ rbo->ang_sleep_thresh = 0.5f; /* 0.5 is half of Bullet default */ - rbo->lin_damping = 0.04f; /* 0.04 is game engine default */ - rbo->ang_damping = 0.1f; /* 0.1 is game engine default */ + rbo->lin_damping = 0.04f; + rbo->ang_damping = 0.1f; rbo->col_groups = 1; @@ -1128,12 +1125,11 @@ RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) return scene->rigidbody_world; } -void BKE_rigidbody_remove_object(Scene *scene, Object *ob) +void BKE_rigidbody_remove_object(struct Main *bmain, Scene *scene, Object *ob) { RigidBodyWorld *rbw = scene->rigidbody_world; RigidBodyOb *rbo = ob->rigidbody_object; RigidBodyCon *rbc; - GroupObject *go; int i; if (rbw) { @@ -1153,8 +1149,8 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob) /* remove object from rigid body constraints */ if (rbw->constraints) { - for (go = rbw->constraints->gobject.first; go; go = go->next) { - Object *obt = go->ob; + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, obt) + { if (obt && obt->rigidbody_constraint) { rbc = obt->rigidbody_constraint; if (ELEM(ob, rbc->ob1, rbc->ob2)) { @@ -1162,7 +1158,9 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob) } } } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } + BKE_collection_object_remove(bmain, rbw->group, ob, false); } /* remove object's settings */ @@ -1195,20 +1193,26 @@ void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) /* Update object array and rigid body count so they're in sync with the rigid body group */ static void rigidbody_update_ob_array(RigidBodyWorld *rbw) { - GroupObject *go; - int i, n; - - n = BLI_listbase_count(&rbw->group->gobject); + int n = 0; + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object) + { + (void)object; + n++; + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; if (rbw->numbodies != n) { rbw->numbodies = n; rbw->objects = realloc(rbw->objects, sizeof(Object *) * rbw->numbodies); } - for (go = rbw->group->gobject.first, i = 0; go; go = go->next, i++) { - Object *ob = go->ob; - rbw->objects[i] = ob; + int i = 0; + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object) + { + rbw->objects[i] = object; + i++; } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw) @@ -1231,7 +1235,7 @@ static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw) rigidbody_update_ob_array(rbw); } -static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo) +static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo) { float loc[3]; float rot[4]; @@ -1242,10 +1246,10 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o return; if (rbo->shape == RB_SHAPE_TRIMESH && rbo->flag & RBO_FLAG_USE_DEFORM) { - DerivedMesh *dm = ob->derivedDeform; - if (dm) { - MVert *mvert = dm->getVertArray(dm); - int totvert = dm->getNumVerts(dm); + Mesh *mesh = ob->runtime.mesh_deform_eval; + if (mesh) { + MVert *mvert = mesh->mvert; + int totvert = mesh->totvert; BoundBox *bb = BKE_object_boundbox_get(ob); RB_shape_trimesh_update(rbo->physics_shape, (float *)mvert, totvert, sizeof(MVert), bb->vec[0], bb->vec[6]); @@ -1279,7 +1283,7 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o ListBase *effectors; /* get effectors present in the group specified by effector_weights */ - effectors = pdInitEffectors(scene, ob, NULL, effector_weights, true); + effectors = BKE_effectors_create(depsgraph, scene, ob, NULL, effector_weights); if (effectors) { float eff_force[3] = {0.0f, 0.0f, 0.0f}; float eff_loc[3], eff_vel[3]; @@ -1294,7 +1298,7 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o /* calculate net force of effectors, and apply to sim object * - we use 'central force' since apply force requires a "relative position" which we don't have... */ - pdDoEffectors(effectors, NULL, effector_weights, &epoint, eff_force, NULL); + BKE_effectors_apply(effectors, NULL, effector_weights, &epoint, eff_force, NULL); if (G.f & G_DEBUG) printf("\tapplying force (%f,%f,%f) to '%s'\n", eff_force[0], eff_force[1], eff_force[2], ob->id.name + 2); /* activate object in case it is deactivated */ @@ -1306,7 +1310,7 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o printf("\tno forces to apply to '%s'\n", ob->id.name + 2); /* cleanup */ - pdEndEffectors(&effectors); + BKE_effectors_free(effectors); } /* NOTE: passive objects don't need to be updated since they don't move */ @@ -1320,10 +1324,8 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o * * \param rebuild Rebuild entire simulation */ -static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool rebuild) +static void rigidbody_update_simulation(Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, bool rebuild) { - GroupObject *go; - /* update world */ if (rebuild) BKE_rigidbody_validate_sim_world(scene, rbw, true); @@ -1336,28 +1338,26 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool * Memory management needs redesign here, this is just a dirty workaround. */ if (rebuild && rbw->constraints) { - for (go = rbw->constraints->gobject.first; go; go = go->next) { - Object *ob = go->ob; - if (ob) { - RigidBodyCon *rbc = ob->rigidbody_constraint; - if (rbc && rbc->physics_constraint) { - RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); - RB_constraint_delete(rbc->physics_constraint); - rbc->physics_constraint = NULL; - } + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, ob) + { + RigidBodyCon *rbc = ob->rigidbody_constraint; + if (rbc && rbc->physics_constraint) { + RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + RB_constraint_delete(rbc->physics_constraint); + rbc->physics_constraint = NULL; } } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } /* update objects */ - for (go = rbw->group->gobject.first; go; go = go->next) { - Object *ob = go->ob; - - if (ob && ob->type == OB_MESH) { + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, ob) + { + if (ob->type == OB_MESH) { /* validate that we've got valid object set up here... */ RigidBodyOb *rbo = ob->rigidbody_object; /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ - BKE_object_where_is_calc(scene, ob); + BKE_object_where_is_calc(depsgraph, scene, ob); if (rbo == NULL) { /* Since this object is included in the sim group but doesn't have @@ -1391,65 +1391,64 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool } /* update simulation object... */ - rigidbody_update_sim_ob(scene, rbw, ob, rbo); + rigidbody_update_sim_ob(depsgraph, scene, rbw, ob, rbo); } } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; /* update constraints */ if (rbw->constraints == NULL) /* no constraints, move on */ return; - for (go = rbw->constraints->gobject.first; go; go = go->next) { - Object *ob = go->ob; - if (ob) { - /* validate that we've got valid object set up here... */ - RigidBodyCon *rbc = ob->rigidbody_constraint; - /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ - BKE_object_where_is_calc(scene, ob); + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, ob) + { + /* validate that we've got valid object set up here... */ + RigidBodyCon *rbc = ob->rigidbody_constraint; + /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ + BKE_object_where_is_calc(depsgraph, scene, ob); - if (rbc == NULL) { - /* Since this object is included in the group but doesn't have - * constraint settings (perhaps it was added manually), add! - */ - ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED); - rigidbody_validate_sim_constraint(rbw, ob, true); + if (rbc == NULL) { + /* Since this object is included in the group but doesn't have + * constraint settings (perhaps it was added manually), add! + */ + ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED); + rigidbody_validate_sim_constraint(rbw, ob, true); - rbc = ob->rigidbody_constraint; + rbc = ob->rigidbody_constraint; + } + else { + /* perform simulation data updates as tagged */ + if (rebuild) { + /* World has been rebuilt so rebuild constraint */ + rigidbody_validate_sim_constraint(rbw, ob, true); } - else { - /* perform simulation data updates as tagged */ - if (rebuild) { - /* World has been rebuilt so rebuild constraint */ - rigidbody_validate_sim_constraint(rbw, ob, true); - } - else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) { - rigidbody_validate_sim_constraint(rbw, ob, false); - } - rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE; + else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) { + rigidbody_validate_sim_constraint(rbw, ob, false); } + rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE; } } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } -static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw) +static void rigidbody_update_simulation_post_step(Depsgraph *depsgraph, RigidBodyWorld *rbw) { - GroupObject *go; - - for (go = rbw->group->gobject.first; go; go = go->next) { - Object *ob = go->ob; - - if (ob) { - RigidBodyOb *rbo = ob->rigidbody_object; - /* reset kinematic state for transformed objects */ - if (rbo && (ob->flag & SELECT) && (G.moving & G_TRANSFORM_OBJ)) { - RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); - RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); - /* deactivate passive objects so they don't interfere with deactivation of active objects */ - if (rbo->type == RBO_TYPE_PASSIVE) - RB_body_deactivate(rbo->physics_object); - } + ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); + + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, ob) + { + Base *base = BKE_view_layer_base_find(view_layer, ob); + RigidBodyOb *rbo = ob->rigidbody_object; + /* Reset kinematic state for transformed objects. */ + if (rbo && base && (base->flag & BASE_SELECTED) && (G.moving & G_TRANSFORM_OBJ)) { + RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); + RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); + /* Deactivate passive objects so they don't interfere with deactivation of active objects. */ + if (rbo->type == RBO_TYPE_PASSIVE) + RB_body_deactivate(rbo->physics_object); } } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime) @@ -1564,7 +1563,7 @@ void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) /* 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) +void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime) { RigidBodyWorld *rbw = scene->rigidbody_world; PointCache *cache; @@ -1576,14 +1575,22 @@ void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) cache = rbw->pointcache; /* 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_listbase_count(&rbw->group->gobject)) { + int n = 0; + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object) + { + (void)object; + n++; + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + + if (rbw->physics_world == NULL || rbw->numbodies != n) { cache->flag |= PTCACHE_OUTDATED; } 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); + rigidbody_update_simulation(depsgraph, scene, rbw, true); BKE_ptcache_validate(cache, (int)ctime); cache->last_exact = 0; cache->flag &= ~PTCACHE_REDO_NEEDED; @@ -1592,7 +1599,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) +void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime) { float timestep; RigidBodyWorld *rbw = scene->rigidbody_world; @@ -1630,21 +1637,21 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) } /* advance simulation, we can only step one frame forward */ - if (can_simulate) { + if (compare_ff_relative(ctime, rbw->ltime + 1, FLT_EPSILON, 64)) { /* write cache for first frame when on second frame */ if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) { BKE_ptcache_write(&pid, startframe); } /* update and validate simulation */ - rigidbody_update_simulation(scene, rbw, false); + rigidbody_update_simulation(depsgraph, scene, rbw, false); /* 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)); - rigidbody_update_simulation_post_step(rbw); + rigidbody_update_simulation_post_step(depsgraph, rbw); /* write cache for current frame */ BKE_ptcache_validate(cache, (int)ctime); @@ -1675,14 +1682,14 @@ void BKE_rigidbody_world_id_loop(struct RigidBodyWorld *rbw, RigidbodyWorldIDFun struct RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) { return NULL; } struct RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type) { return NULL; } struct RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) { return NULL; } -void BKE_rigidbody_remove_object(Scene *scene, Object *ob) {} +void BKE_rigidbody_remove_object(struct Main *bmain, Scene *scene, Object *ob) {} void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) {} void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) {} void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {} bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime) { return false; } void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {} -void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) {} -void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {} +void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime) {} +void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime) {} #if defined(__GNUC__) || defined(__clang__) # pragma GCC diagnostic pop @@ -1690,38 +1697,67 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {} #endif /* WITH_BULLET */ + +/* Copy the pointcache from the evaluated to the original scene. + * This allows the re-evaluation of the original scene to use the + * physics cache. + */ +static void rigidbody_copy_cache_to_orig(Scene *scene_eval) +{ + if ((scene_eval->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0) { + /* Scene is already an original, this function is a no-op. */ + return; + } + + Scene *scene_orig = (Scene *)DEG_get_original_id(&scene_eval->id); + RigidBodyWorld *rbw_orig = scene_orig->rigidbody_world; + RigidBodyWorld *rbw_eval = scene_eval->rigidbody_world; + + BKE_ptcache_free_list(&rbw_orig->ptcaches); + rbw_orig->pointcache = BKE_ptcache_copy_list(&rbw_orig->ptcaches, &rbw_eval->ptcaches, LIB_ID_COPY_CACHES); +} + + /* -------------------- */ /* Depsgraph evaluation */ -void BKE_rigidbody_rebuild_sim(EvaluationContext *UNUSED(eval_ctx), +void BKE_rigidbody_rebuild_sim(Depsgraph *depsgraph, Scene *scene) { - float ctime = BKE_scene_frame_get(scene); - DEG_debug_print_eval_time(__func__, scene->id.name, scene, ctime); + float ctime = DEG_get_ctime(depsgraph); + DEG_debug_print_eval_time(depsgraph, __func__, scene->id.name, scene, ctime); /* rebuild sim data (i.e. after resetting to start of timeline) */ if (BKE_scene_check_rigidbody_active(scene)) { - BKE_rigidbody_rebuild_world(scene, ctime); + BKE_rigidbody_rebuild_world(depsgraph, scene, ctime); } } -void BKE_rigidbody_eval_simulation(EvaluationContext *UNUSED(eval_ctx), +void BKE_rigidbody_eval_simulation(Depsgraph *depsgraph, Scene *scene) { - float ctime = BKE_scene_frame_get(scene); - DEG_debug_print_eval_time(__func__, scene->id.name, scene, ctime); + float ctime = DEG_get_ctime(depsgraph); + DEG_debug_print_eval_time(depsgraph, __func__, scene->id.name, scene, ctime); + /* evaluate rigidbody sim */ - if (BKE_scene_check_rigidbody_active(scene)) { - BKE_rigidbody_do_simulation(scene, ctime); + if (!BKE_scene_check_rigidbody_active(scene)) { + return; + } + BKE_rigidbody_do_simulation(depsgraph, scene, ctime); + + /* Make sure re-evaluation can use the cache from this simulation */ + if (!DEG_is_active(depsgraph)) { + return; } + rigidbody_copy_cache_to_orig(scene); } -void BKE_rigidbody_object_sync_transforms(EvaluationContext *UNUSED(eval_ctx), +void BKE_rigidbody_object_sync_transforms(Depsgraph *depsgraph, Scene *scene, Object *ob) { RigidBodyWorld *rbw = scene->rigidbody_world; - float ctime = BKE_scene_frame_get(scene); - DEG_debug_print_eval_time(__func__, ob->id.name, ob, ctime); + float ctime = DEG_get_ctime(depsgraph); + DEG_debug_print_eval_time(depsgraph, __func__, ob->id.name, ob, ctime); /* read values pushed into RBO from sim/cache... */ BKE_rigidbody_sync_transforms(rbw, ob, ctime); } |