2 and 3-dimensional rigid body physics engine for Rust.

Overview

crates.io

crates.io (nphysics2d) crates.io (nphysics3d) Build status

Users guide | 2D Documentation | 3D Documentation | Forum

⚠️ **This crate is now passively-maintained. It is being superseded by the Rapier project.** ⚠️


nphysics

nphysics is a 2 and 3-dimensional physics engine for games and animations. It uses ncollide for collision detection, and nalgebra for vector/matrix math. 2D and 3D implementations both share the same code!

Examples are available in the examples2d and examples3d directories. Interactive 3D are available there. Because those demos are based on WASM and WebGl 1.0 they should work on most modern browsers. Feel free to ask for help and discuss features on the official user forum.

Why another physics engine?

There are a lot of physics engine out there. However having a physics engine written in Rust is much more fun than writing bindings and has several advantages:

  • It shows that Rust is suitable for soft real-time applications. − It features an efficient implementation of multibodies using the reduced-coordinates approach. Constraint-based joints are also supported.
  • It shows that there is no need to write two separate engines for 2D and 3D: genericity wrt the dimension is possible (modulo low level arithmetic specializations for each dimension).
  • In a not-that-near future, C++ will die of ugliness. Then, people will search for a physics engine and nphysics will be there, proudly exhibiting its Rusty sexiness.

Features

  • Static, dynamic, and kinematic rigid bodies.
  • Common convex primitives: box, ball, convex polyhedron.
  • Concave geometries built from convex primitives: compound geometries, triangle mesh, polylines.
  • Multibodies using reduced-coordinates approaches or constraints-based joints.
  • Multibody joint limits and motors.
  • Stable stacking due to non-linear a position-based penetration correction and one-shot contact manifold generation.
  • Island based sleeping (objects deactivation when they are at rest).
  • Ray casting.
  • Swept sphere based continuous collision detection.
  • Ball-in-socket joint.
  • FixedJoint joint.
  • Sensors.
  • Deformable bodies (aka. soft-bodies)
  • Kinematic bodies
  • WASM support

What is missing?

nphysics is a very young library and needs to learn a lot of things to become a grown up. Many missing features are because of missing features on ncollide. Features missing from nphysics itself include:

  • more joints, joint limits, joint motors and breakable joints.
  • parallel pipeline
  • GPU-based pipeline

Dependencies

The libraries needed to compile the physics engine are:

  • ncollide: the collision detection library.
  • nalgebra: the linear algebra library.

The libraries needed to compile the examples are:

  • kiss3d: the 3d graphics engine.
