[][src]Crate specs_physics

Usage

To use specs-physics, add the following dependency to your projects Cargo.toml:

[dependencies]
specs-physics = "0.3.0"

specs-physics defines a set of Specs Systems and Components to handle the creation, modification and removal of nphysics objects (RigidBody, Collider) and the synchronisation of object positions and global gravity between both worlds.

Generic types

All Systems and Components provided by this crate require between one and two type parameters to function properly. These were explicitly introduced to keep this integration as generic as possible and allow compatibility with as many external crates and game engines as possible.

N: RealField

nphysics is built upon nalgebra and uses various types and structures from this crate. specs-physics builds up on this even further and utilises the same structures, which all work with any type that implements nalgebra::RealField. nalgebra::RealField is by default implemented for various standard types, such as f32 andf64. nalgebra is re-exported under specs_physics::nalgebra.

P: Position<N>

a type parameter which implements the specs_physics::bodies::Position trait, requiring also a Component implementation with a FlaggedStorage. This Position Component is used to initially place a RigidBody in the nphysics world and later used to synchronise the updated translation and rotation of these bodies back into the Specs world.

Example for a Position Component, simply using the "Isometry" type (aka combined translation and rotation structure) directly:

use specs::{Component, DenseVecStorage, FlaggedStorage};
use specs_physics::{bodies::Position, nalgebra::Isometry3};

struct Pos(pub Isometry3<f32>);

impl Component for Pos {
    type Storage = FlaggedStorage<Self, DenseVecStorage<Self>>;
}

impl Position<f32> for Pos {
    fn isometry(&self) -> &Isometry3<f32> {
        &self.0
    }

    fn isometry_mut(&mut self) -> &mut Isometry3<f32> {
        &mut self.0
    }

    fn set_isometry(&mut self, isometry: &Isometry3<f32>) -> &mut Pos {
        self.0 = *isometry;
        self
    }
}

If you're using Amethyst, you can enable the "amethyst" feature for this crate which provides a Position<Float> impl for Transform.

[dependencies]
specs-physics = { version = "0.3", features = ["amethyst"] }

Components

PhysicsBody

The specs_physics::PhysicsBody Component is used to define RigidBody from the comforts of your Specs world. Changes to the PhysicsBody will automatically be synchronised with nphysics.

Example:

use specs_physics::{
    nalgebra::{Matrix3, Point3},
    nphysics::{algebra::Velocity3, object::BodyStatus},
    PhysicsBodyBuilder,
};

let physics_body = PhysicsBodyBuilder::from(BodyStatus::Dynamic)
    .gravity_enabled(true)
    .velocity(Velocity3::linear(1.0, 1.0, 1.0))
    .angular_inertia(Matrix3::from_diagonal_element(3.0))
    .mass(1.3)
    .local_center_of_mass(Point3::new(0.0, 0.0, 0.0))
    .build();
PhysicsCollider

specs_physics::PhysicsColliders are the counterpart to PhysicsBodys. They can exist on their own or as a part of a PhysicsBody PhysicsColliders are used to define and create Collider's in nphysics.

Example:

use specs_physics::{
    colliders::Shape,
    nalgebra::Isometry3,
    ncollide::world::CollisionGroups,
    nphysics::material::{BasicMaterial, MaterialHandle},
    PhysicsColliderBuilder,
};

let physics_collider = PhysicsColliderBuilder::from(Shape::Rectangle(10.0, 10.0, 1.0))
    .offset_from_parent(Isometry3::identity())
    .density(1.2)
    .material(MaterialHandle::new(BasicMaterial::default()))
    .margin(0.02)
    .collision_groups(CollisionGroups::default())
    .linear_prediction(0.001)
    .angular_prediction(0.0)
    .sensor(true)
    .build();

To assign multiple Collider's the the same body, Entity hierarchy can be used. This utilises specs-hierarchy.

Systems

The following Systems currently exist and should be added to your Dispatcher in order:

  1. specs_physics::systems::SyncBodiesToPhysicsSystem - handles the creation, modification and removal of RigidBody's based on the PhysicsBody Component and an implementation of the Position trait.

  2. specs_physics::systems::SyncCollidersToPhysicsSystem - handles the creation, modification and removal of Collider's based on the PhysicsCollider Component. This System depends on SyncBodiesToPhysicsSystem as Collider can depend on RigidBody.

  3. specs_physics::systems::SyncParametersToPhysicsSystem - handles the modification of the nphysics Worlds parameters.

  4. specs_physics::systems::PhysicsStepperSystem - handles the progression of the nphysics World and causes objects to actually move and change their position. This System is the backbone for collision detection.

  5. specs_physics::systems::SyncBodiesFromPhysicsSystem - handles the synchronisation of RigidBody positions and dynamics back into the Specs Components. This System also utilises the Position trait implementation.

An example Dispatcher with all required Systems:

use specs::DispatcherBuilder;
use specs_physics::{
    systems::{
        PhysicsStepperSystem,
        SyncBodiesFromPhysicsSystem,
        SyncBodiesToPhysicsSystem,
        SyncCollidersToPhysicsSystem,
        SyncParametersToPhysicsSystem,
    },
    SimplePosition,
};

let dispatcher = DispatcherBuilder::new()
    .with(
        SyncBodiesToPhysicsSystem::<f32, SimplePosition<f32>>::default(),
        "sync_bodies_to_physics_system",
        &[],
    )
    .with(
        SyncCollidersToPhysicsSystem::<f32, SimplePosition<f32>>::default(),
        "sync_colliders_to_physics_system",
        &["sync_bodies_to_physics_system"],
    )
    .with(
        SyncParametersToPhysicsSystem::<f32>::default(),
        "sync_gravity_to_physics_system",
        &[],
    )
    .with(
        PhysicsStepperSystem::<f32>::default(),
        "physics_stepper_system",
        &[
            "sync_bodies_to_physics_system",
            "sync_colliders_to_physics_system",
            "sync_gravity_to_physics_system",
        ],
    )
    .with(
        SyncBodiesFromPhysicsSystem::<f32, SimplePosition<f32>>::default(),
        "sync_bodies_from_physics_system",
        &["physics_stepper_system"],
    )
    .build();

If you're using Amethyst Transforms directly, you'd pass the generic arguments like so:

use amethyst_core::{Float, Transform};
use specs_physics::systems::SyncBodiesToPhysicsSystem;
SyncBodiesToPhysicsSystem::<Float, Transform>::default();

Alternatively to building your own Dispatcher, you can always fall back on the convenience function specs_physics::physics_dispatcher(), which returns a configured default Dispatcher for you or specs_physics::register_physics_systems() which takes a DispatcherBuilder as an argument and registers the required Systems for you.

Re-exports

pub use nalgebra;
pub use ncollide3d as ncollide;
pub use nphysics3d as nphysics;
pub use shrev;
pub use self::bodies::util::SimplePosition;
pub use self::bodies::PhysicsBody;
pub use self::bodies::PhysicsBodyBuilder;
pub use self::colliders::PhysicsCollider;
pub use self::colliders::PhysicsColliderBuilder;

Modules

bodies
colliders
events
parameters

Parameters module

systems

Structs

Physics

Resource holding the internal fields where physics computation occurs. Some inspection methods are exposed to allow debugging.

PhysicsParent

The PhysicsParent Component is used to represent a parent/child relationship between physics based Entitys.

Functions

physics_dispatcher

Convenience function for configuring and building a Dispatcher with all required physics related Systems.

register_physics_systems

Convenience function for registering all required physics related Systems to the given DispatcherBuilder. This also serves as a blueprint on how