Page MenuHome

Add compound shape for rigid body simulation
ClosedPublic

Authored by David Vogel (Dadido3) on Sep 14 2019, 7:43 PM.
Tags
None
Tokens
"Like" token, awarded by TakingFire."Love" token, awarded by MartinAckerl."Love" token, awarded by metabaronen."Love" token, awarded by MarkTwinkle."Love" token, awarded by duarteframos."Love" token, awarded by brilliant_ape."Love" token, awarded by theois.

Details

Summary

This patch adds a new entry to the shape selection dropdown. It also corrects wrong inertia calculation for convex hulls, that resulted in strange behavior for small objects.

Compound shape

With the help of this new shape it's possible to build concave shapes out of other primitive shapes. Because most primitive shapes are much more stable than the "Mesh" shape (Which was the only option to create concave collision shapes for now), it's possible to create create more complex simulations. Furthermore, it's possible to exploit the margin, and simplify collision meshes to speed up simulations.

To use this feature a rigid body object's shape has to be set to "Compound Parent". When this shape is used, all direct children shapes will be added to the compound shape of the parent automatically.

The weight and other settings will be ignored, only the shape and margin settings of children are used. Mass, center of mass and other physical properties are determined by the parent object.

The inertia of the compound will be approximated with the bounding box that encloses all child bounding boxes. By default, bullet adds the margin of the parent to that bounding box, best is to enable "Collision Margin" and set it to 0. (That's something that needs to be improved, similar to the other shapes, where it's not clear to the user, if the margin is embedded into the shape or added)

Compound example #1

About 700 concave objects with a length of 3cm each.

Compound example #2

Chains with compound shapes made out of several single edge convex hulls. Each of the 42 chain elements has a length of about 11cm. The simulation runs in realtime. (Remove the baked data, if you want to test the simulation speed)

Inertia fix for convex hulls

Depending on the settings, and if the margin was embedded into the convex hull, it was calculated wrongly.

In the worst case the margin was added to each side of the bounding box. And later when approximating inertia from the bounding box it was added again. Now the bounding box dimensions and inertia of a cube is equal, no matter if the "Cube" or "Convex Hull" is used as shape.

Diff Detail

Repository
rB Blender

Event Timeline

David Vogel (Dadido3) edited the summary of this revision. (Show Details)Sep 14 2019, 7:54 PM

As Blender 2.81 got released, and there is more focus on features for 2.82, i wanted to poke a bit. Is there anything missing, or anything to be improved, so that this diff can be merged?

@David Vogel (Dadido3) are the changes you made to the bullet library upstream changes or does this issue still exist with latest version of the bullet library?

The inertia fix is my own. I wanted to create a merge request for it in the official bullet repository, but i haven't done so yet. It's not important for the compound bodies to work, so i could remove it from here and create a new patch if needed.

The inertia fix is my own. I wanted to create a merge request for it in the official bullet repository, but i haven't done so yet. It's not important for the compound bodies to work, so i could remove it from here and create a new patch if needed.

No need to remove it :)

Just create a .patch file with your changes and put it in the bullet2/patches folder. This way we can easily keep track of the changes we have done that is not upstream (or if we backported fixes).

Try getting it up streamed too of course :)

@Brecht Van Lommel (brecht) @Campbell Barton (campbellbarton) is there anything holding this up or can I allocate some time to review this and get this approved for merging?

I added a patch file for the margin fix in the ineratia calculation.

I haven't looked at this in detail, but it seems fine in general and can be reviewed.

Which properties are used on the children seems non-obvious. It should be possible to check for a compound parent in the UI code and hide any unused properties and make it clear this is part of a compound shape.

It's also not clear to me if such a child can be dynamic, and if compound parents can be used recursively so you can have grandchildren included.

@David Vogel (Dadido3) sorry for taking some time to get back to this.
Do you have any answers to Brecht's statements?

If I just look at the UI side of things, then I also think that some more polish is needed.

