Skip to content

Commit

Permalink
Merge pull request #10 from Utsira/feature/deprecate-voxelscene
Browse files Browse the repository at this point in the history
Feature/deprecate voxelscene
  • Loading branch information
Utsira authored Aug 24, 2024
2 parents a1ccfb4 + c83049d commit 21ccb7e
Show file tree
Hide file tree
Showing 19 changed files with 583 additions and 685 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ bevy_vox_scene = "0.14.0"

```rust no_run
use bevy::prelude::*;
use bevy_vox_scene::{VoxScenePlugin, VoxelSceneBundle}; // 2.
use bevy_vox_scene::VoxScenePlugin; // 2.

fn main() {
App::new()
Expand All @@ -54,7 +54,7 @@ fn main() {
}

fn setup(mut commands: Commands, assets: Res<AssetServer>) {
commands.spawn(VoxelSceneBundle { // 4.
commands.spawn(SceneBundle { // 4.
scene: assets.load("study.vox#workstation/desk"),
..default()
});
Expand All @@ -63,7 +63,7 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>) {

2. Import the library.
3. Add the plugin to the app.
4. Spawn a scene graph using `VoxelSceneBundle`. Alternatively, spawn any node of the scene graph, down to individual models, using the name you assigned to the node in MagicaVoxel.
4. Spawn a scene graph using `SceneBundle`. Alternatively, spawn any node of the scene graph, down to individual models, using the name you assigned to the node in MagicaVoxel.

Take a look in the `examples/` directory for complete working examples. To run an example, type the following into the terminal:
```ignore
Expand Down
4 changes: 2 additions & 2 deletions examples/basic-model.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bevy::prelude::*;
use bevy_vox_scene::{VoxScenePlugin, VoxelSceneBundle};
use bevy_vox_scene::VoxScenePlugin;

fn main() {
App::new()
Expand All @@ -21,7 +21,7 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>) {
},
));

