pub struct Body {
pub name: String,
pub inertia: SpatialInertia,
pub parent: i32,
pub joint_idx: usize,
pub geometry: Option<Geometry>,
pub collisions: Vec<GeomInstance>,
pub visuals: Vec<GeomInstance>,
pub material: Option<ContactMaterial>,
}Expand description
A rigid body in the kinematic tree.
Fields§
§name: StringName of the body (optional, for debugging).
inertia: SpatialInertiaSpatial inertia in body-local frame.
parent: i32Index of the parent body (-1 for world/root).
joint_idx: usizeIndex of the joint connecting this body to its parent.
geometry: Option<Geometry>Primary collision geometry, centred on the body frame (if any).
This is the shape used by the contact pipeline. For sources that
describe several offset shapes per body (URDF, MJCF) the full set
lives in Body::collisions; geometry mirrors the first one whose
origin is the identity, so existing single-shape consumers keep working.
collisions: Vec<GeomInstance>All collision shapes attached to this body, each with its own offset.
visuals: Vec<GeomInstance>Visual-only shapes attached to this body (not used for contact).
material: Option<ContactMaterial>This body’s own contact material, or None to use the scene default.
The material applies to every contact this body is part of —
against the ground and against every other body — and the pair is
resolved by ContactMaterial::combine. None means “whatever the
scene is made of”, which is what keeps existing models unchanged:
crate::Model::contact_materials fills those slots with the scene
material and the assembled problem is bit-identical to the old
vec![one; n_bodies].
Which body you attach it to is a physical decision, not a
bookkeeping one. combine takes the maximum friction of the pair,
so a grippy material grips everything the body touches. Putting grip
tape’s mu = 1.5 on a skateboard deck also makes the deck’s underside
grab the asphalt when the tail scrapes — measured, that braked a board
from 0.6 to 0.39 m/s and killed the trick. Putting the same 1.5 on the
shoes raises only the foot-on-deck contacts and leaves the deck-on-
ground contact at wood’s 0.6. See the crate docs on
ContactMaterial::combine.
§The ground has no material of its own
A contact against the ground plane or a heightfield uses the touching
body’s material verbatim — there is no second material to combine
with, so nothing is combined. That is easy to miss now that bodies
differ from one another: setting a deck to wood’s 0.6 and passing
asphalt’s 0.8 as the scene material gives a deck-on-ground friction
of 0.6, not max(0.6, 0.8). The scene material is a default filler
for bodies that carry none, not a property of the ground.
So the friction a body has against the ground is exactly the friction you wrote on that body, and a “road surface” is expressed by leaving the bodies that touch it on the scene material.
Implementations§
Source§impl Body
impl Body
Sourcepub fn new(
name: &str,
inertia: SpatialInertia,
parent: i32,
joint_idx: usize,
) -> Self
pub fn new( name: &str, inertia: SpatialInertia, parent: i32, joint_idx: usize, ) -> Self
Create a body with no attached geometry.
Sourcepub fn with_material(self, material: ContactMaterial) -> Self
pub fn with_material(self, material: ContactMaterial) -> Self
Attach a contact material to this body.
Read Body::material before choosing which body gets it: friction
combines by max, so the material belongs on the part that should
grip, not on the part it touches.