Files
rapier/Claude.md
2025-10-17 12:59:19 +02:00

33 KiB
Raw Blame History

Rapier Physics Engine - Complete Codebase Guide

What is Rapier?

Rapier is a high-performance 2D and 3D physics engine written in Rust by Dimforge. It's designed for games, animation, and robotics applications, offering deterministic simulations, snapshot/restore capabilities, and cross-platform support (including WASM).

License: Apache 2.0 (free and open-source) Repository: https://github.com/dimforge/rapier Documentation: https://rapier.rs/docs/ Crate: https://crates.io/crates/rapier3d

Key Features

  • Dual-dimensional support: Both 2D (rapier2d) and 3D (rapier3d) with f32 and f64 precision variants
  • Deterministic simulation: Identical results across different machines (IEEE 754-2008 compliant)
  • Snapshot & restore: Complete physics state serialization
  • Cross-platform: Desktop, mobile, web (WASM), consoles
  • Performance-focused: SIMD optimizations, optional multi-threading, sleeping system
  • Flexible: Can be used for full physics or just collision detection

Repository Architecture

The repository uses an unusual structure to share code between 2D/3D versions:

rapier/
├── src/                    # Shared source code (2D/3D agnostic)
├── crates/                 # Concrete 2D/3D crate definitions
│   ├── rapier2d/          # 2D f32
│   ├── rapier3d/          # 3D f32
│   ├── rapier2d-f64/      # 2D f64
│   ├── rapier3d-f64/      # 3D f64
│   ├── rapier_testbed2d/  # 2D visual debugger
│   ├── rapier_testbed3d/  # 3D visual debugger
│   └── rapier3d-urdf/     # Robot model loader
├── examples2d/            # 2D demos
├── examples3d/            # 3D demos
├── benchmarks2d/          # 2D performance tests
├── benchmarks3d/          # 3D performance tests
└── src_testbed/           # Testbed source

Core Modules Deep Dive

1. src/dynamics/ - Physics Simulation

Handles movement, forces, and constraints.

RigidBody System

RigidBody (rigid_body.rs) - The fundamental physics object

  • Three body types:
    • Dynamic: Fully simulated - responds to forces, gravity, collisions
    • Fixed: Never moves - infinite mass (walls, floors, terrain)
    • Kinematic: User-controlled movement - pushes but isn't pushed (platforms, doors)

Key properties:

  • Position/rotation: translation(), rotation(), position()
  • Velocity: linvel(), angvel(), set_linvel(), set_angvel()
  • Mass: mass(), center_of_mass(), computed from attached colliders
  • Forces: add_force(), add_torque(), add_force_at_point() (continuous, cleared each step)
  • Impulses: apply_impulse(), apply_torque_impulse(), apply_impulse_at_point() (instant)
  • Damping: linear_damping(), angular_damping() (air resistance, drag)
  • Sleeping: sleep(), wake_up(), is_sleeping() (performance optimization)
  • CCD: enable_ccd(), prevents fast objects tunneling through walls
  • Locking: lock_rotations(), lock_translations(), set_locked_axes() (constrain movement)
  • Gravity: gravity_scale(), set_gravity_scale() (0.0 = zero-g, 1.0 = normal, 2.0 = heavy)
  • Energy: kinetic_energy(), gravitational_potential_energy()
  • Prediction: predict_position_using_velocity(), predict_position_using_velocity_and_forces()

RigidBodySet (rigid_body_set.rs) - Collection of all bodies

  • Handle-based storage (generational indices prevent use-after-free)
  • Methods: insert(), remove(), get(), get_mut(), iter(), contains()
  • propagate_modified_body_positions_to_colliders() for manual position sync

RigidBodyBuilder - Builder pattern for creating bodies

  • Type constructors: dynamic(), fixed(), kinematic_velocity_based(), kinematic_position_based()
  • Configuration: translation(), rotation(), linvel(), angvel()
  • Settings: gravity_scale(), can_sleep(), ccd_enabled(), linear_damping(), angular_damping()
  • Constraints: locked_axes(), lock_rotations(), lock_translations(), enabled_rotations()
  • Advanced: dominance_group(), additional_mass(), enable_gyroscopic_forces()

Joint System

