mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added pyramids
This commit is contained in:
parent
92d4b4dfbe
commit
09717f1c56
@ -1,7 +1,7 @@
|
||||
mod natural;
|
||||
|
||||
use crate::{
|
||||
column::{ColumnGen, ColumnSample},
|
||||
column::{ColumnGen, ColumnSample, StructureData},
|
||||
util::{HashCache, RandomField, Sampler, SamplerMut},
|
||||
World, CONFIG,
|
||||
};
|
||||
@ -88,28 +88,36 @@ impl<'a> BlockGen<'a> {
|
||||
// Tree samples
|
||||
let mut structure_samples = [None, None, None, None, None, None, None, None, None];
|
||||
for i in 0..structure_samples.len() {
|
||||
let st_sample = Self::sample_column(
|
||||
column_gen,
|
||||
column_cache,
|
||||
Vec2::from(sample.close_trees[i].0),
|
||||
);
|
||||
structure_samples[i] = st_sample;
|
||||
if let Some(st) = sample.close_structures[i] {
|
||||
let st_sample = Self::sample_column(column_gen, column_cache, Vec2::from(st.pos));
|
||||
structure_samples[i] = st_sample;
|
||||
}
|
||||
}
|
||||
|
||||
let mut structures = [None, None, None, None, None, None, None, None, None];
|
||||
for i in 0..structures.len() {
|
||||
let (st_pos, st_seed) = sample.close_trees[i];
|
||||
let st_info = natural::structure_gen(
|
||||
column_gen,
|
||||
column_cache,
|
||||
i,
|
||||
st_pos,
|
||||
st_seed,
|
||||
&structure_samples,
|
||||
);
|
||||
if let (Some(st), Some(st_sample)) =
|
||||
(sample.close_structures[i], structure_samples[i].clone())
|
||||
{
|
||||
let st_info = match st.meta {
|
||||
None => natural::structure_gen(
|
||||
column_gen,
|
||||
column_cache,
|
||||
i,
|
||||
st.pos,
|
||||
st.seed,
|
||||
&structure_samples,
|
||||
),
|
||||
Some(meta) => Some(StructureInfo {
|
||||
pos: Vec3::from(st.pos) + Vec3::unit_z() * st_sample.alt as i32,
|
||||
seed: st.seed,
|
||||
meta,
|
||||
}),
|
||||
};
|
||||
|
||||
if let (Some(st_info), Some(st_sample)) = (st_info, structure_samples[i].clone()) {
|
||||
structures[i] = Some((st_info, st_sample));
|
||||
if let Some(st_info) = st_info {
|
||||
structures[i] = Some((st_info, st_sample));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +144,7 @@ impl<'a> BlockGen<'a> {
|
||||
sub_surface_color,
|
||||
//tree_density,
|
||||
//forest_kind,
|
||||
close_trees,
|
||||
//close_structures,
|
||||
cave_xy,
|
||||
cave_alt,
|
||||
rock,
|
||||
@ -281,57 +289,6 @@ impl<'a> BlockGen<'a> {
|
||||
}
|
||||
});
|
||||
|
||||
fn block_from_structure(
|
||||
sblock: StructureBlock,
|
||||
pos: Vec3<i32>,
|
||||
structure_pos: Vec2<i32>,
|
||||
structure_seed: u32,
|
||||
_sample: &ColumnSample,
|
||||
) -> Block {
|
||||
let field = RandomField::new(structure_seed + 0);
|
||||
|
||||
let lerp = 0.5
|
||||
+ ((field.get(Vec3::from(structure_pos)) % 256) as f32 / 256.0 - 0.5) * 0.65
|
||||
+ ((field.get(Vec3::from(pos)) % 256) as f32 / 256.0 - 0.5) * 0.15;
|
||||
|
||||
match sblock {
|
||||
StructureBlock::TemperateLeaves => Block::new(
|
||||
1,
|
||||
Lerp::lerp(Rgb::new(0.0, 70.0, 35.0), Rgb::new(100.0, 140.0, 0.0), lerp)
|
||||
.map(|e| e as u8),
|
||||
),
|
||||
StructureBlock::PineLeaves => Block::new(
|
||||
1,
|
||||
Lerp::lerp(Rgb::new(0.0, 60.0, 50.0), Rgb::new(30.0, 100.0, 10.0), lerp)
|
||||
.map(|e| e as u8),
|
||||
),
|
||||
StructureBlock::PalmLeaves => Block::new(
|
||||
1,
|
||||
Lerp::lerp(
|
||||
Rgb::new(15.0, 100.0, 30.0),
|
||||
Rgb::new(55.0, 220.0, 0.0),
|
||||
lerp,
|
||||
)
|
||||
.map(|e| e as u8),
|
||||
),
|
||||
StructureBlock::Acacia => Block::new(
|
||||
1,
|
||||
Lerp::lerp(
|
||||
Rgb::new(35.0, 100.0, 10.0),
|
||||
Rgb::new(70.0, 190.0, 25.0),
|
||||
lerp,
|
||||
)
|
||||
.map(|e| e as u8),
|
||||
),
|
||||
StructureBlock::Fruit => Block::new(
|
||||
1,
|
||||
Lerp::lerp(Rgb::new(255.0, 0.0, 0.0), Rgb::new(200.0, 255.0, 6.0), lerp)
|
||||
.map(|e| e as u8),
|
||||
),
|
||||
StructureBlock::Block(block) => block,
|
||||
}
|
||||
}
|
||||
|
||||
let block = if definitely_underground {
|
||||
block.unwrap_or(Block::empty())
|
||||
} else {
|
||||
@ -340,6 +297,9 @@ impl<'a> BlockGen<'a> {
|
||||
structures.iter().find_map(|st| {
|
||||
let (st, st_sample) = st.as_ref()?;
|
||||
|
||||
st.get(wpos, st_sample)
|
||||
|
||||
/*
|
||||
let rpos = wpos - st.pos;
|
||||
let block_pos = Vec3::unit_z() * rpos.z
|
||||
+ Vec3::from(st.units.0) * rpos.x
|
||||
@ -358,6 +318,7 @@ impl<'a> BlockGen<'a> {
|
||||
})
|
||||
.ok()
|
||||
.filter(|block| !block.is_empty())
|
||||
*/
|
||||
})
|
||||
})
|
||||
.unwrap_or(Block::empty())
|
||||
@ -388,16 +349,13 @@ impl<'a> ZCache<'a> {
|
||||
let structure = self.structures.iter().filter_map(|st| st.as_ref()).fold(
|
||||
0,
|
||||
|a, (st_info, st_sample)| {
|
||||
let bounds = st_info.volume.get_bounds();
|
||||
let bounds = st_info.get_bounds();
|
||||
let st_area = Aabr {
|
||||
min: Vec2::from(bounds.min),
|
||||
max: Vec2::from(bounds.max),
|
||||
};
|
||||
|
||||
let rpos = self.wpos - st_info.pos;
|
||||
let unit_rpos = st_info.units.0 * rpos.x + st_info.units.1 * rpos.y;
|
||||
|
||||
if st_area.contains_point(unit_rpos) {
|
||||
if st_area.contains_point(self.wpos - st_info.pos) {
|
||||
a.max(bounds.max.z)
|
||||
} else {
|
||||
a
|
||||
@ -413,13 +371,6 @@ impl<'a> ZCache<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StructureInfo {
|
||||
pos: Vec3<i32>,
|
||||
seed: u32,
|
||||
units: (Vec2<i32>, Vec2<i32>),
|
||||
volume: &'static Structure,
|
||||
}
|
||||
|
||||
impl<'a> SamplerMut for BlockGen<'a> {
|
||||
type Index = Vec3<i32>;
|
||||
type Sample = Option<Block>;
|
||||
@ -429,3 +380,127 @@ impl<'a> SamplerMut for BlockGen<'a> {
|
||||
self.get_with_z_cache(wpos, z_cache.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum StructureMeta {
|
||||
Pyramid {
|
||||
height: i32,
|
||||
},
|
||||
Volume {
|
||||
units: (Vec2<i32>, Vec2<i32>),
|
||||
volume: &'static Structure,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct StructureInfo {
|
||||
pos: Vec3<i32>,
|
||||
seed: u32,
|
||||
meta: StructureMeta,
|
||||
}
|
||||
|
||||
impl StructureInfo {
|
||||
fn get_bounds(&self) -> Aabb<i32> {
|
||||
match self.meta {
|
||||
StructureMeta::Pyramid { height } => {
|
||||
let base = 40;
|
||||
Aabb {
|
||||
min: Vec3::new(-base - height, -base - height, -base),
|
||||
max: Vec3::new(base + height, base + height, height),
|
||||
}
|
||||
}
|
||||
StructureMeta::Volume { units, volume } => {
|
||||
let bounds = volume.get_bounds();
|
||||
|
||||
(Aabb {
|
||||
min: Vec3::from(units.0 * bounds.min.x + units.1 * bounds.min.y)
|
||||
+ Vec3::unit_z() * bounds.min.z,
|
||||
max: Vec3::from(units.0 * bounds.max.x + units.1 * bounds.max.y)
|
||||
+ Vec3::unit_z() * bounds.max.z,
|
||||
})
|
||||
.made_valid()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self, wpos: Vec3<i32>, sample: &ColumnSample) -> Option<Block> {
|
||||
match self.meta {
|
||||
StructureMeta::Pyramid { height } => {
|
||||
if wpos.z - self.pos.z
|
||||
< height
|
||||
- Vec2::from(wpos - self.pos)
|
||||
.map(|e: i32| (e.abs() / 2) * 2)
|
||||
.reduce_max()
|
||||
{
|
||||
Some(Block::new(2, Rgb::new(180, 140, 90)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
StructureMeta::Volume { units, volume } => {
|
||||
let rpos = wpos - self.pos;
|
||||
let block_pos = Vec3::unit_z() * rpos.z
|
||||
+ Vec3::from(units.0) * rpos.x
|
||||
+ Vec3::from(units.1) * rpos.y;
|
||||
|
||||
volume
|
||||
.get((block_pos * 128) / 128) // Scaling
|
||||
.map(|b| {
|
||||
block_from_structure(*b, block_pos, self.pos.into(), self.seed, sample)
|
||||
})
|
||||
.ok()
|
||||
.filter(|block| !block.is_empty())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn block_from_structure(
|
||||
sblock: StructureBlock,
|
||||
pos: Vec3<i32>,
|
||||
structure_pos: Vec2<i32>,
|
||||
structure_seed: u32,
|
||||
_sample: &ColumnSample,
|
||||
) -> Block {
|
||||
let field = RandomField::new(structure_seed + 0);
|
||||
|
||||
let lerp = 0.5
|
||||
+ ((field.get(Vec3::from(structure_pos)) % 256) as f32 / 256.0 - 0.5) * 0.65
|
||||
+ ((field.get(Vec3::from(pos)) % 256) as f32 / 256.0 - 0.5) * 0.15;
|
||||
|
||||
match sblock {
|
||||
StructureBlock::TemperateLeaves => Block::new(
|
||||
1,
|
||||
Lerp::lerp(Rgb::new(0.0, 70.0, 35.0), Rgb::new(100.0, 140.0, 0.0), lerp)
|
||||
.map(|e| e as u8),
|
||||
),
|
||||
StructureBlock::PineLeaves => Block::new(
|
||||
1,
|
||||
Lerp::lerp(Rgb::new(0.0, 60.0, 50.0), Rgb::new(30.0, 100.0, 10.0), lerp)
|
||||
.map(|e| e as u8),
|
||||
),
|
||||
StructureBlock::PalmLeaves => Block::new(
|
||||
1,
|
||||
Lerp::lerp(
|
||||
Rgb::new(15.0, 100.0, 30.0),
|
||||
Rgb::new(55.0, 220.0, 0.0),
|
||||
lerp,
|
||||
)
|
||||
.map(|e| e as u8),
|
||||
),
|
||||
StructureBlock::Acacia => Block::new(
|
||||
1,
|
||||
Lerp::lerp(
|
||||
Rgb::new(35.0, 100.0, 10.0),
|
||||
Rgb::new(70.0, 190.0, 25.0),
|
||||
lerp,
|
||||
)
|
||||
.map(|e| e as u8),
|
||||
),
|
||||
StructureBlock::Fruit => Block::new(
|
||||
1,
|
||||
Lerp::lerp(Rgb::new(255.0, 0.0, 0.0), Rgb::new(200.0, 255.0, 6.0), lerp)
|
||||
.map(|e| e as u8),
|
||||
),
|
||||
StructureBlock::Block(block) => block,
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{BlockGen, StructureInfo, ZCache};
|
||||
use super::{BlockGen, StructureInfo, StructureMeta, ZCache};
|
||||
use crate::{
|
||||
all::ForestKind,
|
||||
column::{ColumnGen, ColumnSample},
|
||||
@ -75,8 +75,10 @@ pub fn structure_gen<'a>(
|
||||
Some(StructureInfo {
|
||||
pos: st_pos3d,
|
||||
seed: st_seed,
|
||||
units: UNIT_CHOICES[UNIT_RAND.get(st_seed) as usize % UNIT_CHOICES.len()],
|
||||
volume: &volumes[(VOLUME_RAND.get(st_seed) / 13) as usize % volumes.len()],
|
||||
meta: StructureMeta::Volume {
|
||||
units: UNIT_CHOICES[UNIT_RAND.get(st_seed) as usize % UNIT_CHOICES.len()],
|
||||
volume: &volumes[(VOLUME_RAND.get(st_seed) / 13) as usize % volumes.len()],
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,10 @@
|
||||
use crate::{all::ForestKind, sim::LocationInfo, util::Sampler, World, CONFIG};
|
||||
use crate::{
|
||||
all::ForestKind,
|
||||
block::StructureMeta,
|
||||
sim::{LocationInfo, SimChunk},
|
||||
util::Sampler,
|
||||
World, CONFIG,
|
||||
};
|
||||
use common::{terrain::TerrainChunkSize, vol::VolSize};
|
||||
use noise::NoiseFn;
|
||||
use std::{
|
||||
@ -15,6 +21,53 @@ impl<'a> ColumnGen<'a> {
|
||||
pub fn new(world: &'a World) -> Self {
|
||||
Self { world }
|
||||
}
|
||||
|
||||
fn get_local_structure(&self, wpos: Vec2<i32>, chunk: &SimChunk) -> Option<StructureData> {
|
||||
let (pos, seed) = self
|
||||
.world
|
||||
.sim()
|
||||
.gen_ctx
|
||||
.region_gen
|
||||
.get(wpos)
|
||||
.iter()
|
||||
.copied()
|
||||
.min_by_key(|(pos, _)| pos.distance_squared(wpos))
|
||||
.unwrap();
|
||||
|
||||
if seed % 5 == 2 && chunk.temp > CONFIG.desert_temp && chunk.alt > CONFIG.sea_level + 5.0 {
|
||||
Some(StructureData {
|
||||
pos,
|
||||
seed,
|
||||
meta: Some(StructureMeta::Pyramid { height: 140 }),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_close_structures(
|
||||
&self,
|
||||
wpos: Vec2<i32>,
|
||||
chunk: &SimChunk,
|
||||
) -> [Option<StructureData>; 9] {
|
||||
let mut metas = [None; 9];
|
||||
self.world
|
||||
.sim()
|
||||
.gen_ctx
|
||||
.structure_gen
|
||||
.get(wpos)
|
||||
.into_iter()
|
||||
.copied()
|
||||
.enumerate()
|
||||
.for_each(|(i, (pos, seed))| {
|
||||
metas[i] = self.get_local_structure(pos, chunk).or(Some(StructureData {
|
||||
pos,
|
||||
seed,
|
||||
meta: None,
|
||||
}));
|
||||
});
|
||||
metas
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Sampler for ColumnGen<'a> {
|
||||
@ -250,7 +303,7 @@ impl<'a> Sampler for ColumnGen<'a> {
|
||||
sub_surface_color: dirt,
|
||||
tree_density,
|
||||
forest_kind: sim_chunk.forest_kind,
|
||||
close_trees: sim.gen_ctx.tree_gen.get(wpos),
|
||||
close_structures: self.gen_close_structures(wpos, sim_chunk),
|
||||
cave_xy,
|
||||
cave_alt,
|
||||
rock,
|
||||
@ -275,7 +328,7 @@ pub struct ColumnSample<'a> {
|
||||
pub sub_surface_color: Rgb<f32>,
|
||||
pub tree_density: f32,
|
||||
pub forest_kind: ForestKind,
|
||||
pub close_trees: [(Vec2<i32>, u32); 9],
|
||||
pub close_structures: [Option<StructureData>; 9],
|
||||
pub cave_xy: f32,
|
||||
pub cave_alt: f32,
|
||||
pub rock: f32,
|
||||
@ -287,3 +340,10 @@ pub struct ColumnSample<'a> {
|
||||
pub spawn_rate: f32,
|
||||
pub location: Option<&'a LocationInfo>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct StructureData {
|
||||
pub pos: Vec2<i32>,
|
||||
pub seed: u32,
|
||||
pub meta: Option<StructureMeta>,
|
||||
}
|
||||
|
@ -38,7 +38,8 @@ pub(crate) struct GenCtx {
|
||||
pub cave_0_nz: SuperSimplex,
|
||||
pub cave_1_nz: SuperSimplex,
|
||||
|
||||
pub tree_gen: StructureGen2d,
|
||||
pub structure_gen: StructureGen2d,
|
||||
pub region_gen: StructureGen2d,
|
||||
pub cliff_gen: StructureGen2d,
|
||||
}
|
||||
|
||||
@ -75,8 +76,9 @@ impl WorldSim {
|
||||
cave_0_nz: SuperSimplex::new().set_seed(seed + 13),
|
||||
cave_1_nz: SuperSimplex::new().set_seed(seed + 14),
|
||||
|
||||
tree_gen: StructureGen2d::new(seed, 32, 24),
|
||||
cliff_gen: StructureGen2d::new(seed, 80, 56),
|
||||
structure_gen: StructureGen2d::new(seed, 32, 24),
|
||||
region_gen: StructureGen2d::new(seed + 1, 400, 96),
|
||||
cliff_gen: StructureGen2d::new(seed + 2, 80, 56),
|
||||
};
|
||||
|
||||
let mut chunks = Vec::new();
|
||||
|
Loading…
Reference in New Issue
Block a user