# When Should I Use Each Joint Type in Box3D? A Complete Guide to Revolute, Prismatic, Spherical, Wheel, Distance, Weld, Motor, and Parallel Joints

> Master Box3D joints: revolute, prismatic, spherical, wheel, distance, weld, motor, and parallel. Learn which joint type to use for specific motion constraints and achieve optimal physics simulations.

- Repository: [Erin Catto/box3d](https://github.com/erincatto/box3d)
- Tags: deep-dive
- Published: 2026-08-01

---

**Select Box3D joints based on required degrees of freedom: use revolute for single-axis hinges, prismatic for linear sliders, spherical for ball-socket rotation, wheel for vehicle suspension, distance for rope-like constraints, weld for rigid bonding, motor for active velocity control, and parallel for keeping axes aligned during translation.**

Box3D, the 3D physics engine maintained by Erin Catto, provides eight specialized joint primitives that constrain rigid-body motion through specific mechanical relationships. Knowing when to use each joint type is critical for building stable simulations ranging from robotic arms to vehicle dynamics. This guide explains the specific use cases, degrees of freedom (DoF), and implementation details for each joint type according to the erincatto/box3d source code.

## Revolute Joint: Single-Axis Rotation

Use the **revolute joint** when you need pure rotation around a fixed axis with no translation. This joint provides **1 rotational DoF** and acts like a hinge or pin.

Typical applications include doors, swinging robot arms, and piston rods that rotate. In [`src/revolute_joint.c`](https://github.com/erincatto/box3d/blob/main/src/revolute_joint.c), the `b3PrepareRevoluteJoint` function computes the hinge axis and axial mass, while `b3SolveRevoluteJoint` enforces angular limits and optional spring motors. You can constrain the rotation range using `lowerAngle` and `upperAngle` parameters.

## Prismatic Joint: Linear Translation

Choose the **prismatic joint** for motion constrained to a single axis of translation. This joint provides **1 translational DoF**, functioning as a slider or linear actuator.

Apply this joint to model railway cars, hydraulic pistons, or drawer slides. The implementation in [`src/prismatic_joint.c`](https://github.com/erincatto/box3d/blob/main/src/prismatic_joint.c) handles the linear constraint through `b3PreparePrismaticJoint`, which calculates the sliding axis and effective mass. Enable limits with `lowerTranslation` and `upperTranslation` to define the allowable travel range.

## Spherical Joint: Ball-Socket Freedom

Implement the **spherical joint** when you need full rotational freedom in three dimensions. This joint provides **3 rotational DoF** (swing and twist), functioning as a ball-and-socket connection.

This is the ideal choice for shoulder joints in ragdolls, free-spinning connectors, or any mechanism requiring unrestricted rotation. According to [`src/spherical_joint.c`](https://github.com/erincatto/box3d/blob/main/src/spherical_joint.c), you can optionally limit the motion using cone limits (`coneAngle`) for swing and twist limits (`lowerTwistAngle`, `upperTwistAngle`) to prevent unnatural rotations.

## Wheel Joint: Vehicle Suspension and Steering

Select the **wheel joint** for vehicle simulations requiring suspension travel, wheel spin, and steering capabilities. This joint provides **1 translational DoF** (suspension travel) plus **1 rotational DoF** (wheel spin), with an optional third axis for steering.

Use this for car wheels that must maintain contact with terrain while absorbing bumps. The [`src/wheel_joint.c`](https://github.com/erincatto/box3d/blob/main/src/wheel_joint.c) implementation manages suspension springs through `suspensionHertz` and damping parameters, while `enableSteering` allows you to set the wheel orientation relative to the chassis.

## Distance Joint: Fixed Separation Constraints

Apply the **distance joint** to maintain a specific scalar distance between two points on different bodies. This joint removes **1 translational DoF** by constraining the distance between anchor points.

This joint excels for rope-like linkages, cables, or spring-damper connections where bodies must stay connected but can otherwise move freely. In [`src/distance_joint.c`](https://github.com/erincatto/box3d/blob/main/src/distance_joint.c), the constraint preserves the target `length` between anchors, with optional spring physics controlled by `hertz` and `dampingRatio` parameters.

## Weld Joint: Rigid Bonding

Use the **weld joint** to fuse two bodies into a single rigid unit. This joint provides **0 DoF**, locking both relative position and orientation.

Apply this when you need bodies to behave as one object, such as permanently attaching fixtures or creating complex shapes from multiple rigid bodies. The implementation in [`src/weld_joint.c`](https://github.com/erincatto/box3d/blob/main/src/weld_joint.c) constrains all six degrees of freedom (three linear, three angular) through the `b3PrepareWeldJoint` and `b3SolveWeldJoint` functions.

## Motor Joint: Active Velocity Control

Implement the **motor joint** when you need to actively drive a body toward specific linear or angular velocities rather than constraining its position. This joint prescribes motion with optional force/torque limits.

Use this for moving platforms, controlled rotors, or animation-driven physics where you want bodies to follow a target velocity. According to [`src/motor_joint.c`](https://github.com/erincatto/box3d/blob/main/src/motor_joint.c), you set `linearVelocity` and `angularVelocity` targets, then clamp the applied forces using `maxVelocityForce` and `maxVelocityTorque`.

## Parallel Joint: Axis Alignment During Translation

Choose the **parallel joint** when two bodies must maintain parallel orientation axes while translating relative to each other. This joint constrains the relative rotation to keep two local axes aligned.

This is essential for telescopic linkages, parallel shaft couplings, or mechanisms where orientation must remain constant during linear motion. The [`src/parallel_joint.c`](https://github.com/erincatto/box3d/blob/main/src/parallel_joint.c) implementation uses `localAxisA` and `localAxisB` to define the directions that must stay parallel, with optional translation limits similar to the prismatic joint.

## Solver Architecture and Joint Lifecycle

All Box3D joints follow a consistent pipeline defined in the solver architecture. Understanding this lifecycle helps debug constraint behavior and optimize performance.

The process begins with a **joint definition** (`b3JointDef`) where you specify anchor frames, limits, and motor parameters. Calling `b3World_CreateJoint` allocates a `b3JointSim` and selects the concrete joint structure (such as `b3RevoluteJoint` or `b3PrismaticJoint`).

During each simulation step, the solver executes four phases:

1. **Preparation**: Functions like `b3PrepareRevoluteJoint` compute world-space anchors, Jacobian matrices, and effective masses.
2. **Warm-starting**: The system reapplies previous frame impulses (`b3WarmStart*Joint`) to improve solver convergence.
3. **Solving**: `b3Solve*Joint` enforces constraints, applying impulses to satisfy limits, springs, and motor targets while respecting softness parameters set via `b3MakeSoft`.
4. **Debug Rendering**: Each joint implements `b3Draw*Joint` for visualizing constraint axes and limits.

The core physics solver resides in [`src/solver.c`](https://github.com/erincatto/box3d/blob/main/src/solver.c), which orchestrates these callbacks across all joint types uniformly.

## Code Examples for Each Joint Type

Below are minimal C snippets demonstrating how to create and configure each joint type using the public API ([`box3d.h`](https://github.com/erincatto/box3d/blob/main/box3d.h)). All examples assume you have a `b3World* world` and two bodies `bodyA` and `bodyB`.

### Revolute Joint

```c
b3RevoluteJointDef jd = b3DefaultRevoluteJointDef();
jd.bodyA = bodyA;
jd.bodyB = bodyB;
jd.localAnchorA = (b3Vec3){0.0f, 0.0f, 0.0f};
jd.localAnchorB = (b3Vec3){0.0f, 0.0f, 0.0f};
jd.enableLimit = true;
jd.lowerAngle = -0.5f * B3_PI;
jd.upperAngle = 0.5f * B3_PI;
b3JointId joint = b3World_CreateJoint(world, &jd);

```

### Prismatic Joint

```c
b3PrismaticJointDef jd = b3DefaultPrismaticJointDef();
jd.bodyA = bodyA;
jd.bodyB = bodyB;
jd.localAxisA = (b3Vec3){1.0f, 0.0f, 0.0f};
jd.enableLimit = true;
jd.lowerTranslation = -2.0f;
jd.upperTranslation = 2.0f;
b3JointId joint = b3World_CreateJoint(world, &jd);

```

### Spherical Joint

```c
b3SphericalJointDef jd = b3DefaultSphericalJointDef();
jd.bodyA = bodyA;
jd.bodyB = bodyB;
jd.enableConeLimit = true;
jd.coneAngle = 0.5f * B3_PI;
jd.enableTwistLimit = true;
jd.lowerTwistAngle = -0.25f * B3_PI;
jd.upperTwistAngle = 0.25f * B3_PI;
b3JointId joint = b3World_CreateJoint(world, &jd);

```

### Wheel Joint

```c
b3WheelJointDef jd = b3DefaultWheelJointDef();
jd.bodyA = chassis;
jd.bodyB = wheel;
jd.enableSuspension = true;
jd.suspensionHertz = 5.0f;
jd.enableSteering = true;
jd.steeringHertz = 2.0f;
b3JointId joint = b3World_CreateJoint(world, &jd);

```

### Distance Joint

```c
b3DistanceJointDef jd = b3DefaultDistanceJointDef();
jd.bodyA = bodyA;
jd.bodyB = bodyB;
jd.length = 1.0f;
jd.enableSpring = true;
jd.hertz = 4.0f;
jd.dampingRatio = 0.7f;
b3JointId joint = b3World_CreateJoint(world, &jd);

```

### Weld Joint

```c
b3WeldJointDef jd = b3DefaultWeldJointDef();
jd.bodyA = bodyA;
jd.bodyB = bodyB;
b3JointId joint = b3World_CreateJoint(world, &jd);

```

### Motor Joint

```c
b3MotorJointDef jd = b3DefaultMotorJointDef();
jd.bodyA = bodyA;
jd.bodyB = bodyB;
jd.linearVelocity = (b3Vec3){0.0f, 2.0f, 0.0f};
jd.angularVelocity = (b3Vec3){0.0f, 0.0f, 5.0f};
jd.maxVelocityForce = 100.0f;
jd.maxVelocityTorque = 50.0f;
b3JointId joint = b3World_CreateJoint(world, &jd);

```

### Parallel Joint

```c
b3ParallelJointDef jd = b3DefaultParallelJointDef();
jd.bodyA = bodyA;
jd.bodyB = bodyB;
jd.localAxisA = (b3Vec3){0.0f, 1.0f, 0.0f};
jd.localAxisB = (b3Vec3){0.0f, 1.0f, 0.0f};
jd.enableLimit = true;
jd.lowerTranslation = -1.0f;
jd.upperTranslation = 1.0f;
b3JointId joint = b3World_CreateJoint(world, &jd);

```

## Summary

- **Revolute** ([`src/revolute_joint.c`](https://github.com/erincatto/box3d/blob/main/src/revolute_joint.c)) provides single-axis rotation for hinges and swinging mechanisms.
- **Prismatic** ([`src/prismatic_joint.c`](https://github.com/erincatto/box3d/blob/main/src/prismatic_joint.c)) constrains motion to linear sliding along a fixed axis.
- **Spherical** ([`src/spherical_joint.c`](https://github.com/erincatto/box3d/blob/main/src/spherical_joint.c)) allows full 3D rotation with optional cone and twist limits.
- **Wheel** ([`src/wheel_joint.c`](https://github.com/erincatto/box3d/blob/main/src/wheel_joint.c)) combines suspension travel, steering, and spinning for vehicle simulations.
- **Distance** ([`src/distance_joint.c`](https://github.com/erincatto/box3d/blob/main/src/distance_joint.c)) maintains fixed separation between points with optional spring physics.
- **Weld** ([`src/weld_joint.c`](https://github.com/erincatto/box3d/blob/main/src/weld_joint.c)) rigidly bonds bodies by constraining all relative motion.
- **Motor** ([`src/motor_joint.c`](https://github.com/erincatto/box3d/blob/main/src/motor_joint.c)) actively drives target velocities with force and torque limits.
- **Parallel** ([`src/parallel_joint.c`](https://github.com/erincatto/box3d/blob/main/src/parallel_joint.c)) keeps two local axes aligned while allowing relative translation.

## Frequently Asked Questions

### Can I combine multiple joints between the same two bodies?

Yes, Box3D allows you to create multiple joints connecting the same pair of bodies to build compound constraints. For example, you might combine a revolute joint with a distance joint to create a hinged linkage with length limits. The solver in [`src/solver.c`](https://github.com/erincatto/box3d/blob/main/src/solver.c) processes all constraints simultaneously during the resolution phase.

### What is the difference between the Motor joint and enabling a motor on a Revolute joint?

The **Motor joint** ([`src/motor_joint.c`](https://github.com/erincatto/box3d/blob/main/src/motor_joint.c)) drives a body toward specific world-space linear and angular velocities without constraining position, making it ideal for free-body control like moving platforms. In contrast, enabling a motor on a **Revolute joint** drives the relative angular velocity between two bodies around the hinge axis while maintaining the joint's positional constraints. Use the Revolute motor for actuator joints and the Motor joint for velocity-based animation or AI control.

### Should I use a Weld joint or merge fixtures into a single body?

Use a **Weld joint** when you need to combine bodies dynamically at runtime or preserve the option to break them apart later using joint destruction. If the parts never separate and creation-time performance is critical, merge the fixtures into a single body with multiple shapes instead, as this reduces solver overhead by eliminating constraint calculations entirely.

### When does the Wheel joint outperform a Spherical joint with limits?

The **Wheel joint** outperforms a Spherical joint when modeling vehicle suspension because it provides dedicated parameters for spring frequency (`suspensionHertz`) and steering axes that align with vehicle coordinate systems. While you could approximate wheel behavior using a Spherical joint combined with separate spring forces, the Wheel joint handles the specific constraint mathematics more robustly in [`src/wheel_joint.c`](https://github.com/erincatto/box3d/blob/main/src/wheel_joint.c), ensuring stable contact response and proper suspension dynamics under high load.