For example when you choose to use the compound collider shape, it should warn you in some way if it doesn't have any children that is can use.
And as Brecht stated, the children should probably have something that simplifies the settings shown for them.

I should also note that I needed to update blender/makesdna/DNA_rigidbody_types.h to get this to apply to master. But it is an easy change.
We now explicitly have numbers assigned to the enums.
So RB_SHAPE_TRIMESH = 6 and RB_SHAPE_COMPOUND = 7

source/blender/blenkernel/intern/rigidbody.c
557

I don't think we have a more elegant way to get object children.

If I just look at the UI side of things, then I also think that some more polish is needed.

For example when you choose to use the compound collider shape, it should warn you in some way if it doesn't have any children that is can use.
And as Brecht stated, the children should probably have something that simplifies the settings shown for them.

I agree with that. Even though i haven't done much with UI in blender yet, i'll take a look. My plan is to hide any rigid body related settings when the parent is a rigid body object, but show the shape related settings when the parent's shape is a compound.
And when there is a parent, but it's not a RBO, all the settings will be available like before. I tested the latter case, and the physics seems to be correct even when the parent is moved or rotated.

I should also note that I needed to update blender/makesdna/DNA_rigidbody_types.h to get this to apply to master. But it is an easy change.
We now explicitly have numbers assigned to the enums.
So RB_SHAPE_TRIMESH = 6 and RB_SHAPE_COMPOUND = 7

No problem, i'll add numbers to all these enums. Also i'll remove the todo, as it is the best way to get the childs for now.

I removed the todo entry, and also added an explicit enum number to RB_SHAPE_COMPOUND.

Also, i added messages pointing out what's wrong with a compound shape setup and removed not needed elements. The cases are:

  • Selected object has a compound shape, but there are no rigid body children.
  • Selected rigid body object is a child of a non compound RBO. This message will only appear if the parent is a RBO, so it's still possible to have normal (non RBO) objects as parent for whatever reason, which in my tests worked fine.
  • Selected object is a child of a compound RBO, but the child also has a compound shape. Compound shapes inside compound shapes are not allowed. Ideally the "Compound Parent" entry of the drop down list should be omitted/disabled, but i don't know how to achieve that.
  • Selected object is a child of a compound RBO, everything is set up correctly.

Much better!

Just a few other things:

  1. When applying the patch, I get a lot of whitespace warings (trailing whitespace, mixed tab and spaces etc).

I think you should be able to get rid of these by just running clang-format. (make format if you are on mac/linux)

  1. Did you try to upstream you patch to bullet? If so, is it already merged?
  1. The example files reports a lot of cyclic dependencies. However it seems to work fine regardless. (Tested both when just playing back in viewport and when rendering out the animation)

I guess the dep cycle detector doesn't like that the child uses data from the parent and the parent uses data from the child.
But it seems fine in this case, so perhaps we can just suppress these. @Brecht Van Lommel (brecht) @Campbell Barton (campbellbarton) ?

Cyclic dependency warnings should not be suppressed, they can cause problems. The graph should be built in such a way that there are no cyclic dependencies and there is a well defined execution order.

  1. When applying the patch, I get a lot of whitespace warings (trailing whitespace, mixed tab and spaces etc).

I think you should be able to get rid of these by just running clang-format. (make format if you are on mac/linux)

I never mixed tabs and spaces, and the source got formatted with clang. At least the blender source code, the bullet library is excluded from any formatting, and it's a mess. (Just as a side note, i have replaced the whole bullet lib with the newest version, it comes with its own clang formatting rules. Also it's faster and the simulation is more stable. I'll probably create a new diff for that soon)

  1. Did you try to upstream you patch to bullet? If so, is it already merged?

I have created a pull request, but it's not merged yet.

I never mixed tabs and spaces, and the source got formatted with clang. That is the blender source code, the bullet library is excluded from any formatting, and it's a mess.

Ah sorry, my bad. I didn't notice that it was from the patch file ><

