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
path: root/source
diff options
context:
space:
mode:
authorDavid Vogel <Dadido3>2020-07-30 19:35:34 +0300
committerSebastian Parborg <darkdefende@gmail.com>2020-07-30 19:53:35 +0300
commit820ca419e098f1ac90b499180a3206dd44692ba8 (patch)
treea2b7288ca2a8a9124b4977ae0a03cadd41282ecd /source
parentd3944940f9862386cfad692b9d338b670584908c (diff)
Add compound shape for rigid body simulation
This patch adds a new compound shape entry to the shape selection dropdown. It also corrects wrong inertia calculation for convex hulls, that resulted in strange behavior for small objects. The compound shape take the collision shapes from its object children and combines them. This makes it possible to create concave shapes from primitive shapes. Using this instead of the mesh collision shape is often many times faster. Reviewed By: Sergey, Sebastian Parborg Differential Revision: http://developer.blender.org/D5797
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/pointcache.c2
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c123
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc10
-rw-r--r--source/blender/makesdna/DNA_rigidbody_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_rigidbody.c5
5 files changed, 116 insertions, 26 deletions
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 4b09f7542c7..c2c5b42dbb0 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1511,7 +1511,7 @@ static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSE
if (ob && ob->rigidbody_object) {
RigidBodyOb *rbo = ob->rigidbody_object;
- if (rbo->type == RBO_TYPE_ACTIVE) {
+ if (rbo->type == RBO_TYPE_ACTIVE && rbo->shared->physics_object != NULL) {
#ifdef WITH_BULLET
RB_body_get_position(rbo->shared->physics_object, rbo->pos);
RB_body_get_orientation(rbo->shared->physics_object, rbo->orn);
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 4752782eaeb..481a643229e 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -466,10 +466,10 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
return shape;
}
-/* Create new physics sim collision shape for object and store it,
- * or remove the existing one first and replace...
+/* Helper function to create physics collision shape for object.
+ * Returns a new collision shape.
*/
-static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
+static rbCollisionShape *rigidbody_validate_sim_shape_helper(RigidBodyWorld *rbw, Object *ob)
{
RigidBodyOb *rbo = ob->rigidbody_object;
rbCollisionShape *new_shape = NULL;
@@ -484,12 +484,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
/* sanity check */
if (rbo == NULL) {
- return;
- }
-
- /* don't create a new shape if we already have one and don't want to rebuild it */
- if (rbo->shared->physics_shape && !rebuild) {
- return;
+ return NULL;
}
/* if automatically determining dimensions, use the Object's boundbox
@@ -539,7 +534,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
break;
case RB_SHAPE_CONVEXH:
- /* try to emged collision margin */
+ /* try to embed collision margin */
has_volume = (MIN3(size[0], size[1], size[2]) > 0.0f);
if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && has_volume) {
@@ -555,18 +550,69 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
case RB_SHAPE_TRIMESH:
new_shape = rigidbody_get_shape_trimesh_from_mesh(ob);
break;
+ case RB_SHAPE_COMPOUND:
+ new_shape = RB_shape_new_compound(radius);
+ rbCollisionShape *childShape = NULL;
+ float loc[3], rot[4];
+ float mat[4][4];
+ /* Add children to the compound shape */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, childObject) {
+ if (childObject->parent == ob) {
+ childShape = rigidbody_validate_sim_shape_helper(rbw, childObject);
+ if (childShape) {
+ BKE_object_matrix_local_get(childObject, mat);
+ mat4_to_loc_quat(loc, rot, mat);
+ RB_compound_add_child_shape(new_shape, childShape, loc, rot);
+ }
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+
+ break;
}
- /* use box shape if we can't fall back to old shape */
- if (new_shape == NULL && rbo->shared->physics_shape == NULL) {
+ /* use box shape if it failed to create new shape */
+ if (new_shape == NULL) {
new_shape = RB_shape_new_box(size[0], size[1], size[2]);
}
+ if (new_shape) {
+ RB_shape_set_margin(new_shape, RBO_GET_MARGIN(rbo));
+ }
+
+ return new_shape;
+}
+
+/* Create new physics sim collision shape for object and store it,
+ * or remove the existing one first and replace...
+ */
+static void rigidbody_validate_sim_shape(RigidBodyWorld *rbw, Object *ob, bool rebuild)
+{
+ RigidBodyOb *rbo = ob->rigidbody_object;
+ rbCollisionShape *new_shape = NULL;
+
+ /* sanity check */
+ if (rbo == NULL) {
+ return;
+ }
+
+ /* don't create a new shape if we already have one and don't want to rebuild it */
+ if (rbo->shared->physics_shape && !rebuild) {
+ return;
+ }
+
+ /* Also don't create a shape if this object is parent of a compound shape */
+ if (ob->parent != NULL && ob->parent->rigidbody_object != NULL &&
+ ob->parent->rigidbody_object->shape == RB_SHAPE_COMPOUND) {
+ return;
+ }
+
+ new_shape = rigidbody_validate_sim_shape_helper(rbw, ob);
+
/* assign new collision shape if creation was successful */
if (new_shape) {
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));
}
}
@@ -750,7 +796,7 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool
/* FIXME we shouldn't always have to rebuild collision shapes when rebuilding objects,
* but it's needed for constraints to update correctly. */
if (rbo->shared->physics_shape == NULL || rebuild) {
- rigidbody_validate_sim_shape(ob, true);
+ rigidbody_validate_sim_shape(rbw, ob, true);
}
if (rbo->shared->physics_object) {
@@ -760,6 +806,12 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool
/* remove rigid body if it already exists before creating a new one */
if (rbo->shared->physics_object) {
RB_body_delete(rbo->shared->physics_object);
+ rbo->shared->physics_object = NULL;
+ }
+ /* Don't create rigid body object if the parent is a compound shape */
+ if (ob->parent != NULL && ob->parent->rigidbody_object != NULL &&
+ ob->parent->rigidbody_object->shape == RB_SHAPE_COMPOUND) {
+ return;
}
mat4_to_loc_quat(loc, rot, ob->obmat);
@@ -793,7 +845,7 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool
rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
}
- if (rbw && rbw->shared->physics_world) {
+ if (rbw && rbw->shared->physics_world && rbo->shared->physics_object) {
RB_dworld_add_body(rbw->shared->physics_world, rbo->shared->physics_object, rbo->col_groups);
}
}
@@ -1179,9 +1231,12 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
* - object must exist
* - cannot add rigid body if it already exists
*/
- if (ob == NULL || (ob->rigidbody_object != NULL)) {
+ if (ob == NULL) {
return NULL;
}
+ if (ob->rigidbody_object != NULL) {
+ return ob->rigidbody_object;
+ }
/* create new settings data, and link it up */
rbo = MEM_callocN(sizeof(RigidBodyOb), "RigidBodyOb");
@@ -1530,7 +1585,11 @@ static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
int n = 0;
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, object) {
(void)object;
- n++;
+ /* Ignore if this object is the direct child of an object with a compound shape */
+ if (object->parent == NULL || object->parent->rigidbody_object == NULL ||
+ object->parent->rigidbody_object->shape != RB_SHAPE_COMPOUND) {
+ n++;
+ }
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
@@ -1541,8 +1600,12 @@ static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
int i = 0;
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, object) {
- rbw->objects[i] = object;
- i++;
+ /* Ignore if this object is the direct child of an object with a compound shape */
+ if (object->parent == NULL || object->parent->rigidbody_object == NULL ||
+ object->parent->rigidbody_object->shape != RB_SHAPE_COMPOUND) {
+ rbw->objects[i] = object;
+ i++;
+ }
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
@@ -1754,11 +1817,13 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph,
/* refresh shape... */
if (rbo->flag & RBO_FLAG_NEEDS_RESHAPE) {
/* mesh/shape data changed, so force shape refresh */
- rigidbody_validate_sim_shape(ob, true);
+ rigidbody_validate_sim_shape(rbw, ob, true);
/* now tell RB sim about it */
/* XXX: we assume that this can only get applied for active/passive shapes
* that will be included as rigidbodies. */
- RB_body_set_collision_shape(rbo->shared->physics_object, rbo->shared->physics_shape);
+ if (rbo->shared->physics_object != NULL && rbo->shared->physics_shape != NULL) {
+ RB_body_set_collision_shape(rbo->shared->physics_object, rbo->shared->physics_shape);
+ }
}
}
rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE);
@@ -1817,7 +1882,8 @@ static void rigidbody_update_simulation_post_step(Depsgraph *depsgraph, RigidBod
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)) {
+ if (rbo && base && (base->flag & BASE_SELECTED) && (G.moving & G_TRANSFORM_OBJ) &&
+ rbo->shared->physics_object) {
RB_body_set_kinematic_state(rbo->shared->physics_object,
rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
RB_body_set_mass(rbo->shared->physics_object, RBO_GET_MASS(rbo));
@@ -1840,8 +1906,13 @@ void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
{
RigidBodyOb *rbo = ob->rigidbody_object;
+ /* True if the shape of this object's parent is of type compound */
+ bool obCompoundParent = (ob->parent != NULL && ob->parent->rigidbody_object != NULL &&
+ ob->parent->rigidbody_object->shape == RB_SHAPE_COMPOUND);
+
/* keep original transform for kinematic and passive objects */
- if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE) {
+ if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE ||
+ obCompoundParent) {
return;
}
@@ -1963,7 +2034,11 @@ void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime
int n = 0;
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, object) {
(void)object;
- n++;
+ /* Ignore if this object is the direct child of an object with a compound shape */
+ if (object->parent == NULL || object->parent->rigidbody_object == NULL ||
+ object->parent->rigidbody_object->shape != RB_SHAPE_COMPOUND) {
+ n++;
+ }
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 8932d875776..5ae71dd1792 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -1704,6 +1704,16 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
if (object->rigidbody_object->type == RBO_TYPE_PASSIVE) {
continue;
}
+
+ if (object->parent != nullptr && object->parent->rigidbody_object != nullptr &&
+ object->parent->rigidbody_object->shape == RB_SHAPE_COMPOUND) {
+ /* If we are a child of a compound shape object, the transforms and sim evaluation will be
+ * handled by the parent compound shape object. Do not add any evaluation triggers
+ * for the child objects.
+ */
+ continue;
+ }
+
OperationKey rb_transform_copy_key(
&object->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY);
/* Rigid body synchronization depends on the actual simulation. */
diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h
index 7ad50dc04de..facf4c6636f 100644
--- a/source/blender/makesdna/DNA_rigidbody_types.h
+++ b/source/blender/makesdna/DNA_rigidbody_types.h
@@ -214,7 +214,7 @@ typedef enum eRigidBody_Shape {
RB_SHAPE_TRIMESH = 6,
/* concave mesh approximated using primitives */
- // RB_SHAPE_COMPOUND,
+ RB_SHAPE_COMPOUND = 7,
} eRigidBody_Shape;
typedef enum eRigidBody_MeshSource {
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
index 325c4e3caa9..450d148d8a3 100644
--- a/source/blender/makesrna/intern/rna_rigidbody.c
+++ b/source/blender/makesrna/intern/rna_rigidbody.c
@@ -75,6 +75,11 @@ const EnumPropertyItem rna_enum_rigidbody_object_shape_items[] = {
"Mesh",
"Mesh consisting of triangles only, allowing for more detailed interactions than convex "
"hulls"},
+ {RB_SHAPE_COMPOUND,
+ "COMPOUND",
+ ICON_MESH_DATA,
+ "Compound Parent",
+ "Combines all of its direct rigid body children into one rigid object."},
{0, NULL, 0, NULL, NULL},
};