Understanding btUniversalConstraint vs 6DOF in ammo.js

This article explores the differences between the btUniversalConstraint and the standard 6-Degrees-of-Freedom (6DOF) joint in ammo.js, the JavaScript port of the Bullet physics engine. You will learn what each constraint does, how they structurally differ, and how to choose the right one for your 3D physics simulations.

What is btUniversalConstraint?

The btUniversalConstraint is a specialized constraint in ammo.js designed to model a classic universal joint (also known as a Cardan or Hooke's joint). It connects two rigid bodies, allowing them to rotate around two perpendicular axes while restricting all translational movement and rotation around the third axis.

By default, it allows rotation around the local X and Y axes while locking the Z axis and locking all translational movement (X, Y, and Z translation). It is commonly used in physics simulations for vehicle driveshafts, suspension systems, steering knuckles, and robotic gimbals.

What is a Standard 6DOF Joint?

The standard 6DOF joint in ammo.js, represented by btGeneric6DofConstraint (or its spring-enabled variant btGeneric6DofSpring2Constraint), is a highly versatile, general-purpose constraint.

Unlike the universal joint, a 6DOF joint allows you to independently configure all six degrees of freedom: three translational axes (X, Y, Z) and three rotational axes (roll, pitch, yaw). For each axis, you can lock motion, leave it completely free, limit it to a specific angular or linear range, or apply motor and spring forces.

Key Differences Between the Two Constraints

While a 6DOF joint can be configured to behave exactly like a universal joint, they differ significantly in their implementation, ease of use, and intent:

  • Configuration and Setup: The btUniversalConstraint is essentially a pre-configured helper class. When you instantiate it, the engine automatically locks the three translation axes and one rotation axis for you. With a standard btGeneric6DofConstraint, you must manually define the linear and angular limits for all six axes using code to achieve the same result.
  • Degrees of Freedom: The universal joint is strictly limited to 2 rotational degrees of freedom. The 6DOF joint can handle anywhere from 0 to 6 degrees of freedom, making it suitable for complex behaviors like sliding drawers, swinging ropes, or bouncy suspension springs.
  • Performance: Under the hood in Bullet/ammo.js, btUniversalConstraint inherits from the 6DOF constraint class. Because they share the same underlying solver logic, their physics calculation performance is nearly identical. However, using the specialized universal joint reduces the overhead of writing initialization code.
  • API Simplicity: The universal joint API exposes direct methods to set limits on its two active rotational axes. The 6DOF API requires you to reference axes by index numbers (0 through 5), which can be more prone to developer error during setup.

When to Use Which?

Use btUniversalConstraint if you are modeling physical hardware that utilizes a two-axis gimbal or universal joint, such as car drivetrains or robotic limbs. It simplifies your codebase and prevents configuration errors.

Use the standard 6DOF joint if your joint requires translational movement (like sliding or telescoping), needs spring physics, or requires complex limits on all three rotational axes.