#big_space

2175 messages · Page 3 of 3 (latest)

mighty crescent
#

Changelog

v0.10.0 - 2025-06-21

Bevy 0.16, no_std, removed precision generics, switch to plugin groups, naming consistency pass.

Updated: Bevy 0.16

Due to changes in bevy, this plugin once again requires you to disable bevy's built-in transform system:

DefaultPlugins.build().disable::<TransformPlugin>(),

Removed: GridPrecision generics

The precision of grids is now a feature flag instead of a generic, and GridPrecision is now an integer type instead of a trait.

Having multiple precisions in the same app has been a persistent footgun, and is flexibility that no one uses or needs. This change has simplified the API by removing significant amounts of line noise caused by ::<P>. For example GridCell<P> is now simply GridCell.

The integer precision used for grids is now selected from a set of features: i8, i16, i32, i64. and i128. If no feature is specified, big_space will default to i64. If multiple precision features are specified, the highest will be used.

Changed: BigSpaceDefaultPlugins plugin group

Instead of adding common plugins individually, they have been grouped into the BigSpaceDefaultPlugins plugin group, similar to the DefaultPlugins plugin group in Bevy.

For example, the hierarchy validation plugin is enabled whenever debug assertions are enabled but can be manually enabled or disabled to override this behavior:

BigSpaceDefaultPlugins
    .build()
    .enable::<BigSpaceValidationPlugin>()

Plugins that are behind feature flags are automatically enabled when their corresponding feature is enabled; you no longer need to manually add the camera controller plugin, you only need to enable the feature and add BigSpaceDefaultPlugins to your app.

This replaces BigSpacePlugin.

The existing plugin structure has been organized into more fine grained plugins, with the addition of the BigSpaceMinimalPlugins composed of BigSpaceCorePlugin and BigSpacePropagationPlugin. These are particularly useful for tests, benchmarks, and serverside applications. Future serverside physics will likely only use the BigSpaceCorePlugin to handle grid cell recentering, and not do any propagation which is only needed for rendering.

Changed: Naming consistency

To avoid common name collisions and improve searchability, names have been standardized:

  • FloatingOriginSystem -> BigSpaceSystems
  • CameraControllerPlugin -> BigSpaceCameraControllerPlugin
    • CameraController -> BigSpaceCameraController
    • CameraInput -> BigSpaceCameraInput
  • TimingStatsPlugin -> BigSpaceTimingStatsPlugin
  • FloatingOriginDebugPlugin -> BigSpaceDebugPlugin
  • BigSpaceValidationPlugin (new)
  • BigSpaceDefaultPlugins (new)
  • BigSpaceMinimalPlugins (new)
  • BigSpaceCorePlugin (new)
  • BigSpacePropagationPlugin (new)

Based on user feedback, the world query types have also been renamed:

  • GridTransform -> CellTransform
  • GridTransformOwned -> CellTransformOwned
  • GridTransformReadOnly -> CellTransformReadOnly

Changed: Default plugin filters

Plugins that accept an optional query filter no longer require specifying the default empty filter tuple turbofish ::<()>:

  • GridHashPlugin::<()>::default() -> GridHashPlugin::default()
  • GridPartitionPlugin::<()>::default() -> GridPartitionPlugin::default()

To construct a plugin with a custom filter, use the new() method:
GridHashPlugin::<With<Player>>::new()

New: no_std Support

Thanks to bushrat011899's efforts upstream and in this crate, it is now possible to use the plugin without the rust standard library. This is particularly useful when targeting embedded or console targets.

Optimized: Partition Bounds

Partition bounds are now computed and cached when the partition is updated instead of on the fly. Adding a cell to the partition is an O(1) update to the partition bounds, and a removal is O(n). Previously, every bound query was O(n).

#

Partitions exist to begin to solve this. It does these calculations at a grid cell level, and maintains a list of groups of possibly-interacting islands (partitions) within each grid.

#

I've spent a good amount of time already testing and optimizing this feature, and it is used heavily in the spatial_partitioning example.

#

still feels more universal and precise than translating coords of all island entities into a single FO-relative coord system like for renderer.
Right, if you do everying FO-relative, you are opening the door to a world of complexity and added physics engine integration. Partitioning your world into small islands that easily fit into f64 or even f32 means you can use any physic engine off the shelf, and the simulation will be fair to all clients, because the simulation is running in the same reference frame.

