Skip to content

Conversation

@stevehello166
Copy link
Contributor

@stevehello166 stevehello166 commented Dec 11, 2025

Objective

When working with 64 bit numbers and transforms i would find it much more convenient if bevy natively had a 64 bit direction type. Therefore I added a 64 bit direction type.

Solution

Added a 64 bit direction type for 3d directions called DDir3. I was going to add one for Dir2, however, it would involve adding a 64 bit version of Rot2 which was out of the scope that I had intended for this PR.
I'm not entirely sold on the name DDir3, but it does follow glam's convention of 64bit structs being prefaced with D.

Testing

  • Did you test these changes? If so, how?
    I added tests to the testing suite covering the new features added in this PR.
  • Are there any parts that need more testing?
    Nope, not as far as I know.
  • How can other people (reviewers) test your changes? Is there anything specific they need to know?
    currently the ddir3_slerp test fails with the following message and I haven't the faintest clue how to fix it.
thread 'direction::tests::ddir3_slerp' (32568) panicked at crates/bevy_math/src/direction.rs:1663:9:
assert_relative_eq!(DDir3::Z.slerp(DDir3::Y, 2.0 / 3.0), DDir3::from_xyz(0.0, 0.75f64.sqrt(), 0.5f64).unwrap())

   left  = DDir3(DVec3(0.0, 0.8660254037844384, 0.5))
   right = DDir3(DVec3(0.0, 0.8660254037844387, 0.5000000000000001))
  • If relevant, what platforms did you test these changes on, and are there any important ones you can't test?
    64 bit Linux mint

@IQuick143 IQuick143 added C-Feature A new feature, making something new possible A-Math Fundamental domain-agnostic mathematical operations D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Review Needs reviewer attention (from anyone!) to move forward S-Needs-Help The author needs help finishing this PR. labels Dec 11, 2025
);
assert_relative_eq!(
DDir3::Z.slerp(DDir3::Y, 2.0 / 3.0),
DDir3::from_xyz(0.0, 0.75f64.sqrt(), 0.5f64).unwrap()
Copy link
Contributor

@kfc35 kfc35 Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you mentioned this in the description of the pull request as something you’d like input on:
To deal with the floating point imprecision issue, you can just add an episilon argument to this assert like in the previous assert. From what I can tell from the test failure you put, it seems like the miniscule 0.0000000000000001 difference should probably be acceptable, right?
https://docs.rs/approx/latest/approx/

/// and similarly for the error.
#[cfg(debug_assertions)]
fn assert_is_normalized_64(message: &str, length_squared: f64) {
let length_error_squared = (length_squared - 1.0).abs();
Copy link
Contributor

@kfc35 kfc35 Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, following the convention of assert_is_normalized, you probably need to add f64 appropriate abs and sqrt methods to ops.rs for std_ops_for_no_std and libm_ops_for_no_std and reference them here

I checked for you, and it should be pretty easy. For std_ops_for_no_std something like:

#[inline]
    pub fn abs64(x: f64) -> f64 {
        f64::abs(x)
    }

and

 #[inline]
    pub fn sqrt(x: f32) -> f32 {
        f64::sqrt(x)
    }

and the libm portion should be

#[inline]
    pub fn abs64(x: f64) -> f64 {
        libm::fabs(x)
    }

and

    #[inline]
    pub fn sqrt64(x: f64) -> f64 {
        libm::sqrt(x)
    }

With the correct comments and with the correct line indentations of course

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm adding these operators, should I just add 64bit equivalents for all the operators in ops.rs while I'm at it?

Copy link
Contributor

@kfc35 kfc35 Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since they’re public facing utilities, you could, but I also want to be mindful of keeping the pull request scoped to your new struct. The other operations could be another pull request if you so choose / think it would be valuable to expose to others. I only think sqrt and abs 64-bit impls are necessary to have here since they can then be used by this assert function

all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[doc(alias = "Direction3d")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This alias should probably be updated to not conflict with the existing alias

DDirection3d with what seems to be what you’re going for

Fix doc aliases

Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[doc(alias = “DDirection3d")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#[doc(alias = DDirection3d")]
#[doc(alias = "DDirection3d")]

Oops, I think somehow the double quote got weird with my previous suggestion, sorry about that!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Math Fundamental domain-agnostic mathematical operations C-Feature A new feature, making something new possible D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Help The author needs help finishing this PR. S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants