Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ImpulseJointSet::get_mut option to wake up connected bodies #716

Merged
merged 3 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions examples3d/vehicle_joints3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,17 @@ pub fn init_world(testbed: &mut Testbed) {
_ => {}
}
}

let mut should_wake_up = false;
if thrust != 0.0 || steering != 0.0 {
physics.bodies.get_mut(body_handle).unwrap().wake_up(true);
should_wake_up = true;
}

// Apply steering to the axles.
for steering_handle in &steering_joints {
let steering_joint = physics.impulse_joints.get_mut(*steering_handle).unwrap();
let steering_joint = physics
.impulse_joints
.get_mut(*steering_handle, should_wake_up)
.unwrap();
steering_joint.data.set_motor_position(
JointAxis::AngY,
max_steering_angle * steering,
Expand All @@ -187,7 +190,10 @@ pub fn init_world(testbed: &mut Testbed) {

let ms = [1.0 / speed_diff, speed_diff];
for (motor_handle, &ms) in motor_joints.iter().copied().zip(ms.iter()) {
let motor_joint = physics.impulse_joints.get_mut(motor_handle).unwrap();
let motor_joint = physics
.impulse_joints
.get_mut(motor_handle, should_wake_up)
.unwrap();
motor_joint.data.set_motor_velocity(
JointAxis::AngX,
-30.0 * thrust * ms * boost,
Expand Down
33 changes: 23 additions & 10 deletions src/dynamics/joint/impulse_joint/impulse_joint_set.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashSet;

use super::ImpulseJoint;
use crate::geometry::{InteractionGraph, RigidBodyGraphIndex, TemporaryInteractionIndex};

Expand Down Expand Up @@ -42,7 +44,7 @@ pub struct ImpulseJointSet {
rb_graph_ids: Coarena<RigidBodyGraphIndex>,
joint_ids: Arena<TemporaryInteractionIndex>, // Map joint handles to edge ids on the graph.
joint_graph: InteractionGraph<RigidBodyHandle, ImpulseJoint>,
pub(crate) to_wake_up: Vec<RigidBodyHandle>, // A set of rigid-body handles to wake-up during the next timestep.
pub(crate) to_wake_up: HashSet<RigidBodyHandle>, // A set of rigid-body handles to wake-up during the next timestep.
Copy link
Member

@sebcrozet sebcrozet Sep 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can’t use std::collections::HashSet here because that would break determinism due to internal randomness and unstable iteration order. Instead it should use parry::utils::HashMap<RigidBodyHandle, ()> (unfortunately, parry::utils doesn’t have a HashSet. But we could add one in parry and switch it here afterward).

}

impl ImpulseJointSet {
Expand All @@ -52,7 +54,7 @@ impl ImpulseJointSet {
rb_graph_ids: Coarena::new(),
joint_ids: Arena::new(),
joint_graph: InteractionGraph::new(),
to_wake_up: vec![],
to_wake_up: HashSet::new(),
}
}

Expand Down Expand Up @@ -145,9 +147,20 @@ impl ImpulseJointSet {
}

/// Gets a mutable reference to the joint with the given handle.
pub fn get_mut(&mut self, handle: ImpulseJointHandle) -> Option<&mut ImpulseJoint> {
pub fn get_mut(
&mut self,
handle: ImpulseJointHandle,
wake_up_connected_bodies: bool,
) -> Option<&mut ImpulseJoint> {
let id = self.joint_ids.get(handle.0)?;
self.joint_graph.graph.edge_weight_mut(*id)
let joint = self.joint_graph.graph.edge_weight_mut(*id);
if wake_up_connected_bodies {
if let Some(joint) = &joint {
self.to_wake_up.insert(joint.body1);
self.to_wake_up.insert(joint.body2);
}
}
joint
}

/// Gets the joint with the given handle without a known generation.
Expand Down Expand Up @@ -269,8 +282,8 @@ impl ImpulseJointSet {
self.joint_ids[handle] = self.joint_graph.add_edge(graph_index1, graph_index2, joint);

if wake_up {
self.to_wake_up.push(body1);
self.to_wake_up.push(body2);
self.to_wake_up.insert(body1);
self.to_wake_up.insert(body2);
}

ImpulseJointHandle(handle)
Expand Down Expand Up @@ -320,10 +333,10 @@ impl ImpulseJointSet {

if wake_up {
if let Some(rb_handle) = self.joint_graph.graph.node_weight(endpoints.0) {
self.to_wake_up.push(*rb_handle);
self.to_wake_up.insert(*rb_handle);
}
if let Some(rb_handle) = self.joint_graph.graph.node_weight(endpoints.1) {
self.to_wake_up.push(*rb_handle);
self.to_wake_up.insert(*rb_handle);
}
}

Expand Down Expand Up @@ -372,8 +385,8 @@ impl ImpulseJointSet {
}

// Wake up the attached bodies.
self.to_wake_up.push(h1);
self.to_wake_up.push(h2);
self.to_wake_up.insert(h1);
self.to_wake_up.insert(h2);
}

if let Some(other) = self.joint_graph.remove_node(deleted_id) {
Expand Down
2 changes: 1 addition & 1 deletion src/pipeline/physics_pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ impl PhysicsPipeline {
self.counters.stages.user_changes.start();
for handle in impulse_joints
.to_wake_up
.drain(..)
.drain()
.chain(multibody_joints.to_wake_up.drain(..))
{
islands.wake_up(bodies, handle, true);
Expand Down