mighty crescent
#

e.g. in this screenshot from the spatial hashing example, each partition is a different color (with the partition bounding box shown in the same color), computed automatically at runtime if you have the plugin added

naive elk
#

Idk, physics engine tinkering might be inevitable as I'm looking into microcell load balancing with causal graphs and possible authority handoff for when one island gets too big for a single core to handle. Just exploring possibilities.

naive elk
naive elk
#

Damn, looks like these guys https://hadean.com/ already solved the big space and load-balancing simulation problem. In Rust, too.

Synthetic Environments that provide cutting edge training, real-time situational understanding and predictive intelligence for Governments, National Security and Commercial Enterprises

mighty crescent
#

That marketing is setting off alarm bells left and right. I'm not sure I see the connection tbh.

naive elk
#

They've implemented the 2005 whitepaper on microcell load balancing for 3d worlds. I think the only other known project to do that is SpatialOS, but that seems dead. It's something that every game has to eventually do if it's doing big worlds with a lot of online players. At least, I haven't heard about any other solutions to distribute a single world tick across many servers.

#

I guess it's only relevant to big space in the sense that where else would you have 100,000 players fighting one battle

#

But yeah, not directly

sharp scroll
#

hi, how do i access big space grid after I've spawned one (from another bevy system)?

sharp scroll
#

can i query a grid and spawn something into?

sharp scroll
sharp scroll
naive elk
#

a grid is a component, you can query for it like any component

sharp scroll
#

so i would have to place the world areas in setup and then later access those grids.

#

for now just to throw things into a bucket than handles big numbers

naive elk
#

For an entity to be part of the BS coordinate system, it has to have a GridCell component on it, and its parent has to have a Grid component. So you can add these components yourself without the BS helper functions

#

You could even just check what the helpers are doing to be sure

mighty crescent
#

you add it as a child and make sure it has the gridcell component

mighty crescent
worthy vector
#

Doesn't f64 give you centimeter precision at a light year away? I just made my orbit data structure double precision and convert back and forth between big space and f64

mighty crescent
#

That's best case

#

Math ops can make it much worse if you are working with two different scales and you end up with destructive cancellation

#

You're probably fine though.

worthy vector
#

Ah fair enough. Out of curiosity do you know how much worse? Are we talking a factor of 10, 100, 1000? Sounds like useful stuff to know if you're working with huge scales

mighty crescent
#

so, if you do something like 1e10 + 1e-10, the small value is going to be absolutely obliterated. You would need to do all your small scale math before bringing in values of another scale.

worthy vector
mighty crescent
#

Right, yeah. It's easy to accidentally look at the precision of f64, and think you get that level of precision at n lightyears no matter what math you are doing, when the precision you are discussing is the best possible case.

next wharf
#

you might want to check next_up,next_down with f32/64

marsh drift
#

Is there any physics plugin that works with big_space? Or are there any efforts to make it work? I'm interested in using the plugin, but without physics on the server I can't do much. I do have some time to contribute if there are efforts.

mighty crescent
#

I'm slowly working on physics.

#

@wild tangle has that as a long term goal, I think.

marsh drift
#

I can see that there is a branch. Is there any issue that a person without deep physics simulation experience can work on? If not that's fine, thanks for working on it.

mighty crescent
#

Probably not, sorry!

wild tangle
proper ingot
#

if you're fine with ignoring collision at cell boundaries, is there much to do beyond preventing cross-cell interaction & rewriting the Position/Rotation sync?

wild tangle
#

I believe that should work in theory, it will just make the broad phase and spatial queries kinda inefficient since the cells would still be overlapping in physics space

#

big_space should have some built-in stuff already to group entities into disjoint islands/groups that could be separate physics instances

#

Avian just doesn't support multiple physics instances or contexts yet

sharp lark
#

Does it matter if you spawn the player in a root_grid or not?

worthy vector
#

If you don't parent the player to some grid, when you get far from the origin everything will get jittery just like without big_space

worthy vector
sharp lark
worthy vector
# sharp lark Does that include a root_grid?

