bevyengine / bevyengine/bevy

Make `GlobalTransform` more usable

Open
#22,474 3 comments 0 reactions 0 assignees View on GitHub
A-Math A-Transform C-Feature C-Usability D-Modest S-Needs-Design X-Needs-SME
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 16h
Merged PRs (30d)
171

Description

## What problem does this solve or what need does it fill?

`GlobalTransform` is useless outside of purely passing data around, due to:
- lack of mutation functions
- impossibility to access its content `Affine3` to modify it (can only get a copy)
- impossibility to create a new `GlobalTransform` (no constructor)

On the other hand it contains valuable functions like `.scale()` not available on other math types (it's indirectly available in `Affine3::to_scale_rotation_translation()` but that assumes you want the full conversion).

## What solution would you like?

- Either add `affine_mut()` as an escape hatch so user can modify the content of an existing instance:
```rust
pub fn affine_mut(&mut self) -> &mut Affine3 { &mut self.0 }
```
- Or move those critical utilities out of `GlobalTransform` into traits or whatnot, if the intent is for `GlobalTransform` to be a storage-only component.

## What alternative(s) have you considered?

I struggled to find one so far, outside of making a bunch of copies and conversions back and forth, like `Affine3::to_scale_rotation_translation()` which is relatively costly when you don't need the full conversion (for example, you only need to apply an extra scale to an existing transform).

## Additional context

Writing some code to display some gizmos for a bunch of objects (the colliders of Avian). This requires access to `GlobalTransform` to display in the correct world location. Some of those may be recursive (e.g. an object to render contains several child objects to render too; note that I'm not talking about the `Transform` hierarchy here, but some other relationship, the Avian compound colliders which have offsets).
- I started by using `&GlobalTransform` which works as long as you pass unmodified transforms around. As soon as you need to mutate, e.g. to add the child position to the parent's global transform to call recursively the draw code, then you're in an impasse because you 1) cannot create a `GlobalTransform` outside Bevy's own code, and 2) cannot access the content of an existing one to mutate it.
- I tried then to use `Affine3` directly, but I need to extract the scale with `GlobalTransform::scale()` which doesn't exist on `Affine3`. I could just copy/paste the implementation but this is ugly and harder to maintain, and defeats the point of having a math library.
- I can't immediately think of any other solution. I guess I'll have to use separate translation/rotation/scale parameters? But then manipulating those probably means locally building a `Transform` or other math type to access their math functions, then re-decomposing back.

Contributor guide

Open the contributing guide

Research direction

Start by reading the existing GlobalTransform and Affine3 APIs, including GlobalTransform::scale() and the limitations described in the issue. Determine the intended ownership and mutability model, then define completion as a documented, maintainable way to manipulate or construct global transforms without unnecessary conversions.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
game-dev
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.