Here is an outline of the basic steps for building a rigid body simulation using the
Bullet Physics nodes in MCG.
Create a World
A Bullet Physics system is known as a "world". The world is what needs to be cached and updated during the simulation, and it should contain all of the rigid bodies that participate in the simulation together with their constraints and relations.
Before you can add rigid bodies to the world, you must create the world itself. It requires an initial time, which is typically the start time of your scene. You can also set the world's gravity.
Add a Dynamic Object
Dynamic objects are rigid bodies whose transforms get updated by the Bullet Physics engine, as opposed to other objects that serve only as potential collision objects.
- For an animation controller, you can only output one transform so you can have only one dynamic object.
- In other situations, you can have multiple dynamic objects. For example, you could create a geometry by distributing transforms within a volume and using them to instantiate multiple copies of a mesh. In such a case, you can use an
Aggregate operator with an array of transforms to add multiple rigid bodies with the same dynamic properties to the world.
Adding a dynamic object to the world involves the following basic steps:
- Set up the rigid body's dynamic properties.
For a dynamic object, the mass must be a positive, non-zero value.
- Use the dynamic properties to create a rigid body.
- For a dynamic object, you must set the isKinematic port to False.
- The convexHull is the mesh used for collision detection. It should be watertight, and if it has concavities then only its convex hull is used. Note that it does not need to be the same mesh that is used for the object rendered shape — for example, you might want to use a simplified mesh for faster collision computations, or a smaller mesh to avoid explosive forces caused by interpenetrations with closely packed objects.
- Optionally, you can set the object's initial velocity, as well as create constraints.
- Add the dynamic object to the world.
Later you will need a dynamic object's index to get its transform value back from the world, so keep track of the number of dynamic objects added to the world and their order. The first object added to the world has index 0, the second has index 1, and so on.
Add Collision Objects
The Bullet Physics engine uses collision objects for collisions of dynamic objects, but it will not update their transforms. They are typically used for things like floors and walls, but can also be animated.
Adding collision objects is similar to adding dynamic objects, but simpler:
- isKinematic must be true. This does not necessarily mean that the collision object is animated, but if it is, your graph is responsible for updating its transforms before stepping the world forward.
- Mass is ignored (always zero).
- Velocity and constraints do not apply.
Again, you can use arrays to add multiple collision objects.
Create a World Cache
After you have added the last rigid body, use the resulting function to set the initial state of the world's cache.
Update the World Cache
Now, you need to define how to update the cache on each frame. There may be two steps to this:
- If the collision objects are animated, update the world with their new transforms.
- Step the world forward in time.
Update the Collision Object Transforms
Updating the transforms of the collision objects involves getting their current transform matrices from the INodes in the scene, and setting the transforms of the corresponding rigid bodies in the world by index. As before, you can use arrays for multiple objects.
Step Forward in Time
Step the simulation forward, based on the difference between the scene's current time and the last simulation time. Connect the resulting function to the updateFunc port of the
CreateCache node.
Get the Updated Transforms
The last step is to get the simulated transform values from the cached world by index, and use them somehow.
- For a controller, you would output the single transform.
- For something like a geometry, you could instantiate copies of a mesh on an array of transforms.