Comments
  • extensions for 2D convex shape

    extensions for 2D convex shape

    Hello Sébastien,

    I tried to play around with 2D convex shapes and noticed that they are not completely supported yet. Then I tried to patch in what's missing and to my surprise succeeded in getting a basic 2D convex demo up and running. Maybe you want to take a look at it, comment and - if everything is ok - merge? This pull request contains the parts of nphysics.

    Note: I also created "demo2Dconvex" branches in my github repositories. They have the dependencies properly set so that they compile and can be tested.

    Michi

    opened by MichaelRiss 17
  • Need overhaul for embedable multi-theading support

    Need overhaul for embedable multi-theading support

    Dear Authors, this project is valuable and has much better potential use if you provide and overhaul for putting the World and other stuff Arc/Mutex compatible.

    Regards

    opened by ahmedaliadeel 16
  • Allow user-defined data inside RigidBody

    Allow user-defined data inside RigidBody

    Original issue from @WaDelma : sebcrozet/ncollide#122.

    Currently if you register ContactSignalHandler nphysics World there is no way to detect which entities are colliding.

    enhancement breaking change P-high 
    opened by sebcrozet 16
  • Partially integrated collision groups into nphysics

    Partially integrated collision groups into nphysics

    Don't really know if this integration is good for you, I didn't implement this from https://github.com/sebcrozet/nphysics/issues/55:

    the modification will have no effect if it is performed after the rigid body has been added to the scene). If the rigid body is static, the corresponding group should be set automatically after the user modified the group

    opened by Kerollmops 12
  • Allow avoidance of exclusive World's ownership from Testbed

    Allow avoidance of exclusive World's ownership from Testbed

    Referencing https://github.com/sebcrozet/nphysics/issues/131

    Current state

    I succeeded in compiling:

    • balls2d official nphysics example, which is working fine.
    • my target repository compiled and is now working

    I'm opening the pull request to show my progress, and discuss about the shortcomings.

    TODO List

    Tasks this PR will certainly not cover

    They should be copied over to https://github.com/sebcrozet/nphysics/issues/131 to keep track of them.

    Failed attempts

    This section is only for reference, to help understand why some choices have been made.

    Very first attempt

    Within Testbed, I tried to replace World by &mut World, no chance in compiling ever after.

    Second attempt

    Within Testbed, I tried to add a "WorldOwner", which objective was to own a reference to a &mut World, then have a retrieve function to access it.

    I lost myself again in complex lifetime annotations.

    Third attempt

    I started small, read some articles (again) Then, I used RefCell<World> to store a mutable world inside Testbed. Once compiling and at least 1 official example working, I used Rc<RefCell<World>.

    Balls2d compiled successfully, but not my reproduction repository : indeed, specs::System needs its resources to be sync::Send to be sent beetween threads.

    So I tried to Arc<RefCell<World>>, but I quickly realized I had no choice but to use Arc<RefCell<World>>, since RefCell is not sync::Send.

    Minor mistakes

    I thought I had a deadlock, but it was actually lack of gravity 🙄; then graphicsManager was not called when modifying nphysics::World, so it leads to a crash when attempting to modify color when moving an object. I fixed it by updating graphics nodes after the update loop.

    opened by Vrixyz 10
  • Give access to body set in broad phase filter

    Give access to body set in broad phase filter

    Meant to be paired with ncollide#359.

    This utilizes the new formulation of the BroadPhasePairFilter trait to supply both the BodySet and ColliderSet to the broad phase pair filter. This allows for the filter to take into account information that exists in the body, such as multibody link ancestry, velocity, etc.

    From the user's perspective, this removes GeometricalWorld::set_broad_phase_pair_filter and provides a MechanicalWorld::step_with_filter(.., impl BroadPhasePairFilter) where the filter has access to the body set.

    enhancement breaking change 
    opened by neachdainn 8
  • Make `ColliderDesc` derive `Clone`.

    Make `ColliderDesc` derive `Clone`.

    I'm not sure if this is a terrible idea, but this lets me do:

    struct Body(Vec<ColliderDesc<f32>>);
    
            // Create my simple Player shape.
            let body_shape = ShapeHandle::new(Ball::new(radius));
            let mut collision_groups = CollisionGroups::new();
            collision_groups.set_membership(&[2]);
            let body_collider = ColliderDesc::new(body_shape)
                .set_collision_groups(collision_groups)
                .clone();
            let body = Body(vec![body_collider]);
    

    Then I have a single place in my code that detects when a Body component is added, then iterates through the colliders I create and adds them. It probably isn't terribly helpful for more complex use cases, but for my simple case of wanting to model a physical environment and not caring a whole lot about the actual physics, it beats creating a separate struct identical to ColliderDesc just so I can copy over the values from something that isn't a reference.

    I'm open to deriving Clone not being the best solution. Maybe an .into_owned() method that returns self rather than &self or something else. And maybe there's an easy workaround I'm just missing. I mainly wanted to see if this compiled, and when it did, I thought I'd save you a bit of work. :)

    Thanks.

    opened by ndarilek 7
  • Examples execution errors on OSX

    Examples execution errors on OSX

    It seems that sfml/csml cannot create the proper context for OpenGl or something like that. When I ./examples2d/target/release/gravity --help:

    Warning. OpenGL debugging not supported on this platform.
    Error. Unable to find a suitable pixel format.
    Warning: The created OpenGL context does not fully meet the settings that were requested
    Requested: version = 0.1 ; depth bits = 10 ; stencil bits = 10 ; AA level = 2 ; core = true ; debug = true
    Created: version = 2.1 ; depth bits = 10 ; stencil bits = 10 ; AA level = 2 ; core = false ; debug = false
    Failed to activate the window's context
    Failed to activate the window's context
    

    I have set the dynamics and statics libraries paths like this:

    export LD_LIBRARY_PATH=$HOME/.brew/lib/
    export DYLD_LIBRARY_PATH=$HOME/.brew/lib/
    

    When I execute the gravity example, sometimes I get a segfault, sometimes an infinite loop of Failed to activate the window's context...

    opened by Kerollmops 7
  • first draft for forces and impulses, one enhanced demo and tests for 2D

    first draft for forces and impulses, one enhanced demo and tests for 2D

    Hello Sebastien!

    I send you a draft of force and impulse integration into nphysics.

    Some aspects:

    • Theoretically the implementation should/could already be complete for 2D and 3D. However, so far I only tested and played around in 2D. I wanted you to have a look at the design decisions first before I go into fine tuning and testing the code also in 3D.

    • I looked at the construct with the BodyForceGenerator but couldn't grasp its philosophy. Therefore - for the time being - I replaced it with my own construct:

      • Forces get appended and keep acting on the bodies until they get cleared.
      • Impulses act one-time only.

      I believe this is performance-wise a good solution as forces are usually act over time and impulses are usually instantaneous. Other engines clear the forces in each step and then the application has to re-add the forces immediately afterwards. That's a lot of overhead in my opinion, especially when you think about moving the physics calculation to the GPU eventually. That would result in a lot of data traffic between CPU and GPU each simulation step. Please comment on it and maybe explain what your design idea with the BodyForceGenerator is.

    • In the functions append_force_wrt_point and apply_impulse_wrt_point I chose to let the relative pointer point from where the force acts towards the center of mass. When I imagine the vectors for the force decomposition in components that act on the center of mass and in components that make the body rotate, it is the intuitive way to do it. However, bullet - it seems - has the opposite idea: They have the pointer point from the center of mass to the point where the force acts on. What do you think? Follow intuition or follow convention and make it easy for people that switch to nphysics from other engines? I start to lean towards the bullet approach as their idea could also be seen as a "local vector" where the origin is at the center of mass of the corresponding body.

    • The gravity handling has been pulled into RigidBody. This design trade-off means that each RigidBody contains a copy of the gravity of its World. It was either this duplication of data or a back reference from each RigidBody to its World in order to access the gravity. But this would mean that each World must be encapsulated into an Rc<T> so that we can give out Weak<T> pointers to each RigidBody. I'm undecided on this, so I went with the less intrusive option. If you favor the weak pointer over the data duplication, the change shouldn't cause too much problems in my code sections.

    • During the development of the tests and the enhanced demo I repeatedly ran into problems with the deactivation of resting bodies. As a user of the library I think I would prefer calls similar to PhysX where the calls for applying forces and impulses contain a boolean flag wakeup that activates the corresponding body. That might be an API change that should probably even be done before the initial merge it into the master.

    • The nphysics_testbed2 modification to allow user defined key controls is just a draft. Eventually I would like to avoid the code duplication for each key. But how do you feel generally about the idea of allowing demos to provide user defined functions?

    • About the tests:

      • The first test with the unrealistic big time step should probably be removed.

      • Right now each test routine tests quite a range of functionality. What do you think about cutting these large test routines down so that each tests just a single feature? I would lean to it, but it would lead to code duplication ... and probably a more impressive looking test output. :smiley:

      • While writing the tests I stumbled across two bugs that seem to be situated in other parts of nphysics or rust.

        • One is a division by zero panic when instantiating two bodies at exactly the same position and then starting the simulation and applying forces on them.
        • The other happens when you remove a RigidBody from World.

        I left the commented sections that trigger the bugs in the tests.rs file for further investigation.

    • I inverted the scroll wheel direction in nphysics_testbed2 so that it's more in line with the zoom scroll direction of applications like google earth, etc.

    • The rotation direction in nphysics_testbed2 may be counter intuitive as it seems the y-axis of sfml points downwards and therefore the z-axis (rotation axis) points into the monitor. Therefore the bodies on the screen rotate in the opposite direction than what the right hand three finger rule would intuitively suggest.

    I hope this draft is of some use to you and does not go completely against your design ideas. And if so, just tell me, I know that I took a risk with this design draft. Also, don't feel pressured to review it quickly, it took a long time to code, it can take a long time to review then :laughing: and I'm not in a rush. Have some fun with the "meteor impacts" in the demo when switching off the forces after the bodies have reached some altitude!

    cu Michi

    opened by MichaelRiss 7
  • Simulations are no longer deterministic.

    Simulations are no longer deterministic.

    The HashMap api related to custom hasher is not yet accessible from a stable Rust compiler. Thus, we cannot use a non-random hasher. This should be fixable in future version of the compiler.

    opened by sebcrozet 7
  • Utilize BodySet as a trait object instead of param

    Utilize BodySet as a trait object instead of param

    This commit prevents BodySet from polluting as a type parameter into all the core types required for physics stepping. Thanks to this, problems involved in dealing with these types in Specs usage are alleviated. However, this commit also removes the associated type of Body and always assumes dynamic dispatch on the Body type. This is an evolution of #226 that loosens future restrictions mentioned in that thread.

    enhancement breaking change P-high 
    opened by distransient 6
  • FEMVolume `renumber_dofs` breaks kinematic indices

    FEMVolume `renumber_dofs` breaks kinematic indices

    Hello,

    the boundary_collider_desc in FEMVolume method calls renumber_dofs under the hood, which appears to neglect to update the kinematic_nodes, causing the kinematic nodes to be scattered throughout the volume.

    Minimal code example:

    let mut fem_body = FEMVolumeDesc::cube(5, 2, 2)
            .scale(Vector3::new(10.0, 0.5, 0.5))
            .young_modulus(1.0e3)
            .poisson_ratio(0.2)
            .mass_damping(0.2)
            .build();
    
        let to_be_kinematized = fem_body.positions().iter().enumerate().filter_map(|(i,p)| {
            if i % 3 == 0 && *p == -5.0 {
                dbg!(p);
                Some(i/3)
            } else {
                None
            }
        }).collect::<Vec<_>>();
    
        for i in to_be_kinematized.iter() {
            fem_body.set_node_kinematic(*i, true);
        }
    
        let co = fem_body.boundary_collider_desc();
    
        {
            let pp = fem_body.positions();
            dbg!(to_be_kinematized.iter().map(|i| {
                [pp[i * 3], pp[i * 3 + 1], pp[i * 3 + 2]]
            }).collect::<Vec<_>>());
        }
    

    Observe, in the output from dbg!, that the x-coordinates are all over the place.

    opened by werner291 0
  • Wrong inertia calculation in `<RigidBody<N> as BodyPart<N>>::add_local_inertia_and_com`

    Wrong inertia calculation in ` as BodyPart>::add_local_inertia_and_com`

    As the Parallel axis theorem shows, one cannot just add inertia tensors of two "objects" whose CoM isn't overlapping.

    The method <RigidBody<N> as BodyPart<N>>::add_local_inertia_and_com just adds the given inertia to the local inertia.

    // Update local inertia.
    self.local_inertia += inertia;
    

    found in: https://github.com/dimforge/nphysics/blob/master/src/object/rigid_body.rs#L747-L766

    opened by DasEtwas 0
  • Until `MechanicalWorld::step` is called, `GeometricalWorld::interferences_with_point` uses old collider positions

    Until `MechanicalWorld::step` is called, `GeometricalWorld::interferences_with_point` uses old collider positions

    For context, I am writing a level editor that uses interferences_with_point to determine the entities the user are clicking on. When the user moves an entity, the underlying body's position is moved. However, the call to interferences_with_point still seems to be using the old object's position until the next time step is called. I have tried both updating the collider position along with the body and using GeometricalWorld::sync_colliders, which has had no effect. Reading through the source of step, I have taken a few stabs in the dark on what will finally allow interferences_with_point to work (without actually calling step), culminating with this:

    mech: DefaultMechanicalWorld<f32>,
    geo: DefaultGeometricalWorld<f32>,
    bodies: DefaultBodySet<f32>,
    colliders: DefaultColliderSet<f32>,
    joints: DefaultJointConstraintSet<f32>,
    forces: DefaultForceGeneratorSet<f32>,
    ...
    self.mech.maintain(&mut self.geo, &mut self.bodies, &mut self.colliders, &mut self.joints);
    self.geo.clear_events();
    self.geo.sync_colliders(&self.bodies, &mut self.colliders);
    self.geo.perform_broad_phase(&self.colliders);
    self.geo.perform_narrow_phase(&self.colliders);
    self.colliders.foreach_mut(|_, c| c.clear_update_flags());
    

    Still, this did not work. In the end, my workaround was this:

    let old_timestep = self.mech.timestep();
    self.mech.set_timestep(0.0);
    self.mech.step(
        &mut self.geo,
        &mut self.bodies,
        &mut self.colliders,
        &mut self.joints,
        &mut self.forces,
    );
    self.mech.set_timestep(old_timestep);
    

    This feels like a bit of a hack, especially in the presence of all those other functions which I expected to work, having read the source, but I am all out of leads.

    Is there a specific algorithm that users of nphysics are supposed to use to ensure interferences_with_point is querying an up to date world, or is this perhaps a bug in the library?

    opened by zachreizner 1
  • Broad phase pair filters cannot access body information

    Broad phase pair filters cannot access body information

    The current API for the broad phase pair filter cannot access any information about the bodies that are colliding. The filter has access to the handles via the BroadPhasePairFilter trait but there is not way to retrieve the body information from the set due to the fact that MechanicalWorld::step, which calls the filter, requires mutable access to the body set. Utilizing the user data on the collider is sufficient for cases where the information does not change during each step (e.g., parent information) but cannot be used for information about a body that may have been updated.

    opened by neachdainn 2
  • URDF, SDF, MJCF Model Loading

    URDF, SDF, MJCF Model Loading

    Hey all,

    I am curious if support exists, or will in the future, for the loading of URDF, SDF and/or MJCF model files into nphysics. This functionality would make nphysics highly desirable for simulating robotics and help Rust expand into the robotics world in general. This is something I could potentially help with if there agreement to support such model files.

    Perhaps the library is still too young in that it is missing a large variety of joint types, motor types, and sensor types etc,. to make URDF loading of models feasible.

    enhancement good first issue P-low 
    opened by cmuell89 7
