Skip to main content

rigid_body_creation_and_insertion

A rigid-body is created by a RigidBodyBuilder structure that is based on the builder pattern. Then it needs to be inserted into the physics world, i.e., into its RigidBodySet, which is processed by the physics-pipeline and the query-pipeline.

info

The following example shows several setters that can be called to customize the rigid-body being built. The input values are just random so using this example as-is will not lead to a useful result.

use rapier2d::prelude::*;

// The world that will contain our rigid-bodies.
let mut world = PhysicsWorld::new();

// Builder for a fixed rigid-body.
let _ = RigidBodyBuilder::fixed();
// Builder for a dynamic rigid-body.
let _ = RigidBodyBuilder::dynamic();
// Builder for a kinematic rigid-body controlled at the velocity level.
let _ = RigidBodyBuilder::kinematic_velocity_based();
// Builder for a kinematic rigid-body controlled at the position level.
let _ = RigidBodyBuilder::kinematic_position_based();
// Builder for a body with a status specified by an enum.
let rigid_body = RigidBodyBuilder::new(RigidBodyType::Dynamic)
// The rigid body translation.
// Default: zero vector.
.translation(Vector::new(0.0, 5.0))
// The rigid body rotation.
// Default: no rotation.
.rotation(5.0)
// The rigid body position. Will override `.translation(...)` and `.rotation(...)`.
// Default: the identity isometry.
.pose(Pose::new(Vector::new(1.0, 2.0), 0.4))
// The linear velocity of this body.
// Default: zero velocity.
.linvel(Vector::new(1.0, 2.0))
// The angular velocity of this body.
// Default: zero velocity.
.angvel(2.0)
// The scaling factor applied to the gravity affecting the rigid-body.
// Default: 1.0
.gravity_scale(0.5)
// Whether or not this body can sleep.
// Default: true
.can_sleep(true)
// Whether or not CCD is enabled for this rigid-body.
// Default: false
.ccd_enabled(false)
// All done, actually build the rigid-body.
.build();
// Insert the rigid-body into the world.
let rigid_body_handle = world.insert_body(rigid_body);

All the properties are optional. The only calls that are required are RigidBodyBuilder::new(status), RigidBodyBuilder::fixed(), RigidBodyBuilder::dynamic(), RigidBodyBuilder::kinematic_velocity_based(), or RigidBodyBuilder::kinematic_position_based(), to initialize the builder, and .build() to actually build the rigid-body.

A rigid-body is created by adding the RigidBody component to an entity. Other components like Transform, Velocity, Ccd, etc. can be added for further customization of the rigid-body. Removing one of these optional components afterwards resets the corresponding property of the rigid-body to its default value.

info

The following example shows several initialization of components to customize rigid-body being built. The input values are just random so using this example as-is will not lead to a useful result.

use bevy::prelude::*;
use bevy_rapier2d::prelude::*;

commands
.spawn(RigidBody::Dynamic)
.insert(Transform::from_xyz(0.0, 5.0, 0.0))
.insert(Velocity {
linear: Vec2::new(1.0, 2.0),
angular: 0.2,
})
.insert(GravityScale(0.5))
.insert(Sleeping::disabled())
.insert(Ccd::enabled());

A rigid-body is created by a World.createRigidBody method. The initial state of the rigid-body to create is described by an instance of the RigidBodyDesc class.

Each rigid-body create by the physics world is given an integer identifier rigidBody.handle. This identifier is guaranteed to the different from any identifier of rigid-bodies still existing (or that existed) in the physics world.

info

The following example shows several setters that can be called to customize the rigid-body being built. The input values are just random so using this example as-is will not lead to a useful result.

// The world that will contain our rigid-bodies.
let world = new RAPIER.World({ x: 0.0, y: -9.81 });

