Switched path generation to canvas

This commit is contained in:
Joshua Barretto 2020-11-04 00:30:47 +00:00
parent 981b71759e
commit 647dcb2fec
3 changed files with 99 additions and 21 deletions

63
world/src/canvas.rs Normal file
View File

@ -0,0 +1,63 @@
use vek::*;
use common::{
terrain::{TerrainChunk, Block, TerrainChunkSize},
vol::{ReadVol, WriteVol, RectVolSize},
};
use crate::{
block::ZCache,
util::Grid,
column::ColumnSample,
index::IndexRef,
};
pub struct CanvasInfo<'a> {
pub(crate) wpos: Vec2<i32>,
pub(crate) column_grid: &'a Grid<Option<ZCache<'a>>>,
pub(crate) column_grid_border: i32,
pub(crate) index: IndexRef<'a>,
}
impl<'a> CanvasInfo<'a> {
pub fn wpos(&self) -> Vec2<i32> {
self.wpos
}
pub fn area(&self) -> Aabr<i32> {
Rect::from((self.wpos(), Extent2::from(TerrainChunkSize::RECT_SIZE.map(|e| e as i32)))).into()
}
pub fn col(&self, pos: Vec2<i32>) -> Option<&ColumnSample> {
self.column_grid
.get(self.column_grid_border + pos - self.wpos())
.map(Option::as_ref)
.flatten()
.map(|zc| &zc.sample)
}
pub fn index(&self) -> IndexRef {
self.index
}
}
pub struct Canvas<'a> {
pub(crate) wpos: Vec2<i32>,
pub(crate) chunk: &'a mut TerrainChunk,
}
impl<'a> Canvas<'a> {
pub fn wpos(&self) -> Vec2<i32> {
self.wpos
}
pub fn area(&self) -> Aabr<i32> {
Rect::from((self.wpos(), Extent2::from(TerrainChunkSize::RECT_SIZE.map(|e| e as i32)))).into()
}
pub fn get(&mut self, pos: Vec3<i32>) -> Option<Block> {
self.chunk.get(pos - self.wpos()).ok().copied()
}
pub fn set(&mut self, pos: Vec3<i32>, block: Block) {
let _ = self.chunk.set(pos - self.wpos(), block);
}
}

View File

@ -6,6 +6,8 @@ use crate::{
column::ColumnSample,
util::{RandomField, Sampler},
IndexRef,
Canvas,
CanvasInfo,
};
use common::{
assets::Asset,
@ -33,19 +35,17 @@ pub struct Colors {
const EMPTY_AIR: Block = Block::air(SpriteKind::Empty);
pub fn apply_paths_to<'a>(
wpos2d: Vec2<i32>,
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
vol: &mut (impl BaseVol<Vox = Block> + RectSizedVol + ReadVol + WriteVol),
index: IndexRef,
canvas: &mut Canvas,
info: &CanvasInfo,
) {
for y in 0..vol.size_xy().y as i32 {
for x in 0..vol.size_xy().x as i32 {
for y in 0..canvas.area().size().h as i32 {
for x in 0..canvas.area().size().w as i32 {
let offs = Vec2::new(x, y);
let wpos2d = wpos2d + offs;
let wpos2d = canvas.wpos() + offs;
// Sample terrain
let col_sample = if let Some(col_sample) = get_column(offs) {
let col_sample = if let Some(col_sample) = info.col(wpos2d) {
col_sample
} else {
continue;
@ -70,10 +70,10 @@ pub fn apply_paths_to<'a>(
// Try to use the column at the centre of the path for sampling to make them
// flatter
let col_pos = (offs - wpos2d).map(|e| e as f32) + path_nearest;
let col00 = get_column(col_pos.map(|e| e.floor() as i32) + Vec2::new(0, 0));
let col10 = get_column(col_pos.map(|e| e.floor() as i32) + Vec2::new(1, 0));
let col01 = get_column(col_pos.map(|e| e.floor() as i32) + Vec2::new(0, 1));
let col11 = get_column(col_pos.map(|e| e.floor() as i32) + Vec2::new(1, 1));
let col00 = info.col(info.wpos() + col_pos.map(|e| e.floor() as i32) + Vec2::new(0, 0));
let col10 = info.col(info.wpos() + col_pos.map(|e| e.floor() as i32) + Vec2::new(1, 0));
let col01 = info.col(info.wpos() + col_pos.map(|e| e.floor() as i32) + Vec2::new(0, 1));
let col11 = info.col(info.wpos() + col_pos.map(|e| e.floor() as i32) + Vec2::new(1, 1));
let col_attr = |col: &ColumnSample| {
Vec3::new(col.riverless_alt, col.alt, col.water_dist.unwrap_or(1000.0))
};
@ -96,12 +96,12 @@ pub fn apply_paths_to<'a>(
let surface_z = (riverless_alt + bridge_offset).floor() as i32;
for z in inset - depth..inset {
let _ = vol.set(
Vec3::new(offs.x, offs.y, surface_z + z),
let _ = canvas.set(
Vec3::new(wpos2d.x, wpos2d.y, surface_z + z),
if bridge_offset >= 2.0 && path_dist >= 3.0 || z < inset - 1 {
Block::new(
BlockKind::Rock,
noisy_color(index.colors.layer.bridge.into(), 8),
noisy_color(info.index().colors.layer.bridge.into(), 8),
)
} else {
let path_color = path.surface_color(
@ -113,9 +113,9 @@ pub fn apply_paths_to<'a>(
}
let head_space = path.head_space(path_dist);
for z in inset..inset + head_space {
let pos = Vec3::new(offs.x, offs.y, surface_z + z);
if vol.get(pos).unwrap().kind() != BlockKind::Water {
let _ = vol.set(pos, EMPTY_AIR);
let pos = Vec3::new(wpos2d.x, wpos2d.y, surface_z + z);
if canvas.get(pos).unwrap().kind() != BlockKind::Water {
let _ = canvas.set(pos, EMPTY_AIR);
}
}
}

View File

@ -13,6 +13,7 @@
mod all;
mod block;
pub mod canvas;
pub mod civ;
mod column;
pub mod config;
@ -25,7 +26,10 @@ pub mod site;
pub mod util;
// Reexports
pub use crate::config::CONFIG;
pub use crate::{
config::CONFIG,
canvas::{Canvas, CanvasInfo},
};
pub use block::BlockGen;
pub use column::ColumnSample;
pub use index::{IndexOwned, IndexRef};
@ -126,7 +130,6 @@ impl World {
);
let water = Block::new(BlockKind::Water, Rgb::zero());
let _chunk_size2d = TerrainChunkSize::RECT_SIZE;
let (base_z, sim_chunk) = match self
.sim
/*.get_interpolated(
@ -203,7 +206,19 @@ impl World {
// Apply layers (paths, caves, etc.)
layer::apply_caves_to(chunk_wpos2d, sample_get, &mut chunk, index);
layer::apply_scatter_to(chunk_wpos2d, sample_get, &mut chunk, index, sim_chunk);
layer::apply_paths_to(chunk_wpos2d, sample_get, &mut chunk, index);
let canvas_info = CanvasInfo {
wpos: chunk_pos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
column_grid: &zcache_grid,
column_grid_border: grid_border,
index,
};
let mut canvas = Canvas {
wpos: chunk_pos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
chunk: &mut chunk,
};
layer::apply_paths_to(&mut canvas, &canvas_info);
// Apply site generation
sim_chunk.sites.iter().for_each(|site| {