[Bf-blender-cvs] [98a0bcd4252] blender2.8: Prevent copying too much in the Rigid Body simulation

Sybren A. Stüvel noreply at git.blender.org
Thu Jun 28 14:21:37 CEST 2018


Commit: 98a0bcd4252e952fa5438e9d1b69b0204f8a8746
Author: Sybren A. Stüvel
Date:   Wed Jun 27 17:08:58 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB98a0bcd4252e952fa5438e9d1b69b0204f8a8746

Prevent copying too much in the Rigid Body simulation

To prevent the pointcache from being copied-on-write too (and requiring
copying back), the cache is now shared between the original and
evaluated scenes. Reading from the cache is always allowed; running the
sim and writing to the cache is only allowed when the depsgraph is
active.

Some pointers have moved from RigidBodyWorld (RBO) to
RigidBodyWorldShared (RBOS). writefile.c copies some pointers back from
RBOS to RBO so that the file can still be opened on older Blenders
without crashing on a segfault.

The RigidBodyWorldShared struct is written to the blend file, because it
refers to the PointCache ID block.

The RigidObjectShared struct is runtime-only, and thus not saved to the
blend file.

An RNA getter-function is used to hide the new 'shared' pointer. As a
result the Python API hasn't changed.

Reviewed by: campbellbarton

Differential Revision: https://developer.blender.org/D3508

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

M	source/blender/blenkernel/BKE_rigidbody.h
M	source/blender/blenkernel/intern/object.c
M	source/blender/blenkernel/intern/pointcache.c
M	source/blender/blenkernel/intern/rigidbody.c
M	source/blender/blenkernel/intern/scene.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/blenloader/intern/versioning_280.c
M	source/blender/blenloader/intern/writefile.c
M	source/blender/editors/physics/rigidbody_world.c
M	source/blender/makesdna/DNA_rigidbody_types.h
M	source/blender/makesrna/intern/rna_rigidbody.c

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

diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index b7d27cc7101..1fa8106d63b 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -44,8 +44,8 @@ struct Object;
 /* -------------- */
 /* Memory Management */
 
-void BKE_rigidbody_free_world(struct RigidBodyWorld *rbw);
-void BKE_rigidbody_free_object(struct Object *ob);
+void BKE_rigidbody_free_world(struct Scene *scene);
+void BKE_rigidbody_free_object(struct Object *ob, struct RigidBodyWorld *rbw);
 void BKE_rigidbody_free_constraint(struct Object *ob);
 
 /* ...... */
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 210e6f096b8..8295fccc810 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -449,7 +449,7 @@ void BKE_object_free(Object *ob)
 	BKE_constraints_free_ex(&ob->constraints, false);
 
 	free_partdeflect(ob->pd);
-	BKE_rigidbody_free_object(ob);
+	BKE_rigidbody_free_object(ob, NULL);
 	BKE_rigidbody_free_constraint(ob);
 
 	if (ob->soft) {
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 3e8e6a69dd8..a8c6091124a 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1295,8 +1295,8 @@ static int  ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUS
 
 		if (rbo->type == RBO_TYPE_ACTIVE) {
 #ifdef WITH_BULLET
-			RB_body_get_position(rbo->physics_object, rbo->pos);
-			RB_body_get_orientation(rbo->physics_object, rbo->orn);
+			RB_body_get_position(rbo->shared->physics_object, rbo->pos);
+			RB_body_get_orientation(rbo->shared->physics_object, rbo->orn);
 #endif
 			PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, rbo->pos);
 			PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, rbo->orn);
@@ -1619,9 +1619,9 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
 	pid->ob= ob;
 	pid->calldata= rbw;
 	pid->type= PTCACHE_TYPE_RIGIDBODY;
-	pid->cache= rbw->pointcache;
-	pid->cache_ptr= &rbw->pointcache;
-	pid->ptcaches= &rbw->ptcaches;
+	pid->cache= rbw->shared->pointcache;
+	pid->cache_ptr= &rbw->shared->pointcache;
+	pid->ptcaches= &rbw->shared->ptcaches;
 	pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint;
 	pid->error					= ptcache_rigidbody_error;
 
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 03fa4ec3cf2..91dd1e3dbaa 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -76,8 +76,10 @@
 
 /* Freeing Methods --------------------- */
 