commands.spawn(VoxelSceneBundle {
commands.spawn(SceneBundle {
// Load a single model using the name assigned to it in MagicaVoxel
// If a model is nested in a named group, than the group will form part of the path
// Path components are separated with a slash
Expand Down
4 changes: 2 additions & 2 deletions examples/emissive-model.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bevy::{core_pipeline::bloom::BloomSettings, prelude::*};
use bevy_vox_scene::{VoxScenePlugin, VoxelSceneBundle};
use bevy_vox_scene::VoxScenePlugin;
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};

fn main() {
Expand Down Expand Up @@ -36,7 +36,7 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>) {
},
));

commands.spawn(VoxelSceneBundle {
commands.spawn(SceneBundle {
// Load a single model using the name assigned to it in MagicaVoxel
scene: assets.load("study.vox#workstation/computer"),
..default()
Expand Down
18 changes: 7 additions & 11 deletions examples/modify-scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use bevy::{
input::keyboard::KeyboardInput,
prelude::*,
};
use bevy_vox_scene::{VoxScenePlugin, VoxelModelInstance, VoxelSceneBundle};
use bevy_vox_scene::VoxScenePlugin;
use rand::Rng;
use std::f32::consts::PI;
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};

/// Uses the [`bevy_vox_scene::VoxelSceneHook`] component to add extra components into the scene graph.
/// Uses an observer triggered by `VoxelModelInstance` being added to add extra components into the scene graph.
/// Press any key to toggle the fish tank black-light on and off
fn main() {
let mut app = App::new();
Expand Down Expand Up @@ -73,7 +73,7 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>) {
intensity: 500.0,
},
));
commands.spawn(VoxelSceneBundle {
commands.spawn(SceneBundle {
// "tank" is the name of the group containing the glass walls, the body of water, the scenery in the tank and the fish
scene: assets.load("study.vox#tank"),
transform: Transform::from_scale(Vec3::splat(0.05)),
Expand All @@ -82,19 +82,15 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>) {
commands.observe(on_spawn_voxel_instance);
}

// Will run against every child entity that gets spawned in the scene
// Will run against every named child entity that gets spawned in the scene
fn on_spawn_voxel_instance(
trigger: Trigger<OnAdd, VoxelModelInstance>,
model_query: Query<&VoxelModelInstance>,
trigger: Trigger<OnAdd, Name>,
model_query: Query<&Name>,
mut commands: Commands,
assets: Res<AssetServer>,
) {
let mut entity_commands = commands.entity(trigger.entity());
let name = model_query
.get(trigger.entity())
.unwrap()
.model_name
.as_str();
let name = model_query.get(trigger.entity()).unwrap().as_str();
match name {
"tank/black-light" => {
entity_commands.insert(EmissiveToggle {
Expand Down
39 changes: 20 additions & 19 deletions examples/modify-voxels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use bevy::{
time::common_conditions::on_timer,
};
use bevy_vox_scene::{
ModifyVoxelCommandsExt, VoxScenePlugin, Voxel, VoxelModelInstance, VoxelRegion,
VoxelRegionMode, VoxelSceneBundle,
ModifyVoxelCommandsExt, VoxScenePlugin, Voxel, VoxelModelInstance, VoxelRegion, VoxelRegionMode,
};
use rand::Rng;
use std::{ops::RangeInclusive, time::Duration};
Expand All @@ -30,6 +29,7 @@ fn main() {
struct Floor;

fn setup(mut commands: Commands, assets: Res<AssetServer>) {
commands.observe(on_spawn_voxel_instance);
commands.spawn((
Camera3dBundle {
camera: Camera {
Expand All @@ -50,36 +50,37 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>) {
specular_map: assets.load("pisa_specular.ktx2"),
intensity: 500.0,
},
Name::new("camera"),
));

commands.spawn(DirectionalLightBundle {
directional_light: DirectionalLight {
illuminance: 5000.0,
shadows_enabled: true,
..Default::default()
commands.spawn((
DirectionalLightBundle {
directional_light: DirectionalLight {
illuminance: 5000.0,
shadows_enabled: true,
..Default::default()
},
transform: Transform::IDENTITY.looking_to(Vec3::new(1.0, -2.5, 0.85), Vec3::Y),
..default()
},
transform: Transform::IDENTITY.looking_to(Vec3::new(1.0, -2.5, 0.85), Vec3::Y),
..default()
});
Name::new("light"),
));

commands.spawn(VoxelSceneBundle {
commands.spawn(SceneBundle {
scene: assets.load("study.vox"),
transform: Transform::from_scale(Vec3::splat(0.05)),
..default()
});
commands.observe(on_spawn_voxel_instance);
}

fn on_spawn_voxel_instance(
trigger: Trigger<OnAdd, VoxelModelInstance>,
model_query: Query<&VoxelModelInstance>,
trigger: Trigger<OnAdd, Name>,
model_query: Query<&Name>,
mut commands: Commands,
) {
let name = model_query
.get(trigger.entity())
.unwrap()
.model_name
.as_str();
let Ok(name) = model_query.get(trigger.entity()).map(|n| n.as_str()) else {
return;
};
if name == "floor" {
commands.entity(trigger.entity()).insert(Floor);
}
Expand Down
4 changes: 2 additions & 2 deletions examples/scene-slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy::{
},
prelude::*,
};
use bevy_vox_scene::{VoxScenePlugin, VoxelSceneBundle};
use bevy_vox_scene::VoxScenePlugin;
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};

/// Asset labels aren't just for loading individual models within a scene, they can load any named group within a scene, a "slice" of the scene
Expand Down Expand Up @@ -62,7 +62,7 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>) {
},
));

commands.spawn(VoxelSceneBundle {
commands.spawn(SceneBundle {
// "workstation" is the name of the group containing the desk, computer, & keyboard
scene: assets.load("study.vox#workstation"),
transform: Transform::from_scale(Vec3::splat(0.05)),
Expand Down
4 changes: 2 additions & 2 deletions examples/ssao-model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy::{
pbr::ScreenSpaceAmbientOcclusionBundle,
prelude::*,
};
use bevy_vox_scene::{VoxScenePlugin, VoxelSceneBundle};
use bevy_vox_scene::VoxScenePlugin;
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};

/// Press any key to toggle Screen Space Ambient Occlusion
Expand Down Expand Up @@ -66,7 +66,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
))
.insert(ScreenSpaceAmbientOcclusionBundle::default());

commands.spawn(VoxelSceneBundle {
commands.spawn(SceneBundle {
// Load a model nested inside a group by using a `/` to separate the path components
scene: asset_server.load("study.vox#tank/goldfish"),
..default()
Expand Down
7 changes: 3 additions & 4 deletions examples/transmission-scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use bevy::{
pbr::{VolumetricFogSettings, VolumetricLight},
prelude::*,
};
use bevy_vox_scene::{VoxLoaderSettings, VoxScenePlugin, VoxelSceneBundle};
use bevy_vox_scene::{VoxLoaderSettings, VoxScenePlugin};
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};

fn main() {
Expand All @@ -19,7 +19,7 @@ fn main() {
PanOrbitCameraPlugin,
VoxScenePlugin {
global_settings: Some(VoxLoaderSettings {
voxel_size: 0.5,
voxel_size: 0.05,
..default()
}),
},
Expand Down Expand Up @@ -80,9 +80,8 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>) {
VolumetricLight,
));

commands.spawn(VoxelSceneBundle {
commands.spawn(SceneBundle {
scene: assets.load("study.vox"),
transform: Transform::from_scale(Vec3::splat(0.05)),
..default()
});
}
57 changes: 26 additions & 31 deletions examples/voxel-collisions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use bevy::{
time::common_conditions::on_timer,
};
use bevy_vox_scene::{
DidSpawnVoxelChild, ModifyVoxelCommandsExt, VoxScenePlugin, Voxel, VoxelModelCollection,
VoxelModelInstance, VoxelQueryable, VoxelRegion, VoxelRegionMode, VoxelScene, VoxelSceneBundle,
ModifyVoxelCommandsExt, VoxScenePlugin, Voxel, VoxelModel, VoxelModelInstance, VoxelQueryable,
VoxelRegion, VoxelRegionMode,
};
use rand::Rng;
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};
Expand Down Expand Up @@ -51,22 +51,19 @@ fn main() {

#[derive(Resource)]
struct Scenes {
snowflake: Handle<VoxelScene>,
snowflake: Handle<Mesh>,
voxel_material: Handle<StandardMaterial>,
}

/// The [`DidSpawnVoxelChild`] event is targeted at the root of a specific [`VoxelScene`], and triggers
/// once for each child [`VoxelModelInstance`] that gets spawned in that node graph.
/// This is useful when we will be spawning other voxel scenes, so that we can scope the observer
/// to one scene and not worry about adding in defensive code.
/// The event also includes the [`model_name`] and [`layer_name`] so you need fewer queries in your observer.
/// Compare with the observer triggered with [`Trigger<OnAdd, VoxelModelInstance>`] in [modify scene](./modify-scene.rs).
fn on_spawn_voxel_instance(trigger: Trigger<DidSpawnVoxelChild>, mut commands: Commands) {
// Note that we're interested in the child entity, which is `trigger.event().child`
// Not the root entity, which is `trigger.entity()`
let mut entity_commands = commands.entity(trigger.event().child);
let name = trigger.event().model_name.as_str();
fn on_spawn_voxel_instance(
trigger: Trigger<OnAdd, Name>,
query: Query<&Name>,
mut commands: Commands,
) {
let mut entity_commands = commands.entity(trigger.entity());
let name = query.get(trigger.entity()).map_or("", |n| n.as_str());
match name {
"snowflake" => panic!("This should never be executed, because this observer is scoped to the 'workstation' scene graph"),
"snowflake" => return,
"workstation/computer" => {
// Focus on the computer screen by suppling the local voxel coordinates of the center of the screen
entity_commands.insert(FocalPoint(Vec3::new(0., 0., 9.)));
Expand Down Expand Up @@ -112,17 +109,16 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>) {
},
));
commands.insert_resource(Scenes {
snowflake: assets.load("study.vox#snowflake"),
snowflake: assets.load("study.vox#snowflake@mesh"),
voxel_material: assets.load("study.vox#snowflake@material"),
});

// NB the `on_spawn_voxel_instance` observer is scoped to just this scene graph: we don't want it firing when snowflakes are spawned later on.
commands
.spawn(VoxelSceneBundle {
// Load a slice of the scene
scene: assets.load("study.vox#workstation"),
..default()
})
.observe(on_spawn_voxel_instance);
commands.spawn(SceneBundle {
// Load a slice of the scene
scene: assets.load("study.vox#workstation"),
..default()
});
commands.observe(on_spawn_voxel_instance);
}

#[derive(Component)]
Expand All @@ -142,9 +138,11 @@ fn spawn_snow(mut commands: Commands, scenes: Res<Scenes>) {
Vec3::new(rng.gen_range(-0.5..0.5), 1.0, rng.gen_range(-0.5..0.5)).normalize();
let angular_velocity = Quat::from_axis_angle(rotation_axis, 0.01);
commands.spawn((
Name::new("snowflake"),
Snowflake(angular_velocity),
VoxelSceneBundle {
scene: scenes.snowflake.clone(),
PbrBundle {
mesh: scenes.snowflake.clone(),
material: scenes.voxel_material.clone(),
transform: Transform::from_translation(position),
..default()
},
Expand All @@ -155,7 +153,7 @@ fn update_snow(
mut commands: Commands,
mut snowflakes: Query<(Entity, &Snowflake, &mut Transform), Without<Scenery>>,
scenery: Query<(&GlobalTransform, &VoxelModelInstance), (With<Scenery>, Without<Snowflake>)>,
model_collections: Res<Assets<VoxelModelCollection>>,
models: Res<Assets<VoxelModel>>,
) {
for (snowflake, snowflake_angular_vel, mut snowflake_xform) in snowflakes.iter_mut() {
let old_ypos = snowflake_xform.translation.y;
Expand All @@ -166,10 +164,7 @@ fn update_snow(
continue;
}
for (item_xform, item_instance) in scenery.iter() {
let Some(collection) = model_collections.get(item_instance.collection.id()) else {
continue;
};
let Some(model) = collection.model(&item_instance.model_name) else {
let Some(model) = models.get(&item_instance.model) else {
continue;
};
let vox_pos =
Expand Down
14 changes: 6 additions & 8 deletions examples/voxel-generation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bevy::{core_pipeline::bloom::BloomSettings, prelude::*};
use bevy_vox_scene::{
VoxScenePlugin, Voxel, VoxelModelCollection, VoxelModelInstance, VoxelPalette, SDF,
VoxScenePlugin, Voxel, VoxelContext, VoxelModel, VoxelModelInstance, VoxelPalette, SDF,
};
use utilities::{PanOrbitCamera, PanOrbitCameraPlugin};

Expand Down Expand Up @@ -52,12 +52,10 @@ fn setup(world: &mut World) {
x if x >= 0.0 => Voxel::EMPTY,
_ => Voxel::EMPTY,
});
let Some(collection) = VoxelModelCollection::new(world, palette) else {
return;
};
let context = VoxelContext::new(world, palette);
let model_name = "my sdf model";
let Some(model) =
VoxelModelCollection::add(world, data, model_name.to_string(), collection.clone())
let Some((model_handle, model)) =
VoxelModel::new(world, data, model_name.to_string(), context.clone())
else {
return;
};
Expand All @@ -69,8 +67,8 @@ fn setup(world: &mut World) {
},
// The [`VoxelModelInstance`] component is only needed if you want to be able to modify the model at a later time:
VoxelModelInstance {
collection,
model_name: model_name.to_string(),
model: model_handle,
context,
},
));
}
Loading

0 comments on commit 21ccb7e

Please sign in to comment.