Skip to content

Commit

Permalink
content: Add ability to place exhibits underground.
Browse files Browse the repository at this point in the history
This is not yet used due to various missing details:

* Decide what wall surfaces underground exhibits should have.
  (Probably the enclosure should not have air but walls.)
* Add exhibit fields to define what kind of entrance doorway they want.
* Generate appropriate entranceway blocks rather than Road.
* Decide how to handle when the exhibit is tall enough to stick out.
* Add access stairs-or-something down.
  • Loading branch information
kpreid committed Oct 22, 2023
1 parent 15c0c83 commit 3a9850f
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 12 deletions.
44 changes: 34 additions & 10 deletions all-is-cubes-content/src/city.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ pub(crate) async fn demo_city<I: Instant>(
let lamp_spacing = 20;
let sky_height = 30;
let ground_depth = 30; // TODO: wavy_landscape is forcing us to have extra symmetry here
let underground_floor_y = -5;
let space_size = params.size.unwrap_or(GridVector::new(160, 60, 160));
let bounds = GridAab::from_lower_upper(
[-space_size.x / 2, -ground_depth, -space_size.z / 2],
Expand Down Expand Up @@ -192,7 +191,7 @@ pub(crate) async fn demo_city<I: Instant>(
// Dig underground passages
// TODO: They need a connection to the surface
for p in -road_radius..=road_radius {
for y in underground_floor_y..0 {
for y in CityPlanner::UNDERGROUND_FLOOR_Y..0 {
space.set(
step.cube_ahead() + perpendicular * p + GridVector::new(0, y, 0),
&AIR,
Expand Down Expand Up @@ -354,12 +353,11 @@ async fn place_exhibits_in_city<I: Instant>(
};
exhibit_progress.progress(0.33).await;

// Now that we know the size of the exhibit, find a place for it.
// Now that we know the size of the exhibit, find a place for it that fits its bounds.
let exhibit_footprint = exhibit_space.bounds();

let enclosure_footprint = exhibit_footprint.expand(FaceMap::repeat(1));

let Some(plot_transform) = planner.find_plot(enclosure_footprint) else {
let Some(plot_transform) = planner.find_plot(enclosure_footprint, exhibit.placement) else {
log::error!("Out of city space!");
break 'exhibit;
};
Expand All @@ -372,7 +370,9 @@ async fn place_exhibits_in_city<I: Instant>(
enclosure_at_plot.lower_bounds(),
[
enclosure_at_plot.upper_bounds().x,
1.max(plot.lower_bounds().y), // handles case where plot is floating
// max()ing handles the case where the plot is floating but should still
// have enclosure floor
exhibit.placement.floor().max(plot.lower_bounds().y),
enclosure_at_plot.upper_bounds().z,
],
);
Expand Down Expand Up @@ -591,10 +591,27 @@ fn place_lamppost(
pub(crate) struct Exhibit {
pub name: &'static str,
pub subtitle: &'static str,
pub placement: Placement,
pub factory:
for<'a> fn(&'a Exhibit, &'a mut Universe) -> BoxFuture<'a, Result<Space, InGenError>>,
}

#[derive(Clone, Copy, Debug)]
pub(crate) enum Placement {
Surface,
#[allow(unused)] // TODO: polish this and then use it
Underground,
}

impl Placement {
fn floor(self) -> GridCoordinate {
match self {
Placement::Surface => CityPlanner::SURFACE_Y,
Placement::Underground => CityPlanner::UNDERGROUND_FLOOR_Y,
}
}
}

/// Generate a Space containing text voxels to put on the signboard for an exhibit.
///
/// The space's bounds extend upward from [0, 0, 0].
Expand Down Expand Up @@ -660,13 +677,20 @@ impl CityPlanner {
const PLOT_FRONT_RADIUS: GridCoordinate = Self::LAMP_POSITION_RADIUS;
const GAP_BETWEEN_PLOTS: GridCoordinate = 1;

const SURFACE_Y: GridCoordinate = 1;
const UNDERGROUND_FLOOR_Y: GridCoordinate = -10;

pub fn new(space_bounds: GridAab) -> Self {
let city_radius = space_bounds.upper_bounds().x; // TODO: compare everything and take the max

let mut occupied_plots = Vec::new();
let road = GridAab::from_lower_upper(
[-Self::ROAD_RADIUS, 0, -city_radius],
[Self::ROAD_RADIUS + 1, 2, city_radius + 1],
[
-Self::ROAD_RADIUS,
Self::UNDERGROUND_FLOOR_Y - 1,
-city_radius,
],
[Self::ROAD_RADIUS + 1, Self::SURFACE_Y + 2, city_radius + 1],
);
occupied_plots.push(road);
occupied_plots.push(road.transform(GridRotation::CLOCKWISE.into()).unwrap());
Expand All @@ -677,7 +701,7 @@ impl CityPlanner {
}
}

pub fn find_plot(&mut self, plot_shape: GridAab) -> Option<Gridgid> {
pub fn find_plot(&mut self, plot_shape: GridAab, placement: Placement) -> Option<Gridgid> {
// TODO: We'd like to resume the search from _when we left off_, but that's tricky since a
// smaller plot might fit where a large one didn't. So, quadratic search it is for now.
for d in 0..=self.city_radius {
Expand All @@ -692,7 +716,7 @@ impl CityPlanner {

let mut transform = Gridgid::from_translation(GridVector::new(
d,
1,
placement.floor(),
if left_side {
-Self::PLOT_FRONT_RADIUS - plot_shape.upper_bounds().z
} else {
Expand Down
25 changes: 24 additions & 1 deletion all-is-cubes-content/src/exhibits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@ use all_is_cubes::{
use all_is_cubes::{include_image, rgb_const, rgba_const};

use crate::alg::{four_walls, voronoi_pattern};
use crate::city::{Exhibit, Placement};
use crate::{
make_slab, make_some_blocks, make_some_voxel_blocks, palette, tree, AnimatedVoxels, DemoBlocks,
Exhibit, Fire, LandscapeBlocks,
Fire, LandscapeBlocks,
};

/// All exhibits which will show up in [`crate::UniverseTemplate::DemoCity`].
Expand Down Expand Up @@ -100,6 +101,7 @@ macro_rules! exhibit {
subtitle:
"Test depth sorting and blending.\n\
Lighting of volumes still needs work.",
placement: Placement::Surface,
)]
async fn TRANSPARENCY_LARGE(_: &Exhibit, _universe: &mut Universe) {
let mut space = Space::empty(GridAab::from_lower_size([-3, 0, -3], [7, 5, 7]));
Expand Down Expand Up @@ -135,6 +137,7 @@ async fn TRANSPARENCY_LARGE(_: &Exhibit, _universe: &mut Universe) {
subtitle:
"Transparency in complex blocks is not correctly implemented.\n\
We also need something for surface properties.",
placement: Placement::Surface,
)]
async fn TRANSPARENCY_SMALL(_: &Exhibit, universe: &mut Universe) {
let footprint = GridAab::from_lower_size([0, 0, 0], [7, 4, 7]);
Expand Down Expand Up @@ -217,6 +220,7 @@ async fn TRANSPARENCY_SMALL(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Knot",
subtitle: "Complex voxel shape",
placement: Placement::Surface,
)]
async fn KNOT(this: &Exhibit, universe: &mut Universe) {
let footprint = GridAab::from_lower_size([-2, -2, -1], [5, 5, 3]);
Expand Down Expand Up @@ -291,6 +295,7 @@ async fn KNOT(this: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Text",
subtitle: "",
placement: Placement::Surface,
)]
async fn TEXT(_: &Exhibit, universe: &mut Universe) {
let space = draw_to_blocks(
Expand All @@ -313,6 +318,7 @@ async fn TEXT(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Animation",
subtitle: "Blocks whose definition is animated",
placement: Placement::Surface,
)]
async fn ANIMATION(_: &Exhibit, universe: &mut Universe) {
let demo_blocks = BlockProvider::<DemoBlocks>::using(universe)?;
Expand Down Expand Up @@ -384,6 +390,7 @@ async fn ANIMATION(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Collision",
subtitle: "Test cases for character/world collision",
placement: Placement::Surface,
)]
async fn COLLISION(_: &Exhibit, universe: &mut Universe) {
let half_block = make_slab(universe, 2, R4);
Expand Down Expand Up @@ -433,6 +440,7 @@ async fn COLLISION(_: &Exhibit, universe: &mut Universe) {
subtitle:
"Voxel blocks can be subdivided into\n\
powers of 2 from 2 to 256.",
placement: Placement::Surface,
)]
async fn RESOLUTIONS(_: &Exhibit, universe: &mut Universe) {
let footprint = GridAab::from_lower_size([0, 0, 0], [5, 3, 3]);
Expand Down Expand Up @@ -496,6 +504,7 @@ async fn RESOLUTIONS(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "World's Smallest Voxel",
subtitle: "1/128th the length of a standard block",
placement: Placement::Surface,
)]
async fn SMALLEST(_: &Exhibit, universe: &mut Universe) {
let demo_blocks = BlockProvider::<DemoBlocks>::using(universe)?;
Expand Down Expand Up @@ -528,6 +537,7 @@ async fn SMALLEST(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Rotations",
subtitle: "Rotated blocks and GridRotation::from_to()",
placement: Placement::Surface,
)]
async fn ROTATIONS(_: &Exhibit, universe: &mut Universe) {
let demo_blocks = BlockProvider::<DemoBlocks>::using(universe)?;
Expand Down Expand Up @@ -577,6 +587,7 @@ async fn ROTATIONS(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Modifier::Zoom",
subtitle: "",
placement: Placement::Surface,
)]
async fn ZOOM(_: &Exhibit, universe: &mut Universe) {
let demo_blocks = BlockProvider::<DemoBlocks>::using(universe)?;
Expand Down Expand Up @@ -613,6 +624,7 @@ async fn ZOOM(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Modifier::Composite",
subtitle: "",
placement: Placement::Surface,
)]
async fn COMPOSITE(_: &Exhibit, universe: &mut Universe) {
let demo_blocks = BlockProvider::<DemoBlocks>::using(universe)?;
Expand Down Expand Up @@ -695,6 +707,7 @@ async fn COMPOSITE(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Modifier::Move",
subtitle: "Stationary but not animated cases.",
placement: Placement::Surface,
)]
async fn MOVED_BLOCKS(_: &Exhibit, universe: &mut Universe) {
let mut space = Space::empty(GridAab::from_lower_upper([0, 0, -3], [16, 2, 3]));
Expand Down Expand Up @@ -729,6 +742,7 @@ async fn MOVED_BLOCKS(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Colors",
subtitle: "RGB cube of 5 linear color steps",
placement: Placement::Surface,
)]
async fn COLORS(_: &Exhibit, universe: &mut Universe) {
let gradient_resolution = 5;
Expand Down Expand Up @@ -801,6 +815,7 @@ async fn COLORS(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Colored Lights",
subtitle: "RGBCMY lights in an enclosed room",
placement: Placement::Surface,
)]
async fn COLOR_LIGHTS(_: &Exhibit, universe: &mut Universe) {
let room_width = 11;
Expand Down Expand Up @@ -962,6 +977,7 @@ async fn COLOR_LIGHTS(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "ChunkChart",
subtitle: "Volume of world chunks in view at a distance of 4.99",
placement: Placement::Surface,
)]
async fn CHUNK_CHART(_: &Exhibit, _: &mut Universe) {
use all_is_cubes::chunking::ChunkChart;
Expand All @@ -975,6 +991,7 @@ async fn CHUNK_CHART(_: &Exhibit, _: &mut Universe) {
#[exhibit(
name: "make_some_blocks()",
subtitle: "",
placement: Placement::Surface,
)]
async fn MAKE_SOME_BLOCKS(_: &Exhibit, universe: &mut Universe) {
const ROWS: GridCoordinate = 5;
Expand Down Expand Up @@ -1005,6 +1022,7 @@ async fn MAKE_SOME_BLOCKS(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Dashed outline boxes",
subtitle: "",
placement: Placement::Surface,
)]
async fn DASHED_BOXES(_: &Exhibit, universe: &mut Universe) {
let color = Rgb::new(1.0, 0.5, 0.5);
Expand Down Expand Up @@ -1054,6 +1072,7 @@ async fn DASHED_BOXES(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Swimming Pool",
subtitle: "Transparent blocks that can be passed through",
placement: Placement::Surface,
)]
async fn SWIMMING_POOL(_: &Exhibit, _: &mut Universe) {
let width = 6;
Expand All @@ -1075,6 +1094,7 @@ async fn SWIMMING_POOL(_: &Exhibit, _: &mut Universe) {
#[exhibit(
name: "space_from_image()",
subtitle: "Using rotations XYZ, XyZ, XZY, xYZ",
placement: Placement::Surface,
)]
async fn IMAGES(_: &Exhibit, universe: &mut Universe) {
// TODO: it would be nice if this exhibit visualized the generated bounding box somehow
Expand Down Expand Up @@ -1119,6 +1139,7 @@ async fn IMAGES(_: &Exhibit, universe: &mut Universe) {
name: "UI Blocks",
subtitle:
"Blocks from the UI system (inactive)",
placement: Placement::Surface,
)]
async fn UI_BLOCKS(_: &Exhibit, universe: &mut Universe) {
// TODO: This was designed for a render test and is still shaped for that rather than
Expand Down Expand Up @@ -1183,6 +1204,7 @@ async fn UI_BLOCKS(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Trees",
subtitle: "",
placement: Placement::Surface,
)]
async fn TREES(_: &Exhibit, universe: &mut Universe) {
let landscape_blocks = BlockProvider::<LandscapeBlocks>::using(universe)?;
Expand Down Expand Up @@ -1239,6 +1261,7 @@ async fn TREES(_: &Exhibit, universe: &mut Universe) {
#[exhibit(
name: "Block Destruction",
subtitle: "Animation prototype",
placement: Placement::Surface,
)]
async fn DESTRUCTION(_: &Exhibit, universe: &mut Universe) {
let width = 7;
Expand Down
2 changes: 1 addition & 1 deletion all-is-cubes-content/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ mod atrium;
mod blocks;
pub use blocks::*;
mod city;
pub(crate) use city::*;
pub(crate) use city::demo_city;
mod clouds;
mod template;
pub use template::*;
Expand Down

0 comments on commit 3a9850f

Please sign in to comment.