diff --git a/Cargo.toml b/Cargo.toml index e44d159..cc5732c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,13 +15,17 @@ bevy = { version = "0.13", default_features = false } [dev-dependencies] bevy = { version = "0.13", default-features = false, features = [ + "bevy_scene", + "bevy_gltf", "bevy_winit", "default_font", "bevy_ui", "bevy_pbr", "x11", "tonemapping_luts", + "multi-threaded", ] } +bevy-inspector-egui = "0.24" bevy_framepace = { version = "0.15", default-features = false } rand = "0.8.5" @@ -60,3 +64,9 @@ name = "planets" path = "examples/planets.rs" required-features = ["default"] doc-scrape-examples = true + +[[example]] +name = "split_screen" +path = "examples/split_screen.rs" +required-features = ["default"] +doc-scrape-examples = true diff --git a/README.md b/README.md index f1e2364..1ce0c23 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ https://user-images.githubusercontent.com/2632925/215318129-5bab3095-a7dd-455b-a Lots of space to play in. -This is a simple floating origin plugin, useful if you want to work with very, very large scales. It works with bevy's existing `f32`-based `Transform`s, which means it's largely compatible with the bevy ecosystem. The plugin positions entities within large fixed precision grids, effectively adding precision to the location of objects. +This is a floating origin plugin, useful if you want to work with very large or very small scales. It works with bevy's existing `f32`-based `Transform`s, which means it's largely compatible with the bevy ecosystem. The plugin positions entities within large fixed precision grids, effectively adding precision to the location of objects. -Additionally, you can use reference frames to nest high precision coordinate systems. For example you might want to put all entities on a planet into the same reference frame. You can then rotate this reference frame with the planet, and orbit that planet around a star. +Additionally, you can use reference frames to nest high precision coordinate systems. For example you might want to put all entities on a planet's surface into the same reference frame. You can then rotate this reference frame with the planet, and orbit that planet around a star. The plugin is generic over a few integer types, to trade off scale and precision for memory use. Some fun numbers with a worst case precision of 0.5mm: - `i8`: 2,560 km = 74% of the diameter of the Moon @@ -30,12 +30,12 @@ The plugin is generic over a few integer types, to trade off scale and precision - `i64`: 19.5 million light years = ~100 times the width of the milky way galaxy - `i128`: 3.6e+26 light years = ~3.9e+15 times the width of the observable universe -From the docs: https://docs.rs/big_space/latest/big_space/struct.GridCell.html +This can also be used for small scales. With a cell edge length of `1e-11`, and using `i128`, there is enough precision to render objects the size of quarks anywhere in the observable universe. + +From the docs: https://docs.rs/big_space/latest/big_space/precision/trait.GridPrecision.html # Bevy Version Support -I intend to track the `main` branch of Bevy. PRs supporting this are welcome! - | bevy | big_space | | ---- | --------- | | 0.13 | 0.5, 0.6 | diff --git a/assets/models/low_poly_spaceship/license.txt b/assets/models/low_poly_spaceship/license.txt new file mode 100644 index 0000000..9124690 --- /dev/null +++ b/assets/models/low_poly_spaceship/license.txt @@ -0,0 +1,11 @@ +Model Information: +* title: Low Poly Spaceship +* source: https://sketchfab.com/3d-models/low-poly-spaceship-f854128cf78d4dafb28d16b3c15001ba +* author: FriendlyCreep (https://sketchfab.com/FriendlyCreep) + +Model License: +* license type: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/) +* requirements: Author must be credited. Commercial use is allowed. + +If you use this 3D model in your project be sure to copy paste this credit wherever you share it: +This work is based on "Low Poly Spaceship" (https://sketchfab.com/3d-models/low-poly-spaceship-f854128cf78d4dafb28d16b3c15001ba) by FriendlyCreep (https://sketchfab.com/FriendlyCreep) licensed under CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/) \ No newline at end of file diff --git a/assets/models/low_poly_spaceship/scene.bin b/assets/models/low_poly_spaceship/scene.bin new file mode 100644 index 0000000..2ca8904 Binary files /dev/null and b/assets/models/low_poly_spaceship/scene.bin differ diff --git a/assets/models/low_poly_spaceship/scene.gltf b/assets/models/low_poly_spaceship/scene.gltf new file mode 100644 index 0000000..f637834 --- /dev/null +++ b/assets/models/low_poly_spaceship/scene.gltf @@ -0,0 +1,470 @@ +{ + "accessors": [ + { + "bufferView": 2, + "componentType": 5126, + "count": 712, + "max": [ + 4.986988067626953, + 0.5560435652732849, + 9.616311073303223 + ], + "min": [ + -4.986988067626953, + -1.969908356666565, + -4.9558634757995605 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 8544, + "componentType": 5126, + "count": 712, + "max": [ + 1.0, + 0.9917697906494141, + 0.9999937415122986 + ], + "min": [ + -1.0, + -0.9730851054191589, + -0.9999937415122986 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "componentType": 5126, + "count": 712, + "max": [ + 0.7559658885002136, + 0.75 + ], + "min": [ + 0.1249999925494194, + 0.24999994039535522 + ], + "type": "VEC2" + }, + { + "bufferView": 0, + "componentType": 5125, + "count": 1164, + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 17088, + "componentType": 5126, + "count": 1768, + "max": [ + 5.272348403930664, + 0.6022237539291382, + 9.626778602600098 + ], + "min": [ + -5.272348403930664, + -2.1259989738464355, + -4.9558634757995605 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 38304, + "componentType": 5126, + "count": 1768, + "max": [ + 1.0, + 1.0, + 1.0 + ], + "min": [ + -1.0, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 5696, + "componentType": 5126, + "count": 1768, + "max": [ + 0.875, + 1.0 + ], + "min": [ + 0.0, + 0.0 + ], + "type": "VEC2" + }, + { + "bufferView": 0, + "byteOffset": 4656, + "componentType": 5125, + "count": 5070, + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 59520, + "componentType": 5126, + "count": 866, + "max": [ + 3.563509702682495, + 0.6022237539291382, + 9.626778602600098 + ], + "min": [ + -3.563509702682495, + -1.5118601322174072, + -4.9558634757995605 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 69912, + "componentType": 5126, + "count": 866, + "max": [ + 1.0, + 1.0, + 1.0 + ], + "min": [ + -1.0, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 19840, + "componentType": 5126, + "count": 866, + "max": [ + 0.875, + 0.75 + ], + "min": [ + 0.0, + 0.0 + ], + "type": "VEC2" + }, + { + "bufferView": 0, + "byteOffset": 24936, + "componentType": 5125, + "count": 1476, + "type": "SCALAR" + }, + { + "bufferView": 2, + "byteOffset": 80304, + "componentType": 5126, + "count": 296, + "max": [ + 4.863146781921387, + 0.5145567655563354, + 9.446455955505371 + ], + "min": [ + -4.863146781921387, + -1.8699951171875, + -4.738320827484131 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 83856, + "componentType": 5126, + "count": 296, + "max": [ + 1.0, + 1.0, + 0.9979816675186157 + ], + "min": [ + -0.8001577854156494, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 26768, + "componentType": 5126, + "count": 296, + "max": [ + 0.7559658885002136, + 0.735460638999939 + ], + "min": [ + 0.0, + 0.0 + ], + "type": "VEC2" + }, + { + "bufferView": 0, + "byteOffset": 30840, + "componentType": 5125, + "count": 600, + "type": "SCALAR" + } + ], + "asset": { + "extras": { + "author": "FriendlyCreep (https://sketchfab.com/FriendlyCreep)", + "license": "CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)", + "source": "https://sketchfab.com/3d-models/low-poly-spaceship-f854128cf78d4dafb28d16b3c15001ba", + "title": "Low Poly Spaceship" + }, + "generator": "Sketchfab-12.68.0", + "version": "2.0" + }, + "bufferViews": [ + { + "buffer": 0, + "byteLength": 33240, + "name": "floatBufferViews", + "target": 34963 + }, + { + "buffer": 0, + "byteLength": 29136, + "byteOffset": 33240, + "byteStride": 8, + "name": "floatBufferViews", + "target": 34962 + }, + { + "buffer": 0, + "byteLength": 87408, + "byteOffset": 62376, + "byteStride": 12, + "name": "floatBufferViews", + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 149784, + "uri": "scene.bin" + } + ], + "materials": [ + { + "doubleSided": true, + "name": "Material.001", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.0, + 0.0, + 0.0, + 1.0 + ], + "metallicFactor": 0.0, + "roughnessFactor": 0.5 + } + }, + { + "doubleSided": true, + "name": "Material.002", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.226583, + 0.226583, + 0.226583, + 1.0 + ], + "metallicFactor": 0.0, + "roughnessFactor": 0.5 + } + }, + { + "doubleSided": true, + "name": "Material.003", + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.8, + 0.0113789, + 0.0, + 1.0 + ], + "metallicFactor": 0.0, + "roughnessFactor": 0.5 + } + }, + { + "doubleSided": true, + "emissiveFactor": [ + 0.0, + 0.161466, + 1.0 + ], + "name": "Material.004" + } + ], + "meshes": [ + { + "name": "Object_0", + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 0, + "TEXCOORD_0": 2 + }, + "indices": 3, + "material": 0, + "mode": 4 + } + ] + }, + { + "name": "Object_1", + "primitives": [ + { + "attributes": { + "NORMAL": 5, + "POSITION": 4, + "TEXCOORD_0": 6 + }, + "indices": 7, + "material": 1, + "mode": 4 + } + ] + }, + { + "name": "Object_2", + "primitives": [ + { + "attributes": { + "NORMAL": 9, + "POSITION": 8, + "TEXCOORD_0": 10 + }, + "indices": 11, + "material": 2, + "mode": 4 + } + ] + }, + { + "name": "Object_3", + "primitives": [ + { + "attributes": { + "NORMAL": 13, + "POSITION": 12, + "TEXCOORD_0": 14 + }, + "indices": 15, + "material": 3, + "mode": 4 + } + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 2.220446049250313e-16, + -1.0, + 0.0, + 0.0, + 1.0, + 2.220446049250313e-16, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ], + "name": "Sketchfab_model" + }, + { + "children": [ + 2 + ], + "name": "root" + }, + { + "children": [ + 3 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 2.220446049250313e-16, + 1.0, + 0.0, + 0.0, + -1.0, + 2.220446049250313e-16, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ], + "name": "GLTF_SceneRootNode" + }, + { + "children": [ + 4, + 5, + 6, + 7 + ], + "name": "Cube_0" + }, + { + "mesh": 0, + "name": "Object_4" + }, + { + "mesh": 1, + "name": "Object_5" + }, + { + "mesh": 2, + "name": "Object_6" + }, + { + "mesh": 3, + "name": "Object_7" + } + ], + "scene": 0, + "scenes": [ + { + "name": "Sketchfab_Scene", + "nodes": [ + 0 + ] + } + ] +} diff --git a/examples/debug.rs b/examples/debug.rs index 162b7d9..65a5aa9 100644 --- a/examples/debug.rs +++ b/examples/debug.rs @@ -1,13 +1,13 @@ #![allow(clippy::type_complexity)] use bevy::prelude::*; -use big_space::{reference_frame::ReferenceFrame, FloatingOrigin, GridCell}; +use big_space::{commands::BigSpaceCommands, reference_frame::ReferenceFrame, FloatingOrigin}; fn main() { App::new() .add_plugins(( DefaultPlugins.build().disable::(), - big_space::FloatingOriginPlugin::::new(0.5, 0.01), + big_space::BigSpacePlugin::::default(), big_space::debug::FloatingOriginDebugPlugin::::default(), )) .insert_resource(ClearColor(Color::BLACK)) @@ -65,69 +65,63 @@ fn setup( ..default() }); - commands.spawn(( - PbrBundle { - mesh: mesh_handle.clone(), - material: matl_handle.clone(), - transform: Transform::from_xyz(0.0, 0.0, 1.0), - ..default() - }, - GridCell::::default(), - Mover::<1>, - )); - commands.spawn(( - PbrBundle { - mesh: mesh_handle.clone(), - material: matl_handle.clone(), - transform: Transform::from_xyz(1.0, 0.0, 0.0), - ..default() - }, - GridCell::::default(), - Mover::<2>, - )); - commands - .spawn(( + commands.spawn_big_space(ReferenceFrame::::new(1.0, 0.01), |root| { + root.spawn_spatial(( PbrBundle { mesh: mesh_handle.clone(), material: matl_handle.clone(), - transform: Transform::from_xyz(0.0, 1.0, 0.0), + transform: Transform::from_xyz(0.0, 0.0, 1.0), ..default() }, - GridCell::::default(), - ReferenceFrame::::new(0.2, 0.01), - Rotator, - Mover::<3>, - )) - .with_children(|parent| { - parent.spawn(( + Mover::<1>, + )); + + root.spawn_spatial(( + PbrBundle { + mesh: mesh_handle.clone(), + material: matl_handle.clone(), + transform: Transform::from_xyz(1.0, 0.0, 0.0), + ..default() + }, + Mover::<2>, + )); + + root.with_frame(ReferenceFrame::new(0.2, 0.01), |new_frame| { + new_frame.insert(( + PbrBundle { + mesh: mesh_handle.clone(), + material: matl_handle.clone(), + transform: Transform::from_xyz(0.0, 1.0, 0.0), + ..default() + }, + Rotator, + Mover::<3>, + )); + new_frame.spawn_spatial(( PbrBundle { mesh: mesh_handle, material: matl_handle, transform: Transform::from_xyz(0.0, 0.5, 0.0), ..default() }, - GridCell::::default(), Mover::<4>, )); }); - // light - commands.spawn(( - PointLightBundle { + // light + root.spawn_spatial((PointLightBundle { transform: Transform::from_xyz(4.0, 8.0, 4.0), ..default() - }, - GridCell::::default(), - )); + },)); - // camera - commands.spawn(( - Camera3dBundle { - transform: Transform::from_xyz(0.0, 0.0, 8.0) - .looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y), - ..default() - }, - GridCell::::default(), - FloatingOrigin, - )); + // camera + root.spawn_spatial(( + Camera3dBundle { + transform: Transform::from_xyz(0.0, 0.0, 8.0) + .looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y), + ..default() + }, + FloatingOrigin, + )); + }); } diff --git a/examples/demo.rs b/examples/demo.rs index feb746b..37a4812 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -5,27 +5,27 @@ use bevy::{ }; use big_space::{ camera::{CameraController, CameraInput}, - propagation::IgnoreFloatingOrigin, - reference_frame::RootReferenceFrame, + commands::BigSpaceCommands, + reference_frame::{local_origin::ReferenceFrames, ReferenceFrame}, world_query::GridTransformReadOnly, - FloatingOrigin, GridCell, + FloatingOrigin, }; fn main() { App::new() .add_plugins(( DefaultPlugins.build().disable::(), - big_space::FloatingOriginPlugin::::default(), + big_space::BigSpacePlugin::::default(), big_space::debug::FloatingOriginDebugPlugin::::default(), big_space::camera::CameraControllerPlugin::::default(), bevy_framepace::FramepacePlugin, )) .insert_resource(ClearColor(Color::BLACK)) .add_systems(Startup, (setup, ui_setup)) - .add_systems(PreUpdate, cursor_grab_system) + .add_systems(PreUpdate, (cursor_grab_system, ui_text_system)) .add_systems( PostUpdate, - (highlight_nearest_sphere, ui_text_system).after(TransformSystem::TransformPropagate), + highlight_nearest_sphere.after(TransformSystem::TransformPropagate), ) .run() } @@ -35,57 +35,56 @@ fn setup( mut meshes: ResMut>, mut materials: ResMut>, ) { - // camera - commands.spawn(( - Camera3dBundle { - transform: Transform::from_xyz(0.0, 0.0, 8.0) - .looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y), - projection: Projection::Perspective(PerspectiveProjection { - near: 1e-18, + commands.spawn_big_space(ReferenceFrame::::default(), |root| { + root.spawn_spatial(( + Camera3dBundle { + transform: Transform::from_xyz(0.0, 0.0, 8.0) + .looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y), + projection: Projection::Perspective(PerspectiveProjection { + near: 1e-18, + ..default() + }), ..default() - }), + }, + FloatingOrigin, // Important: marks the floating origin entity for rendering. + CameraController::default() // Built-in camera controller + .with_speed_bounds([10e-18, 10e35]) + .with_smoothness(0.9, 0.8) + .with_speed(1.0), + )); + + let mesh_handle = meshes.add(Sphere::new(0.5).mesh().ico(32).unwrap()); + let matl_handle = materials.add(StandardMaterial { + base_color: Color::BLUE, + perceptual_roughness: 0.8, + reflectance: 1.0, ..default() - }, - GridCell::::default(), // All spatial entities need this component - FloatingOrigin, // Important: marks the floating origin entity for rendering. - CameraController::default() // Built-in camera controller - .with_speed_bounds([10e-18, 10e35]) - .with_smoothness(0.9, 0.8) - .with_speed(1.0), - )); + }); - let mesh_handle = meshes.add(Sphere::new(0.5).mesh().ico(32).unwrap()); - let matl_handle = materials.add(StandardMaterial { - base_color: Color::BLUE, - perceptual_roughness: 0.8, - reflectance: 1.0, - ..default() - }); + let mut translation = Vec3::ZERO; + for i in -16..=27 { + let j = 10_f32.powf(i as f32); + let k = 10_f32.powf((i - 1) as f32); + translation.x += j / 2.0 + k; + translation.y = j / 2.0; - let mut translation = Vec3::ZERO; - for i in -16..=27 { - let j = 10_f32.powf(i as f32); - let k = 10_f32.powf((i - 1) as f32); - translation.x += j / 2.0 + k; - commands.spawn(( - PbrBundle { + root.spawn_spatial(PbrBundle { mesh: mesh_handle.clone(), material: matl_handle.clone(), transform: Transform::from_scale(Vec3::splat(j)).with_translation(translation), ..default() - }, - GridCell::::default(), - )); - } + }); + } - // light - commands.spawn((DirectionalLightBundle { - directional_light: DirectionalLight { - illuminance: 100_000.0, + // light + root.spawn_spatial(DirectionalLightBundle { + directional_light: DirectionalLight { + illuminance: 100_000.0, + ..default() + }, ..default() - }, - ..default() - },)); + }); + }); } #[derive(Component, Reflect)] @@ -112,7 +111,6 @@ fn ui_setup(mut commands: Commands) { ..default() }), BigSpaceDebugText, - IgnoreFloatingOrigin, )); commands.spawn(( @@ -133,7 +131,6 @@ fn ui_setup(mut commands: Commands) { }) .with_text_justify(JustifyText::Center), FunFactText, - IgnoreFloatingOrigin, )); } @@ -162,18 +159,18 @@ fn ui_text_system( (With, Without), >, mut fun_text: Query<&mut Text, (With, Without)>, + ref_frames: ReferenceFrames, time: Res