soft_body_attachments
A particle can also be attached directly to a rigid-body (SoftBody::attach_particleSoftBodyAttachments componentSoftBody.attachParticler3SoftBody_AttachParticleSoftBody.attach_particleSoftBody::detach_particleSoftBodyAttachments component (removing the
component detaches every particle)SoftBody.detachParticler3SoftBody_DetachParticleSoftBody.detach_particle
- Example 2D
- Example 3D
// Attach the last particle of a rope to a rigid box, at the particle's position.
let rope = SoftBodyBuilder::rope(Vector::new(8.0, 9.0), Vector::new(12.0, 9.0), 25)
.pinned_particles([0])
.softness(SpringCoefficients::new(40.0, 1.0));
let rope_handle = world.insert_soft_body(rope);
let last_position = world.soft_bodies[rope_handle].particle_position(24);
let (weight, _) = world.insert(
RigidBodyBuilder::dynamic().translation(last_position - Vector::new(0.0, 0.4)),
ColliderBuilder::cuboid(0.3, 0.3).density(2.0),
);
world.soft_bodies[rope_handle].attach_particle(24, weight, &world.bodies);
// Attach the last particle of a rope to a rigid ball, at the particle's position.
let rope = SoftBodyBuilder::rope(Vector::new(-0.5, 5.0, 3.0), Vector::new(2.5, 5.0, 3.0), 30)
.pinned_particles([0])
.softness(SpringCoefficients::new(40.0, 1.0));
let rope_handle = world.insert_soft_body(rope);
let last_position = world.soft_bodies[rope_handle].particle_position(29);
let (ball, _) = world.insert(
RigidBodyBuilder::dynamic().translation(last_position - Vector::new(0.0, 0.3, 0.0)),
ColliderBuilder::ball(0.25).density(2.0),
);
world.soft_bodies[rope_handle].attach_particle(29, ball, &world.bodies);
- Example 2D
- Example 3D
// Attach the last particle of a rope to a rigid box, at the particle's position.
let ropeDesc = RAPIER.SoftBodyDesc.rope({ x: 8.0, y: 9.0 }, { x: 12.0, y: 9.0 }, 25)
.setPinnedParticles([0])
.setSoftness(40.0, 1.0);
let rope = world.createSoftBody(ropeDesc);
let last = rope.particlePosition(24);
let weight = world.createRigidBody(RAPIER.RigidBodyDesc.dynamic().setTranslation(last.x, last.y - 0.4));
world.createCollider(RAPIER.ColliderDesc.cuboid(0.3, 0.3).setDensity(2.0), weight);
rope.attachParticle(24, weight);
// Attach the last particle of a rope to a rigid ball, at the particle's position.
let ropeDesc = RAPIER.SoftBodyDesc.rope({ x: -0.5, y: 5.0, z: 3.0 }, { x: 2.5, y: 5.0, z: 3.0 }, 30)
.setPinnedParticles([0])
.setSoftness(40.0, 1.0);
let rope = world.createSoftBody(ropeDesc);
let last = rope.particlePosition(29);
let ball = world.createRigidBody(RAPIER.RigidBodyDesc.dynamic().setTranslation(last.x, last.y - 0.3, last.z));
world.createCollider(RAPIER.ColliderDesc.ball(0.25).setDensity(2.0), ball);
rope.attachParticle(29, ball);
Each entry of the SoftBodyAttachments component attaches one particle to the entity of a
rigid-body (or of a cluster). Each time the component changes, the attachments of the
soft-body are updated to match it: the attachments that didn't change keep their anchor, and the ones targeting an
entity which rigid-body isn't created yet are retried on the next frames:
- Example 2D
- Example 3D
// Attach the last particle of a rope to a rigid box, at the particle's position.
let weight = commands
.spawn((
Transform::from_xyz(12.0, 8.6, 0.0),
RigidBody::Dynamic,
Collider::cuboid(0.3, 0.3),
ColliderMassProperties::Density(2.0),
))
.id();
commands.spawn((
Rope,
Transform::from_xyz(8.0, 9.0, 0.0),
SoftBody::rope(Vec2::ZERO, Vec2::new(4.0, 0.0), 25).map(|builder| {
builder
.pinned_particles([0])
.softness(SpringCoefficients::new(40.0, 1.0))
}),
SoftBodyAttachments(vec![SoftBodyAttachment {
particle: 24,
body: weight,
}]),
));
// Attach the last particle of a rope to a rigid ball, at the particle's position.
let ball = commands
.spawn((
Transform::from_xyz(2.5, 4.7, 3.0),
RigidBody::Dynamic,
Collider::ball(0.25),
ColliderMassProperties::Density(2.0),
))
.id();
commands.spawn((
Rope,
Transform::from_xyz(-0.5, 5.0, 3.0),
SoftBody::rope(Vec3::ZERO, Vec3::new(3.0, 0.0, 0.0), 30).map(|builder| {
builder
.pinned_particles([0])
.softness(SpringCoefficients::new(40.0, 1.0))
}),
SoftBodyAttachments(vec![SoftBodyAttachment {
particle: 29,
body: ball,
}]),
));
- Example 2D
- Example 3D
// Attach the last particle of a rope to a rigid box, at the particle's position.
R2SoftBodyDesc rope = r2RopeSoftBodyDesc(r2Vector(8.0, 9.0), r2Vector(12.0, 9.0), 25);
uint32_t pinned[] = {0};
r2SoftBodyDesc_SetPinnedParticles(&rope, (R2IndexView){pinned, 1});
rope.material = r2UniformSoftBodyMaterial((R2SpringCoefficients){40.0, 1.0});
R2SoftBodyHandle rope_handle = r2InsertSoftBody(world, &rope);
R2Vector last_position = r2SoftBody_ParticlePosition(rope_handle, 24);
R2RigidBodyDesc weight_body = r2DynamicRigidBodyDesc();
weight_body.position.translation = r2VectorSub(last_position, r2Vector(0.0, 0.4));
R2RigidBodyHandle weight = r2InsertRigidBody(world, &weight_body);
R2ColliderDesc weight_collider = r2CuboidColliderDesc(r2Vector(0.3, 0.3));
weight_collider.density = 2.0;
r2InsertCollider(weight, &weight_collider);
r2SoftBody_AttachParticle(rope_handle, 24, weight);
// Attach the last particle of a rope to a rigid ball, at the particle's position.
R3SoftBodyDesc rope = r3RopeSoftBodyDesc(r3Vector(-0.5, 5.0, 3.0), r3Vector(2.5, 5.0, 3.0), 30);
uint32_t pinned[] = {0};
r3SoftBodyDesc_SetPinnedParticles(&rope, (R3IndexView){pinned, 1});
rope.material = r3UniformSoftBodyMaterial((R3SpringCoefficients){40.0, 1.0});
R3SoftBodyHandle rope_handle = r3InsertSoftBody(world, &rope);
R3Vector last_position = r3SoftBody_ParticlePosition(rope_handle, 29);
R3RigidBodyDesc ball_body = r3DynamicRigidBodyDesc();
ball_body.position.translation = r3VectorSub(last_position, r3Vector(0.0, 0.3, 0.0));
R3RigidBodyHandle ball = r3InsertRigidBody(world, &ball_body);
R3ColliderDesc ball_collider = r3BallColliderDesc(0.25);
ball_collider.density = 2.0;
r3InsertCollider(ball, &ball_collider);
r3SoftBody_AttachParticle(rope_handle, 29, ball);
Note that r3SoftBody_DetachParticle returns whether the particle was attached at all.
The target of an attachment must be an ordinary rigid-body: r3SoftBody_AttachParticle rejects the root body and
the cluster proxies of a soft-body (they are rigid-bodies too, see r3RigidBody_IsSoftFrame). Two soft-bodies are
linked with a joint between their soft frames instead.
# Attach the last particle of a rope to a rigid ball, at the particle's position.
rope = rp.SoftBody.rope((-0.5, 5.0, 3.0), (2.5, 5.0, 3.0), 30).pinned_particles([0]).softness((40.0, 1.0))
rope_handle = world.add_soft_body(rope)
last_position = world.soft_bodies[rope_handle].particle_position(29)
ball = world.add_body(
rp.RigidBody.dynamic(translation=last_position - (0.0, 0.3, 0.0)),
colliders=[rp.Collider.ball(0.25).density(2.0)],
)
world.soft_bodies[rope_handle].attach_particle(29, ball, world.rigid_bodies)
Note that the rigid-body set of the world is given to SoftBody.attach_particle, so that the anchor can be expressed in
the local frame of the rigid-body. The attachments of a soft-body are listed by its particle_attachments property,
each SoftParticleAttachment giving its particle, its rigid-body (body), its local_anchor, and the impulse it
applied during the last step.