Yeah. There's not really much difference between a root grid and a non-root grid. You can mostly think of grids as a reference frame. The root grid is just the "universe reference frame", usually sits at the identity. You often don't need extra grids beyond that unless you're doing fun stuff with large, moving/rotating/accelerating bodies.

mighty crescent
#

A query

#

Query<&GridCell>

mighty crescent
#

I'm considering some name changes

#

Trying to make the names better reflect the underlying concepts and usage

#

e.g. GridCell -> CellIndex, the component is only the cell's index, it isn't the cell itself. Cells themselves are not entities.

#

GridHash -> CellUid: this component isn't a hash of the grid, it's a globally unique identifier of a cell, and it also contains a prehashed value for this ID.
FastGridHash -> CellHash: this was always a spatial hash of the cell, but previously conflicted with the above component

#

Renamed the map resource to _Lookup, because I'm also adding some convenience types for CellHashMap<T> and CellHashSet - similar to EntityHashMap, and the names were too similar, and the lookup resources contained these map types, making it even more confusing.

mighty crescent
#

Naming is hard.

#

This came up because I'm working on adding a feature that tracks when entities change partitions, needed for physics.

#

Might remove the prefix for the partition types as well

worthy vector
#

CellCoord maybe?

mighty crescent
#

I like that idea. Index seems more precise though, The index is used to look up the translation/coordinate, but it doesn't define it directly, it's more like an occupancy grid.

sharp lark
#

and if not that, a runtime cost to simply doing x * width + y

#

everytime you want to index a coordinate instead of an index

worthy vector
slate quiver
#

