One of the most appealing features of a physics engine is to simulate articulations. Articulations, aka. joints, allow the restriction of the motion of one body relative to another. For example, one well-known joint is the ball-in-socket joint also known as the ball joint: it allows one object to rotate freely with regard to the other but not to translate. This is typically used to simulate shoulders of a ragdoll.
Joints can be modeled in various ways but let's talk about the concept of Degrees Of Freedom (DOF) first. In 3D, a rigid-body is capable of translating along the 3 coordinates axes , and , and to rotate along those three axes as well. Therefore, a rigid-body is said to have 3 translational DOF and 3 rotational DOF. We can also say a 3D rigid-body has a total of 6 DOF. The 2D case is similar but with less possibilities of movements: a 2D rigid-body has 2 translational DOF and only 1 rotational DOF (which forms a total of 3 DOF). The number of relative DOF of a body wrt. another body is the number of possible relative translations and rotations. The goal of a joint is to reduce the number of DOF a body has. For example, the aforementioned ball joint removes all relative translations between two bodies. Therefore, it allows only the 3 rotational DOF in 3D simulations or the 1 rotational DOF in 2D simulations. Other joints exist allowing other combinations of relative DOF. Note that because there are less possible motions in 2D, some joints are only defined in 3D. This is illustrated by empty cells in the following table for joints that are not defined in 2D:
|Joint||Allowed DOF in 2D||Allowed DOF in 3D|
|Prismatic joint||1 Translation||1 Translation|
|Revolute joint||1 Rotation||1 Rotation|
|Ball joint||1 Rotation||3 Rotations|
|Cartesian joint||2 Translations||3 Translations|
|Planar joint||2 Translations + 1 Rotation|
|Cylindrical joint||1 Translation + 1 Rotation (along the same axis)|
|Pin-slot joint||1 Translation + 1 Rotation (along different axes)|
|Rectangular joint||2 Translations|
|Universal joint||2 Rotations|
In 3D, a special Helical joint also exists: it allows only one DOF which is a bit special as it is the combination of a rotation and a translation. In other words, a body attached to the ground by an helical joint will only be able to translate and rotate simultaneously: any translation induce automatically a rotation and vice-versa.
In practice, there are two main ways of modeling joints:
- The reduced-coordinates approach encodes the reduction of DOF directly into the equations of motion. For example, a 3D rigid-body attached to the ground with a revolute joint will have its position encoded by only one variable: the rotation angle. Therefore, integrating its motion only changes this one variable and doesn't need additional forces or mathematical constraints to be generated. The clear advantage is that there is no way for the physics engine to apply any motion other than that single rotation to this body, meaning there is no way the body shifts to a position that is not realistic, even if the dynamics solver does not converge completely.
- The constraints-based approach (or full-coordinates approach) is the most commonly available approach on other physics engines for video-games and animations. Here, a 3D rigid-body attached to the ground with a revolute joint will still have its position encoded by 6 variables (3 for translations and 3 for rotations) just like any rigid-body without a joint. Then the integrator will add mathematical constraints to the dynamic system to ensure forces are applied to simulate the reduction of the number of DOF as imposed by the joints. In practice, this means that the rigid-body will break the joint constraint if the constraint solver does not converge completely.
This description shows only one aspect of the difference between the reduced-coordinates approach and the constraints-based approach. More generally, the reduced-coordinates approach favors accuracy while the constraints-based approach favors versatility.
Currently, Rapier only implements the constraints-based approach. A reduced-coordinates implementation will be added to a future version of Rapier.
Joint constraints implement the constraints-based approach. The following table summarizes the types corresponding to the joints mentioned at the beginning of this chapter:
|Joint name||Joint constraint type on Rapier|
Other joints will be added in the future.
A joint constraint geometry is completely configured at its creation, and added to the joint set by the
joint_set.insert(&mut bodies, body1, body2, joint) method by specifying the handles of the bodies the joint is