Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Rigid Bodies

Rigid bodies are the foundation of physics simulation. They define how objects move and respond to forces.

Body Types

Dynamic Bodies

Fully simulated physics objects:

#![allow(unused)]
fn main() {
let entity = world.spawn_entities(
    LOCAL_TRANSFORM | GLOBAL_TRANSFORM | RIGID_BODY | COLLIDER,
    1
)[0];

world.core.set_rigid_body(entity, RigidBodyComponent::new_dynamic());

world.core.set_collider(entity, ColliderComponent::new_ball(0.5));
}

Kinematic Bodies

Controlled by code, not affected by forces:

#![allow(unused)]
fn main() {
world.core.set_rigid_body(entity, RigidBodyComponent::new_kinematic());
}

Move kinematic bodies by updating their transform:

#![allow(unused)]
fn main() {
if let Some(transform) = world.core.get_local_transform_mut(kinematic_entity) {
    transform.translation.x += velocity.x * dt;
}
mark_local_transform_dirty(world, kinematic_entity);
}

Static Bodies

Immovable objects (floors, walls):

#![allow(unused)]
fn main() {
world.core.set_rigid_body(entity, RigidBodyComponent::new_static());
}

Helper Functions

Spawning Physics Cubes

#![allow(unused)]
fn main() {
use nightshade::ecs::physics::*;

let cube = spawn_cube_at(world, Vec3::new(0.0, 5.0, 0.0));
}

Spawning Physics Spheres

#![allow(unused)]
fn main() {
let sphere = spawn_sphere_at(world, Vec3::new(0.0, 10.0, 0.0));
}

Applying Forces

Access the Rapier rigid body directly:

#![allow(unused)]
fn main() {
fn apply_force(world: &mut World, entity: Entity, force: Vec3) {
    let Some(rb_component) = world.core.get_rigid_body(entity) else { return };
    let Some(handle) = rb_component.handle else { return };

    if let Some(rigid_body) = world.resources.physics.rigid_body_set.get_mut(handle.into()) {
        rigid_body.add_force(
            rapier3d::prelude::Vector::new(force.x, force.y, force.z),
            true,  // wake up if sleeping
        );
    }
}
}

Applying Impulses

Instant velocity change:

#![allow(unused)]
fn main() {
fn apply_impulse(world: &mut World, entity: Entity, impulse: Vec3) {
    let Some(rb_component) = world.core.get_rigid_body(entity) else { return };
    let Some(handle) = rb_component.handle else { return };

    if let Some(rigid_body) = world.resources.physics.rigid_body_set.get_mut(handle.into()) {
        rigid_body.apply_impulse(
            rapier3d::prelude::Vector::new(impulse.x, impulse.y, impulse.z),
            true,
        );
    }
}
}

Setting Velocity

#![allow(unused)]
fn main() {
fn set_velocity(world: &mut World, entity: Entity, velocity: Vec3) {
    let Some(rb_component) = world.core.get_rigid_body(entity) else { return };
    let Some(handle) = rb_component.handle else { return };

    if let Some(rigid_body) = world.resources.physics.rigid_body_set.get_mut(handle.into()) {
        rigid_body.set_linvel(
            rapier3d::prelude::Vector::new(velocity.x, velocity.y, velocity.z),
            true,
        );
    }
}
}

Getting Velocity

#![allow(unused)]
fn main() {
fn get_velocity(world: &World, entity: Entity) -> Option<Vec3> {
    let rb_component = world.core.get_rigid_body(entity)?;
    let handle = rb_component.handle?;
    let rigid_body = world.resources.physics.rigid_body_set.get(handle.into())?;

    let vel = rigid_body.linvel();
    Some(Vec3::new(vel.x, vel.y, vel.z))
}
}

Mass Properties

#![allow(unused)]
fn main() {
fn set_mass(world: &mut World, entity: Entity, mass: f32) {
    let Some(rb_component) = world.core.get_rigid_body(entity) else { return };
    let Some(handle) = rb_component.handle else { return };

    if let Some(rigid_body) = world.resources.physics.rigid_body_set.get_mut(handle.into()) {
        rigid_body.set_additional_mass(mass, true);
    }
}
}

Locking Axes

Prevent rotation or translation on specific axes:

#![allow(unused)]
fn main() {
if let Some(rigid_body) = world.resources.physics.rigid_body_set.get_mut(handle.into()) {
    // Lock rotation (useful for character controllers)
    rigid_body.lock_rotations(true, true);

    // Lock specific translation axes
    // rigid_body.lock_translations(true, true);  // Lock X and Y
}
}

Damping

Add drag to slow objects:

#![allow(unused)]
fn main() {
if let Some(rigid_body) = world.resources.physics.rigid_body_set.get_mut(handle.into()) {
    rigid_body.set_linear_damping(0.5);   // Translation damping
    rigid_body.set_angular_damping(0.5);  // Rotation damping
}
}

Sleeping

Bodies automatically sleep when stationary. Wake them:

#![allow(unused)]
fn main() {
if let Some(rigid_body) = world.resources.physics.rigid_body_set.get_mut(handle.into()) {
    rigid_body.wake_up(true);
}
}