Skip to content

Bevy XPBD v0.3.0

Compare
Choose a tag to compare
@Jondolf Jondolf released this 04 Nov 22:16
· 185 commits to main since this release

0.3 is a huge release with tons of new features, bug fixes, and quality of life improvements, especially for collision detection. Here are some highlights:

  • Modular narrow phase: Narrow phase collision detection has been refactored into modular plugins instead of being tightly coupled with the solver
  • Improved contact stability: Collisions are significantly more stable, and dynamic friction has been fixed to handle different masses correctly
  • Collider scale: Colliders can be scaled using Transform
  • Child colliders: Colliders can be freely nested using entity hierarchies
  • Async colliders: Colliders can be automatically generated from meshes and glTF scenes
  • Accessing, modifying and filtering collision: The new Collisions resource can be used for accessing and modifying contacts in custom systems
  • Transform for positions: Transform can be used instead of the internal Position and Rotation components
  • Debug rendering: Physics objects and interactions can be rendered for debugging purposes
  • Dominance: Dynamic bodies can be configured to have infinite mass relative to bodies with a lesser dominance
  • Bevy 0.12 support: Bevy XPBD has been updated to Bevy 0.12
  • Time unification: Timing and scheduling resources have been replaced by the unified Time<Physics> and Time<Substeps> resources

Read the more complete changelog after the migration guide for more details.

Migration guide

Here is a (non-exhaustive) migration guide for migrating from 0.2 to 0.3.

Collision iteration

Before:

fn my_system(mut collision_event_reader: EventReader<Collision>) {
    for Collision(contact) in collision_event_reader.iter() {
        println!("Penetration depth: {}", contact.penetration);
    }
}

After:

fn my_system(mut collision_event_reader: EventReader<Collision>) {
    for Collision(contacts) in collision_event_reader.read() {
        for manifold in contacts.manifolds.iter() {
            for contact in manifold.contacts.iter() {
                println!("Penetration depth: {}", contact.penetration);
            }
        }
    }
}

This is more verbose, but it provides multiple contact points instead just one. In the future, this will hopefully be made more ergonomic with helper methods.

A new and more powerful Collisions resource was also added. It can be used to achieve a similar result.

