Skip to content

world_to_ndc returns inf that triggers panic in bevy_ui layout #18252

Open
@tbillington

Description

@tbillington

Bevy version

0.15.2 (0.15.3 does not have commits related to this)

What you did

I'm creating worldspace UI using Camera::world_to_ndc to translate worldspace positions to screen space to position bevy_ui elements.

What went wrong

The below call to world_to_ndc outputs a Vec3::INFINITY.

Camera is the default Camera3d required component.

let cam_pos = GlobalTransform::from(Transform::default());
let target_pos = Vec3::new(5.0, 0.5, 0.0);
let ndc_pos = camera.world_to_ndc(&cam_pos, target_pos).unwrap();

println!("ndc_pos {ndc_pos}"); // ndc_pos [inf, inf, inf]

The inf ended up being used to position a Node, resulting in node.left = Val::Px(inf);.

This ended up triggering a panic in bevy_ui::layout because the layout code is not robust against this invalid value.

Additional information

Shifting the translation to be non-zero avoids the infinite values from world_to_ndc.

let cam_pos = GlobalTransform::from(Transform::from_xyz(-2.5, 4.5, 9.0));
let target_pos = Vec3::new(5.0, 0.5, 0.0);
let ndc_pos = camera.world_to_ndc(&cam_pos, target_pos).unwrap();

println!("ndc_pos {ndc_pos}"); // ndc_pos [1.1316626, -1.0729837, 0.011111111]

This seems to be 2 issues

  1. world_to_ndc gives infinite values instead of returning None or some other result type or valid values
  2. bevy_ui::layout panics on invalid position values, which can easily happen when multiplying floats around. I would feel much better if this was an error log

I initially thought this was related to #16765 but the UI node has no parent/hierarchy, focuses on the panic on inf, and doesn't mention world_to_ndc.

Backtraces from the panic:

RUST_BACKTRACE=1

thread 'Compute Task Pool (2)' panicked at /Users/choc/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/num/f32.rs:1406:9:
min > max, or either was NaN. min = 0.0, max = NaN
stack backtrace:
   0: _rust_begin_unwind
   1: core::panicking::panic_fmt
   2: bevy_ui::ui_node::BorderRadius::resolve_single_corner
   3: bevy_ui::layout::ui_layout_system::update_uinode_geometry_recursive
   4: bevy_ui::layout::ui_layout_system
   5: <bevy_ecs::system::function_system::FunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run_unsafe

RUST_BACKTRACE=full

thread 'Compute Task Pool (1)' panicked at /Users/choc/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/num/f32.rs:1406:9:
min > max, or either was NaN. min = 0.0, max = NaN
stack backtrace:
   0:        0x103b692e4 - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::h7adefaad4a31afc0
   1:        0x103bad2a4 - core::fmt::write::h381c0b0ce6ab972a
   2:        0x103b5e610 - std::io::Write::write_fmt::h75af97148630d8d3
   3:        0x103b69198 - std::sys::backtrace::BacktraceLock::print::h8baf33e22611de71
   4:        0x103b6b504 - std::panicking::default_hook::{{closure}}::h369c7295ef58c5b1
   5:        0x103b6b348 - std::panicking::default_hook::h50746358288a9d6a
   6:        0x103b6bd50 - std::panicking::rust_panic_with_hook::h7d795911432661cb
   7:        0x103b6ba04 - std::panicking::begin_panic_handler::{{closure}}::h36f15310ecbde379
   8:        0x103b697a8 - std::sys::backtrace::__rust_end_short_backtrace::heed121414170e0c7
   9:        0x103b6b6bc - _rust_begin_unwind
  10:        0x103bcb658 - core::panicking::panic_fmt::h17b1b80ec02ffd19
  11:        0x10a35078c - bevy_ui::ui_node::BorderRadius::resolve_single_corner::h96e0353d5156373e
  12:        0x10a499244 - bevy_ui::layout::ui_layout_system::update_uinode_geometry_recursive::h9f6a40c905df7d90
  13:        0x10a49846c - bevy_ui::layout::ui_layout_system::h6edb8fb65ab422e7
  14:        0x10a4785dc - <bevy_ecs::system::function_system::FunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run_unsafe::heafee9ceac417da3
  15:        0x10ccb8404 - bevy_ecs::schedule::executor::__rust_begin_short_backtrace::run_unsafe::haeaadbcd5fa25db3
  16:        0x10ccc6410 - <futures_lite::future::CatchUnwind<F> as core::future::future::Future>::poll::hd78e37e2bf3891b3
  17:        0x10cc8638c - async_executor::Executor::spawn_inner::{{closure}}::h3cba66f2fed0b69c
  18:        0x10cc84af0 - async_task::raw::RawTask<F,T,S,M>::run::hee81aae3c0549a93
  19:        0x10cccb74c - futures_lite::future::block_on::h43baf863f956827a
  20:        0x10ccd15b8 - std::sys::backtrace::__rust_begin_short_backtrace::h8c788a5f9414b8a6
  21:        0x10ccd09f0 - core::ops::function::FnOnce::call_once{{vtable.shim}}::ha7e3aec6aa0855b8
  22:        0x103b73eb0 - std::sys::pal::unix::thread::Thread::new::thread_start::h44ebc83f14222f58
  23:        0x18f0682e4 - __pthread_deallocate

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-UIGraphical user interfaces, styles, layouts, and widgetsC-BugAn unexpected or incorrect behaviorP-CrashA sudden unexpected crashS-Needs-InvestigationThis issue requires detective work to figure out what's going wrong

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions