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

Fast renormalize #14316

Merged
merged 15 commits into from
Jul 22, 2024
Prev Previous commit
Next Next commit
Tests for Rot2 renorm + change the used constructor to avoid a debug_…
…assertion.
  • Loading branch information
IQuick143 committed Jul 14, 2024
commit af1730fb1346471cfdd89e7098f20eca820c192c
42 changes: 38 additions & 4 deletions crates/bevy_math/src/rotation2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,10 @@ impl Rot2 {
let length_squared = self.length_squared();
// Based on a taylor approximation of the inverse square root, see `[Dir3::fast_renormalize]` for more details.
IQuick143 marked this conversation as resolved.
Show resolved Hide resolved
let length_recip_approx = 0.5 * (3.0 - length_squared);
Rot2::from_sin_cos(
self.sin * length_recip_approx,
self.cos * length_recip_approx,
)
Rot2 {
sin: self.sin * length_recip_approx,
cos: self.cos * length_recip_approx,
}
}

/// Returns `true` if the rotation is neither infinite nor NaN.
Expand Down Expand Up @@ -535,6 +535,40 @@ mod tests {
assert!(normalized_rotation.is_normalized());
}

#[test]
fn fast_renormalize() {
let rotation = Rot2 {
sin: 1.0,
cos: 0.5,
};
let normalized_rotation = rotation.normalize();

let mut unnormalized_rot = rotation;
let mut renormalized_rot = rotation;
let mut initially_normalized_rot = normalized_rotation;
let mut fully_normalized_rot = normalized_rotation;

// Compute a 64x (=2^6) multiple of the rotation.
IQuick143 marked this conversation as resolved.
Show resolved Hide resolved
for _ in 0..6 {
unnormalized_rot = unnormalized_rot * unnormalized_rot;
renormalized_rot = renormalized_rot * renormalized_rot;
initially_normalized_rot = initially_normalized_rot * initially_normalized_rot;
fully_normalized_rot = fully_normalized_rot * fully_normalized_rot;

renormalized_rot = renormalized_rot.fast_renormalize();
fully_normalized_rot = fully_normalized_rot.normalize();
}

assert!(!unnormalized_rot.is_normalized());

assert!(renormalized_rot.is_normalized());
assert!(fully_normalized_rot.is_normalized());

assert_relative_eq!(fully_normalized_rot, renormalized_rot, epsilon = 0.000001);
assert_relative_eq!(fully_normalized_rot, unnormalized_rot.normalize(), epsilon = 0.000001);
assert_relative_eq!(fully_normalized_rot, initially_normalized_rot.normalize(), epsilon = 0.000001);
}

#[test]
fn try_normalize() {
// Valid
Expand Down
Loading