Rigid body node

Rigid body node is the one of main physical entities in the engine. Rigid body nodes can be affected by gravity, external forces and other rigid bodies. Use rigid body node everywhere you need natural physical behaviour for your objects.

How to create

Use RigidBodyBuilder to create a rigid body instance:

#![allow(unused)]
fn main() {
extern crate fyrox;
use fyrox::{
    core::{algebra::Vector3, pool::Handle},
    scene::{
        base::BaseBuilder,
        collider::{ColliderBuilder, ColliderShape},
        graph::Graph,
        node::Node,
        rigidbody::RigidBodyBuilder,
    },
};
fn create_cube_rigid_body(graph: &mut Graph) -> Handle<Node> {
    RigidBodyBuilder::new(BaseBuilder::new().with_children(&[
            // Rigid body must have at least one collider
            ColliderBuilder::new(BaseBuilder::new())
                .with_shape(ColliderShape::cuboid(0.5, 0.5, 0.5))
                .build(graph),
        ]))
    .with_mass(2.0)
    .with_lin_vel(Vector3::new(0.0, 3.0, 1.0))
    .build(graph)
}
}

Colliders

Rigid body must have at least one collider to participate in simulation properly, multiple colliders can be used to create complex shapes from simple shapes, you can create concave objects this way. Every collider must be a direct child node of a rigid body. In the editor it could look like this:

colliders

Note that, Box node here is an instance of Rigid Body 2D, and it has Collider 2D as a child and some sprite. This structure (when a rigid body has a collider as a child) is mandatory for physics engine to work correctly! Collider won't work (participate in physical simulation) without a rigid body and a rigid body won't work without a collider. This applied to both 2D and 3D.

Keep in mind, that your graphical representation of an object (some node like Mesh, Sprite, etc.) must be attached to a rigid body. Otherwise, the rigid body will move, but the graphical representation won't. You can also arrange it other way around: a graphical node can have rigid body with a collider, but that requires the rigid body to be kinematic. This is used to create hit boxes, or any other things that should have physical representation, but move together with graphical node.

Force and torque

You can apply forces and torque to any rigid body, but only dynamic bodies will be affected. There is two ways of applying force to a rigid body: at center of mass or at particular point at the body:

#![allow(unused)]
fn main() {
extern crate fyrox;
use fyrox::{core::algebra::Vector3, scene::rigidbody::RigidBody};
fn apply_force_and_torque(rigid_body: &mut RigidBody) {
    // Push rigid body forward at the center of mass.
    rigid_body.apply_force(Vector3::new(0.0, 0.0, 1.0));

    // Kick rigid body at the side (this will also make it rotate)
    rigid_body.apply_force_at_point(Vector3::new(0.0, 0.0, 1.0), Vector3::new(1.0, 0.0, 0.0));

    // Turn rigid body around center of mass.
    rigid_body.apply_torque(Vector3::new(0.0, 3.0, 0.0));
}
}

Kinematic rigid bodies

Sometimes you may want to have direct control over position/rotation of a rigid body and tell the physics engine to not do simulation for the body. This can be achieved by making the rigid body kinematic:

#![allow(unused)]
fn main() {
extern crate fyrox;
use fyrox::{
    core::{algebra::Vector3, pool::Handle},
    scene::{
        base::BaseBuilder,
        collider::{ColliderBuilder, ColliderShape},
        graph::Graph,
        node::Node,
        rigidbody::{RigidBodyBuilder, RigidBodyType},
    },
};

fn create_kinematic_rigid_body(graph: &mut Graph) -> Handle<Node> {
    RigidBodyBuilder::new(BaseBuilder::new().with_children(&[
            // Rigid body must have at least one collider
            ColliderBuilder::new(BaseBuilder::new())
                .with_shape(ColliderShape::cuboid(0.5, 0.5, 0.5))
                .build(graph),
        ]))
    .with_body_type(RigidBodyType::KinematicPositionBased)
    .build(graph)
}
}

Continuous collision detection

Fast-moving rigid bodies can "fly through" other objects (for example a bullet can completely ignore walls if it is moving too fast), this happens because of discrete calculation. This can be fixed by using continuous collision detection, to enable it use either .with_ccd_enabled(state) of RigidBodyBuilder or .set_ccd_enabled(state) of RigidBody.

Dominance

Dominance allows you to set a priority of forces applied to rigid bodies. It defines which rigid body can affect what rigid body, for example you can set the highest dominance for actors and leave dominance of everything else at zero, this way actors will be able to push any other dynamic bodies, but dynamic bodies won't affect actors. This is useful when you don't want your actors be pushed by surrounding objects (like if someone throws a box at an actor, it will stay still if it has higher dominance)

2D rigid bodies

2D rigid bodies have no difference with 3D, except the simulation happens in oXY plane and Z coordinate is ignored.