Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/rigidbody.c')
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c374
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);
}