Regarding the dependency cycles, they also happen without this patch (tested in blender 2.82). So in this sense it's not a regression, but i'll take a look to prevent them.

I have tried to prevent the dependency cycle, but haven't got it working. Everything i tried somehow prevented the objects from updating their transformation correctly.

Somehow the chain needs to be broken where a compound child's transformation is updated from the simulation. As compound child transformations should not depend on the simulation, but on the normal parent child constraint (As if the child didn't had a rigid body). I just have no clue how to to achieve this, as i don't know enough about the dependency graph and how it works in detail.

Here is the output:

Dependency cycle detected:
  OBCube.001/Transform Component/TRANSFORM_SIMULATION_INIT() depends on
  OBCube.001/Transform Component/TRANSFORM_EVAL() via 'Transform Eval -> Simulation Init'
  OBCube.001/Transform Component/TRANSFORM_PARENT() via 'Eval'
  OBCube.001/Transform Component/TRANSFORM_LOCAL() via 'ObLocal -> ObParent'
  OBCube.001/Transform Component/TRANSFORM_INIT() via 'Transform Init'
  OBCube/Transform Component/TRANSFORM_FINAL() via 'Parent'
  OBCube/Transform Component/RIGIDBODY_TRANSFORM_COPY() via 'Rigidbody Sync -> Transform Final'
  SCScene/Transform Component/RIGIDBODY_SIM() via 'Rigidbody Sim Eval -> RBO Sync'
  OBCube.001/Transform Component/TRANSFORM_SIMULATION_INIT() via 'Object Transform -> Rigidbody Sim Eval'
Dependency cycle detected:
  OBCube.001/PointCache Component/POINT_CACHE_RESET() depends on
  OBCube.001/Transform Component/TRANSFORM_EVAL() via 'Transform Simulation -> Point Cache'
  OBCube.001/Transform Component/TRANSFORM_PARENT() via 'Eval'
  OBCube.001/Transform Component/TRANSFORM_LOCAL() via 'ObLocal -> ObParent'
  OBCube.001/Transform Component/TRANSFORM_INIT() via 'Transform Init'
  OBCube/Transform Component/TRANSFORM_FINAL() via 'Parent'
  OBCube/Transform Component/RIGIDBODY_TRANSFORM_COPY() via 'Rigidbody Sync -> Transform Final'
  SCScene/Transform Component/RIGIDBODY_SIM() via 'Rigidbody Sim Eval -> RBO Sync'
  OBCube.001/Transform Component/TRANSFORM_SIMULATION_INIT() via 'Object Transform -> Rigidbody Sim Eval'
  OBCube.001/PointCache Component/POINT_CACHE_RESET() via 'Point Cache -> Rigid Body'
Detected 2 dependency cycles

It happens right after the RBO (OBCube.001) is made child of another RBO (OBCube). It doesn't happen when objects are moved around and the cache gets invalidated.

@Sebastian Parborg (zeddb), please give some minimal context so people who are not familiar with the area do not need to spend a long time trying to understand what is the core of the issue here.

From quick look, T58044 and D6834#166171 seems relevant to your poke here.

I think I have fixed the deps cycle.
No warnings are printed anymore and the simulation seems to be working fine.

diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index d0e8246caa9..6d4fed7047e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -1698,6 +1698,16 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
       if (object->type != OB_MESH) {
         continue;
       }
+
+      if (object->parent != NULL && object->parent->rigidbody_object != NULL &&
+          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. */

@Sergey Sharybin (sergey) is this the correct way to do things?

Did you verify the relations makes sense using graphviz debug output?

This revision was not accepted when it landed; it landed in state Needs Review.Jul 30 2020, 6:54 PM
This revision was automatically updated to reflect the committed changes.

As a reminder, don't forgot to document this in the 2.91 release notes.

As a reminder, don't forgot to document this in the 2.91 release notes.

Already done. I'll update the wiki tomorrow as well!

Thanks to everyone for their time. Also thanks to @Sebastian Parborg (zeddb) for reviewing and fixing the dependency cycle.