An introduction to RigidBodyControl

By themselves, collision objects are invisible, while scene-graph spatials have no effect on physics. To visualize a collision object, it must be associated with one or more spatials. Such associations are implemented using physics controls: scene-graph controls that implement the PhysicsControl interface.

To associate a rigid body with a spatial, there’s a RigidBodyControl class that extends PhysicsRigidBody and implements PhysicsControl.

In this case, the physics control and its collision object are the same object!

Because each RigidBodyControl (RBC) instance is also a rigid body, you can configure it and add it to a space just like a directly instantiated rigid body. For instance, you can configure friction using setFriction() and disable contact response using setContactResponse(false).

After being added to a spatial, the control synchronizes the motion of the rigid body with that of the controlled spatial.

RBCs are enabled by default. Disabling an RBC causes the body to be removed from the space it’s in, if any.

Constructors

There are 3 RigidBodyControl constructors:

new RigidBodyControl(collisionShape, mass);
new RigidBodyControl(collisionShape);
new RigidBodyControl(mass);

If you specify mass > 0, a dynamic body is created. If you specify mass = 0, a static body is created. If you construct an RBC without specifying a mass, you get a dynamic body with mass = 1.

If you construct an RBC without specifying a collision shape, you get an incomplete RBC.

You can’t do much with an incomplete RBC other than add it to a spatial.

In particular, adding an incomplete RBC to a physics space will cause a crash—​as will accessing its activation state, CCD parameters, collision groups, friction parameters, ignore list, or restitution parameter.

To complete the RBC, simply add it to a spatial (before adding it to a space). A collision shape will be generated based on the controlled spatial, using:

  • SphereCollisionShape if the spatial is a geometry with spherical mesh,

  • BoxCollisionShape if the spatial is a geometry with a box-shaped mesh,

  • CollisionShapeFactory.createDynamicMeshShape() (for a dynamic body), or

  • CollisionShapeFactory.createMeshShape() (for a static one).

HelloRbc is a simple application that demonstrates the use of RigidBodyControl. Things to notice while running the app:

  1. The RBCs behave like directly instantiated rigid bodies.

  2. Each geometry matches the motion of its corresponding RBC.

Kinematic flags

To create a physics control for a kinematic rigid body, first instantiate a dynamic RBC (with mass > 0), then convert it to kinematic using rigidBodyControl.setKinematic(true).

HelloKinematicRbc is a simple application that demonstrates a kinematic RBC.

By default, the physics object of a kinematic RBC follows the motion of the spatial. To reposition it, you must reposition the spatial.

To avoid this behavior, use setKinematicSpatial(false). The body will remain kinematic, but it will no longer follow the motion of the spatial. The body can then be positioned directly, using setPhysicsLocation() and setPhysicsRotation().

Synchronizing scales

While the motion of the controlled spatial matches that of the body, their sizes might differ. By default, there’s no connection between the scale of the spatial and the scale of the body’s collision shape.

To synchronize those scales, use setApplyScale(true).

HelloApplyScale is a simple application that demonstrates setApplyScale(). Things to notice while running the app:

  1. The rigid body is visualized as a blue wireframe.

  2. The controlled geometry is shaded white.

  3. The size of the rigid body matches that of the controlled geometry, even as it pulsates.

Local physics

In JMonkeyEngine, world coordinates are 3-D coordinates that are used (for instance) to position cameras and lights.

The world transform of a spatial transforms (or converts) the spatial’s coordinate system to the world coordinate system, using a combination of translation, rotation, and scaling.

The local transform of a spatial transforms its coordinate system to that of its parent node in the scene graph.

By default, a rigid-body control matches the world transform of its controlled spatial. For most applications, this is what you want.

To match the spatial’s local transform instead, use setApplyPhysicsLocal(true).

HelloLocalPhysics is a simple application that demonstrates local physics. Things to notice while running the app:

  1. Two balls: the top one dynamic, the bottom one kinematic.

  2. Both geometries are attached to a scene-graph node that orbits a fixed point in world space.

  3. While the kinematic ball is motionless in physics space, its path in world space is a circular orbit.

  4. While the dynamic ball falls straight downward in physics space, it follows a corkscrew path in world space.

Summary

  • To associate a rigid body with a scene-graph spatial, use a RigidBodyControl (RBC).

  • If you construct an RBC without specifying a collision shape, it will be incomplete until it gets added to a spatial.

  • An RBC can be static, dynamic, or kinematic.

  • Generally, the motion of the controlled spatial matches that of the body, but you can disable the matching behavior of a kinematic RBC.

  • To match the scales of the body and the controlled spatial, use setApplyScale(true).

  • To match the controlled spatial’s local transform (instead of its world transform) use setApplyPhysicsLocal(true).