Collider scale (#189)

Before:

let mesh = meshes.add(Mesh::from(shape::Cube { size: 1.0 }));
commands.spawn((
    PbrBundle {
        mesh,
        transform: Transform::from_scale(Vec3::new(10.0, 1.0, 10.0)),
        ..default()
    },
    // Collider isn't scaled by transform
    Collider::cuboid(10.0, 1.0, 10.0),
    RigidBody::Static,
));

After:

let mesh = meshes.add(Mesh::from(shape::Cube { size: 1.0 }));
commands.spawn((
    PbrBundle {
        mesh,
        transform: Transform::from_scale(Vec3::new(10.0, 1.0, 10.0)),
        ..default()
    },
    // Collider size takes transform scale into account
    Collider::cuboid(1.0, 1.0, 1.0),
    RigidBody::Static,
));

Collider creation from meshes

  • trimesh_from_bevy_meshtrimesh_from_mesh
  • convex_decomposition_from_bevy_meshconvex_decomposition_from_mesh

Unified time (#214)

  • Replace every DeltaTime in PhysicsSchedule and every SubDeltaTime in SubstepSchedule with Time, elsewhere explicitly use Time<Physics> and Time<Substep>
  • When advancing physics manually, instead of setting DeltaTime, advance the Time<Physics> clock using time.advance_by(...)
  • Replace PhysicsTimestep with Time::new_with(Physics::fixed_hz(...)) and so on
  • Replace PhysicsLoop::pause/resume with Time::<Physics>::pause/unpause
  • Replace PhysicsLoop::step with advancing the physics clock using Time::<Physics>::advance_by
  • Replace PhysicsTimescale usage with Time::<Physics>::with/set_relative_speed

What's Changed

  • Debug render colliders by @Jondolf in #73
  • Add more global and entity-level debug render options by @Jondolf in #74
  • Add debug rendering axes and joints and improve configuration API by @Jondolf in #76
  • Move SpatialQuery methods to SpatialQueryPipeline by @LeshaInc in #77
  • Add enabled flag to PhysicsDebugConfig to globally disable debug rendering at runtime by @LeshaInc in #78
  • Add trimesh_with_flags and trimesh_from_bevy_mesh_with_flags by @Jondolf in #79
  • Add PhysicsTimescale resource for slow-motion or fast-forward simulation by @dasisdormax in #80
  • Use world-space center of mass in penetration constraint by @Jondolf in #81
  • Add clear methods for ray and shape hits and clear the hits on disable by @Jondolf in #82
  • Expand AABBs only in the movement direction by @Jondolf in #83
  • Improve simulation stability when object are far from world origin by @LeshaInc in #84
  • Add back global contact positions by @Jondolf in #86
  • Run transform propagation before init_rigid_bodies. Fixes #88 by @LeshaInc in #89
  • Add criterion benchmarks by @LeshaInc in #91
  • Setup PhysicsSchedule and SubstepSchedule to use single-threaded executor by @LeshaInc in #92
  • Use contact manifolds instead of single contacts for collisions by @Jondolf in #90
  • Add ExternalImpulse and ExternalAngularImpulse by @Jondolf in #95
  • Filter operation reodered for a little performance boost by @TrustNoOneElse in #98
  • Store local contact normals and transform them into world-space at each solve by @Jondolf in #97
  • Support Transform for moving and positioning bodies by @Jondolf in #96
  • Fix typo in docs by @Zentropivity in #103
  • Automatically add Position and Rotation for colliders by @Jondolf in #101
  • Separate narrow phase from solver into NarrowPhasePlugin by @Jondolf in #100
  • feature: Add DistanceJoint and 2D and 3D examples. by @shanecelis in #105
  • Debug render rigid body axes at center of mass by @Jondolf in #109
  • Added text that explained how to use the example 'chain_3d' by @Aztro-dev in #107
  • Add "Bounciness" and "Elasticity" aliases for Restitution by @Jondolf in #117
  • Clamp coefficient of restitution between 0 and 1 and improve restitution docs by @Jondolf in #118
  • Add current_position getter for RigidBodyQueryItem by @Jondolf in #120
  • Remove solver iteration loop by @Jondolf in #121
  • Clarify that external forces and impulses are local (edit: not true, fixed by #144) by @Jondolf in #123
  • Register CoefficientCombine by @grace125 in #126
  • Correct time dilation for FixedUpdate schedule. by @starwolfy in #128
  • Fix center of mass and inertia computations and add tests by @Jondolf in #127
  • add Rotation::from_sin_cos constructor by @RJ in #130
  • Avoid allocate on spatial queries. ray_hits_callback, shape_hits_callback, intersections_callback by @bnyu in #133
  • Dynamic friction fix by @felixbjorkeson in #52
  • Fix 2d position_to_transform changing child Transform z-component by @ShaddowSpy in #134
  • Make Rotation & PreviousRotation derive PartialEq by @RJ in #136
  • Fix tests on mac m1 by @RJ in #138
  • Register/Reflect Component of Sensor by @grace125 in #141
  • Fix Transform initialization for children and refactor prepare.rs by @Jondolf in #140
  • Clarify that forces are in world space and improve force docs by @Jondolf in #144
  • Fix math cross-platform determinism by @Jondolf in #145
  • Combine insert calls into bundles to reduce archetype count by @Jondolf in #151
  • Avoid incremental updates to Qbvh by @NiseVoid in #152
  • Fix contact stability for non-convex colliders by @Jondolf in #156
  • Collision post processing by @datael in #155
  • Add Trigger alias for Sensor and improve Sensor docs by @Jondolf in #160
  • Make PreviousGlobalTransform public and derive traits by @Jondolf in #166
  • Add contact queries by @Jondolf in #169
  • Use cache in CI and run tests on multiple operating systems by @Jondolf in #153
  • Ensure newly created bodies get simulated the frame they are added by @RJ in #174
  • Skip re-writing the same values to components, to satisfy bevy's change detection. by @RJ in #173
  • Add PR template by @Jondolf in #176
  • Improve Collisions API and docs by @Jondolf in #175
  • Fix sleeping and collision event issues by @Jondolf in #112
  • Add Dominance by @Jondolf in #178
  • Move narrow phase collision validity checks to broad phase by @Jondolf in #179
  • Add ContactReportingPlugin by @Jondolf in #182
  • Move all collision logic and plugins into new collision module by @Jondolf in #184
  • Add debug rendering for sleeping bodies by @Jondolf in #185
  • Use swept AABBs for collider AABBs by @Jondolf in #188
  • Child colliders by @Jondolf in #154
  • Collider scale by @Jondolf in #189
  • Map entities by @johanhelsing in #192
  • Add ColliderDensity by @Jondolf in #194
  • Debug render spatial queries by @Jondolf in #186
  • Expose SyncConfig fields by @johanhelsing in #195
  • Async colliders by @Jondolf in #190
  • Warn about explosive behavior caused by overlapping at spawn by @Jondolf in #202
  • Add ignore_self property for RayCaster and ShapeCaster by @Jondolf in #205
  • Use Transform instead of Position and Rotation in examples by @Jondolf in #201
  • Fix sleeping debug rendering for child colliders by @Jondolf in #206
  • Improve documentation by @Jondolf in #208
  • Make debug-plugin a default feature and improve docs by @Jondolf in #209
  • Enable bevy's png feature in the 3d examples by @Friz64 in #203
  • Improve movement in examples by @Jondolf in #210
  • Refactor character controller examples and support gamepad input by @Jondolf in #212
  • Update to actions/checkout@v4. by @waywardmonkeys in #215
  • docs: Use more backticks. by @waywardmonkeys in #216
  • Use intradoc links rather than #method anchors. by @waywardmonkeys in #220
  • Move x comparison in broad phase up to early-out as soon as possible by @datael in #219
  • Improve character controller examples by @Jondolf in #222
  • Add "Acknowledgements" section to README.md by @Jondolf in #143
  • Upgrade to Bevy 0.12 by @Jondolf in #187

New Contributors

Full Changelog: v0.2.0...v0.3.0