// Builder for a fixed rigid-body.
let example1 = RAPIER.RigidBodyDesc.fixed();
// Builder for a dynamic rigid-body.
let example2 = RAPIER.RigidBodyDesc.dynamic();
// Builder for a kinematic rigid-body controlled at the velocity level.
let example3 = RAPIER.RigidBodyDesc.kinematicVelocityBased();
// Builder for a kinematic rigid-body controlled at the position level.
let example4 = RAPIER.RigidBodyDesc.kinematicPositionBased();
// Builder for a body with a status specified by an enum.
let rigidBodyDesc = new RAPIER.RigidBodyDesc(RAPIER.RigidBodyType.Dynamic)
// The rigid body translation.
// Default: zero vector.
.setTranslation(0.0, 5.0)
// The rigid body rotation.
// Default: no rotation.
.setRotation(5.0)
// The linear velocity of this body.
// Default: zero velocity.
.setLinvel(1.0, 2.0)
// The angular velocity of this body.
// Default: zero velocity.
.setAngvel(2.0)
// The scaling factor applied to the gravity affecting the rigid-body.
// Default: 1.0
.setGravityScale(0.5)
// Whether or not this body can sleep.
// Default: true
.setCanSleep(true)
// Whether or not CCD is enabled for this rigid-body.
// Default: false
.setCcdEnabled(false);

// All done, actually build the rigid-body.
let rigidBody = world.createRigidBody(rigidBodyDesc);
// The integer handle of the rigid-body can be read from the `handle` field.
let rigidBodyHandle = rigidBody.handle;

A rigid-body is created from a R3RigidBodyDesc description. This plain structure must first be initialized by one of its constructors (which set the default value of every field), then any of its fields can be modified before it is inserted into the physics world with r3InsertRigidBody. The world copies the description and returns the R3RigidBodyHandle identifying the new rigid-body, which is then given to every function reading or modifying it.

info

The following example shows several fields that can be set to customize the rigid-body being built. The input values are just random so using this example as-is will not lead to a useful result.

// The world that will contain our rigid-bodies.
R2World *world = r2NewWorld();

// Description of a fixed rigid-body.
R2RigidBodyDesc fixed_desc = r2FixedRigidBodyDesc();
// Description of a dynamic rigid-body.
R2RigidBodyDesc dynamic_desc = r2DynamicRigidBodyDesc();
// Description of a kinematic rigid-body controlled at the velocity level.
R2RigidBodyDesc kinematic_velocity_desc = r2KinematicVelocityBasedRigidBodyDesc();
// Description of a kinematic rigid-body controlled at the position level.
R2RigidBodyDesc kinematic_position_desc = r2KinematicPositionBasedRigidBodyDesc();

R2RigidBodyDesc rigid_body = r2DynamicRigidBodyDesc();
// The body type: R2_DYNAMIC, R2_FIXED, R2_KINEMATIC_VELOCITY_BASED, or R2_KINEMATIC_POSITION_BASED.
// Default: the type of the constructor used to initialize the description.
rigid_body.bodyType = R2_DYNAMIC;
// The rigid body translation.
// Default: zero vector.
rigid_body.position.translation = r2Vector(0.0, 5.0);
// The rigid body rotation.
// Default: no rotation.
rigid_body.position.rotation = r2Rotation(5.0);
// The rigid body position. Will override the translation and rotation set above.
// Default: the identity pose.
rigid_body.position = r2Pose(r2Vector(1.0, 2.0), r2Rotation(0.4));
// The linear velocity of this body.
// Default: zero velocity.
rigid_body.linvel = r2Vector(1.0, 2.0);
// The angular velocity of this body.
// Default: zero velocity.
rigid_body.angvel = 2.0;
// The scaling factor applied to the gravity affecting the rigid-body.
// Default: 1.0
rigid_body.gravityScale = 0.5;
// Whether or not this body can sleep.
// Default: 1
rigid_body.canSleep = 1;
// Whether or not CCD is enabled for this rigid-body.
// Default: 0
rigid_body.ccdEnabled = 0;
// All done, actually create the rigid-body and insert it into the world.
R2RigidBodyHandle rigid_body_handle = r2InsertRigidBody(world, &rigid_body);

