Rigid Actors
Rigid actors represent non-deformable bodies. They serve as standalone dynamic or static objects and as the building blocks for more complex constructs such as articulated bodies.
A rigid actor's state is fully described by a position (Real3) and an orientation (Quaternion), and solution updates can be parameterized in terms of 6 independent degrees of freedom (DoFs; 3 translational and 3 rotational).
Static vs. Dynamic
Certain rigid actors can have their positions prescribed directly by setting the isStatic / is_static flag.
Static actors may still act as colliders for other actors, but they do not respond to contact reactions or other external forces.
While the term "static" may suggest that static actors are stationary (and this is often true), they can still move with nonzero velocity if their prescribed positions are updated at each time step.
Common use cases for static actors are environmental obstacles such as ground planes, walls, tables, and similar.
The remainder of this page is concerned with modeling dynamic rigid actors.
Formulation
Continuous Model
Let be a rigid body's volume in a reference configuration. Its mass and center of mass are
where is the mass density field and is a material point in the body.
For the remainder of this discussion, use a body frame centered at the center of mass, with axes aligned with the actor's local frame, and define the body-frame offset .
Let be the world-space center of mass and let be the world-from-body rotation, which is also the rotation of the actor's worldFromLocal transform.
The position is the world-space image of the centerOfMass parameter and, in general, differs from the translation of worldFromLocal.
The mass second-moment tensor in the body frame is
For some vector , the corresponding skew-symmetric matrix is defined by
The body-frame angular velocity then satisfies
Let be the conventional moment-of-inertia tensor about the center of mass. The kinetic energy decomposes into translational and rotational contributions
where
The second form of rotational energy reexpresses the first in terms of the world-space angular velocity . The first form can be recovered from the third by invoking the expression of above and inverting the definition of in terms of .
For a constant world-space force applied at body-frame offset from the center of mass, the external potential contributing to the general dynamics formulation is
where
For multiple loads, these potentials are summed. Other (possibly non-conservative) forces on rigid actors typically arise from interactions like contact or constraints, as documented on separate dedicated pages.
Discretization
Time discretization of the translational term of kinetic energy follows straightforwardly from the generic recipe outlined for systems whose configurations are in linear spaces with configuration-independent mass matrices. The discretization of rotational inertia, on the other hand, involves some nontrivial choices, which are discussed in the remainder of this section.
The first expression for above may initially look like a quadratic form in angular velocity, but is defined in a frame following the body's rotation, which introduces an implicit dependence on rotational state. This emerges as a gyration term when deriving the Newton–Euler equations of motion from variational arguments, and is made more explicit by the second form using world-space angular velocity , where the mass matrix clearly depends on rotational state. The default incremental-potential discretization of rotational inertia in SuperDex Physics is instead derived from the third form, following the approach of Ferguson et al. (2021), but using the Lie algebra linearization of Romanyà-Serrasolsas et al. (2025) to formulate the discrete residual and Newton Jacobian. While the cited references formulate an incremental potential for backward Euler integration of rotational inertia, we generalize this to the implicit stage problem of our unified time integration framework.
At stage , define the discrete rotational velocity by the finite difference
Here denotes this stage difference, not the exact derivative of a continuous rotation trajectory. For an exact rotation rate, right multiplication by gives the skew-symmetric world-frame angular-velocity matrix . Applying the same operation to the stage difference generally also produces a symmetric part. SuperDex Physics therefore decomposes it as
where and are respectively the skew-symmetric and symmetric parts of the left-hand side. Equivalently,
The symmetric term is not an additional physical velocity; it retains the part of the finite-difference rotation velocity that would be lost if only were stored. After each stage, SuperDex Physics stores the pair as its rotational velocity state. For the simplest case of backward Euler, the stage-start rotation and velocity representation are simply the previous completed step's solution: , , and . When generalizing to our unified multistep/multistage framework, the stage-start and completed-step solutions are reconstructed from prior and intermediate states as discussed below.
The stage-start rotation and rotational velocity then define the predictor
The rotational contribution to the stage incremental potential is
where may vary from step to step, but is independent of the stage-end rotation , so it may safely be omitted from the incremental potential. The second equality uses the invariance of under rotational similarity transforms and is helpful for simplifying Lie derivatives used in the implementation.
Solution Reconstruction
Because rotations form a nonlinear Lie group, the linear combinations in the general time integration method are instead evaluated in the Lie algebra relative to a base rotation. For base , the Lie-algebra linear combination of rotations with coefficients is given by
Here is the matrix exponential on , evaluated by the Rodrigues formula: for a rotation vector with angle and unit axis ,
The map denotes its inverse: is a rotation vector with such that . The three rotation reconstructions corresponding to the general time integration formulas are then
Thus, the most recent completed rotation is the base for constructing , while is the base for both the stage-start and completed-step reconstructions.
Properties of the Discrete Problem
The derivation of the discrete equations from an incremental potential results in a symmetric Newton Jacobian and allows for the use of nonlinear solution techniques that are specialized to problems with optimization structure. It is therefore preferred for robustness in complicated nonlinear problems, where rigid bodies interact with other systems through contact and constraints. However, unlike some other discretizations of rigid body dynamics, this formulation does not provide exact conservation of angular momentum or rotational kinetic energy at finite time step sizes, only convergence in the limit of . It may introduce noticeable dissipation at moderate-to-large time step sizes.
A nonlinear residual that directly discretizes the Newton–Euler equations without deriving from an incremental potential is available as an experimental feature, and can be selected with experimental::EnableNewtonEulerInertia.
This formulation may provide higher accuracy in certain limiting cases, such as applying a constant torque along a principal axis of a free-floating rigid body initialized to rotate about that axis.
In this case, at a fixed time step size, the default formulation's dissipation will cause the angular velocity to asymptote to a constant value rather than continuing to increase linearly.
While exact conservation properties may provide satisfying solutions to simple test problems, they are rarely needed in practical scenarios, where numerous dissipative mechanisms are often at play.
For robust nonlinear convergence in complex scenes, it is recommended to use the default rotational inertia formulation with a time step size that provides sufficient accuracy for a given application.
Creating Rigid Actors
Dynamic Rigid Body
- C++
- Python
// Load a sphere mesh shape
ShapeHandle sphereShape = context->LoadShapeFromFile(
"sphere/icosphere_3subdiv.1.mochi.json",
Real3{0.2_r, 0.2_r, 0.2_r}, // bake scale
error);
// Create a dynamic rigid sphere
RigidActorParams params;
params.name = "sphere";
params.shape = sphereShape;
params.density = 1000_r; // kg/m^3
params.colliderType = ColliderType::Sphere;
params.worldFromLocal = TransformRT(Real3{0_r, 1.2_r, 0_r});
Actor* sphere = scene->CreateRigidActor(params, error);
# Load a sphere mesh shape
sphere_shape = mochi.load_shape_from_file(
file_path=str(ASSETS_PATH / "sphere/icosphere_3subdiv.1.mochi.json"),
bake_scale=[0.2, 0.2, 0.2],
)
# Create a dynamic rigid sphere
sphere_actor = scene.create_rigid_actor(
name="sphere",
shape=sphere_shape,
density=1000.0, # kg/m^3
collider_type=mochi.ColliderType.SPHERE,
world_from_local=mochi.TransformRT(translation=[0, 1.2, 0]),
)
Static Rigid Body (Ground Plane)
- C++
- Python
// Create an implicit plane shape (no mesh needed)
ShapeHandle planeShape = context->CreatePlaneShape(
Real3{0_r, 1_r, 0_r}, // normal (Y-up)
0_r, // distance from origin
error);
// Create a static ground plane
RigidActorParams params;
params.name = "ground";
params.shape = planeShape;
params.isStatic = true;
params.colliderType = ColliderType::Plane;
Actor* ground = scene->CreateRigidActor(params, error);
# Create an implicit plane shape (no mesh needed)
plane_shape = mochi.create_plane_shape(normal=[0, 1, 0], distance=0)
# Create a static ground plane
ground_actor = scene.create_rigid_actor(
name="ground",
shape=plane_shape,
is_static=True,
)
Setting Initial Velocity
Dynamic rigid actors can be given an initial linear and/or angular velocity at creation time.
- C++
- Python
RigidActorParams params;
params.name = "projectile";
params.shape = shape;
params.density = 1000_r;
params.linearVelocity = Real3{0_r, -1_r, 0_r}; // downward at 1 m/s
params.angularVelocity = Real3{0_r, 0_r, 3.14_r}; // spinning about Z
Actor* projectile = scene->CreateRigidActor(params, error);
projectile = scene.create_rigid_actor(
name="projectile",
shape=shape,
density=1000.0,
linear_velocity=[0, -1, 0], # downward at 1 m/s
angular_velocity=[0, 0, 3.14], # spinning about Z
)
Parameters Reference
RigidActorParams
The creation fields are defined by RigidActorParams (C++, Python).
| Parameter | C++ Type | Python Name | Default | Description |
|---|---|---|---|---|
name | DynamicString | name | "" | Human-readable name for the actor. |
layer | DynamicString | layer | "" | Contact layer. Contact can be selectively enabled or disabled between actors on the same or different layers. |
shape | ShapeHandle | shape | (none) | Handle to the shape geometry. Created via LoadShapeFromFile, CreatePlaneShape, CreateTriMeshShape, etc. |
worldFromLocal | TransformRT | world_from_local | Identity | Initial transform (rotation + translation) of the actor in world space. |
colliderType | ColliderType | collider_type | Auto | Collision geometry representation used by other actors to detect contact with this actor. See Collider Representations. |
isStatic | bool | is_static | false | If true, the actor has infinite mass and is not moved by the solver. |
contact | ContactParams | contact | (defaults) | Contact and friction parameters. See Contact Parameter Reference. |
sdf | GridSdfParams | sdf | (defaults) | Grid SDF resolution and padding parameters. Only relevant when colliderType is Sdf. |
hasGravity | bool | has_gravity | true | Whether gravity is applied to this actor. Ignored for static actors. |
density | optional<real> | density | (unset) | Material density in kg/m^3. Used to compute mass, center of mass, and inertia from the shape geometry. |
mass | optional<real> | mass | (unset) | Total mass in kg. Overrides density-based mass computation. |
centerOfMass | optional<Real3> | center_of_mass | (unset) | Center of mass in the actor's local frame. If unset, computed from the shape assuming uniform density. |
momentOfInertia | optional<Real6> | moment_of_inertia | (unset) | Upper-triangle of the 3x3 rotational inertia tensor (Ixx, Ixy, Ixz, Iyy, Iyz, Izz). If unset, computed from the shape. |
boundaryElementType | ActorBoundaryElementType | boundary_element_type | Default (P1Q3) | Quadrature order for boundary surface integrals used in contact evaluation. |
boundarySubsampling | optional<BoundarySubsamplingParams> | boundary_subsampling | (unset) | Optional subsampling of boundary elements for contact. |
linearVelocity | optional<Real3> | linear_velocity | (unset) | Initial linear velocity in m/s. |
angularVelocity | optional<Real3> | angular_velocity | (unset) | Initial angular velocity in rad/s (rotation vector). |
Mass and Inertia
For dynamic rigid actors, mass properties are required for integration. The density, mass, centerOfMass, and momentOfInertia parameters can be combined in several ways:
- From density — Provide
densityand SuperDex Physics computes total mass, center of mass, and rotational inertia from the shape geometry automatically. - Explicit mass — Set
massdirectly. If the inertia tensor is not provided, it is derived from the shape geometry and scaled to match the specified mass. - Explicit mass and inertia — Set
mass,centerOfMass, andmomentOfInertiadirectly. Useful when mass properties are known from a CAD model or URDF file.
Do not set both density and mass at the same time. If neither is specified, a default density is used. If centerOfMass or momentOfInertia is provided without the other, the missing value is computed assuming uniform density.
Shapes
Rigid actors support several shape types:
| Shape Type | Creation Method | Typical Use |
|---|---|---|
| Plane | CreatePlaneShape / create_plane_shape | Ground planes, infinite walls |
| Triangle mesh | CreateTriMeshShape / create_tri_mesh_shape | Arbitrary surface geometry defined programmatically |
| Mesh from file | LoadShapeFromFile / load_shape_from_file | Pre-built mesh assets (.mochi.json, .mochi.h5) |
| Sphere (implicit) | CreateSphereShape / create_sphere_shape | Analytically defined spheres |
| Box (from tetmesh) | Tetmesh utility functions | Box colliders with volumetric mesh |
The shape defines the visual and collision geometry. The colliderType parameter then controls which collision representation is used at runtime (SDF, bounding sphere, AABB, etc.).
For full details on shape creation and management, see the Shapes page.
Role in Articulated Bodies
Rigid actors also serve as the links (bones) within articulated body actors. In that context, individual rigid links do not own independent degrees of freedom — their transforms are derived from the joint states of the parent articulated actor. The RigidActorParams struct is reused as the linkParams array in ArticulatedActorParams. See Articulated Actors for details.
Examples
- Rigid Bodies: demonstrates a sphere and cube falling onto a table, and four ways to create shapes and actors. Python example:
examples/example_rigid_bodies.py.
Related Concepts
- Articulated Actors — Rigid links connected by joints, forming kinematic trees.
- Contact — Contact formulation, collider representations, friction, and filtering.
- Shapes — Shape creation, loading, and management.
- Constraints — Attaching rigid actors to other actors or to world-space anchors.
- Solvers — Newton solver, linear solvers, and time integration methods.
References
- Z. Ferguson, M. Li, T. Schneider, F. Gil-Ureta, T. Langlois, C. Jiang, D. Zorin, D. M. Kaufman, and D. Panozzo, Intersection-free Rigid Body Dynamics, ACM Transactions on Graphics (SIGGRAPH), 40(4):Article 183, 2021.
- M. Romanyà-Serrasolsas, J. J. Casafranca, and M. A. Otaduy, Painless Differentiable Rotation Dynamics, ACM Transactions on Graphics (SIGGRAPH), 44(4), 2025.