Expand description
This bevy plugin makes it easy to build high-precision worlds that exceed the size of the
observable universe, with no added dependencies, while remaining largely compatible with the
rest of the Bevy ecosystem.
Problem
Objects far from the origin suffer from reduced precision, causing rendered meshes to jitter and jiggle, and transformation calculations to encounter catastrophic cancellation.
As the camera moves farther from the origin, the scale of floats needed to describe the position of meshes and the camera get larger, which in turn means there is less precision available. Consequently, when the matrix math is done to compute the position of objects in view space, mesh vertices will be displaced due to this lost precision.
Solution
While using the FloatingOriginPlugin, entities are placed into a GridCell in a large
fixed precision grid. Inside a GridCell, an entity’s Transform is relative to the center of
that grid cell. If an entity moves into a neighboring cell, its transform will be recomputed
relative to the center of that new cell. This prevents Transforms from ever becoming larger
than a single grid cell, and thus prevents floating point precision artifacts.
The same thing happens to the entity marked with the FloatingOrigin component. The only
difference is that the GridCell of the floating origin is used when computing the
GlobalTransform of all other entities. To an outside observer, as the floating origin camera
moves through space and reaches the limits of its GridCell, it would appear to teleport to the
opposite side of the cell, similar to the spaceship in the game Asteroids.
The GlobalTransform of all entities is computed relative to the floating origin’s grid cell.
Because of this, entities very far from the origin will have very large, imprecise positions.
However, this is always relative to the camera (floating origin), so these artifacts will always
be too far away to be seen, no matter where the camera moves. Because this only affects the
GlobalTransform and not the Transform, this also means that entities will never permanently
lose precision just because they were far from the origin at some point.
Getting Started
All that’s needed to start using this plugin:
- Add the
FloatingOriginPluginto yourApp - Add the
GridCellcomponent to all spatial entities - Add the
FloatingOrigincomponent to the active camera
Take a look at FloatingOriginSettings resource for configuration options, as well as some
useful helper methods.
Moving Entities
For the most part, you can update the position of entities normally while using this plugin, and it will automatically handle the tricky bits. However, there is one big caveat:
Avoid setting position absolutely, instead prefer applying a relative delta
Instead of:
transform.translation = a_huge_imprecise_position;do:
let delta = new_pos - old_pos;
transform.translation += delta;Absolute Position
If you are updating the position of an entity with absolute positions, and the position exceeds the bounds of the entity’s grid cell, the floating origin plugin will recenter that entity into its new cell. Every time you update that entity, you will be fighting with the plugin as it constantly recenters your entity. This can especially cause problems with camera controllers which may not expect the large discontinuity in position as an entity moves between cells.
The other reason to avoid this is you will likely run into precision issues! This plugin exists because single precision is limited, and the larger the position coordinates get, the less precision you have.
However, if you have something that must not accumulate error, like the orbit of a planet, you
can instead do the orbital calculation (position as a function of time) to compute the absolute
position of the planet with high precision, then directly compute the GridCell and
[Transform] of that entity using FloatingOriginSettings::translation_to_grid. If the star
this planet is orbiting around is also moving through space, note that you can add/subtract grid
cells. This means you can do each calculation in the reference frame of the moving body, and sum
up the computed translations and grid cell offsets to get a more precise result.
Modules
GridPrecision trait and its implementations.Structs
GridCell.App] to for floating origin functionality.Transform] is relative to.Functions
GlobalTransform] component of entities based on entity hierarchy and
[Transform] component.GlobalTransform relative to the floating origin.