33 KiB
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, collisionsFixed: 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/):
FixedJoint: Welds two bodies rigidly togetherRevoluteJoint: Hinge - rotation around one axis (doors, wheels)PrismaticJoint: Slider - translation along one axis (pistons, elevators)SphericalJoint: Ball-and-socket - free rotation, fixed position (shoulders, gimbals)RopeJoint: Maximum distance constraint (ropes, cables, tethers)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) vsForceBased(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 compliancejoint_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³) ormass()(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/circlecuboid(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 gridconvex_hull(points)- Smallest convex shape containing pointsconvex_decomposition(vertices, indices)- Breaks concave mesh into convex piecessegment(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()
- Material:
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) vsNone
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
ContactManifoldstructures - 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) andfilter(what groups I collide with) - 32 groups available:
Group::GROUP_1throughGroup::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:
predicateclosure for arbitrary filtering
3. src/pipeline/ - Simulation Orchestration
PhysicsPipeline - The main simulation loop
step(): Advances physics by one timestep- Handles user changes (moved bodies, added/removed colliders)
- Runs collision detection (broad-phase → narrow-phase)
- Builds islands and solves constraints (contacts + joints)
- Integrates velocities to update positions
- Runs CCD if needed
- 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 raycast_ray_and_get_normal()- Hit with surface normalintersect_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 colliderintersect_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 touchinghandle_contact_force_event()- When contact forces exceed threshold- Built-in:
ChannelEventCollectorsends events to mpsc channels - Enable per-collider with
ActiveEventsflags
PhysicsHooks trait - Custom collision behavior
filter_contact_pair()- Decide if two colliders should collidefilter_intersection_pair()- Filter sensor intersectionsmodify_solver_contacts()- Modify contact properties before solving- Enable per-collider with
ActiveHooksflags - Advanced feature - most users should use
InteractionGroupsinstead
CollisionEvent - Collision state changes
Started(h1, h2, flags)- Colliders began touchingStopped(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 stoppingautostep: Automatically climb stairs/small obstaclesmax_slope_climb_angle: Max climbable slope (radians)min_slope_slide_angle: When to slide down slopessnap_to_ground: Keep grounded on uneven terrain
- Returns
EffectiveCharacterMovementwithtranslationandgroundedstatus
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)orRigidBodyActivation::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)orbody.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 × volumeor 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::MINtoi8::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 tuneMotorModel::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
- Sleeping: Let objects at rest sleep (default behavior)
- Shape choice: Ball/Cuboid/Capsule >> Convex Hull >> TriMesh
- Solver iterations: Lower
num_solver_iterationsif accuracy isn't critical - Parallel: Enable
parallelfeature for multi-core - Broadphase: Keep objects reasonably distributed (not all in one spot)
- CCD: Only enable for fast objects that need it
- Event generation: Only enable events on colliders that need them
- Collision groups: Filter unnecessary collision checks
- 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
parallelfeature - Reduce
num_solver_iterationsif 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 functionscollider.rs: 118 functionsrigid_body_components.rs: 56 functionsgeneric_joint.rs: 47 functionsquery_pipeline.rs: 29 functions
Documentation Improvements
Session 1: Comprehensive API Documentation
Comprehensively documented 300+ public functions across 45+ files:
Fully Documented Modules:
- PhysicsPipeline - Main simulation loop
- RigidBody (~60 methods) - All position, velocity, force, impulse, damping, CCD, locking methods
- RigidBodySet - All collection management methods
- RigidBodyBuilder (~40 methods) - All configuration methods
- Collider (~50 methods) - All property accessors and setters
- ColliderSet - All collection methods
- ColliderBuilder (~60 methods) - All shape constructors and configuration
- All 6 joint types - Comprehensive docs for Fixed, Revolute, Prismatic, Spherical, Rope, Spring
- ImpulseJointSet - All joint collection methods
- QueryPipeline - All spatial query methods
- EventHandler & events - Complete event system
- InteractionGroups - Collision filtering
- IntegrationParameters - Simulation settings
- IslandManager - Sleep/wake system
- CCDSolver - Tunneling prevention
- BroadPhaseBvh, NarrowPhase - Collision detection
- CharacterController - Player movement
- ContactPair - Contact information
- 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) - LockedAxesdynamics/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) - JointMotordynamics/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) - ActiveCollisionTypesgeometry/contact_pair.rs(2)geometry/mod.rs(1) - CollisionEventgeometry/interaction_graph.rs(1)
Pipeline Module (14 examples):
pipeline/query_pipeline.rs(9) - Raycasting, shape casting, point queriespipeline/event_handler.rs(3) - ActiveEvents, EventHandler trait, ChannelEventCollectorpipeline/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:
-
Removed unnecessary
.build()calls: Builders implementInto<T>, so:RigidBodyBuilder::dynamic().build()→RigidBodyBuilder::dynamic()ColliderBuilder::ball(0.5).build()→ColliderBuilder::ball(0.5)- These work directly with
insert()andinsert_with_parent()
-
Fixed API calls to match actual implementation:
&QueryDispatcher→narrow_phase.query_dispatcher()(QueryPipeline needs a dispatcher reference)- Added
NarrowPhase::new()setup for query pipeline examples
-
Corrected property/field names:
hit.toi→hit.time_of_impact(RayIntersection struct)collider.shape()→collider.shared_shape()(when printing/debugging)
-
Added required setup for complex examples:
project_point()example: AddedIntegrationParameters,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
-
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.rshas 12 ignored examples still marked asignore(these are intentionally left asignorefor 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 shapeskeva3.rs- Large tower of blocks (stress test)platform3.rs- Moving kinematic platformsjoints3.rs- All joint types demonstratedcharacter_controller3.rs- Character movementvehicle_controller3.rs- Vehicle physicsccd3.rs- Fast bullets with CCDsensor3.rs- Trigger zonesdespawn3.rs- Removing objectsdebug_boxes3.rs- Visual debuggingrotating_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 Rustsimd-nightly- More SIMD opts on nightlyserde-serialize- Snapshot/restore supportenhanced-determinism- Stricter determinism (disables SIMD)debug-render- Visual debugging helpersprofiler- Detailed performance countersdim2/dim3- 2D or 3D (set by crate, not user)f32/f64- Precision (set by crate, not user)
Resources
- Official Site: https://rapier.rs
- User Guide: https://rapier.rs/docs/
- API Reference: https://docs.rs/rapier3d
- Discord: https://discord.gg/vt9DJSW
- GitHub: https://github.com/dimforge/rapier
- Blog: https://www.dimforge.com/blog
- Crates.io: https://crates.io/crates/rapier3d
- NPM (JS/WASM): Available for web development
Related Dimforge Projects
- 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, ¶ms, &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!