Starting work on skybox

need to make an example to just prove it out.
But at least it doesn't crash the game!
selection-refactor
Elijah Voigt 2 years ago
parent f87bfb5a6c
commit fe013dcf3c

BIN
assets/Ryfjallet_cubemap.png (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

BIN
assets/images/cube.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/images/cubemap.blend (Stored with Git LFS)

Binary file not shown.

BIN
assets/images/cubemap.blend1 (Stored with Git LFS)

Binary file not shown.

BIN
assets/images/cubemap.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/images/mars-skybox.xcf (Stored with Git LFS)

Binary file not shown.

BIN
assets/images/mars.hdr (Stored with Git LFS)

Binary file not shown.

BIN
assets/images/skybox_negx.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/images/skybox_negy.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/images/skybox_negz.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/images/skybox_posx.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/images/skybox_posy.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/images/skybox_posz.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/models/Martian Chess.glb (Stored with Git LFS)

Binary file not shown.

@ -1,19 +1,32 @@
use crate::{game::BoardIndex, prelude::*};
use crate::{
game::{Board, BoardIndex, Piece, Side},
prelude::*,
};
use bevy::{
core_pipeline::Skybox,
render::render_resource::{TextureViewDescriptor, TextureViewDimension},
};
pub(crate) struct Display3dPlugin;
impl Plugin for Display3dPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, initialize_camera)
.add_systems(OnEnter(GameState::Loading), load_models)
.add_systems(OnExit(GameState::Loading), initialize_board)
app.add_systems(OnEnter(GameState::Loading), load_assets)
.add_systems(
OnExit(GameState::Loading),
(initialize, fix_skybox.before(initialize)),
)
.add_systems(
Update,
menu::exit_to_menu.run_if(in_state(GameState::Display3d)),
)
.add_systems(
Update,
set_piece_position.run_if(in_state(GameState::Display3d)),
(
set_piece_position.run_if(any_component_changed::<BoardIndex>),
set_piece_model.run_if(any_component_changed::<Side>),
set_board_model.run_if(any_component_added::<Board3d>),
),
)
.add_systems(
Update,
@ -32,7 +45,29 @@ struct Display3d;
#[derive(Debug, Component)]
pub(crate) struct Piece3d;
fn initialize_camera(mut commands: Commands) {
#[derive(Debug, Component)]
pub(crate) struct Board3d;
#[derive(Debug, Resource)]
struct AssetsMap {
models: Handle<Gltf>,
skybox: Handle<Image>,
}
/// Load 3d models
/// This is kind of pulling double duty.
/// Both loads the GLTF file _and_ populates the ModelMap once that is loaded.
fn load_assets(server: Res<AssetServer>, mut commands: Commands) {
commands.insert_resource(AssetsMap {
models: server.load("models/Martian Chess.glb"),
skybox: server.load("images/cubemap.png"),
});
}
/// Initialize the 3d board
fn initialize(mut commands: Commands, board: Option<Res<game::Board>>, assets: Res<AssetsMap>) {
info!("Initialize 3d camera");
// let handle = server.load("images/mars.hdr");
commands.spawn((
Display3d,
Camera3dBundle {
@ -48,6 +83,11 @@ fn initialize_camera(mut commands: Commands) {
transform: Transform::from_xyz(0.0, 20.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
},
Skybox(assets.skybox.clone()),
// EnvironmentMapLight {
// diffuse_map: server.load("images/pisa_diffuse_rgb9e5_zstd.ktx2"),
// specular_map: server.load("images/pisa_specular_rgb9e5_zstd.ktx2"),
// },
UiCameraConfig { show_ui: true },
));
// light
@ -60,96 +100,98 @@ fn initialize_camera(mut commands: Commands) {
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
});
info!("Initializing root");
commands
.spawn((
SpatialBundle {
visibility: Visibility::Hidden,
..default()
},
Display3d,
))
.with_children(|parent| {
info!("Initializing 3D lights!");
parent.spawn((
Display3d,
PointLightBundle {
point_light: PointLight {
intensity: 1500.0,
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
},
));
info!("Intializing 3D Board!");
parent
.spawn((Display3d, Board3d, SceneBundle { ..default() }))
.with_children(|parent| {
board.unwrap().pieces().iter().for_each(|(index, piece)| {
let side = Board::side(index).expect("Spawn valid side");
parent.spawn((
side,
Piece3d,
piece.clone(),
index.clone(),
SceneBundle { ..default() },
));
});
});
});
}
#[derive(Debug, Resource)]
struct ModelsFile {
handle: Handle<Gltf>,
fn fix_skybox(mut images: ResMut<Assets<Image>>, assets: Res<AssetsMap>) {
let image = images.get_mut(&assets.skybox).unwrap();
info!("Loaded skybox image");
// NOTE: PNGs do not have any metadata that could indicate they contain a cubemap texture,
// so they appear as one texture. The following code reconfigures the texture as necessary.
if image.texture_descriptor.array_layer_count() == 1 {
image.reinterpret_stacked_2d_as_array(
image.texture_descriptor.size.height / image.texture_descriptor.size.width,
);
image.texture_view_descriptor = Some(TextureViewDescriptor {
dimension: Some(TextureViewDimension::Cube),
..default()
});
}
}
/// Load 3d models
/// This is kind of pulling double duty.
/// Both loads the GLTF file _and_ populates the ModelMap once that is loaded.
fn load_models(server: Res<AssetServer>, mut commands: Commands) {
commands.insert_resource(ModelsFile {
handle: server.load("models/Martian Chess.glb"),
fn set_piece_model(
mut events: Query<(&mut Handle<Scene>, &Piece), (With<Piece3d>, Changed<Side>)>,
assets_map: Option<Res<AssetsMap>>,
gltfs: Res<Assets<Gltf>>,
) {
let mf = assets_map.expect("Models file");
events.iter_mut().for_each(|(mut handle, piece)| {
let gltf = gltfs.get(&mf.models).expect("Load GLTF content");
*handle = match piece {
game::Piece::Pawn => gltf.named_scenes.get("Pawn"),
game::Piece::Drone => gltf.named_scenes.get("Drone"),
game::Piece::Queen => gltf.named_scenes.get("Queen"),
}
.expect("Game board model")
.clone();
});
}
/// Initialize the 3d board
fn initialize_board(
mut commands: Commands,
model_file: Option<Res<ModelsFile>>,
fn set_board_model(
mut events: Query<&mut Handle<Scene>, With<Board3d>>,
assets_map: Option<Res<AssetsMap>>,
gltfs: Res<Assets<Gltf>>,
board: Option<Res<game::Board>>,
) {
info!("Initializing board");
if let Some(mf) = model_file {
let gltf = gltfs.get(&mf.handle).expect("Load GLTF content");
info!("Initializing root");
commands
.spawn((
SpatialBundle {
visibility: Visibility::Hidden,
..default()
},
Display3d,
))
.with_children(|parent| {
info!("Initializing 3D lights!");
parent.spawn((
Display3d,
PointLightBundle {
point_light: PointLight {
intensity: 1500.0,
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
},
));
info!("Intializeing 3D Board!");
parent
.spawn((
Display3d,
SceneBundle {
scene: gltf
.named_scenes
.get("Gameboard")
.expect("Game board model")
.clone(),
..default()
},
))
.with_children(|parent| {
// TODO: Add this to a reactive system when board is added
board
.unwrap()
.pieces()
.into_iter()
.for_each(|(index, piece)| {
// TODO: Move this to a reactive system like index -> Transform
let scene = match piece {
game::Piece::Pawn => gltf.named_scenes.get("Pawn"),
game::Piece::Drone => gltf.named_scenes.get("Drone"),
game::Piece::Queen => gltf.named_scenes.get("Queen"),
}
.expect("Game board model")
.clone();
parent.spawn((
Piece3d,
piece,
index,
SceneBundle { scene, ..default() },
));
});
});
});
}
let mf = assets_map.expect("Models file");
events.iter_mut().for_each(|mut handle| {
let gltf = gltfs.get(&mf.models).expect("Load GLTF content");
*handle = gltf
.named_scenes
.get("Gameboard")
.expect("Game board model")
.clone();
})
}
/// Sets a piece location given it's board index

@ -83,7 +83,7 @@ fn loading(
.filter(|&id| matches!(id, HandleId::AssetPathId(_)))
.collect::<Vec<HandleId>>();
info!(
debug!(
"Sprite len: {:?} | GLTF len: {:?}",
s_ids.len(),
g_ids.len()

Loading…
Cancel
Save