All the fields are optional. The only calls that are required are r3DynamicRigidBodyDesc(), r3FixedRigidBodyDesc(), r3KinematicVelocityBasedRigidBodyDesc(), or r3KinematicPositionBasedRigidBodyDesc(), to initialize the description, and r3InsertRigidBody to actually create the rigid-body. The rigid-body is removed from the world with r3RemoveRigidBody: its last argument indicates if its colliders must be removed as well (if it is 0, they are kept as colliders without parent).

A rigid-body is created by a RigidBodyBuilder that is based on the builder pattern: each of its methods returns a new builder with the corresponding property set, so they can be chained. The builder is obtained from one of the static methods of the RigidBody class. Then it needs to be inserted into the physics world with PhysicsWorld.add_body (or directly into its RigidBodySet with world.rigid_bodies.insert), which returns the RigidBodyHandle identifying the new rigid-body.

info

The following example shows several setters that can be called to customize the rigid-body being built. The input values are just random so using this example as-is will not lead to a useful result.

import rapier3d as rp

# The world that will contain our rigid-bodies.
world = rp.PhysicsWorld()

# Builder for a fixed rigid-body.
_ = rp.RigidBody.fixed()
# Builder for a dynamic rigid-body.
_ = rp.RigidBody.dynamic()
# Builder for a kinematic rigid-body controlled at the velocity level.
_ = rp.RigidBody.kinematic_velocity_based()
# Builder for a kinematic rigid-body controlled at the position level.
_ = rp.RigidBody.kinematic_position_based()
# The properties of the builder can also be given as keyword arguments.
_ = rp.RigidBody.dynamic(translation=(0.0, 5.0, 1.0), gravity_scale=0.5)
# Builder for a body with a status specified by an enum.
rigid_body = (
rp.RigidBody.new_body(rp.RigidBodyType.DYNAMIC)
# The rigid body translation.
# Default: zero vector.
.translation((0.0, 5.0, 1.0))
# The rigid body rotation, as a scaled rotation axis.
# Default: no rotation.
.rotation((0.0, 0.0, 5.0))
# The rigid body position. Will override `.translation(...)` and `.rotation(...)`.
# Default: the identity isometry.
.position(rp.Isometry3((1.0, 3.0, 2.0), rp.Rotation3.from_scaled_axis((0.0, 0.0, 0.4))))
# The linear velocity of this body.
# Default: zero velocity.
.linvel((1.0, 3.0, 4.0))
# The angular velocity of this body.
# Default: zero velocity.
.angvel((3.0, 0.0, 1.0))
# The scaling factor applied to the gravity affecting the rigid-body.
# Default: 1.0
.gravity_scale(0.5)
# Whether or not this body can sleep.
# Default: True
.can_sleep(True)
# Whether or not CCD is enabled for this rigid-body.
# Default: False
.ccd_enabled(False)
# All done, actually build the rigid-body.
.build()
)
# Insert the rigid-body into the world.
rigid_body_handle = world.add_body(rigid_body)

All the properties are optional. The only calls that are required are RigidBody.fixed(), RigidBody.dynamic(), RigidBody.kinematic_velocity_based(), RigidBody.kinematic_position_based(), or RigidBody.new_body(body_type), to initialize the builder. Each of them also accepts the builder properties as keyword arguments. Calling .build() to actually build the RigidBody is optional: PhysicsWorld.add_body accepts the builder as well, and its optional colliders argument attaches a list of colliders to the new rigid-body in the same call.

Once inserted, the rigid-body is accessed with world.rigid_bodies[handle]. The returned RigidBody is a view of the rigid-body stored in the world: modifying its properties (e.g. rigid_body.linvel = (1.0, 0.0, 0.0)) modifies the simulated rigid-body directly, and a RigidBody built but not inserted yet is copied by the insertion (so modifying it afterwards has no effect on the world). The rigid-body is removed from the world, together with its colliders and the joints attached to it, with PhysicsWorld.remove_body.

info

Typically, the inertia and center of mass are automatically set to the inertia and center of mass resulting from the shapes of the colliders attached to the rigid-body. But they can also be set manually.