bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
36.39k stars 3.59k forks source link

Transform::rotation denormalizes after applying successive rotations. #16480

Open Namaarie opened 2 days ago

Namaarie commented 2 days ago

Bevy version

Bevy 0.14.2

Relevant system information

cargo 1.82.0 (8f40fc59f 2024-08-21) Windows 10 Build 19045 No other dependencies

What you did

I used Transform::local_x, y, x] to apply rotations and it slowly caused Transform::rotation to denormalize, and eventually panics. The problem seems to be related to https://github.com/bevyengine/bevy/issues/12981, but the fix didn't seem to address the core issue.

Additional information

Isolated project based on the 3d_rotation example:

//! Illustrates how to rotate an object around an axis.

use bevy::prelude::*;

// Define a component to designate a rotation speed to an entity.
#[derive(Component)]
struct Rotatable {
    speed: f32,
}

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, rotate_cube)
        .run();
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    // Spawn a cube to rotate.
    commands.spawn((
        PbrBundle {
            mesh: meshes.add(Cuboid::default()),
            material: materials.add(Color::WHITE),
            transform: Transform::from_translation(Vec3::ZERO),
            ..default()
        },
        Rotatable { speed: std::f32::consts::FRAC_PI_8 },
    ));

    // Spawn a camera looking at the entities to show what's happening in this example.
    commands.spawn(Camera3dBundle {
        transform: Transform::from_xyz(0.0, 10.0, 20.0).looking_at(Vec3::ZERO, Vec3::Y),
        ..default()
    });

    // Add a light source so we can see clearly.
    commands.spawn(DirectionalLightBundle {
        transform: Transform::from_xyz(3.0, 3.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y),
        ..default()
    });
}

fn rotate_cube(mut cubes: Query<(&mut Transform, &Rotatable)>) {
    for (mut transform, cube) in &mut cubes {

        // rotating around any of these will panic extremely quickly
        let x = transform.local_x();
        let y = transform.local_y();
        let z = transform.local_z();

        // how fast it panics seems to be proportional to the angle
        transform.rotate_axis(x, cube.speed * 100.0);
        transform.rotate_axis(y, cube.speed * 100.0);
        transform.rotate_axis(z, cube.speed * 100.0);

        // error in the rotation also builds up, but is much slower than rotating around local axis
        transform.rotate_x(cube.speed);
        transform.rotate_y(cube.speed);
        transform.rotate_z(cube.speed);

        // prints the magnitude of rotation quaternion
        // should be 1
        println!("{}", transform.rotation.length());
    }
}

Stack trace:

PS D:\Programming\Rust\bevy-fast-spin-mrp> cargo run
   Compiling bevy-fast-spin-mrp v0.1.0 (D:\Programming\Rust\bevy-fast-spin-mrp)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 8.67s
     Running `target\debug\bevy-fast-spin-mrp.exe`
