From BlenderWiki

Jump to: navigation, search
Note: This is an archived version of the Blender Developer Wiki. The current and active wiki is available on wiki.blender.org.

This will be a design overview for the bullet integration project. Right now it's more of a collection of thoughts, ideas, issues and possible solutions. It's still wip and subject to change.

Since this is a continuation of a previous project the basic design stays the same as can be seen in the GSoC 2010 Bullet Design Overview.

There are however several (sometimes quite significant) differences:

Bodies and Worlds

Originally (passive) rigid bodies should have been able to exist in multiple worlds at the same time. This won't be possible because of a limitation in the bullet library. It was also unnecessarily complex to manage in code while confusing to use at the same time.

Scenes could have multiple rigid body worlds, again there are issues with bullet limitations and complexity. Unlike the "bodies in multiple worlds" problem this can be worked around. It's not entirely clear if it's an important enough feature to be worth it though. So now it's only possible to have one world per scene.

One feature that allows separating rigid bodies right now are "Simulation/Collision Groups". They allow the user to put bodies in groups (similar to blender's layers) so that only bodies in the same group can collide with each other.

Rigid Body Types

There are two basic rigid body types, active and passive.

Active objects can be either dynamic (driven by the simulation) or kinematic (driven by the animation system). Users can change between dynamic and kinematic state during the simulation.

Passive objects aren't simulated dynamically and remain static during the simulation. Like active object they can also be kinematic.

Deactivation

It might sound simple but deactivation is a very important part of the rigid body simulation. It has three major functions:

  • Improve performance.
    • Deactivated bodies don't need to be updated.
  • Improve stability.
    • Deactivated bodies don't move around when stacked.
  • Give users another way to control the simulation.
    • One simple example is a fractured wall. if you start the simulation with active rigid bodies the wall will simply collapse. Deactivated bodies on the other hand will sit in place and only start moving after colliding with another object.

Deactivation of rigid bodies can be explicitly disabled.

Kinematic (animated) rigid bodies are activated every simulation step so that deactivation doesn't interfere with the animation system.

Effectors

Effectors allow the simulation to be influenced buy blender's force fields and provide a nice additional way to control the simulation.

In order for them to work better with the rigid body simulation the following changes have been made:

  • The max/min strength of force fields was increased, it was way too low to affect rigid bodies with realistic weight.
  • If the applied force of the effector is > 0, rigid bodies are activated to ensure that they are influenced.

Point Cache

We use blenders point cache system to store rigid body cache. Since our requirements are different than those of the other simulation systems in blender, we only use a subset of it's features.

There is no rigid body physics modifier. The rigid body system is more closely coupled with the animation system and we don't deform objects or generate new data.

We store the point cache data in the rigid body world instead of storing it per object since we only have to keep track of position and orientation (7 floats) of bodies and we usually have at least several hundred objects in a simulation. Dealing with all the generated caches would be both tedious and wasteful.

Cache is invalidated pretty much always when one of the rigid bodies (or it's shapes) is modified. In order for the simulation to stay deterministic we always have to reset the entire world at the beginning of the simulation. This makes partial invalidation difficult since we cannot just start simulation on a arbitrary frame.

Cache is invalidated during playback but is not reset so it's possible to interact with the simulation while it's running.

There is no quick cache feature. It could be done by stepping the world with a small number of steps per second but the result would be drastically different from the actual simulation and more confusing than useful.

Baking works similar to the other systems. The biggest problem with baked simulations is adding or removing bodies (other simulations have the same problem e.g. cloth). There is no good solution, added object will remain sill and removing objects can shuffle objects around (because of index shifts).

Constraints

Rigid body constraints (also known as joints) work differently than most of the constraints in blender. Instead of constraining the movement of one object they define a relationship between the movement of two objects (at least one of which is dynamic). For this reason it doesn't make sense to mix rigid body constraints with the regular constraints.

A better and much more practical approach is to have rigid body constraint objects, similar to how force fields work. This has several advantages, the most important of which is that we can use the object's position and orientation as the pivot of the constraint which is much more intuitive than adjusting number fields (like it's done in the Rigid Body Joint constraint of the game engine). Also it's a much better representation of how they actually work.

Technically constraints work the same as rigid bodies do now. They'd be stored per object and added to a list in the rigid body world. TODO We should also have proper visualization for the different constraints (showing limits and such). Since the pivot of constraints cannot be animated we use the object transformation on start frame to define it like we do with the initial transformation of dynamic rigid bodies.

At the moment bullet supports the following constraints:

  • Hinge
  • Hinge 2
  • Point to point (Ball socket)
  • Slider
  • Cone twist
  • Generic 6dof
  • Generic 6dof spring
  • Unversal

Although they behave differently implementing them is mostly an issue of adding RNA properties and visualization.

It's also useful to add special cases of certain constraints for convenience e.g. the "fixed" constraint is basically a Generic 6dof with all limits locked.

All constraints have the option to override the number of solver iterations made per step so users can tweak the stability of certain joints.

Also they have the option to break on a certain impulse strength. One common use case is to glue object together with fixed constraints and allow them to break apart during the simulation.

Scaling Objects

To make sure that rotation and scale of objects isn't mixed together we decompose the final object transformation matrix before creating and updating rigid bodies.

Rigid bodies are scaled using bullets setLocalScaling() function. It's updated every simulation step which allows rigid bodies to be scaled while the simulation is running.

While this works in most cases, scaling rigid bodies should still be avoided. Especially dynamic bodies can behave very differently and less stable when scaled.

Scaling The World

Having correct units is important for achieving realistic looking simulations. The rigid body simulation uses the 1 blender unit = 1 meter convention. This has a few drawbacks:

  • Small objects aren't very stable (especially because of tunneling).
  • Blenders unit system won't give correct values when unit scaling factor is != 1.0.

The optimal solution is to scale the bullet world when unit scaling is changed. How to do this in bullet has to be investigated.

Collision Margins

In bullet shapes have a collision margin around them. It has two main purposes:

  • Improving stability
  • Improving performance

The drawback is that it introduces a visible gap between objects. However, different shapes handle it differently so some shapes (like boxes) have an embedded margin so that the gap isn't visible.

This is problematic because it's neither consistent nor intuitive. Since there is pretty much always a best choice for the margin, it makes sense to remove it from the ui and calculate it automatically. Before this can be done there are a couple issues that need to be worked out:

  • Figure out best default margin for every shape
  • Ensure there are no visible gaps between shapes
  • Deal with objects that are smaller than the margin

Below are all supported shapes and information about how to handle their margin:

  • Sphere
    • Entire radius is margin.
  • Box
    • Margin is embedded.
  • Capsule
    • Radius should be margin, there is still a bug in bullet though
  • Cone
    • Margin in not embedded, we can embed it manually (although not completely)
  • Cylinder
    • Margin is embedded.
  • Convex Hull
    • Margin in not embedded, we can embed it manually
  • BVH Triangle Mesh
    • Margin in not embedded, can be set to 0 most of the time
  • GImpact Triangle Mesh
    • Margin is not embedded, still unclear how to handle this one, in many cases 0 is a good choice


In some cases it's still desirable to set the margin manually even for shapes that embed it so it's a user option.

Evaluation

Right now the evaluation of the rigid body simulation works like this: Every frame step we:

  • Evaluate the animation system.
  • Update transformation matrix of rigid body objects.
  • Step rigid body world.
  • Evaluate objects, this includes: parenting, constraints, drivers and object level simulations.

Updating the final object transformation matrix takes rigid body transformations into account so that the rb sim has the same influence as the animation system. It doesn't directly change loc/rot of objects and behaves similar to blender's constraints.

Since rigid bodies are evaluated before the final object evaluation there is one important limitation:

  • Indirect animation (parenting, constraints, drivers) has one frame of lag (direct animation of loc/rot works as expected).

To solve this we need to work with the depsgraph and somehow figure out the best moment at which we should step the world.

Geometric Tools

(This will probably be done after GSoC because of lack of time)

There are several geometric tools that are needed in order to make the simulation more useful.

  • Calculate origin based on volume
    • To get a good center of mass for rigid bodies calculating center based on geometry isn't good enough
  • Convex fracturing (A popular approach is to use voroni diagrams)
    • Since convex hulls are the most stable non-primitive collision shape it's important to have was of fracturing object in a way that results in perfectly convex pieces.
  • Arbitrary fracturing (Based on geometry, particles, material, ...)
    • While more realistic there are issues with simulating concave shapes, there is a solution though, see below
  • Convex decomposition (Splitting concave meshes into several convex meshes)
    • Since concave triangle meshes are very unstable and slow to simulate a good alternative is to use compound collision shapes consisting of several convex hulls.