Skip to content

Commit

Permalink
Fix incorrect rotation in Transform::rotate_around. (bevyengine#5300)
Browse files Browse the repository at this point in the history
Someone noted that the `rotate_around` method did not give the results they expected: [discord thread](https://discord.com/channels/691052431525675048/996497295325544479)
I tested `rotate_around` and their workaround and it seems like it was indeed incorrect.

Here is a scene with some cubes at different angles all being rotated around the center on the Y axis.

https://user-images.githubusercontent.com/29694403/178598432-407d7e80-1caf-4b17-b69b-66d9156c81e1.mp4

Interestingly, the middle cube rotates as you might expect. This threw me for a bit of a loop before I added the other cubes to the test haha.

Here is the same scene with the order multiplication of the quaternions flipped in `rotate_around`.

https://user-images.githubusercontent.com/29694403/178598446-a98026f3-524c-448b-8437-4d0d3175c6ca.mp4

That looks better :)

## Changelog

* Fixed `rotate_around` rotating the wrong way around
* Added `translate_around`. - Split out the translation code from `rotate_around`.
* Simplified/optimized `rotate_local_*` methods. - Yep, That works somehow.

<sup>Quaternions sure are wacky. Do not ask me how this works exactly, haha.</sup>

Co-authored-by: devil-ira <justthecooldude@gmail.com>
  • Loading branch information
2 people authored and ItsDoot committed Feb 1, 2023
1 parent 0151f14 commit 3254132
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 9 deletions.
2 changes: 1 addition & 1 deletion crates/bevy_transform/src/components/global_transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ impl GlobalTransform {
#[inline]
pub fn rotate_around(&mut self, point: Vec3, rotation: Quat) {
self.translation = point + rotation * (self.translation - point);
self.rotation *= rotation;
self.rotate(rotation);
}

/// Multiplies `self` with `transform` component by component, returning the
Expand Down
40 changes: 32 additions & 8 deletions crates/bevy_transform/src/components/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ impl Transform {
}

/// Rotates this [`Transform`] by the given rotation.
///
/// If this [`Transform`] has a parent, the `rotation` is relative to the rotation of the parent.
#[inline]
pub fn rotate(&mut self, rotation: Quat) {
self.rotation = rotation * self.rotation;
Expand Down Expand Up @@ -233,31 +235,53 @@ impl Transform {
self.rotate(Quat::from_rotation_z(angle));
}

/// Rotates this [`Transform`] around its `X` axis by `angle` (in radians).
/// Rotates this [`Transform`] by the given `rotation`.
///
/// The `rotation` is relative to this [`Transform`]'s current rotation.
#[inline]
pub fn rotate_local(&mut self, rotation: Quat) {
self.rotation *= rotation;
}

/// Rotates this [`Transform`] around its local `axis` by `angle` (in radians).
#[inline]
pub fn rotate_local_axis(&mut self, axis: Vec3, angle: f32) {
self.rotate_local(Quat::from_axis_angle(axis, angle));
}

/// Rotates this [`Transform`] around its local `X` axis by `angle` (in radians).
#[inline]
pub fn rotate_local_x(&mut self, angle: f32) {
self.rotate_axis(self.local_x(), angle);
self.rotate_local(Quat::from_rotation_x(angle));
}

/// Rotates this [`Transform`] around its `Y` axis by `angle` (in radians).
/// Rotates this [`Transform`] around its local `Y` axis by `angle` (in radians).
#[inline]
pub fn rotate_local_y(&mut self, angle: f32) {
self.rotate_axis(self.local_y(), angle);
self.rotate_local(Quat::from_rotation_y(angle));
}

/// Rotates this [`Transform`] around its `Z` axis by `angle` (in radians).
/// Rotates this [`Transform`] around its local `Z` axis by `angle` (in radians).
#[inline]
pub fn rotate_local_z(&mut self, angle: f32) {
self.rotate_axis(self.local_z(), angle);
self.rotate_local(Quat::from_rotation_z(angle));
}

/// Translates this [`Transform`] around a `point` in space.
///
/// If this [`Transform`] has a parent, the `point` is relative to the [`Transform`] of the parent.
#[inline]
pub fn translate_around(&mut self, point: Vec3, rotation: Quat) {
self.translation = point + rotation * (self.translation - point);
}

/// Rotates this [`Transform`] around a `point` in space.
///
/// If this [`Transform`] has a parent, the `point` is relative to the [`Transform`] of the parent.
#[inline]
pub fn rotate_around(&mut self, point: Vec3, rotation: Quat) {
self.translation = point + rotation * (self.translation - point);
self.rotation *= rotation;
self.translate_around(point, rotation);
self.rotate(rotation);
}

/// Rotates this [`Transform`] so that its local negative `Z` direction is toward
Expand Down

0 comments on commit 3254132

Please sign in to comment.