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

Collider rotation updating #414

Merged
merged 5 commits into from
Aug 6, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
- Add `RapierPhysicsPlugin::in_fixed_schedule`/`::in_schedude` to add rapier’s systems to a fixed/custom
schedule.

### Fix
- Fix debug-renderer lagging one frame behind.
- Fix Collider `Transform` rotation change not being taken into account by the physics engine.

## 0.22.0 (10 July 2023)
### Modified
- Update to Bevy 0.11.
Expand Down
2 changes: 2 additions & 0 deletions src/geometry/collider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,8 @@ impl Default for ContactForceEventThreshold {

/// Component which will be filled (if present) with a list of entities with which the current
/// entity is currently in contact.
///
/// This currently only updates when on an entity with a `Collider`.
#[derive(Component, Default, Reflect)]
#[reflect(Component)]
pub struct CollidingEntities(pub(crate) HashSet<Entity>);
Expand Down
108 changes: 64 additions & 44 deletions src/plugin/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::plugin::configuration::{SimulationToRenderTime, TimestepMode};
use crate::plugin::{RapierConfiguration, RapierContext};
use crate::prelude::{
BevyPhysicsHooks, BevyPhysicsHooksAdapter, CollidingEntities, KinematicCharacterController,
KinematicCharacterControllerOutput, RigidBodyDisabled, Vect,
KinematicCharacterControllerOutput, RigidBodyDisabled,
};
use crate::utils;
use bevy::ecs::system::{StaticSystemParam, SystemParamItem};
Expand Down Expand Up @@ -82,15 +82,9 @@ pub type ColliderComponents<'a> = (
/// System responsible for applying [`GlobalTransform::scale`] and/or [`ColliderScale`] to
/// colliders.
pub fn apply_scale(
mut context: ResMut<RapierContext>,
config: Res<RapierConfiguration>,
mut changed_collider_scales: Query<
(
&mut Collider,
&RapierColliderHandle,
&GlobalTransform,
Option<&ColliderScale>,
),
(&mut Collider, &GlobalTransform, Option<&ColliderScale>),
Or<(
Changed<Collider>,
Changed<GlobalTransform>,
Expand All @@ -101,7 +95,7 @@ pub fn apply_scale(
// NOTE: we don’t have to apply the RapierConfiguration::physics_scale here because
// we are applying the scale to the user-facing shape here, not the ones inside
// colliders (yet).
for (mut shape, handle, transform, custom_scale) in changed_collider_scales.iter_mut() {
for (mut shape, transform, custom_scale) in changed_collider_scales.iter_mut() {
#[cfg(feature = "dim2")]
let effective_scale = match custom_scale {
Some(ColliderScale::Absolute(scale)) => *scale,
Expand All @@ -118,14 +112,6 @@ pub fn apply_scale(
};

if shape.scale != crate::geometry::get_snapped_scale(effective_scale) {
if let Some(co) = context.colliders.get_mut(handle.0) {
if let Some(position) = co.position_wrt_parent() {
let translation: Vect = position.translation.vector.into();
let unscaled_translation: Vect = translation / shape.scale();
let new_translation = unscaled_translation * effective_scale;
co.set_translation_wrt_parent(new_translation.into());
}
}
shape.set_scale(effective_scale, config.scaled_shape_subdivision);
}
}
Expand All @@ -135,10 +121,14 @@ pub fn apply_scale(
pub fn apply_collider_user_changes(
config: Res<RapierConfiguration>,
mut context: ResMut<RapierContext>,
changed_collider_transforms: Query<
(&RapierColliderHandle, &GlobalTransform),
(Without<RapierRigidBodyHandle>, Changed<GlobalTransform>),
>,
(changed_collider_transforms, parent_query, transform_query): (
Query<
(Entity, &RapierColliderHandle, &GlobalTransform),
(Without<RapierRigidBodyHandle>, Changed<GlobalTransform>),
>,
Query<&Parent>,
Query<&Transform>,
),

changed_shapes: Query<(&RapierColliderHandle, &Collider), Changed<Collider>>,
changed_active_events: Query<(&RapierColliderHandle, &ActiveEvents), Changed<ActiveEvents>>,
Expand Down Expand Up @@ -167,14 +157,19 @@ pub fn apply_collider_user_changes(
) {
let scale = context.physics_scale;

for (handle, transform) in changed_collider_transforms.iter() {
if let Some(co) = context.colliders.get_mut(handle.0) {
if co.parent().is_none() {
co.set_position(utils::transform_to_iso(
&transform.compute_transform(),
scale,
))
for (entity, handle, transform) in changed_collider_transforms.iter() {
if context.collider_parent(entity).is_some() {
let (_, collider_position) =
collider_offset(entity, &context, &parent_query, &transform_query);

if let Some(co) = context.colliders.get_mut(handle.0) {
co.set_position_wrt_parent(utils::transform_to_iso(&collider_position, scale));
}
} else if let Some(co) = context.colliders.get_mut(handle.0) {
co.set_position(utils::transform_to_iso(
&transform.compute_transform(),
scale,
))
}
}

Expand Down Expand Up @@ -761,14 +756,51 @@ pub fn init_async_scene_colliders(
}
}

fn collider_offset(
entity: Entity,
context: &RapierContext,
parent_query: &Query<&Parent>,
transform_query: &Query<&Transform>,
) -> (Option<RigidBodyHandle>, Transform) {
let mut body_entity = entity;
let mut body_handle = context.entity2body.get(&body_entity).copied();
let mut child_transform = Transform::default();
while body_handle.is_none() {
if let Ok(parent_entity) = parent_query.get(body_entity) {
if let Ok(transform) = transform_query.get(body_entity) {
child_transform = *transform * child_transform;
}
body_entity = parent_entity.get();
} else {
break;
}

body_handle = context.entity2body.get(&body_entity).copied();
}

if body_handle.is_some() {
if let Ok(transform) = transform_query.get(body_entity) {
let scale_transform = Transform {
scale: transform.scale,
..default()
};

child_transform = scale_transform * child_transform;
}
}

(body_handle, child_transform)
}

/// System responsible for creating new Rapier colliders from the related `bevy_rapier` components.
pub fn init_colliders(
mut commands: Commands,
config: Res<RapierConfiguration>,
mut context: ResMut<RapierContext>,
colliders: Query<(ColliderComponents, Option<&GlobalTransform>), Without<RapierColliderHandle>>,
mut rigid_body_mprops: Query<&mut ReadMassProperties>,
parent_query: Query<(&Parent, Option<&Transform>)>,
parent_query: Query<&Parent>,
transform_query: Query<&Transform>,
) {
let context = &mut *context;
let physics_scale = context.physics_scale;
Expand Down Expand Up @@ -845,21 +877,9 @@ pub fn init_colliders(
builder = builder.contact_force_event_threshold(threshold.0);
}

let mut body_entity = entity;
let mut body_handle = context.entity2body.get(&body_entity).copied();
let mut child_transform = Transform::default();
while body_handle.is_none() {
if let Ok((parent_entity, transform)) = parent_query.get(body_entity) {
if let Some(transform) = transform {
child_transform = *transform * child_transform;
}
body_entity = parent_entity.get();
} else {
break;
}

body_handle = context.entity2body.get(&body_entity).copied();
}
let body_entity = entity;
let (body_handle, child_transform) =
collider_offset(entity, context, &parent_query, &transform_query);

builder = builder.user_data(entity.to_bits() as u128);

Expand Down