diff --git a/assets/world/structure/dungeon/ruins.vox b/assets/world/structure/dungeon/ruins.vox new file mode 100644 index 0000000000..c06fd4d539 --- /dev/null +++ b/assets/world/structure/dungeon/ruins.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df1e59df3b17fcb861dedf6bbd9363db72e55e695508e8b0997f9a05d3b42c63 +size 845603 diff --git a/common/src/sys/movement.rs b/common/src/sys/movement.rs index 401180ba5b..18f4dfb219 100644 --- a/common/src/sys/movement.rs +++ b/common/src/sys/movement.rs @@ -120,7 +120,7 @@ impl<'a> System<'a> for Sys { && (ori.0.normalized() - Vec3::from(ori_dir).normalized()).magnitude_squared() > 0.001 { - ori.0 = vek::ops::Slerp::slerp(ori.0, ori_dir.into(), 5.0 * dt.0); + ori.0 = vek::ops::Slerp::slerp(ori.0, ori_dir.into(), 15.0 * dt.0); } } diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs index 4d386c9743..0ebe337f62 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -15,6 +15,7 @@ pub enum StructureBlock { Acacia, PalmLeaves, Fruit, + Hollow, Block(Block), } @@ -94,6 +95,7 @@ impl Asset for Structure { 2 => StructureBlock::PalmLeaves, 4 => StructureBlock::Acacia, 7 => StructureBlock::Fruit, + 15 => StructureBlock::Hollow, index => { let color = palette .get(index as usize) diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 0c3c0d5871..42c4b010c3 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -289,40 +289,14 @@ impl<'a> BlockGen<'a> { } }); - let block = if definitely_underground { - block.unwrap_or(Block::empty()) - } else { - block - .or_else(|| { - 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 - + Vec3::from(st.units.1) * rpos.y; - - st.volume - .get((block_pos * 128) / 128) // Scaling - .map(|b| { - block_from_structure( - *b, - block_pos, - st.pos.into(), - st.seed, - st_sample, - ) - }) - .ok() - .filter(|block| !block.is_empty()) - */ - }) - }) - .unwrap_or(Block::empty()) - }; + let block = structures + .iter() + .find_map(|st| { + let (st, st_sample) = st.as_ref()?; + st.get(wpos, st_sample) + }) + .or(block) + .unwrap_or(Block::empty()); Some(block) } @@ -346,9 +320,11 @@ impl<'a> ZCache<'a> { let cliff = if self.sample.near_cliffs { 48.0 } else { 0.0 }; let warp = self.sample.chaos * 48.0; - let structure = self.structures.iter().filter_map(|st| st.as_ref()).fold( - 0, - |a, (st_info, st_sample)| { + let (structure_min, structure_max) = self + .structures + .iter() + .filter_map(|st| st.as_ref()) + .fold((0.0f32, 0.0f32), |(min, max), (st_info, st_sample)| { let bounds = st_info.get_bounds(); let st_area = Aabr { min: Vec2::from(bounds.min), @@ -356,14 +332,14 @@ impl<'a> ZCache<'a> { }; if st_area.contains_point(self.wpos - st_info.pos) { - a.max(bounds.max.z) + (min.min(bounds.min.z as f32), max.max(bounds.max.z as f32)) } else { - a + (min, max) } - }, - ) as f32; + }); - let max = (self.sample.alt + cliff + structure + warp + 8.0) + let min = min + structure_min; + let max = (self.sample.alt + cliff + structure_max + warp + 8.0) .max(self.sample.water_level) .max(CONFIG.sea_level + 2.0); @@ -444,11 +420,10 @@ impl StructureInfo { volume .get((block_pos * 128) / 128) // Scaling - .map(|b| { + .ok() + .and_then(|b| { block_from_structure(*b, block_pos, self.pos.into(), self.seed, sample) }) - .ok() - .filter(|block| !block.is_empty()) } } } @@ -460,7 +435,7 @@ fn block_from_structure( structure_pos: Vec2, structure_seed: u32, _sample: &ColumnSample, -) -> Block { +) -> Option { let field = RandomField::new(structure_seed + 0); let lerp = 0.5 @@ -468,17 +443,17 @@ fn block_from_structure( + ((field.get(Vec3::from(pos)) % 256) as f32 / 256.0 - 0.5) * 0.15; match sblock { - StructureBlock::TemperateLeaves => Block::new( + StructureBlock::TemperateLeaves => Some(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( + )), + StructureBlock::PineLeaves => Some(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( + )), + StructureBlock::PalmLeaves => Some(Block::new( 1, Lerp::lerp( Rgb::new(15.0, 100.0, 30.0), @@ -486,8 +461,8 @@ fn block_from_structure( lerp, ) .map(|e| e as u8), - ), - StructureBlock::Acacia => Block::new( + )), + StructureBlock::Acacia => Some(Block::new( 1, Lerp::lerp( Rgb::new(35.0, 100.0, 10.0), @@ -495,12 +470,13 @@ fn block_from_structure( lerp, ) .map(|e| e as u8), - ), - StructureBlock::Fruit => Block::new( + )), + StructureBlock::Fruit => Some(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, + )), + StructureBlock::Hollow => Some(Block::empty()), + StructureBlock::Block(block) => Some(block).filter(|block| !block.is_empty()), } } diff --git a/world/src/block/natural.rs b/world/src/block/natural.rs index 1ecac53823..557015a92c 100644 --- a/world/src/block/natural.rs +++ b/world/src/block/natural.rs @@ -2,7 +2,7 @@ use super::{BlockGen, StructureInfo, StructureMeta, ZCache}; use crate::{ all::ForestKind, column::{ColumnGen, ColumnSample}, - util::{HashCache, RandomPerm, Sampler}, + util::{HashCache, RandomPerm, Sampler, UnitChooser}, CONFIG, }; use common::{assets, terrain::Structure}; @@ -11,7 +11,7 @@ use std::sync::Arc; use vek::*; static VOLUME_RAND: RandomPerm = RandomPerm::new(0xDB21C052); -static UNIT_RAND: RandomPerm = RandomPerm::new(0x700F4EC7); +static UNIT_CHOOSER: UnitChooser = UnitChooser::new(0x700F4EC7); static QUIRKY_RAND: RandomPerm = RandomPerm::new(0xA634460F); pub fn structure_gen<'a>( @@ -61,22 +61,11 @@ pub fn structure_gen<'a>( } }; - const UNIT_CHOICES: [(Vec2, Vec2); 8] = [ - (Vec2 { x: 1, y: 0 }, Vec2 { x: 0, y: 1 }), - (Vec2 { x: 1, y: 0 }, Vec2 { x: 0, y: -1 }), - (Vec2 { x: -1, y: 0 }, Vec2 { x: 0, y: 1 }), - (Vec2 { x: -1, y: 0 }, Vec2 { x: 0, y: -1 }), - (Vec2 { x: 0, y: 1 }, Vec2 { x: 1, y: 0 }), - (Vec2 { x: 0, y: 1 }, Vec2 { x: -1, y: 0 }), - (Vec2 { x: 0, y: -1 }, Vec2 { x: 1, y: 0 }), - (Vec2 { x: 0, y: -1 }, Vec2 { x: -1, y: 0 }), - ]; - Some(StructureInfo { pos: st_pos3d, seed: st_seed, meta: StructureMeta::Volume { - units: UNIT_CHOICES[UNIT_RAND.get(st_seed) as usize % UNIT_CHOICES.len()], + units: UNIT_CHOOSER.get(st_seed), volume: &volumes[(VOLUME_RAND.get(st_seed) / 13) as usize % volumes.len()], }, }) diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index 4e3e7a28f3..443739b17d 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -2,14 +2,20 @@ use crate::{ all::ForestKind, block::StructureMeta, sim::{LocationInfo, SimChunk}, - util::Sampler, + util::{Sampler, UnitChooser}, World, CONFIG, }; -use common::{terrain::TerrainChunkSize, vol::VolSize}; +use common::{ + assets, + terrain::{Structure, TerrainChunkSize}, + vol::VolSize, +}; +use lazy_static::lazy_static; use noise::NoiseFn; use std::{ f32, ops::{Add, Div, Mul, Neg, Sub}, + sync::Arc, }; use vek::*; @@ -17,6 +23,17 @@ pub struct ColumnGen<'a> { world: &'a World, } +static UNIT_CHOOSER: UnitChooser = UnitChooser::new(0x700F4EC7); + +lazy_static! { + pub static ref DUNGEONS: Vec> = vec![ + // green oaks + assets::load_map("world/structure/dungeon/ruins.vox", |s: Structure| s + .with_center(Vec3::new(57, 58, 62))) + .unwrap(), + ]; +} + impl<'a> ColumnGen<'a> { pub fn new(world: &'a World) -> Self { Self { world } @@ -45,6 +62,15 @@ impl<'a> ColumnGen<'a> { seed, meta: Some(StructureMeta::Pyramid { height: 140 }), }) + } else if seed % 17 == 2 && chunk.chaos < 0.2 { + Some(StructureData { + pos, + seed, + meta: Some(StructureMeta::Volume { + units: UNIT_CHOOSER.get(seed), + volume: &DUNGEONS[0], + }), + }) } else { None } diff --git a/world/src/util/mod.rs b/world/src/util/mod.rs index fd538e21ce..a8a71d0c03 100644 --- a/world/src/util/mod.rs +++ b/world/src/util/mod.rs @@ -2,6 +2,7 @@ pub mod hash_cache; pub mod random; pub mod sampler; pub mod structure; +pub mod unit_chooser; // Reexports pub use self::{ @@ -9,4 +10,5 @@ pub use self::{ random::{RandomField, RandomPerm}, sampler::{Sampler, SamplerMut}, structure::StructureGen2d, + unit_chooser::UnitChooser, }; diff --git a/world/src/util/unit_chooser.rs b/world/src/util/unit_chooser.rs new file mode 100644 index 0000000000..c5c0203090 --- /dev/null +++ b/world/src/util/unit_chooser.rs @@ -0,0 +1,34 @@ +use super::{RandomPerm, Sampler}; +use vek::*; + +const UNIT_CHOICES: [(Vec2, Vec2); 8] = [ + (Vec2 { x: 1, y: 0 }, Vec2 { x: 0, y: 1 }), + (Vec2 { x: 1, y: 0 }, Vec2 { x: 0, y: -1 }), + (Vec2 { x: -1, y: 0 }, Vec2 { x: 0, y: 1 }), + (Vec2 { x: -1, y: 0 }, Vec2 { x: 0, y: -1 }), + (Vec2 { x: 0, y: 1 }, Vec2 { x: 1, y: 0 }), + (Vec2 { x: 0, y: 1 }, Vec2 { x: -1, y: 0 }), + (Vec2 { x: 0, y: -1 }, Vec2 { x: 1, y: 0 }), + (Vec2 { x: 0, y: -1 }, Vec2 { x: -1, y: 0 }), +]; + +pub struct UnitChooser { + perm: RandomPerm, +} + +impl UnitChooser { + pub const fn new(seed: u32) -> Self { + Self { + perm: RandomPerm::new(seed), + } + } +} + +impl Sampler for UnitChooser { + type Index = u32; + type Sample = (Vec2, Vec2); + + fn get(&self, perm: Self::Index) -> Self::Sample { + UNIT_CHOICES[self.perm.get(perm) as usize % UNIT_CHOICES.len()] + } +}