-#ifndef WITH_BULLET
+#ifdef WITH_BULLET
+static void rigidbody_update_ob_array(RigidBodyWorld *rbw);
 
+#else
 static void RB_dworld_remove_constraint(void *UNUSED(world), void *UNUSED(con)) {}
 static void RB_dworld_remove_body(void *UNUSED(world), void *UNUSED(body)) {}
 static void RB_dworld_delete(void *UNUSED(world)) {}
@@ -88,13 +90,17 @@ static void RB_constraint_delete(void *UNUSED(con)) {}
 #endif
 
 /* Free rigidbody world */
-void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
+void BKE_rigidbody_free_world(Scene *scene)
 {
+	bool is_orig = (scene->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0;
+	RigidBodyWorld *rbw = scene->rigidbody_world;
+	scene->rigidbody_world = NULL;
+
 	/* sanity check */
 	if (!rbw)
 		return;
 
-	if (rbw->physics_world) {
+	if (is_orig && rbw->shared->physics_world) {
 		/* free physics references, we assume that all physics objects in will have been added to the world */
 		if (rbw->constraints) {
 			FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, object)
@@ -102,7 +108,7 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
 				if (object->rigidbody_constraint) {
 					RigidBodyCon *rbc = object->rigidbody_constraint;
 					if (rbc->physics_constraint) {
-						RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
+						RB_dworld_remove_constraint(rbw->shared->physics_world, rbc->physics_constraint);
 					}
 				}
 			}
@@ -112,24 +118,23 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
 		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);
-					}
-				}
+				BKE_rigidbody_free_object(object, rbw);
 			}
 			FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
 		}
 		/* free dynamics world */
-		RB_dworld_delete(rbw->physics_world);
+		RB_dworld_delete(rbw->shared->physics_world);
 	}
 	if (rbw->objects)
 		free(rbw->objects);
 
-	/* free cache */
-	BKE_ptcache_free_list(&(rbw->ptcaches));
-	rbw->pointcache = NULL;
+	if (is_orig) {
+		/* free cache */
+		BKE_ptcache_free_list(&(rbw->shared->ptcaches));
+		rbw->shared->pointcache = NULL;
+
+		MEM_freeN(rbw->shared);
+	}
 
 	/* free effector weights */
 	if (rbw->effector_weights)
@@ -140,8 +145,9 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
 }
 
 /* Free RigidBody settings and sim instances */
-void BKE_rigidbody_free_object(Object *ob)
+void BKE_rigidbody_free_object(Object *ob, RigidBodyWorld *rbw)
 {
+	bool is_orig = (ob->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0;
 	RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL;
 
 	/* sanity check */
@@ -149,14 +155,26 @@ void BKE_rigidbody_free_object(Object *ob)
 		return;
 
 	/* free physics references */
-	if (rbo->physics_object) {
-		RB_body_delete(rbo->physics_object);
-		rbo->physics_object = NULL;
-	}
+	if (is_orig) {
+		if (rbo->shared->physics_object) {
+			BLI_assert(rbw);
+			if (rbw) {
+				/* We can only remove the body from the world if the world is known.
+				 * The world is generally only unknown if it's an evaluated copy of
+				 * an object that's being freed, in which case this code isn't run anyway. */
+				RB_dworld_remove_body(rbw->shared->physics_world, rbo->shared->physics_object);
+			}
+
+			RB_body_delete(rbo->shared->physics_object);
+			rbo->shared->physics_object = NULL;
+		}
+
+		if (rbo->shared->physics_shape) {
+			RB_shape_delete(rbo->shared->physics_shape);
+			rbo->shared->physics_shape = NULL;
+		}
 
-	if (rbo->physics_shape) {
-		RB_shape_delete(rbo->physics_shape);
-		rbo->physics_shape = NULL;
+		MEM_freeN(rbo->shared);
 	}
 
 	/* free data itself */
@@ -193,7 +211,7 @@ void BKE_rigidbody_free_constraint(Object *ob)
  * be added to relevant groups later...
  */
 
-RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int UNUSED(flag))
+RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int flag)
 {
 	RigidBodyOb *rboN = NULL;
 
@@ -201,12 +219,13 @@ RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int UNUSED(flag))
 		/* just duplicate the whole struct first (to catch all the settings) */
 		rboN = MEM_dupallocN(ob->rigidbody_object);
 
+		if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
+			/* This is a regular copy, and not a CoW copy for depsgraph evaluation */
+			rboN->shared = MEM_callocN(sizeof(*rboN->shared), "RigidBodyOb_Shared");
+		}
+
 		/* tag object as needing to be verified */
 		rboN->flag |= RBO_FLAG_NEEDS_VALIDATE;