Joint Types (all in src/dynamics/joint/):

  1. FixedJoint: Welds two bodies rigidly together
  2. RevoluteJoint: Hinge - rotation around one axis (doors, wheels)
  3. PrismaticJoint: Slider - translation along one axis (pistons, elevators)
  4. SphericalJoint: Ball-and-socket - free rotation, fixed position (shoulders, gimbals)
  5. RopeJoint: Maximum distance constraint (ropes, cables, tethers)
  6. SpringJoint: Elastic connection with stiffness/damping (suspension, soft constraints)

Joint Features:

  • Motors: Powered actuation with set_motor_velocity(), set_motor_position()
    • Velocity control: constant speed rotation/sliding
    • Position control: spring-like movement toward target
    • Max force limits: set_motor_max_force()
    • Motor models: AccelerationBased (mass-independent) vs ForceBased (mass-dependent)
  • Limits: Restrict range with set_limits([min, max])
  • Anchors: Connection points in each body's local space

ImpulseJointSet - Collection of all joints

  • Methods: insert(), remove(), get(), get_mut(), iter()
  • Queries: joints_between(), attached_joints(), attached_enabled_joints()

Integration & Solving

IntegrationParameters - Controls simulation behavior

  • dt: Timestep (1/60 for 60 FPS, 1/120 for 120 FPS)
  • num_solver_iterations: Accuracy vs speed (4 = default, 8-12 = high quality, 1-2 = fast)
  • length_unit: Scale factor if not using meters (100.0 for pixel-based 2D)
  • contact_natural_frequency, contact_damping_ratio: Contact compliance
  • joint_natural_frequency, joint_damping_ratio: Joint compliance
  • Advanced: warmstarting, prediction distance, stabilization iterations

IslandManager - Sleeping/waking optimization

  • Groups connected bodies into "islands" for parallel solving
  • Automatically sleeps bodies at rest (huge performance gain)
  • Wakes bodies when disturbed by collisions/joints
  • Sleep thresholds configurable via RigidBodyActivation

CCDSolver - Prevents tunneling

  • Detects fast-moving bodies that might pass through geometry
  • Predicts time-of-impact and clamps motion
  • Enable per-body with ccd_enabled(true)
  • Soft-CCD: cheaper predictive variant with set_soft_ccd_prediction()

2. src/geometry/ - Collision Detection

Collider System

Collider - Collision shape ("hitbox") attached to bodies

  • Shapes: Ball, Cuboid, Capsule, Cylinder, Cone, Triangle, Segment, HeightField, TriMesh, Compound, ConvexHull
  • Material properties:
    • Friction: 0.0 = ice, 0.5 = wood, 1.0 = rubber
    • Restitution: 0.0 = clay (no bounce), 1.0 = perfect elastic, >1.0 = super bouncy
    • Combine rules: Average, Min, Max, Multiply (how to combine when two colliders touch)
  • Mass: Set via density() (kg/m³) or mass() (kg directly)
  • Sensors: set_sensor(true) for trigger zones (detect overlaps without physical collision)
  • Position: position(), translation(), rotation(), position_wrt_parent()
  • Groups: collision_groups(), solver_groups() for layer-based filtering
  • Events: active_events(), contact_force_event_threshold() for collision notifications
  • Shape queries: compute_aabb(), compute_swept_aabb(), volume(), mass_properties()
  • Enabled: set_enabled() to temporarily disable without removal

ColliderSet - Collection of all colliders

  • Methods: insert(), insert_with_parent(), remove(), set_parent()
  • Access: get(), get_mut(), iter(), iter_enabled()
  • Invalid handle: ColliderSet::invalid_handle()

ColliderBuilder - Creates colliders with builder pattern

  • Primitive shapes:
    • ball(radius) - Sphere/circle
    • cuboid(hx, hy, hz) - Box (half-extents)
    • capsule_y(half_height, radius) - Pill shape (best for characters!)
    • cylinder(half_height, radius), cone(half_height, radius) (3D only)
  • Complex shapes:
    • trimesh(vertices, indices) - Triangle mesh (slow but accurate)
    • heightfield(heights, scale) - Terrain from height grid
    • convex_hull(points) - Smallest convex shape containing points
    • convex_decomposition(vertices, indices) - Breaks concave mesh into convex pieces
    • segment(a, b), triangle(a, b, c) - Simple primitives
  • Configuration:
    • Material: friction(), restitution(), density(), mass()
    • Filtering: collision_groups(), sensor()
    • Events: active_events(), contact_force_event_threshold()
    • Position: translation(), rotation(), position()
    • Advanced: active_hooks(), active_collision_types(), contact_skin()

