Skip to content

Commit ff08dd5

Browse files
Fix positioning due to scaling in hierarchies. (#646)
1 parent 710c163 commit ff08dd5

File tree

4 files changed

+82
-5
lines changed

4 files changed

+82
-5
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
- Added a serialization `serialization2` example for `bevy_rapier2d`.
88

9+
## Fixed
10+
11+
- Fix position being incorrect when a rigidbody bevy entity has a scaled parent. [#646](https://github.com/dimforge/bevy_rapier/pull/646)
12+
913
## v0.29.0 (18 February 2025)
1014

1115
### Added

src/plugin/plugin.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,4 +640,63 @@ mod test {
640640
}
641641
}
642642
}
643+
644+
#[test]
645+
fn parent_child() {
646+
return main();
647+
648+
use bevy::prelude::*;
649+
650+
fn main() {
651+
let mut app = App::new();
652+
app.add_plugins((
653+
TransformPlugin,
654+
TimePlugin,
655+
RapierPhysicsPlugin::<NoUserData>::default().in_fixed_schedule(),
656+
));
657+
run_test(&mut app);
658+
}
659+
660+
fn run_test(app: &mut App) {
661+
app.insert_resource(TimeUpdateStrategy::ManualDuration(
662+
std::time::Duration::from_secs_f32(1f32 / 60f32),
663+
));
664+
app.add_systems(Startup, init_rapier_configuration);
665+
app.add_systems(Startup, setup_physics);
666+
667+
app.finish();
668+
for _ in 0..100 {
669+
app.update();
670+
}
671+
let context = app
672+
.world_mut()
673+
.query::<RapierContext>()
674+
.get_single(&app.world())
675+
.unwrap();
676+
677+
println!("{:#?}", &context.rigidbody_set.bodies);
678+
}
679+
680+
pub fn init_rapier_configuration(
681+
mut config: Query<&mut RapierConfiguration, With<DefaultRapierContext>>,
682+
) {
683+
let mut config = config.single_mut();
684+
*config = RapierConfiguration {
685+
force_update_from_transform_changes: true,
686+
..RapierConfiguration::new(1f32)
687+
};
688+
}
689+
690+
pub fn setup_physics(mut commands: Commands) {
691+
let parent = commands
692+
.spawn(Transform::from_scale(Vec3::splat(5f32)))
693+
.id();
694+
let mut entity = commands.spawn((
695+
Collider::ball(1f32),
696+
Transform::from_translation(Vec3::new(200f32, 100f32, 3f32)),
697+
RigidBody::Fixed,
698+
));
699+
entity.set_parent(parent);
700+
}
701+
}
643702
}

src/plugin/systems/mod.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,23 @@ pub mod tests {
239239
let child_handle = rigidbody_set.entity2body[&child];
240240
let child_body = rigidbody_set.bodies.get(child_handle).unwrap();
241241
let body_transform = utils::iso_to_transform(child_body.position());
242-
assert_eq!(
243-
GlobalTransform::from(body_transform),
244-
*child_transform,
245-
"Collider transform should have have global rotation and translation"
242+
243+
fn transforms_approx_equal(
244+
a: &GlobalTransform,
245+
b: &GlobalTransform,
246+
epsilon: f32,
247+
) -> bool {
248+
a.translation().abs_diff_eq(b.translation(), epsilon)
249+
&& a.scale().abs_diff_eq(b.scale(), epsilon)
250+
&& a.rotation().abs_diff_eq(b.rotation(), epsilon)
251+
}
252+
assert!(
253+
transforms_approx_equal(
254+
&GlobalTransform::from(body_transform),
255+
child_transform,
256+
1.0e-5,
257+
),
258+
"Collider transforms should have have equal global rotation and translation"
246259
);
247260
}
248261
}

src/plugin/systems/rigid_body.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ pub fn writeback_rigid_bodies(
470470
// We need to compute the new local transform such that:
471471
// curr_parent_global_transform * new_transform = interpolated_pos
472472
// new_transform = curr_parent_global_transform.inverse() * interpolated_pos
473-
let (_, inverse_parent_rotation, inverse_parent_translation) =
473+
let (inverse_parent_scale, inverse_parent_rotation, inverse_parent_translation) =
474474
parent_global_transform
475475
.affine()
476476
.inverse()
@@ -479,6 +479,7 @@ pub fn writeback_rigid_bodies(
479479

480480
#[allow(unused_mut)] // mut is needed in 2D but not in 3D.
481481
let mut new_translation = inverse_parent_rotation
482+
* inverse_parent_scale
482483
* interpolated_pos.translation
483484
+ inverse_parent_translation;
484485

0 commit comments

Comments
 (0)