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:
- Disable Bevy’s transform plugin:
DefaultPlugins.build().disable::<TransformPlugin>()
- Add the
FloatingOriginPlugin
to yourApp
- Add the
GridCell
component to all spatial entities - Add the
FloatingOrigin
component 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.