Owner
dimforge
Rust crates for numerical simulation including, but not limited to, real-time (as well as offline) physics, mechanics, and robotics.
dimforge
2D and 3D physics engine based on Extended Position Based Dynamics for Bevy.

Bevy XPBD Bevy XPBD is a 2D and 3D physics engine based on Extended Position Based Dynamics (XPBD) for the Bevy game engine. Design Below are some of

Joona Aalto 203 Jul 6, 2023
A physics lib for the bevy game engine based on physme

physimple Physimple aims to be the simplest(and capable) physics engine(currently for bevy) WARNING Beware for breaking changes with each update for n

null 24 Oct 28, 2022
Little 2D physics engine used for my game Crate Before Attack.

Circle2D Circle2D is a little physics library used for my game CrateBeforeAttack. Live demo: https://koalefant.github.io/circle2d/ It is not productio

Evgeny Andreeshchev 24 Jan 14, 2022
Rust implementations of Fast Fourier Transform convolution and correlation for n-dimensional arrays

fftconvolve Rust implementations of Fast Fourier Transform convolution and correlation for n-dimensional arrays Examples 1-dimensional use fftconvolve

Rhys Newell 33 Jan 5, 2023
Sandbox is a pixel physics simulator inspired by other such like Sandspiel and Noita

