//! `big_space` isn't only useful for objects that are large, it's useful any time you want to work //! with big *differences* in scale. You might normally think of human scale and solar system scale //! being mixed in games that use double precision (f64) worlds, but you can use this floating //! origin plugin to work on almost any set of scales. //! //! In this example, we will be spawning spheres the size of carbon atoms, across the width of the //! milky way galaxy. use bevy::prelude::*; use bevy_math::DVec3; use big_space::prelude::*; const BIG_DISTANCE: f64 = 100_000_000_000_000_000_000.0; // Diameter of the milky way galaxy const SMALL_SCALE: f32 = 0.000_000_000_154; // Diameter of a carbon atom fn main() { App::new() .add_plugins(( DefaultPlugins, BigSpacePlugin::::default(), FloatingOriginDebugPlugin::::default(), // Draws cell AABBs and grids big_space::camera::CameraControllerPlugin::::default(), // Compatible controller )) .add_systems(Startup, setup_scene) .add_systems(Update, (bounce_atoms, toggle_cam_pos)) .insert_resource(ClearColor(Color::BLACK)) .run(); } #[derive(Component)] struct Atom; fn setup_scene( mut commands: Commands, asset_server: Res, mut meshes: ResMut>, mut materials: ResMut>, ) { // Because we are working on such small scales, we need to make the grid very small. This // ensures that the maximum floating point error is also very small, because no entities can // ever get farther than `SMALL_SCALE * 500` units from the origin. let small_grid = Grid::::new(SMALL_SCALE * 1_000.0, 0.0); commands.spawn_big_space(small_grid, |root_grid| { root_grid.spawn_spatial(DirectionalLight::default()); // A carbon atom at the origin root_grid.spawn_spatial(( Atom, Mesh3d(meshes.add(Sphere::default())), MeshMaterial3d(materials.add(Color::WHITE)), Transform::from_scale(Vec3::splat(SMALL_SCALE)), )); // Compute the grid cell for the far away objects let (grid_cell, cell_offset) = root_grid .grid() .translation_to_grid(DVec3::X * BIG_DISTANCE); // A carbon atom at the other side of the milky way root_grid.spawn_spatial(( Atom, Mesh3d(meshes.add(Sphere::default())), MeshMaterial3d(materials.add(Color::WHITE)), Transform::from_translation(cell_offset).with_scale(Vec3::splat(SMALL_SCALE)), grid_cell, )); root_grid.spawn_spatial(( Camera3d::default(), Projection::Perspective(PerspectiveProjection { near: SMALL_SCALE * 0.01, // Without this, the atom would be clipped ..Default::default() }), Transform::from_xyz(0.0, 0.0, SMALL_SCALE * 2.0), grid_cell, FloatingOrigin, big_space::camera::CameraController::default(), )); // A space ship root_grid.spawn_spatial(( SceneRoot(asset_server.load("models/low_poly_spaceship/scene.gltf#Scene0")), Transform::from_xyz(0.0, 0.0, 2.5) .with_rotation(Quat::from_rotation_y(std::f32::consts::PI)), grid_cell, )); }); commands.spawn(Text::new(format!( "Press `T` to teleport between the origin and ship {BIG_DISTANCE}m away." ))); } fn bounce_atoms(mut atoms: Query<&mut Transform, With>, time: Res