Hey, thanks for this awesome crate! I just have a quick question, if I only care about what is happening around the player (which is my FloatingOrigin), will I have issues with physics (I'm mostly interested in collision detection and ray casts for interactions with objects)? I'm using Avian3d if that matters

mighty crescent
#

big_space doesn't neatly integrate with any physics engines out of the box, you will need to do some integration work, or find a branch someone else has made.

#

if all you care about are colliders and spatial queries, you might be able to make it work, assuming the physics engine is reading GlobalTransform and not Transform.

slate quiver
#

I see, thank you 🙂

bitter cliff
#

I'm trying to create a custom picking backend using RayMap, but I'm having some strange issues. If I use the demo example, and add the following system in really any schedule

fn rays(ray_map: Res<RayMap>) {
    for (&id, &ray) in ray_map.iter() {
        println!("{:?}, {:?}", id, ray);
    }
}

then on start of program it will keep logging the ray for the mouse pointer when looking around with the camera. but as soon as i move the camera using wasd, then it stops completely. nothing is logged.

bitter cliff
#

with some initial debugging I can see that after having moved the camera, in the viewport_to_world method in bevy_render, world_far_plane - world_near_plane returns [0, 0, 0] which is an invalid value for Dir3::new

#

ok looks like it's the near: 1e-18, setting on camera projection that screws it up

mighty crescent
#

Had some time to catch up on OSS and released v0.11 for bevy 0.17

worthy vector
mighty crescent
mighty crescent
#

infinite looping worlds + physics lel

hollow harbor
#

Hey, this looks really nice, I'm currently considering whether to use this crate or just implement a manual regular origin shift myself. If I would just have a single grid (no nesting) and I don't care that much about far-away stuff being persistent, would this crate be overkill? I do like that it would automatically handle some stuff for me, but maybe it will introduce some other obstacles that I am currently not thinking about...

mighty crescent
#

If you're using a single grid, this crate probably won't get in your way. The crate level docs talk about how things work and compare to origin shifting in more depth.

hollow harbor
#

awesome, I'll give it a shot

sharp scroll
#

any big space experts here? how do i insert into big space root from a separate system after i've already set the one with floating origin?

mighty crescent
sharp scroll
#

how do i query to bigspace root entiry?

mighty crescent
#

You can add a marker component if you want, or just query for BigSpace

sharp scroll
#

add, query for marker then insert. thx

#

i did try querying for just BigSpace autocomplete wasn't finding it

#

that's gonna have to be in an update system

mighty crescent
sharp scroll
#

i've been here

#

all big_space need is an example with a button to spawn a thing i'll figure it out

sharp scroll
#

i'm still stuck, how do i spawn_big_space from multiple files?

sharp scroll
#

can i do this as many times as i want? Spawn a BigSpace with spawn_big_space, and add entities to it.?

sharp scroll
#

what am i doing wrong here?

fn main() {
    App::new()
        .add_plugins((
            BigSpaceDefaultPlugins,
        ))
...
fn setup_player(
    mut commands: Commands,
    mut asset_server: Res<AssetServer>,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
){

    let player_handle = asset_server.load(
            "models/G-91Dropship.glb#Scene0",
    );

    commands.spawn_big_space(Grid::default(), |root| {
        let d = space::DISTANCE / root.grid().cell_edge_length() as GridPrecision;
        let distant_grid_cell = CellCoord::new(d, d, d);
        root.spawn_spatial((
                Name::new("Player"),
                ...
                Transform {
                    translation: Vec3::new(9.0, 10000.0, 68.0),
                    ..default()
                }
            ))
            .with_children(|parent| {
                parent.spawn((
                    ...
                ));
            });
        });
fn setup_earth(
    mut commands: Commands,
    images: Res<Assets<Image>>,
    asset_server: Res<AssetServer>,
    ...
    grid: Query<&Grid>,
){

    let scene_handle = asset_server.load(
            "models/Earth_1_12756.glb#Scene0",
    );

    commands.spawn_big_space(Grid::new(10000.0,10000.0), |root| {
        root.spawn_spatial((
            FloatingOrigin {},
        ));

        root.spawn_spatial((
            Name::new("Planet"),
            ...
        ));
    });
}
#

commented out some non big_space stuff

mighty crescent
mighty crescent
sharp scroll
#

how do insert them into the same space?

#

I'd like to do it from separate systems

mighty crescent
#

like I said before, query the existing big space and add entities as children

sharp scroll
#

ok how to query an existing bigspace from setup?

mighty crescent
#

A query

mighty crescent
#

Query<Entity, With<BigSpace>>

sterile gate
#

can we simply add rigidbody to entities inside bigspace ?

sharp scroll
sharp lark
sharp lark
#

Are you supposed to usually keep the player from being spawned in a grid?

proper ingot
#

no

pure quail
#

I want camera to pan between different planets in a star system, which are a hierarchical grid. Should I reparent the camera to the planet/moon/star they are currently focusing on?

mighty crescent
pure quail
#

@mighty crescent I guess I'm curious what implications are. My idea is that you switch camera from "system view" to "planetary view", maybe I could also just have separate cameras that I switch between

mighty crescent
#

you can use the local origin of the grids to do it relatively easily though, that way you don't need to crawl the heirarchy or anything

#

(unrelated below 🙂)

I've been working on optimizations for stationary entities, and better parallelizing transform prop using some of the things I've built in bevy for optimizing bevy's own transform prop.

I'm disabling meshes here, to avoid bevy's overhead with many meshes (though @tardy phoenix's work will make this way better in 0.19). I'm running 32 million entities across 4 grids, with spatial hashing, partitioning, and all that jazz, at 50fps.

#

This also does a better job of doing much less work when the camera is not moving between grid cells. Stationary entities only need to have their GT updated when the camera moves into a new cell.

mighty crescent
pure quail
pure quail
#

ok, so reparenting worked out quite well if I just set a new position via grid methods

mighty crescent
#

2 fps -> 45 fps
not too shabby

#

this is all with static optimizations, so if you move the floating origin into another cell, it's going to be a very expensive frame

proper ingot
#

wonder if it's possible to stagger cell updates

#

no way i can think of rn without worse consequences

mighty crescent
#

0.2 billion entities >30fps lel

#

granted, they don't have rendering components, but still

mighty crescent
#

@tardy phoenix some fun ballpark numbers on 0.18.

0.2 Billion entities @ 30fps without rendering.

It's doing custom (big_space) transform prop, occupancy cell/spatial hashes, and partitions reactively. These numbers are in the realm of possibility (memory use, runtime perf) if your renderer is also super reactive.

tardy phoenix
mighty crescent
mighty crescent
pure quail
#

so I'm having slight bit of trouble with using gizmos to draw orbits. it looks fine when I look at solar system scales, but orbits really loose precision when I zoom in next to the planet. I'm trying to figure out the best way to actually compute the points for the system, current code is smth like that

fn render_orbit_gizmo_system(
    mut gizmos: Gizmos<OrbitGizmos>,
    orbits: Query<(&orbital::Orbit, &orbital::IsOrbiting, &Visibility), With<RenderedBody>>,
    bodies: Query<(&orbital::OrbitalBody, &Grid)>,
) -> Result<(), BevyError> {
    const SEGMENTS: usize = 256;

    for (orbit, is_orbiting, visibility) in &orbits {
        if matches!(visibility, Visibility::Visible) {
            let (parent_body, parent_grid) = bodies.get(is_orbiting.0)?;

            let points: Vec<Vec3> = (0..=SEGMENTS)
                .map(|i| {
                    let nu = (i as f64 / SEGMENTS as f64) * std::f64::consts::TAU;
                    let position = orbit.position_at_true_anomaly(parent_body, nu);
                    let (cell_coord, local_position) = parent_grid.translation_to_grid(position);
                    parent_grid
                        .global_transform(&cell_coord, &Transform::from_translation(local_position))
                        .transform_point(Vec3::ZERO)
                })
                .collect();

            gizmos.linestrip(points, orbit.color);
        }
    }

    Ok(())
}

but I think i'm missing some foo on how to convert from "solar system grid space" to "screen space"

#

I suspect the problem is that Sun is very far away for eg Jupiter, who computes orbit relative to sun, because I don't thave similar problem when I focus on moons of jupiter, which compute their orbits relative to jupiter

#

this is post some tries to fix it, before I added position_at_true_anomaly to parents global transform, which naturally lost some precision

mighty crescent
#

Probably depends on how the lines themselves are being transformed in the scene for rendering

#

e.g. if it is positioning the linestrip from the first point and transforming it, you'd want to be sure the first point is the one nearest the camera

shut cradle
# pure quail so I'm having slight bit of trouble with using gizmos to draw orbits. it looks f...

Have you tried increasing your SEGMENTS constant and see if and how this improves things? If so, you probably want some sort of adaptive algorithm to change how many points you are generating (using bounding boxes or the angular distance between points). 256 segments means around 1.4 days for each segment for Earth, I wouldn't be surprised if it looked like the planet wasn't following the line between the points. This dev diary from KSP2 could be helpful since you're using Kepler orbits.

inland hull
#

In bevy directly

proper ingot
#

this conflicts with the architecture of my desklike contract-building game (/j)

pure quail
#

@mighty crescent @shut cradle good idea, I'll try that

#

thanks a lot!

pure quail
#

it was exactly not enough sampling points. thanks a lot again!

bitter cliff
#

additionally you could render more points on the orbit closer to the body (and/or camera) and less points further away

abstract quarry
#

hows the current state of physics with bigspace?

mighty crescent
#

DIY

abstract quarry
#

hmm

pure quail
#

cause it felt a waste to sample all orbits at high precision all the time

abstract quarry
wild tangle
#

For proper big_space support we kinda need multi-world physics so you can simulate each partition in its own physics context

abstract quarry
#

yeah thats what I realized it only works in the same cell as the origin

wild tangle
#

It's something I do want to support, just takes some more design work and actually implementing the thing

#

I left a longer comment re: multiple physics worlds here

mighty crescent
#

There are a few ways to do it, but you need some elbow grease.

nimble agate
#

big space is fun, thanks for putting it together!

modest moon
#

Trying to figure out if this is a big space issue or if the PBR stuff just isnt meant for these kind of distances

modest moon
#

I noticed the planets example used a directional light pointing from the suns direction instead, and updating it as you move. This gives the expected results (though I might need to tweak the bloom a bit haha)

modest moon
#

Though I was hoping to render miniatures of each planet while zooming out to see the whole solar system, which doesn't work with this method 🙁

quaint moth
#

I went through something similar when I took a stab at my solar system, I was leaning towards a custom shader or light implementation but never quite got there

mighty crescent
#

point lights dont work at those scales

#

the directional light is more performant and equivalent at large distances

#

especially with shadows

quaint moth
#

The "zoomed out" view suffers though, because the sun at the center of the system should emit light radially. Multiple directional lights wouldn't quite work right either. I was considering a "point light" emitter with "directional light" falloff, but shelved the project before I started exploring that

mighty crescent
#

at 1:1 scales you'd likely only use a directional light on planet surface, and switch to a custom solution or a point light for a map view or space view