Skip to content

Commit

Permalink
Fix bodies filter method (#152)
Browse files Browse the repository at this point in the history
Only call filter and modify_contacts methods if needed. This should
improve performance. Eg. filter is only needed if we have
exclude_bodies. modify_contacts is only needed for case we have a static
body that acts as a conveyer belt or for shapes with one way direction.
  • Loading branch information
Ughuuu authored Jul 19, 2024
1 parent a3f6c76 commit bee89aa
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 17 deletions.
74 changes: 66 additions & 8 deletions src/bodies/rapier_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,54 @@ impl RapierBody {
send_contacts,
);
}
self.update_collider_filters(collider_handle, space_handle, physics_engine, false);
}

fn update_colliders_filters(&self, physics_engine: &mut PhysicsEngine) {
let colliders = physics_engine
.body_get_colliders(self.base.get_space_handle(), self.base.get_body_handle())
.to_vec();
let mut override_modify_contacts = false;
for shape in self.base.shapes.clone() {
if shape.one_way_collision && !shape.disabled {
override_modify_contacts = true;
break;
}
}
for collider in colliders {
self.update_collider_filters(
collider,
self.base.get_space_handle(),
physics_engine,
override_modify_contacts,
);
}
}

fn update_collider_filters(
&self,
collider_handle: ColliderHandle,
space_handle: WorldHandle,
physics_engine: &mut PhysicsEngine,
override_modify_contacts: bool,
) {
// if it has any exception, it needs to filter for them
let filter_contacts_enabled = !self.exceptions.is_empty();
physics_engine.collider_set_filter_contacts_enabled(
space_handle,
collider_handle,
filter_contacts_enabled,
);
// if we are a conveyer belt, we need to modify contacts
// also if any shape is one-way
let modify_contacts_enabled = self.get_static_angular_velocity() != ANGLE_ZERO
|| self.get_static_linear_velocity() != Vector::ZERO
|| override_modify_contacts;
physics_engine.collider_set_modify_contacts_enabled(
space_handle,
collider_handle,
modify_contacts_enabled,
);
}

