collider_creation_and_insertion
A collider is described by a R3ColliderDesc structure, initialized by one of its constructors (e.g.
r3BallColliderDesc, r3CuboidColliderDesc, r3CapsuleYColliderDesc, or r3DefaultColliderDesc) which set
meaningful default values to all its fields. Its geometric shape is given by its shape field, a R3ShapeDesc
whose kind (e.g. R3_SHAPE_DESC_CUBOID) selects which of its fields are actually read. Then it needs to be
inserted into the physics world: with r3InsertCollider to attach it
to a rigid-body, or with r3InsertColliderWithoutParent otherwise. Both return the R3ColliderHandle identifying
the new collider.
The arrays referenced by a description (vertex buffers, index buffers, compound children, etc.) are only borrowed
until its insertion returns: they can be freed or reused right after. This is also the case of the shared
shapes (R3SharedShape) a description can point to, with the R3_SHAPE_DESC_SHARED kind. A shared shape is an
immutable geometry created by one of the r3...SharedShape functions (e.g. r3BallSharedShape), which can be given
to any number of colliders, and must be freed with r3FreeSharedShape. Some shapes, like convex decompositions or
voxels, can only be created as shared shapes.
The following example shows several fields that can be set to customize the collider being described. The input values are just random so using this example as-is will not lead to a useful result.
- Example 2D
- Example 3D
// The world that will contain our colliders.
R2World *world = r2NewWorld();
// Description of a ball-shaped collider.
R2ColliderDesc ball = r2BallColliderDesc(0.5);
// Description of a cuboid-shaped collider.
R2ColliderDesc cuboid = r2CuboidColliderDesc(r2Vector(0.5, 0.2));
// Description of a capsule-shaped collider. The capsule principal axis is the `x` coordinate axis.
R2ColliderDesc capsule_x = r2CapsuleXColliderDesc(0.5, 0.2);
// Description of a capsule-shaped collider. The capsule principal axis is the `y` coordinate axis.
R2ColliderDesc capsule_y = r2CapsuleYColliderDesc(0.5, 0.2);
// Description of a triangle-mesh-shaped collider.
R2ColliderDesc trimesh = r2DefaultColliderDesc();
r2ShapeDesc_SetTrimesh(&trimesh.shape, (R2VectorView){vertices, 3}, (R2TriangleView){indices, 1}, 0);
// Description of a heightfield-shaped collider.
R2ColliderDesc heightfield = r2DefaultColliderDesc();
heightfield.shape.kind = R2_SHAPE_DESC_HEIGHTFIELD;
heightfield.shape.heights = (R2RealView){heights, 4};
heightfield.shape.rows = 4;
heightfield.shape.columns = 1;
heightfield.shape.scale = scale;
// Description of a collider with the given shared shape.
R2SharedShape *shape = r2BallSharedShape(0.5);
R2ColliderDesc collider = r2DefaultColliderDesc();
collider.shape.kind = R2_SHAPE_DESC_SHARED;
collider.shape.sharedShape = shape;
// The collider translation wrt. the body it is attached to.
// Default: the zero vector.
collider.position.translation = r2Vector(1.0, 2.0);
// The collider rotation wrt. the body it is attached to.
// Default: the identity rotation.
collider.position.rotation = r2Rotation(R2_PI);
// The collider position wrt. the body it is attached to.
// Default: the identity pose.
collider.position = r2Pose(r2Vector(1.0, 2.0), r2Rotation(R2_PI));
// The collider density. If non-zero the collider's mass and angular inertia will be added
// to the inertial properties of the body it is attached to.
// Default: 1.0
collider.density = 1.3;
// The friction coefficient of this collider.
// Default: 0.5
collider.friction = 0.8;
// Whether this collider is a sensor.
// Default: 0
collider.isSensor = 1;
// Insert the collider into the world, without attaching it to a rigid-body.
R2ColliderHandle collider_handle = r2InsertColliderWithoutParent(world, &collider);
R2RigidBodyDesc rigid_body = r2DynamicRigidBodyDesc();
R2RigidBodyHandle rigid_body_handle = r2InsertRigidBody(world, &rigid_body);
// Or insert the collider into the world and attach it to a rigid-body.
R2ColliderHandle handle = r2InsertCollider(rigid_body_handle, &collider);
// The descriptions only borrow the shared shape: free it once it is no longer needed.
r2FreeSharedShape(shape);
// The world that will contain our colliders.
R3World *world = r3NewWorld();
// Description of a ball-shaped collider.
R3ColliderDesc ball = r3BallColliderDesc(0.5);
// Description of a cuboid-shaped collider.
R3ColliderDesc cuboid = r3CuboidColliderDesc(r3Vector(0.5, 0.2, 0.1));
// Description of a capsule-shaped collider. The capsule principal axis is the `x` coordinate axis.
R3ColliderDesc capsule_x = r3CapsuleXColliderDesc(0.5, 0.2);
// Description of a capsule-shaped collider. The capsule principal axis is the `y` coordinate axis.
R3ColliderDesc capsule_y = r3CapsuleYColliderDesc(0.5, 0.2);
// Description of a capsule-shaped collider. The capsule principal axis is the `z` coordinate axis.
R3ColliderDesc capsule_z = r3CapsuleZColliderDesc(0.5, 0.2);
// Description of a triangle-mesh-shaped collider.
R3ColliderDesc trimesh = r3DefaultColliderDesc();
r3ShapeDesc_SetTrimesh(&trimesh.shape, (R3VectorView){vertices, 3}, (R3TriangleView){indices, 1}, 0);
// Description of a heightfield-shaped collider (heights in column-major order).
R3ColliderDesc heightfield = r3DefaultColliderDesc();
heightfield.shape.kind = R3_SHAPE_DESC_HEIGHTFIELD;
heightfield.shape.heights = (R3RealView){heights, 4};
heightfield.shape.rows = 2;
heightfield.shape.columns = 2;
heightfield.shape.scale = scale;
// Description of a collider with the given shared shape.
R3SharedShape *shape = r3BallSharedShape(0.5);
R3ColliderDesc collider = r3DefaultColliderDesc();
collider.shape.kind = R3_SHAPE_DESC_SHARED;
collider.shape.sharedShape = shape;
// The collider translation wrt. the body it is attached to.
// Default: the zero vector.
collider.position.translation = r3Vector(1.0, 2.0, 3.0);
// The collider rotation wrt. the body it is attached to.
// Default: the identity rotation.
collider.position.rotation = r3RotationFromAxisAngle(r3Vector(0.0, 1.0, 0.0), R3_PI);
// The collider position wrt. the body it is attached to.
// Default: the identity pose.
collider.position = r3Pose(r3Vector(1.0, 2.0, 3.0), r3RotationFromAxisAngle(r3Vector(0.0, 1.0, 0.0), R3_PI));
// The collider density. If non-zero the collider's mass and angular inertia will be added
// to the inertial properties of the body it is attached to.
// Default: 1.0
collider.density = 1.3;
// The friction coefficient of this collider.
// Default: 0.5
collider.friction = 0.8;
// Whether this collider is a sensor.
// Default: 0
collider.isSensor = 1;
// Insert the collider into the world, without attaching it to a rigid-body.
R3ColliderHandle collider_handle = r3InsertColliderWithoutParent(world, &collider);
R3RigidBodyDesc rigid_body = r3DynamicRigidBodyDesc();
R3RigidBodyHandle rigid_body_handle = r3InsertRigidBody(world, &rigid_body);
// Or insert the collider into the world and attach it to a rigid-body.
R3ColliderHandle handle = r3InsertCollider(rigid_body_handle, &collider);
// The descriptions only borrow the shared shape: free it once it is no longer needed.
r3FreeSharedShape(shape);
A collider can also be disabled, by setting the enabled field of its description to 0 or, after its creation, with
r3Collider_SetEnabled. A disabled collider is excluded from all the collision-detection and physics until it is
enabled again, which is useful to "turn off" a collider temporarily without removing it (a collider is removed from
the world with r3RemoveCollider).