2024-11-22T16:32:18.293592Z  INFO bevy_diagnostic::system_information_diagnostics_plugin::internal: SystemInfo { os: "Windows 10 Home", kernel: "19045", cpu: "Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz", core_count: "6", memory: "31.9 GiB" }
2024-11-22T16:32:18.680879Z  INFO bevy_render::renderer: AdapterInfo { name: "NVIDIA GeForce GTX 1080", vendor: 4318, device: 7040, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "566.03", backend: 
Vulkan }
2024-11-22T16:32:19.440893Z  INFO bevy_winit::system: Creating new window "App" (Entity { index: 0, generation: 1 })
1.0
0.99999976
0.99999917
0.9999966
0.99998635
0.9999454
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.99989086.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.99989086.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.99989086.
0.9997817
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.9995634.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.9995634.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.9995634.
0.99912715
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.9982551.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.9982551.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.9982551.
0.9965156
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.99304324.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.99304324.
Warning: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.99304324.
0.98617095
thread 'Compute Task Pool (4)' panicked at C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_math-0.14.2\src\direction.rs:62:9:
Error: The vector given to `Dir3::new_unchecked` is not normalized. The length is 0.9725331.
stack backtrace:
   0: std::panicking::begin_panic_handler
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library/std\src\panicking.rs:662
   1: core::panicking::panic_fmt
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library/core\src\panicking.rs:74
   2: bevy_math::direction::assert_is_normalized
             at C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_math-0.14.2\src\direction.rs:62
   3: bevy_math::direction::Dir3::new_unchecked
             at C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_math-0.14.2\src\direction.rs:382
   4: bevy_transform::components::transform::Transform::local_x
             at C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_transform-0.14.2\src\components\transform.rs:226
   5: bevy_fast_spin_mrp::rotate_cube
             at .\src\main.rs:52
   6: core::ops::function::FnMut::call_mut<void (*)(bevy_ecs::system::query::Query<tuple$<ref_mut$<bevy_transform::components::transform::Transform>,ref$<bevy_fast_spin_mrp::Rotatable> >,tuple$<> >),tuple$<bevy_ecs::system::query::Query<tuple$<ref_mut$<bevy_tran
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library\core\src\ops\function.rs:166
   7: core::ops::function::impls::impl$3::call_mut<tuple$<bevy_ecs::system::query::Query<tuple$<ref_mut$<bevy_transform::components::transform::Transform>,ref$<bevy_fast_spin_mrp::Rotatable> >,tuple$<> > >,void (*)(bevy_ecs::system::query::Query<tuple$<ref_mut$<
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14\library\core\src\ops\function.rs:294
   8: bevy_ecs::system::function_system::impl$12::run::call_inner<tuple$<>,bevy_ecs::system::query::Query<tuple$<ref_mut$<bevy_transform::components::transform::Transform>,ref$<bevy_fast_spin_mrp::Rotatable> 
>,tuple$<> >,ref_mut$<void (*)(bevy_ecs::system::query
             at C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_ecs-0.14.2\src\system\function_system.rs:710
   9: bevy_ecs::system::function_system::impl$12::run<tuple$<>,void (*)(bevy_ecs::system::query::Query<tuple$<ref_mut$<bevy_transform::components::transform::Transform>,ref$<bevy_fast_spin_mrp::Rotatable> >,tuple$<> >),bevy_ecs::system::query::Query<tuple$<ref_m
             at C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_ecs-0.14.2\src\system\function_system.rs:713
  10: bevy_ecs::system::function_system::impl$7::run_unsafe<void (*)(bevy_ecs::system::query::Query<tuple$<ref_mut$<bevy_transform::components::transform::Transform>,ref$<bevy_fast_spin_mrp::Rotatable> >,tupluple$<> >),bevy_ecs::system::query::Query<tuple$<ref_m
             at C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_ecs-0.14.2\src\system\function_system.rs:713
uple$<> >),bevy_ecs::system::query::Query<tuple$<ref_m
uple$<> >),bevy_ecs::system::query::Query<tuple$<ref_m
             at C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_ecs-0.14.2\src\system\function_system.rs:713
  10: bevy_ecs::system::function_system::impl$7::run_unsafe<void (*)(bevy_ecs::system::query::Query<tuple$<ref_mut$<bevy_transform::components::transform::Transform>,ref$<bevy_fast_spin_mrp::Rotatable> >,tupluple$<> >),bevy_ecs::system::query::Query<tuple$<ref_m
uple$<> >),bevy_ecs::system::query::Query<tuple$<ref_m
uple$<> >),bevy_ecs::system::query::Query<tuple$<ref_m
uple$<> >),bevy_ecs::system::query::Query<tuple$<ref_m
             at C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_ecs-0.14.2\src\system\function_system.rs:713
  10: bevy_ecs::system::function_system::impl$7::run_unsafe<void (*)(bevy_ecs::system::query::Query<tuple$<ref_mut$<bevy_transform::components::transform::Transform>,ref$<bevy_fast_spin_mrp::Rotatable> >,tuple$<> >),void (*)(bevy_ecs::system::query::Query<tuple$
             at C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_ecs-0.14.2\src\system\function_system.rs:534
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Encountered a panic in system `bevy_fast_spin_mrp::rotate_cube`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
error: process didn't exit successfully: `target\debug\bevy-fast-spin-mrp.exe` (exit code: 101)