pub fn to_add_static_constant_linear_velocity(&mut self, linear_velocity: Vector) {
Expand All @@ -336,6 +384,7 @@ impl RapierBody {
physics_engine: &mut PhysicsEngine,
) {
self.linear_velocity = p_linear_velocity;
self.update_colliders_filters(physics_engine);
if self.base.mode == BodyMode::STATIC || !self.base.is_valid() {
return;
}
Expand Down Expand Up @@ -397,7 +446,10 @@ impl RapierBody {
}

pub fn get_static_linear_velocity(&self) -> Vector {
self.linear_velocity
if self.base.mode == BodyMode::STATIC {
return self.linear_velocity;
}
Vector::default()
}

pub fn set_angular_velocity(
Expand All @@ -406,10 +458,8 @@ impl RapierBody {
physics_engine: &mut PhysicsEngine,
) {
self.angular_velocity = p_angular_velocity;
if self.base.mode == BodyMode::STATIC {
return;
}
if !self.base.is_valid() {
self.update_colliders_filters(physics_engine);
if self.base.mode == BodyMode::STATIC || !self.base.is_valid() {
return;
}
physics_engine.body_set_angular_velocity(
Expand All @@ -433,7 +483,10 @@ impl RapierBody {
}

pub fn get_static_angular_velocity(&self) -> Angle {
self.angular_velocity
if self.base.mode == BodyMode::STATIC {
return self.angular_velocity;
}
ANGLE_ZERO
}

pub fn set_state_sync_callback(&mut self, p_callable: Callable) {
Expand Down Expand Up @@ -804,12 +857,14 @@ impl RapierBody {
c.impulse = impulse;
}

pub fn add_exception(&mut self, exception: Rid) {
pub fn add_exception(&mut self, exception: Rid, physics_engine: &mut PhysicsEngine) {
self.exceptions.insert(exception);
self.update_colliders_filters(physics_engine);
}

pub fn remove_exception(&mut self, exception: Rid) {
pub fn remove_exception(&mut self, exception: Rid, physics_engine: &mut PhysicsEngine) {
self.exceptions.remove(&exception);
self.update_colliders_filters(physics_engine);
}

pub fn has_exception(&self, exception: Rid) -> bool {
Expand Down Expand Up @@ -1435,6 +1490,7 @@ impl RapierBody {
space.body_add_to_active_list(rid);
}
}
self.update_colliders_filters(physics_engine);
if p_mode.ord() >= BodyMode::RIGID.ord() {
self.mass_properties_changed(physics_engine, physics_spaces);
}
Expand Down Expand Up @@ -2050,6 +2106,8 @@ impl IRapierCollisionObject for RapierBody {
) {
self.mass_properties_changed(physics_engine, physics_spaces);
self.wakeup(physics_engine);
// in case we have a one way shape
self.update_colliders_filters(physics_engine);
}

fn shape_changed(
Expand Down
16 changes: 16 additions & 0 deletions src/rapier_wrapper/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -641,4 +641,20 @@ impl PhysicsEngine {
}
RigidBodyMassProps::default()
}

pub fn body_get_colliders(
&mut self,
world_handle: WorldHandle,
rigidbody_handle: RigidBodyHandle,
) -> &[ColliderHandle] {
if let Some(physics_world) = self.get_mut_world(world_handle)
&& let Some(body) = physics_world
.physics_objects
.rigid_body_set
.get_mut(rigidbody_handle)
{
return body.colliders();
}
&[]
}
}
57 changes: 50 additions & 7 deletions src/rapier_wrapper/collider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,52 @@ fn shape_is_halfspace(shape: &SharedShape) -> bool {
shape.shape_type() == ShapeType::HalfSpace
}
impl PhysicsEngine {
pub fn collider_set_modify_contacts_enabled(
&mut self,
world_handle: WorldHandle,
collider_handle: ColliderHandle,
enable: bool,
) {
if let Some(physics_world) = self.get_mut_world(world_handle) {
if let Some(collider) = physics_world
.physics_objects
.collider_set
.get_mut(collider_handle)
{
let mut active_events = collider.active_hooks();
if enable {
active_events |= ActiveHooks::MODIFY_SOLVER_CONTACTS;
} else {
active_events &= !ActiveHooks::MODIFY_SOLVER_CONTACTS;
}
collider.set_active_hooks(active_events);
}
}
}

pub fn collider_set_filter_contacts_enabled(
&mut self,
world_handle: WorldHandle,
collider_handle: ColliderHandle,
enable: bool,
) {
if let Some(physics_world) = self.get_mut_world(world_handle) {
if let Some(collider) = physics_world
.physics_objects
.collider_set
.get_mut(collider_handle)
{
let mut active_events = collider.active_hooks();
if enable {
active_events |= ActiveHooks::FILTER_CONTACT_PAIRS;
} else {
active_events &= !ActiveHooks::FILTER_CONTACT_PAIRS;
}
collider.set_active_hooks(active_events);
}
}
}

pub fn collider_create_solid(
&mut self,
world_handle: WorldHandle,
Expand Down Expand Up @@ -230,15 +276,12 @@ impl PhysicsEngine {
filter: Group::from(mat.collision_mask),
});
collider.set_solver_groups(InteractionGroups {
memberships: Group::NONE,
filter: Group::NONE,
memberships: Group::GROUP_1,
filter: Group::GROUP_1,
});
collider.set_contact_skin(mat.contact_skin);
collider.set_contact_force_event_threshold(-Real::MAX);
collider.user_data = user_data.get_data();
collider.set_active_hooks(
ActiveHooks::FILTER_CONTACT_PAIRS | ActiveHooks::MODIFY_SOLVER_CONTACTS,
);
if let Some(physics_world) = self.get_mut_world(world_handle) {
let collider_handle = physics_world.insert_collider(collider, body_handle);
// register fluid coupling. Dynamic coupling doens't work for halfspace
Expand Down Expand Up @@ -294,8 +337,8 @@ impl PhysicsEngine {
filter: Group::from(mat.collision_layer),
});
collider.set_solver_groups(InteractionGroups {
memberships: Group::NONE,
filter: Group::NONE,
memberships: Group::GROUP_1,
filter: Group::GROUP_1,
});
let mut collision_types = collider.active_collision_types();
// Area vs Area
Expand Down
4 changes: 2 additions & 2 deletions src/servers/rapier_physics_server_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1246,7 +1246,7 @@ impl RapierPhysicsServerImpl {
let physics_data = physics_data();
if let Some(body) = physics_data.collision_objects.get_mut(&body) {
if let Some(body) = body.get_mut_body() {
body.add_exception(excepted_body);
body.add_exception(excepted_body, &mut physics_data.physics_engine);
body.wakeup(&mut physics_data.physics_engine);
}
}
Expand All @@ -1256,7 +1256,7 @@ impl RapierPhysicsServerImpl {
let physics_data = physics_data();
if let Some(body) = physics_data.collision_objects.get_mut(&body) {
if let Some(body) = body.get_mut_body() {
body.remove_exception(excepted_body);
body.remove_exception(excepted_body, &mut physics_data.physics_engine);
body.wakeup(&mut physics_data.physics_engine);
}
}
Expand Down

0 comments on commit bee89aa

Please sign in to comment.