mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added new settlement generation to world, basic rendering
This commit is contained in:
parent
48fb14116a
commit
0021bd6452
@ -4,8 +4,8 @@
|
||||
|
||||
const float PI = 3.141592;
|
||||
|
||||
const vec3 SKY_DAY_TOP = vec3(0.1, 0.2, 0.9);
|
||||
const vec3 SKY_DAY_MID = vec3(0.02, 0.08, 0.8);
|
||||
const vec3 SKY_DAY_TOP = vec3(0.1, 0.5, 0.9);
|
||||
const vec3 SKY_DAY_MID = vec3(0.02, 0.28, 0.8);
|
||||
const vec3 SKY_DAY_BOT = vec3(0.1, 0.2, 0.3);
|
||||
const vec3 DAY_LIGHT = vec3(1.2, 1.0, 1.0);
|
||||
const vec3 SUN_HALO_DAY = vec3(0.35, 0.35, 0.0);
|
||||
|
@ -10,7 +10,7 @@ use super::SceneData;
|
||||
use common::{
|
||||
assets,
|
||||
figure::Segment,
|
||||
spiral::Spiral2D,
|
||||
spiral::Spiral2d,
|
||||
terrain::{Block, BlockKind, TerrainChunk},
|
||||
vol::{BaseVol, ReadVol, RectRasterableVol, SampleVol, Vox},
|
||||
volumes::vol_grid_2d::{VolGrid2d, VolGrid2dError},
|
||||
|
@ -9,7 +9,7 @@ fn main() {
|
||||
let mut win =
|
||||
minifb::Window::new("Settlement Viewer", W, H, minifb::WindowOptions::default()).unwrap();
|
||||
|
||||
let settlement = Settlement::generate(&mut thread_rng());
|
||||
let settlement = Settlement::generate(Vec2::zero(), &mut thread_rng());
|
||||
|
||||
let mut focus = Vec2::<f32>::zero();
|
||||
let mut zoom = 1.0;
|
||||
@ -24,7 +24,7 @@ fn main() {
|
||||
for j in 0..H {
|
||||
let pos = focus + win_to_pos(Vec2::new(i, j)) * zoom;
|
||||
|
||||
let color = settlement.get_color(pos);
|
||||
let color = settlement.get_color(pos).unwrap_or(Rgb::new(35, 50, 20));
|
||||
|
||||
buf[j * W + i] = u32::from_le_bytes([color.b, color.g, color.r, 255]);
|
||||
}
|
||||
|
@ -398,12 +398,14 @@ impl<'a> BlockGen<'a> {
|
||||
};
|
||||
|
||||
// Structures (like towns)
|
||||
/*
|
||||
let block = chunk
|
||||
.structures
|
||||
.town
|
||||
.as_ref()
|
||||
.and_then(|town| TownGen.get((town, wpos, sample, height)))
|
||||
.or(block);
|
||||
*/
|
||||
|
||||
let block = structures
|
||||
.iter()
|
||||
@ -472,6 +474,7 @@ impl<'a> ZCache<'a> {
|
||||
let max = (ground_max + structure_max).max(self.sample.water_level + 2.0);
|
||||
|
||||
// Structures
|
||||
/*
|
||||
let (min, max) = self
|
||||
.sample
|
||||
.chunk
|
||||
@ -483,6 +486,7 @@ impl<'a> ZCache<'a> {
|
||||
(town_min.min(min), town_max.max(max))
|
||||
})
|
||||
.unwrap_or((min, max));
|
||||
*/
|
||||
|
||||
let structures_only_min_z = ground_max.max(self.sample.water_level + 2.0);
|
||||
|
||||
|
@ -1000,6 +1000,13 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
humidity.sub(CONFIG.jungle_hum).mul(1.0),
|
||||
);
|
||||
|
||||
let ground = sim_chunk.sites.iter().fold(ground, |ground, site| {
|
||||
site.get_surface(wpos)
|
||||
.and_then(|block| block.get_color())
|
||||
.map(|col| col.map(|e| e as f32 / 255.0))
|
||||
.unwrap_or(ground)
|
||||
});
|
||||
|
||||
// Snow covering
|
||||
let snow_cover = temp
|
||||
.sub(CONFIG.snow_temp)
|
||||
@ -1095,6 +1102,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
stone_col,
|
||||
|
||||
chunk: sim_chunk,
|
||||
/*
|
||||
spawn_rules: sim_chunk
|
||||
.structures
|
||||
.town
|
||||
@ -1105,6 +1113,11 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
cliffs: !in_water,
|
||||
trees: true,
|
||||
}),
|
||||
*/
|
||||
spawn_rules: SpawnRules {
|
||||
cliffs: !in_water,
|
||||
trees: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,33 @@ pub mod settlement;
|
||||
mod town;
|
||||
|
||||
// Reexports
|
||||
pub use self::town::{TownGen, TownState};
|
||||
pub use self::{
|
||||
settlement::Settlement,
|
||||
town::{TownGen, TownState},
|
||||
};
|
||||
|
||||
use crate::{column::ColumnSample, util::Sampler};
|
||||
use common::terrain::Block;
|
||||
use std::sync::Arc;
|
||||
use vek::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Site {
|
||||
Settlement(Arc<Settlement>),
|
||||
}
|
||||
|
||||
impl Site {
|
||||
pub fn get_surface(&self, wpos: Vec2<i32>) -> Option<Block> {
|
||||
match self {
|
||||
Site::Settlement(settlement) => settlement.get_surface(wpos),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Settlement> for Site {
|
||||
fn from(settlement: Settlement) -> Self { Site::Settlement(Arc::new(settlement)) }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct SpawnRules {
|
||||
pub trees: bool,
|
||||
|
@ -1,5 +1,10 @@
|
||||
use crate::util::{Sampler, StructureGen2d};
|
||||
use common::{astar::Astar, path::Path, spiral::Spiral2d};
|
||||
use common::{
|
||||
astar::Astar,
|
||||
path::Path,
|
||||
spiral::Spiral2d,
|
||||
terrain::{Block, BlockKind},
|
||||
};
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use rand::prelude::*;
|
||||
use std::{collections::VecDeque, f32, marker::PhantomData};
|
||||
@ -56,7 +61,7 @@ pub fn center_of(p: [Vec2<f32>; 3]) -> Vec2<f32> {
|
||||
Vec2::new(x, y)
|
||||
}
|
||||
|
||||
const AREA_SIZE: u32 = 48;
|
||||
const AREA_SIZE: u32 = 64;
|
||||
|
||||
fn to_tile(e: i32) -> i32 { ((e as f32).div_euclid(AREA_SIZE as f32)).floor() as i32 }
|
||||
|
||||
@ -70,6 +75,7 @@ pub struct Structure {
|
||||
}
|
||||
|
||||
pub struct Settlement {
|
||||
origin: Vec2<i32>,
|
||||
land: Land,
|
||||
farms: Store<Farm>,
|
||||
structures: Vec<Structure>,
|
||||
@ -85,15 +91,16 @@ pub struct Farm {
|
||||
}
|
||||
|
||||
impl Settlement {
|
||||
pub fn generate(rng: &mut impl Rng) -> Self {
|
||||
pub fn generate(wpos: Vec2<i32>, rng: &mut impl Rng) -> Self {
|
||||
let mut this = Self {
|
||||
origin: wpos,
|
||||
land: Land::new(rng),
|
||||
farms: Store::default(),
|
||||
structures: Vec::new(),
|
||||
town: None,
|
||||
};
|
||||
|
||||
this.place_river(rng);
|
||||
//this.place_river(rng);
|
||||
|
||||
this.place_farms(rng);
|
||||
this.place_town(rng);
|
||||
@ -296,7 +303,12 @@ impl Settlement {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_color(&self, pos: Vec2<f32>) -> Rgb<u8> {
|
||||
pub fn get_surface(&self, wpos: Vec2<i32>) -> Option<Block> {
|
||||
self.get_color((wpos - self.origin).map(|e| e as f32))
|
||||
.map(|col| Block::new(BlockKind::Normal, col))
|
||||
}
|
||||
|
||||
pub fn get_color(&self, pos: Vec2<f32>) -> Option<Rgb<u8>> {
|
||||
let pos = pos.map(|e| e.floor() as i32);
|
||||
|
||||
if let Some(structure) = self
|
||||
@ -304,13 +316,13 @@ impl Settlement {
|
||||
.iter()
|
||||
.find(|s| s.bounds.contains_point(pos))
|
||||
{
|
||||
return match structure.kind {
|
||||
return Some(match structure.kind {
|
||||
StructureKind::House => Rgb::new(200, 80, 50),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
match self.land.get_at_block(pos) {
|
||||
Sample::Wilderness => Rgb::zero(),
|
||||
Some(match self.land.get_at_block(pos) {
|
||||
Sample::Wilderness => return None,
|
||||
Sample::Way(WayKind::Path) => Rgb::new(130, 100, 0),
|
||||
Sample::Way(WayKind::Hedge) => Rgb::new(0, 150, 0),
|
||||
Sample::Way(WayKind::Wall) => Rgb::new(60, 60, 60),
|
||||
@ -336,7 +348,7 @@ impl Settlement {
|
||||
let furrow = (pos * furrow_dir).sum().rem_euclid(4) < 2;
|
||||
Rgb::new(
|
||||
if furrow {
|
||||
150
|
||||
120
|
||||
} else {
|
||||
48 + seed.to_le_bytes()[0] % 64
|
||||
},
|
||||
@ -344,7 +356,7 @@ impl Settlement {
|
||||
16 + seed.to_le_bytes()[2] % 32,
|
||||
)
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -374,9 +386,9 @@ pub enum WayKind {
|
||||
impl WayKind {
|
||||
pub fn width(&self) -> f32 {
|
||||
match self {
|
||||
WayKind::Path => 2.5,
|
||||
WayKind::Path => 4.0,
|
||||
WayKind::Hedge => 1.5,
|
||||
WayKind::Wall => 2.5,
|
||||
WayKind::Wall => 3.5,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -386,6 +398,14 @@ pub enum Tower {
|
||||
Wall,
|
||||
}
|
||||
|
||||
impl Tower {
|
||||
pub fn radius(&self) -> f32 {
|
||||
match self {
|
||||
Tower::Wall => 8.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Tile {
|
||||
plot: Id<Plot>,
|
||||
ways: [Option<WayKind>; 4],
|
||||
@ -414,7 +434,7 @@ impl Land {
|
||||
Self {
|
||||
tiles: HashMap::new(),
|
||||
plots: Store::default(),
|
||||
sampler_warp: StructureGen2d::new(rng.gen(), AREA_SIZE, 16),
|
||||
sampler_warp: StructureGen2d::new(rng.gen(), AREA_SIZE, AREA_SIZE * 2 / 5),
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,8 +448,8 @@ impl Land {
|
||||
|
||||
let center_tile = self.tile_at(neighbors[4].0.map(to_tile));
|
||||
|
||||
if neighbors[4].0.distance_squared(pos) < 6i32.pow(2) {
|
||||
if let Some(tower) = center_tile.and_then(|tile| tile.tower.as_ref()) {
|
||||
if let Some(tower) = center_tile.and_then(|tile| tile.tower.as_ref()) {
|
||||
if (neighbors[4].0.distance_squared(pos) as f32) < tower.radius().powf(2.0) {
|
||||
return Sample::Tower(tower);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ pub use crate::config::CONFIG;
|
||||
use crate::{
|
||||
block::BlockGen,
|
||||
column::{ColumnGen, ColumnSample},
|
||||
util::Sampler,
|
||||
util::{Grid, Sampler},
|
||||
};
|
||||
use common::{
|
||||
generation::{ChunkSupplement, EntityInfo, EntityKind},
|
||||
@ -95,7 +95,11 @@ impl World {
|
||||
let meta = TerrainChunkMeta::new(sim_chunk.get_name(&self.sim), sim_chunk.get_biome());
|
||||
let mut sampler = self.sample_blocks();
|
||||
|
||||
let chunk_block_pos = Vec3::from(chunk_pos) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32);
|
||||
let chunk_wpos2d = Vec2::from(chunk_pos) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32);
|
||||
let zcache_grid =
|
||||
Grid::populate_from(TerrainChunkSize::RECT_SIZE.map(|e| e as i32), |offs| {
|
||||
sampler.get_z_cache(chunk_wpos2d + offs)
|
||||
});
|
||||
|
||||
let mut chunk = TerrainChunk::new(base_z, stone, air, meta);
|
||||
for y in 0..TerrainChunkSize::RECT_SIZE.y as i32 {
|
||||
@ -103,12 +107,13 @@ impl World {
|
||||
if should_continue() {
|
||||
return Err(());
|
||||
};
|
||||
let wpos2d = Vec2::new(x, y)
|
||||
+ Vec2::from(chunk_pos) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32);
|
||||
|
||||
let z_cache = match sampler.get_z_cache(wpos2d) {
|
||||
Some(z_cache) => z_cache,
|
||||
None => continue,
|
||||
let offs = Vec2::new(x, y);
|
||||
let wpos2d = chunk_wpos2d + offs;
|
||||
|
||||
let z_cache = match zcache_grid.get(offs) {
|
||||
Some(Some(z_cache)) => z_cache,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
let (min_z, only_structures_min_z, max_z) = z_cache.get_z_limits(&mut sampler);
|
||||
@ -119,7 +124,7 @@ impl World {
|
||||
|
||||
(min_z as i32..max_z as i32).for_each(|z| {
|
||||
let lpos = Vec3::new(x, y, z);
|
||||
let wpos = chunk_block_pos + lpos;
|
||||
let wpos = Vec3::from(chunk_wpos2d) + lpos;
|
||||
let only_structures = lpos.z >= only_structures_min_z as i32;
|
||||
|
||||
if let Some(block) =
|
||||
@ -140,7 +145,7 @@ impl World {
|
||||
lpos.z += 1;
|
||||
}
|
||||
|
||||
(chunk_block_pos + lpos).map(|e| e as f32) + 0.5
|
||||
(Vec3::from(chunk_wpos2d) + lpos).map(|e: i32| e as f32) + 0.5
|
||||
};
|
||||
|
||||
const SPAWN_RATE: f32 = 0.1;
|
||||
|
@ -1,4 +1,3 @@
|
||||
use super::Settlement;
|
||||
use hashbrown::HashSet;
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
use vek::*;
|
||||
@ -9,7 +8,6 @@ pub struct Location {
|
||||
pub(crate) center: Vec2<i32>,
|
||||
pub(crate) kingdom: Option<Kingdom>,
|
||||
pub(crate) neighbours: HashSet<usize>,
|
||||
pub(crate) settlement: Settlement,
|
||||
}
|
||||
|
||||
impl Location {
|
||||
@ -19,7 +17,6 @@ impl Location {
|
||||
center,
|
||||
kingdom: None,
|
||||
neighbours: HashSet::default(),
|
||||
settlement: Settlement::generate(rng),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@ pub use self::{
|
||||
},
|
||||
location::Location,
|
||||
map::{MapConfig, MapDebug},
|
||||
settlement::Settlement,
|
||||
util::{
|
||||
cdf_irwin_hall, downhill, get_oceans, local_cells, map_edge_factor, neighbors,
|
||||
uniform_idx_as_vec2, uniform_noise, uphill, vec2_as_uniform_idx, InverseCdf, ScaleBias,
|
||||
@ -27,7 +26,7 @@ use crate::{
|
||||
all::ForestKind,
|
||||
block::BlockGen,
|
||||
column::ColumnGen,
|
||||
generator::TownState,
|
||||
generator::{Settlement, Site},
|
||||
util::{seed_expan, FastNoise, RandomField, Sampler, StructureGen2d},
|
||||
CONFIG,
|
||||
};
|
||||
@ -1450,7 +1449,7 @@ impl WorldSim {
|
||||
e * sz as i32 + sz as i32 / 2
|
||||
})
|
||||
};
|
||||
let maybe_towns = self
|
||||
let sites = self
|
||||
.gen_ctx
|
||||
.town_gen
|
||||
.par_iter(
|
||||
@ -1462,11 +1461,12 @@ impl WorldSim {
|
||||
|mut block_gen, (pos, seed)| {
|
||||
let mut rng = ChaChaRng::from_seed(seed_expan::rng_state(seed));
|
||||
// println!("Town: {:?}", town);
|
||||
TownState::generate(pos, &mut block_gen, &mut rng).map(|t| (pos, Arc::new(t)))
|
||||
//TownState::generate(pos, &mut block_gen, &mut rng).map(|t| (pos,
|
||||
// Arc::new(t)))
|
||||
(pos, Site::from(Settlement::generate(pos, &mut rng)))
|
||||
},
|
||||
)
|
||||
.filter_map(|x| x)
|
||||
.collect::<HashMap<_, _>>();
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let gen_ctx = &self.gen_ctx;
|
||||
self.chunks
|
||||
@ -1476,21 +1476,13 @@ impl WorldSim {
|
||||
let chunk_pos = uniform_idx_as_vec2(ij);
|
||||
let wpos = chunk_idx_center(chunk_pos);
|
||||
|
||||
let near_towns = gen_ctx.town_gen.get(wpos);
|
||||
let town = near_towns
|
||||
if let Some((pos, site)) = sites
|
||||
.iter()
|
||||
.min_by_key(|(pos, _seed)| wpos.distance_squared(*pos));
|
||||
|
||||
let maybe_town = town
|
||||
.and_then(|(pos, _seed)| maybe_towns.get(pos))
|
||||
// Only care if we're close to the town
|
||||
.filter(|town| {
|
||||
Vec2::from(town.center()).distance_squared(wpos)
|
||||
< town.radius().add(64).pow(2)
|
||||
})
|
||||
.cloned();
|
||||
|
||||
chunk.structures.town = maybe_town;
|
||||
.filter(|(pos, _)| pos.distance_squared(wpos) < 1200i32.pow(2))
|
||||
.min_by_key(|(pos, _)| wpos.distance_squared(*pos))
|
||||
{
|
||||
chunk.sites.push(site.clone());
|
||||
}
|
||||
});
|
||||
|
||||
// Create waypoints
|
||||
@ -1771,7 +1763,7 @@ pub struct SimChunk {
|
||||
pub location: Option<LocationInfo>,
|
||||
pub river: RiverData,
|
||||
|
||||
pub structures: Structures,
|
||||
pub sites: Vec<Site>,
|
||||
pub contains_waypoint: bool,
|
||||
}
|
||||
|
||||
@ -1789,11 +1781,6 @@ pub struct LocationInfo {
|
||||
pub near: Vec<RegionInfo>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Structures {
|
||||
pub town: Option<Arc<TownState>>,
|
||||
}
|
||||
|
||||
impl SimChunk {
|
||||
fn generate(posi: usize, gen_ctx: &GenCtx, gen_cdf: &GenCdf) -> Self {
|
||||
let pos = uniform_idx_as_vec2(posi);
|
||||
@ -2015,7 +2002,7 @@ impl SimChunk {
|
||||
spawn_rate: 1.0,
|
||||
location: None,
|
||||
river,
|
||||
structures: Structures { town: None },
|
||||
sites: Vec::new(),
|
||||
contains_waypoint: false,
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,22 @@ pub struct Grid<T> {
|
||||
size: Vec2<i32>,
|
||||
}
|
||||
|
||||
impl<T: Clone> Grid<T> {
|
||||
pub fn new(default_cell: T, size: Vec2<i32>) -> Self {
|
||||
impl<T> Grid<T> {
|
||||
pub fn populate_from(size: Vec2<i32>, mut f: impl FnMut(Vec2<i32>) -> T) -> Self {
|
||||
Self {
|
||||
cells: (0..size.y)
|
||||
.map(|y| (0..size.x).map(move |x| Vec2::new(x, y)))
|
||||
.flatten()
|
||||
.map(&mut f)
|
||||
.collect(),
|
||||
size,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(default_cell: T, size: Vec2<i32>) -> Self
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
Self {
|
||||
cells: vec![default_cell; size.product() as usize],
|
||||
size,
|
||||
|
Loading…
Reference in New Issue
Block a user