Sandbox Sandbox is a pixel physics simulator inspired by other such like Sandspiel and Noita. It's also a precursor for an ongoing game project. Sandb

Okko Hakola 76 Nov 3, 2022
Reimplementation of Matthias Müller's "Ten Minute Physics" demos in Rust with WASM + WebGL

ten-minute-physics-rs reimplements Matthias Müller's "Ten Minute Physics" demos in Rust with WASM + WebGL. Compared with the source pure Javascript im

Lucas V. Schuermann 56 Jan 26, 2023
An ergonomic physics API for bevy games.

Heron An ergonomic physics API for 2d and 3d bevy games. (powered by rapier) How it looks like fn main() { App::build() .add_plugins(DefaultPlug

Jonathan Cornaz 313 Dec 16, 2022
Game physics in one weekend with bevy

Game Physics in a Weekend (in Rust) This project is an implementation of the Game Physics in a Weekend book using the Rust programming language and th

Cameron Hart 28 Dec 23, 2022
Atomic Physics Library

Iridium Atomic Physics Library Attempt at making a atomic database. Uses Nubase2020, ENSDF for decay chains, atomic masses, and half-lives. Nubase2020

J.A Sory 14 Jun 19, 2022
Verlet physics plugin for bevy.

bevy_verlet Simple Verlet points and sticks implementation for bevy. Features You can simply add a VerletPoint component on any entity with a Transfor

Félix Lescaudey de Maneville 34 Dec 9, 2022
A networked (p2p), cross-platform physics simulation example using rollback netcode

bevy_gaff (work in progress) bevy_gaff is an attempt at making a networked (p2p), cross-platform physics simulation using rollback netcode. It synchro

Johan Klokkhammer Helsing 13 Sep 5, 2023
Minecraft-esque voxel engine prototype made with the bevy game engine. Pending bevy 0.6 release to undergo a full rewrite.

vx_bevy A voxel engine prototype made using the Bevy game engine. Goals and features Very basic worldgen Animated chunk loading (ala cube world) Optim

Lucas Arriesse 125 Dec 31, 2022
RTS game/engine in Rust and WebGPU

What is this? A real time strategy game/engine written with Rust and WebGPU. Eventually it will be able to run in a web browser thanks to WebGPU. This

Thomas SIMON 258 Dec 25, 2022
A no-frills Tetris implementation written in Rust with the Piston game engine, and Rodio for music.

rustris A no-frills Tetris implementation written in Rust with the Piston game engine, and Rodio for music. (C) 2020 Ben Cantrick. This code is distri

Ben Cantrick 17 Aug 18, 2022
Rust Game engine 3D (and 2D)

A feature-rich, production-ready, general purpose 2D/3D game engine written in Rust with a scene editor.

rg3d engine 5.4k Jan 9, 2023
2-player game made with Rust and "ggez" engine, based on "Conway's Game of Life"

fight-for-your-life A 2-player game based on the "Conway's Game of Life", made with Rust and the game engine "ggez". Create shapes on the grid that wi

Petros 3 Oct 25, 2021
game engine built in rust, using wgpu and probably other stuff too

horizon game engine engine for devpty games, made in 99.9% rust and 0.1% shell. this is our main project currently. the engine will be used for most i

DEVPTY 2 Apr 12, 2022
Vulkan and Rust rendering~game engine which creation is covered with YouTube videos

Vulkan and Rust rendering~game engine which creation is covered with YouTube videos

小鳥 11 Dec 4, 2022
A simple and minimal game engine library built in rust.

Neptune A brand new free, open-source minimal and compact game engine built in rust. Design Goals We plan to make Neptune a small and minimal engine,

Levitate 17 Jan 25, 2023