Collision Detection Pipeline

BroadPhaseBvh - First pass: quickly find nearby pairs

  • Uses hierarchical BVH tree for spatial indexing
  • Filters out distant objects before expensive narrow-phase
  • Incrementally updated as objects move
  • Optimization strategies: SubtreeOptimizer (default) vs None

NarrowPhase - Second pass: compute exact contacts

  • Calculates precise contact points, normals, penetration depths
  • Builds contact manifolds (groups of contacts sharing properties)
  • Managed automatically by PhysicsPipeline
  • Access via contact_graph() for querying contact pairs

ContactPair - Detailed collision information

  • Methods: total_impulse(), total_impulse_magnitude(), max_impulse(), find_deepest_contact()
  • Contains multiple ContactManifold structures
  • Each manifold has contact points with normals, distances, solver data

Collision Filtering

InteractionGroups - Layer-based collision control

  • Two components: memberships (what groups I'm in) and filter (what groups I collide with)
  • 32 groups available: Group::GROUP_1 through Group::GROUP_32
  • Bidirectional check: A and B collide only if A's memberships overlap B's filter AND vice versa
  • Example: Player bullets (group 1) only hit enemies (group 2)

ActiveCollisionTypes - Filter by body type

  • Controls which body type pairs can collide
  • Defaults: Dynamic↔Dynamic ✓, Dynamic↔Fixed ✓, Dynamic↔Kinematic ✓, Fixed↔Fixed ✗
  • Rarely changed - defaults are correct for most games

QueryFilter - Filter spatial queries

  • Flags: EXCLUDE_FIXED, EXCLUDE_DYNAMIC, EXCLUDE_SENSORS, ONLY_DYNAMIC, etc.
  • Groups: Filter by collision groups
  • Exclusions: exclude_collider, exclude_rigid_body
  • Custom: predicate closure for arbitrary filtering

3. src/pipeline/ - Simulation Orchestration

PhysicsPipeline - The main simulation loop

  • step(): Advances physics by one timestep
    1. Handles user changes (moved bodies, added/removed colliders)
    2. Runs collision detection (broad-phase → narrow-phase)
    3. Builds islands and solves constraints (contacts + joints)
    4. Integrates velocities to update positions
    5. Runs CCD if needed
    6. Generates events
  • Reuse same instance for performance (caches data between frames)

CollisionPipeline - Collision detection without dynamics

  • Use when you only need collision detection, not physics simulation
  • Lighter weight than PhysicsPipeline

QueryPipeline - Spatial queries (created from BroadPhase)

  • Raycasting:
    • cast_ray() - First hit along ray
    • cast_ray_and_get_normal() - Hit with surface normal
    • intersect_ray() - ALL hits along ray
  • Shape casting:
    • cast_shape() - Sweep shape through space (thick raycast)
    • cast_shape_nonlinear() - Non-linear motion sweep
  • Point queries:
    • project_point() - Find closest point on any collider
    • intersect_point() - Find all colliders containing point
  • AABB queries:
    • intersect_aabb_conservative() - Find colliders in bounding box
  • Filtering via QueryFilter

EventHandler trait - Receive physics events

  • handle_collision_event() - When colliders start/stop touching
  • handle_contact_force_event() - When contact forces exceed threshold
  • Built-in: ChannelEventCollector sends events to mpsc channels
  • Enable per-collider with ActiveEvents flags

PhysicsHooks trait - Custom collision behavior

  • filter_contact_pair() - Decide if two colliders should collide
  • filter_intersection_pair() - Filter sensor intersections
  • modify_solver_contacts() - Modify contact properties before solving
  • Enable per-collider with ActiveHooks flags
  • Advanced feature - most users should use InteractionGroups instead

CollisionEvent - Collision state changes

  • Started(h1, h2, flags) - Colliders began touching
  • Stopped(h1, h2, flags) - Colliders stopped touching
  • Methods: started(), stopped(), collider1(), collider2(), sensor()

4. src/control/ - High-Level Controllers

KinematicCharacterController - Player/NPC movement

  • Handles walking, slopes, stairs, wall sliding, ground snapping
  • NOT physics-based - you control movement directly
  • Features:
    • slide: Slide along walls instead of stopping
    • autostep: Automatically climb stairs/small obstacles
    • max_slope_climb_angle: Max climbable slope (radians)
    • min_slope_slide_angle: When to slide down slopes
    • snap_to_ground: Keep grounded on uneven terrain
  • Returns EffectiveCharacterMovement with translation and grounded status

DynamicRayCastVehicleController - Arcade vehicle physics

  • Raycast-based suspension (simpler than constraint-based)
  • Add wheels with suspension, steering, engine force
  • Automatically handles wheel contacts and forces

5. src/data/ - Core Data Structures

Arena<T> - Handle-based storage

  • Generational indices: (index, generation) pair
  • Prevents use-after-free: old handles become invalid when slots reused
  • Used for: RigidBodySet, ColliderSet, ImpulseJointSet
  • Methods: insert(), remove(), get(), get_mut(), iter()
  • Advanced: get_unknown_gen() bypasses generation check (unsafe)

Graph<N, E> - Generic graph structure

  • Nodes and edges with associated data
  • Used for: interaction graph (bodies/colliders), joint graph
  • Enables: "find all joints attached to this body"

ModifiedObjects - Change tracking

  • Flags objects that changed since last frame
  • Enables incremental updates (only process changed objects)
  • Critical for performance

6. src/counters/ - Profiling

Counters - Performance measurements

  • Tracks time in: collision detection, solver, CCD, island construction
  • Subdivided: broad-phase time, narrow-phase time, velocity resolution, etc.
  • Access via physics_pipeline.counters

Complete API Reference

Body Types

RigidBodyType::Dynamic          // Fully simulated
RigidBodyType::Fixed            // Never moves
RigidBodyType::KinematicVelocityBased    // Velocity control
RigidBodyType::KinematicPositionBased    // Position control

Joint Types

FixedJoint::new()               // Weld
RevoluteJoint::new(axis)        // Hinge
PrismaticJoint::new(axis)       // Slider
SphericalJoint::new()           // Ball-and-socket (3D only)
RopeJoint::new(max_dist)        // Distance limit
SpringJoint::new(rest, stiff, damp)  // Elastic

Collision Shapes

// Primitives (fast)
ColliderBuilder::ball(radius)
ColliderBuilder::cuboid(hx, hy, hz)         // Half-extents
ColliderBuilder::capsule_y(half_h, r)       // Best for characters!
ColliderBuilder::cylinder(half_h, r)        // 3D only
ColliderBuilder::cone(half_h, r)            // 3D only

// Complex (slower)
ColliderBuilder::trimesh(verts, indices)    // Arbitrary mesh
ColliderBuilder::heightfield(heights, scale) // Terrain
ColliderBuilder::convex_hull(points)        // Convex wrap
ColliderBuilder::convex_decomposition(v, i) // Auto-split concave

Events & Hooks

// Event flags
ActiveEvents::COLLISION_EVENTS           // Start/stop touching
ActiveEvents::CONTACT_FORCE_EVENTS       // Force threshold exceeded

// Hook flags
ActiveHooks::FILTER_CONTACT_PAIRS        // Custom collision filtering
ActiveHooks::FILTER_INTERSECTION_PAIR    // Custom sensor filtering
ActiveHooks::MODIFY_SOLVER_CONTACTS      // Modify contact properties

Filtering

// Collision groups (layer system)
let groups = InteractionGroups::new(
    Group::GROUP_1,                      // I'm in group 1
    Group::GROUP_2 | Group::GROUP_3      // I collide with 2 and 3
);

// Query filters
QueryFilter::default()
QueryFilter::only_dynamic()              // Ignore static geometry
QueryFilter::exclude_sensors()           // Only solid shapes

Locked Axes

LockedAxes::ROTATION_LOCKED              // Can't rotate at all
LockedAxes::TRANSLATION_LOCKED           // Can't translate at all
LockedAxes::TRANSLATION_LOCKED_Z         // Lock one axis (2D in 3D)
LockedAxes::ROTATION_LOCKED_X | LockedAxes::ROTATION_LOCKED_Y  // Combine

Advanced Concepts

Sleeping System

Bodies automatically sleep when at rest (velocities below threshold for 2 seconds). Sleeping bodies:

  • Skipped in collision detection and simulation
  • Auto-wake when hit or joint-connected to moving body
  • Configured via RigidBodyActivation:
    • normalized_linear_threshold: Linear velocity threshold (default 0.4)
    • angular_threshold: Angular velocity threshold (default 0.5)
    • time_until_sleep: How long to be still before sleeping (default 2.0s)
  • Disable with can_sleep(false) or RigidBodyActivation::cannot_sleep()

CCD (Continuous Collision Detection)

Prevents "tunneling" where fast objects pass through thin walls:

  • Hard CCD: Shape-casting with substeps (expensive but accurate)
  • Soft CCD: Predictive contacts (cheaper, good for medium-speed objects)
  • Enable: RigidBodyBuilder::ccd_enabled(true) or body.enable_ccd(true)
  • Soft: set_soft_ccd_prediction(distance)
  • Active when velocity exceeds auto-computed threshold

Mass Properties

Total mass = collider masses + additional mass:

  • Collider mass: density × volume or set directly
  • Additional mass: set_additional_mass() adds to total
  • Auto-computed: mass, center of mass, angular inertia tensor
  • Manual recompute: recompute_mass_properties_from_colliders()

Dominance Groups

Bodies with higher dominance push lower ones but not vice versa:

  • Range: i8::MIN to i8::MAX
  • Default: 0 (all equal)
  • Rarely needed - use for "heavy objects should always win" scenarios

Contact Skin

Small margin around colliders (keeps objects slightly apart):

  • Improves performance and stability
  • Might create small visual gaps
  • Set via ColliderBuilder::contact_skin(thickness)

Motor Models

How motor spring constants scale with mass:

  • MotorModel::AccelerationBased (default): Auto-scales with mass, easier to tune
  • MotorModel::ForceBased: Absolute forces, mass-dependent behavior

Common Usage Patterns

Creating a Dynamic Object

let body = RigidBodyBuilder::dynamic()
    .translation(vector![0.0, 10.0, 0.0])
    .linvel(vector![1.0, 0.0, 0.0])
    .build();
let body_handle = bodies.insert(body);

let collider = ColliderBuilder::ball(0.5)
    .density(2700.0)  // Aluminum
    .friction(0.7)
    .restitution(0.3)
    .build();
colliders.insert_with_parent(collider, body_handle, &mut bodies);

Raycasting

let query_pipeline = broad_phase.as_query_pipeline(
    &QueryDispatcher,
    &bodies,
    &colliders,
    QueryFilter::default()
);

let ray = Ray::new(point![0.0, 10.0, 0.0], vector![0.0, -1.0, 0.0]);
if let Some((handle, toi)) = query_pipeline.cast_ray(&ray, Real::MAX, true) {
    let hit_point = ray.origin + ray.dir * toi;
    println!("Hit {:?} at {:?}, distance = {}", handle, hit_point, toi);
}

Applying Forces vs Impulses

// IMPULSE: Instant change (jumping, explosions)
body.apply_impulse(vector![0.0, 500.0, 0.0], true);  // Jump!

// FORCE: Continuous (thrust, wind) - call every frame
body.add_force(vector![0.0, 100.0, 0.0], true);  // Rocket thrust

Creating a Joint

let joint = RevoluteJointBuilder::new()
    .local_anchor1(point![1.0, 0.0, 0.0])
    .local_anchor2(point![-1.0, 0.0, 0.0])
    .limits([0.0, std::f32::consts::PI / 2.0])  // 0-90° rotation
    .build();
let joint_handle = joints.insert(body1, body2, joint, true);

Character Controller

let controller = KinematicCharacterController {
    slide: true,
    autostep: Some(CharacterAutostep::default()),
    max_slope_climb_angle: 45.0_f32.to_radians(),
    snap_to_ground: Some(CharacterLength::Relative(0.2)),
    ..Default::default()
};

let desired_movement = vector![input_x, 0.0, input_z] * speed * dt;
let movement = controller.move_shape(
    dt, &bodies, &colliders, &query_pipeline,
    character_shape, &character_pos, desired_movement,
    QueryFilter::default(), |_| {}
);
character_pos.translation.vector += movement.translation;

Collision Events

use std::sync::mpsc::channel;

let (collision_send, collision_recv) = channel();
let (force_send, force_recv) = channel();
let event_handler = ChannelEventCollector::new(collision_send, force_send);

// In physics step
physics_pipeline.step(..., &event_handler);

// After physics
while let Ok(event) = collision_recv.try_recv() {
    match event {
        CollisionEvent::Started(h1, h2, _) => println!("Collision!"),
        CollisionEvent::Stopped(h1, h2, _) => println!("Separated"),
    }
}

Performance Optimization Tips

  1. Sleeping: Let objects at rest sleep (default behavior)
  2. Shape choice: Ball/Cuboid/Capsule >> Convex Hull >> TriMesh
  3. Solver iterations: Lower num_solver_iterations if accuracy isn't critical
  4. Parallel: Enable parallel feature for multi-core
  5. Broadphase: Keep objects reasonably distributed (not all in one spot)
  6. CCD: Only enable for fast objects that need it
  7. Event generation: Only enable events on colliders that need them
  8. Collision groups: Filter unnecessary collision checks
  9. Fixed timestep: Use fixed dt, accumulate remainder for smooth rendering

Common Patterns & Best Practices

Handle Storage

// Store handles, not references
struct Player {
    body_handle: RigidBodyHandle,
    collider_handle: ColliderHandle,
}

// Access when needed
let player_body = &mut bodies[player.body_handle];

2D Game in 3D Engine

let body = RigidBodyBuilder::dynamic()
    .locked_axes(
        LockedAxes::TRANSLATION_LOCKED_Z |
        LockedAxes::ROTATION_LOCKED_X |
        LockedAxes::ROTATION_LOCKED_Y
    )
    .build();

One-Way Platforms (via hooks)

struct OneWayPlatform;
impl PhysicsHooks for OneWayPlatform {
    fn filter_contact_pair(&self, context: &PairFilterContext) -> Option<SolverFlags> {
        // Allow contact only if player is above platform
        if player_above_platform(context) {
            Some(SolverFlags::COMPUTE_IMPULSES)
        } else {
            None  // No collision
        }
    }
}

Compound Shapes

// Multiple colliders on one body
let body_handle = bodies.insert(RigidBodyBuilder::dynamic().build());

colliders.insert_with_parent(
    ColliderBuilder::cuboid(1.0, 1.0, 1.0).translation(vector![0.0, 1.0, 0.0]).build(),
    body_handle, &mut bodies
);
colliders.insert_with_parent(
    ColliderBuilder::ball(0.5).translation(vector![0.0, 3.0, 0.0]).build(),
    body_handle, &mut bodies
);
// Now the body has a box + ball shape

Troubleshooting

Objects Tunneling Through Walls

  • Enable CCD: body.enable_ccd(true)
  • Increase wall thickness
  • Reduce timestep (dt)
  • Increase num_solver_iterations

Unstable Simulation (Jittering, Explosions)

  • Reduce mass ratios (avoid 1kg vs 1000kg objects)
  • Increase num_solver_iterations
  • Check for conflicting constraints
  • Verify joint anchors are reasonable
  • Reduce timestep if using large dt

Poor Performance

  • Check sleeping is enabled (can_sleep(true))
  • Use simpler shapes (capsules instead of meshes)
  • Enable parallel feature
  • Reduce num_solver_iterations if acceptable
  • Use collision groups to avoid unnecessary checks
  • Only enable events on colliders that need them

Bodies Stuck/Not Moving

  • Check if sleeping: body.wake_up(true)
  • Verify mass > 0 (check collider density)
  • Check locked axes aren't preventing movement
  • Verify gravity scale isn't 0

File Statistics

  • 95 total Rust files in src/
  • Top files by public function count:
    • rigid_body.rs: 126 functions
    • collider.rs: 118 functions
    • rigid_body_components.rs: 56 functions
    • generic_joint.rs: 47 functions
    • query_pipeline.rs: 29 functions

Documentation Improvements

Session 1: Comprehensive API Documentation

Comprehensively documented 300+ public functions across 45+ files:

Fully Documented Modules:

  1. PhysicsPipeline - Main simulation loop
  2. RigidBody (~60 methods) - All position, velocity, force, impulse, damping, CCD, locking methods
  3. RigidBodySet - All collection management methods
  4. RigidBodyBuilder (~40 methods) - All configuration methods
  5. Collider (~50 methods) - All property accessors and setters
  6. ColliderSet - All collection methods
  7. ColliderBuilder (~60 methods) - All shape constructors and configuration
  8. All 6 joint types - Comprehensive docs for Fixed, Revolute, Prismatic, Spherical, Rope, Spring
  9. ImpulseJointSet - All joint collection methods
  10. QueryPipeline - All spatial query methods
  11. EventHandler & events - Complete event system
  12. InteractionGroups - Collision filtering
  13. IntegrationParameters - Simulation settings
  14. IslandManager - Sleep/wake system
  15. CCDSolver - Tunneling prevention
  16. BroadPhaseBvh, NarrowPhase - Collision detection
  17. CharacterController - Player movement
  18. ContactPair - Contact information
  19. All major enums/flags: RigidBodyType, LockedAxes, ActiveEvents, ActiveHooks, ActiveCollisionTypes, CoefficientCombineRule, MotorModel, CollisionEvent, QueryFilter

Documentation Style: All functions include:

  • Plain language ("hitbox" not "geometric entity")
  • Real-world use cases (when/why to use)
  • Code examples (copy-paste ready)
  • Value guides (friction 0-1, density values for real materials)
  • Warnings (teleporting, performance costs, common mistakes)
  • Comparisons (forces vs impulses, mass vs density, when to use each)

Session 2: Documentation Example Testing

Converted 75+ ignored documentation examples to be tested by cargo test --doc

Goal: Ensure all documentation examples remain valid and compilable as the codebase evolves.

Files with Fixed Examples:

Dynamics Module (33 examples):

  • dynamics/rigid_body.rs (13)
  • dynamics/rigid_body_set.rs (8)
  • dynamics/rigid_body_components.rs (1) - LockedAxes
  • dynamics/coefficient_combine_rule.rs (1)
  • dynamics/integration_parameters.rs (1)
  • dynamics/island_manager.rs (1)
  • dynamics/joint/rope_joint.rs (1)
  • dynamics/joint/revolute_joint.rs (1)
  • dynamics/joint/generic_joint.rs (1) - JointMotor
  • dynamics/joint/impulse_joint/impulse_joint_set.rs (5)

Geometry Module (10 examples):

  • geometry/interaction_groups.rs (1)
  • geometry/collider_set.rs (4)
  • geometry/collider_components.rs (1) - ActiveCollisionTypes
  • geometry/contact_pair.rs (2)
  • geometry/mod.rs (1) - CollisionEvent
  • geometry/interaction_graph.rs (1)

Pipeline Module (14 examples):

  • pipeline/query_pipeline.rs (9) - Raycasting, shape casting, point queries
  • pipeline/event_handler.rs (3) - ActiveEvents, EventHandler trait, ChannelEventCollector
  • pipeline/physics_pipeline.rs (1)
  • pipeline/collision_pipeline.rs (1)

Control Module (1 example):

  • control/character_controller.rs (1) - Complete character controller setup

Data Module (25 examples):

  • data/arena.rs (25) - All Arena API methods

Other Modules (4 examples):

  • dynamics/joint/multibody_joint/multibody_joint_set.rs (1)

Conversion Pattern:

// Before:
/// ```ignore
/// let body = RigidBodyBuilder::dynamic().build();
/// bodies.insert(body);
/// ```

// After:
/// ```
/// # use rapier3d::prelude::*;
/// # let mut bodies = RigidBodySet::new();
/// let body_handle = bodies.insert(RigidBodyBuilder::dynamic());
/// ```

Hidden lines (prefixed with #) provide setup code while keeping examples readable.

Key Fixes Required for Compilation:

  1. Removed unnecessary .build() calls: Builders implement Into<T>, so:

    • RigidBodyBuilder::dynamic().build()RigidBodyBuilder::dynamic()
    • ColliderBuilder::ball(0.5).build()ColliderBuilder::ball(0.5)
    • These work directly with insert() and insert_with_parent()
  2. Fixed API calls to match actual implementation:

    • &QueryDispatchernarrow_phase.query_dispatcher() (QueryPipeline needs a dispatcher reference)
    • Added NarrowPhase::new() setup for query pipeline examples
  3. Corrected property/field names:

    • hit.toihit.time_of_impact (RayIntersection struct)
    • collider.shape()collider.shared_shape() (when printing/debugging)
  4. Added required setup for complex examples:

    • project_point() example: Added IntegrationParameters, broad_phase.set_aabb() call
    • Character controller: Changed to Ball::new(0.5) instead of shape reference
    • Joint examples: Fixed to use Vector::y_axis() instead of implicit axis
  5. Fixed joint constructor calls:

    • RevoluteJoint::new()RevoluteJoint::new(Vector::y_axis()) (axis required)
    • PrismaticJoint::new(...)PrismaticJoint::new(Vector::x_axis()) (axis required)

Remaining Work:

  • geometry/collider.rs has 12 ignored examples still marked as ignore (these are intentionally left as ignore for documentation purposes where full compilation context would be overly verbose)

Impact:

  • Documentation examples now compile with cargo test --doc
  • Examples stay correct as codebase evolves (tests will catch API changes)
  • Copy-paste ready code that actually works
  • Improved documentation quality and developer experience
  • Builders work seamlessly without explicit .build() calls

Examples Directory

examples3d/ contains many demonstrations:

  • primitives3.rs - Showcase of basic shapes
  • keva3.rs - Large tower of blocks (stress test)
  • platform3.rs - Moving kinematic platforms
  • joints3.rs - All joint types demonstrated
  • character_controller3.rs - Character movement
  • vehicle_controller3.rs - Vehicle physics
  • ccd3.rs - Fast bullets with CCD
  • sensor3.rs - Trigger zones
  • despawn3.rs - Removing objects
  • debug_boxes3.rs - Visual debugging
  • rotating_floor_stacks3.rs - Custom example: 20 pyramids (10×10 cube bases) on slowly rotating floor

Run: cargo run --release --bin all_examples3

Building & Testing

# Development build
cargo build

# Release build (much faster!)
cargo build --release

# Run all 3D examples
cargo run --release --bin all_examples3

# Run all 2D examples
cargo run --release --bin all_examples2

# Run tests
cargo test

# With parallelism
cargo build --features parallel --release

# With SIMD
cargo build --features simd-stable --release

# Benchmarks
cargo run --release --manifest-path benchmarks3d/Cargo.toml

Cargo Features

  • parallel - Multi-threaded solving (big performance gain on multi-core)
  • simd-stable - SIMD optimizations on stable Rust
  • simd-nightly - More SIMD opts on nightly
  • serde-serialize - Snapshot/restore support
  • enhanced-determinism - Stricter determinism (disables SIMD)
  • debug-render - Visual debugging helpers
  • profiler - Detailed performance counters
  • dim2 / dim3 - 2D or 3D (set by crate, not user)
  • f32 / f64 - Precision (set by crate, not user)

Resources

  • Parry: Collision detection library (Rapier's foundation)
  • Salva: SPH fluid simulation
  • nphysics: Previous-gen physics engine (deprecated, use Rapier)
  • nalgebra: Linear algebra library
  • Bevy_rapier: Integration with Bevy game engine

Quick Reference Card

Most Common Operations

// Create world
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let mut joints = ImpulseJointSet::new();
let mut pipeline = PhysicsPipeline::new();

// Add dynamic ball
let body = bodies.insert(RigidBodyBuilder::dynamic().translation(vector![0.0, 5.0, 0.0]).build());
colliders.insert_with_parent(ColliderBuilder::ball(0.5).build(), body, &mut bodies);

// Add static floor
let floor = bodies.insert(RigidBodyBuilder::fixed().build());
colliders.insert_with_parent(ColliderBuilder::cuboid(10.0, 0.1, 10.0).build(), floor, &mut bodies);

// Simulate
pipeline.step(&gravity, &params, &mut islands, &mut broad_phase, &mut narrow_phase,
              &mut bodies, &mut colliders, &mut joints, &mut multibody_joints,
              &mut ccd_solver, &(), &());

// Query
let pos = bodies[body].translation();
let vel = bodies[body].linvel();

// Modify
bodies[body].apply_impulse(vector![0.0, 100.0, 0.0], true);
bodies[body].set_linvel(vector![1.0, 0.0, 0.0], true);

Material Presets

// Ice
.friction(0.01).restitution(0.1)

// Wood
.friction(0.5).restitution(0.2)

// Rubber
.friction(1.0).restitution(0.8)

// Metal
.friction(0.6).restitution(0.3)

// Bouncy ball
.friction(0.7).restitution(0.9)

Common Densities (kg/m³)

.density(1000.0)   // Water
.density(2700.0)   // Aluminum
.density(7850.0)   // Steel
.density(11340.0)  // Lead
.density(920.0)    // Ice
.density(1.2)      // Air

This documentation provides complete coverage of Rapier's architecture, APIs, usage patterns, and best practices for both beginners and advanced users!