-
-		/* clear out all the fields which need to be revalidated later */
-		rboN->physics_object = NULL;
-		rboN->physics_shape = NULL;
 	}
 
 	/* return new copy of settings */
@@ -387,7 +406,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
 		return;
 
 	/* don't create a new shape if we already have one and don't want to rebuild it */
-	if (rbo->physics_shape && !rebuild)
+	if (rbo->shared->physics_shape && !rebuild)
 		return;
 
 	/* if automatically determining dimensions, use the Object's boundbox
@@ -451,15 +470,16 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
 			break;
 	}
 	/* use box shape if we can't fall back to old shape */
-	if (new_shape == NULL && rbo->physics_shape == NULL) {
+	if (new_shape == NULL && rbo->shared->physics_shape == NULL) {
 		new_shape = RB_shape_new_box(size[0], size[1], size[2]);
 	}
 	/* assign new collision shape if creation was successful */
 	if (new_shape) {
-		if (rbo->physics_shape)
-			RB_shape_delete(rbo->physics_shape);
-		rbo->physics_shape = new_shape;
-		RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo));
+		if (rbo->shared->physics_shape) {
+			RB_shape_delete(rbo->shared->physics_shape);
+		}
+		rbo->shared->physics_shape = new_shape;
+		RB_shape_set_margin(rbo->shared->physics_shape, RBO_GET_MARGIN(rbo));
 	}
 }
 
@@ -650,48 +670,48 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool
 
 	/* make sure collision shape exists */
 	/* FIXME we shouldn't always have to rebuild collision shapes when rebuilding objects, but it's needed for constraints to update correctly */
-	if (rbo->physics_shape == NULL || rebuild)
+	if (rbo->shared->physics_shape == NULL || rebuild)
 		rigidbody_validate_sim_shape(ob, true);
 
-	if (rbo->physics_object && rebuild == false) {
-		RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
+	if (rbo->shared->physics_object) {
+		RB_dworld_remove_body(rbw->shared->physics_world, rbo->shared->physics_object);
 	}
-	if (!rbo->physics_object || rebuild) {
+	if (!rbo->shared->physics_object || rebuild) {
 		/* remove rigid body if it already exists before creating a new one */
-		if (rbo->physics_object) {
-			RB_body_delete(rbo->physics_object);
+		if (rbo->shared->physics_object) {
+			RB_body_delete(rbo->shared->physics_object);
 		}
 
 		mat4_to_loc_quat(loc, rot, ob->obmat);
 
-		rbo->physics_object = RB_body_new(rbo->physics_shape, loc, rot);
+		rbo->shared->physics_object = RB_body_new(rbo->shared->physics_shape, loc, rot);
 
-		RB_body_set_friction(rbo->physics_object, rbo->friction);
-		RB_body_set_restitution(rbo->physics_object, rbo->restitution);
+		RB_body_set_friction(rbo->shared->physics_object, rbo->friction);
+		RB_body_set_restitution(rbo->shared->physics_object, rbo->restitution);
 
-		RB_body_set_damping(rbo->physics_object, rbo->lin_damping, rbo->ang_damping);
-		RB_body_set_sleep_thresh

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list