From e5ebbd31fa39a26cc647a685d47429e7e66c17da Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 25 Nov 2020 14:59:28 +0000 Subject: [PATCH] Began using Grid for LoD data --- client/src/lib.rs | 25 +++++++++-------- {world/src/util => common/src}/grid.rs | 37 ++++++++++++++++++++++++++ common/src/lib.rs | 1 + common/src/msg/world_msg.rs | 5 ++-- voxygen/src/scene/lod.rs | 6 ++--- world/src/sim/mod.rs | 5 ++-- world/src/util/mod.rs | 4 +-- 7 files changed, 61 insertions(+), 22 deletions(-) rename {world/src/util => common/src}/grid.rs (68%) diff --git a/client/src/lib.rs b/client/src/lib.rs index 75787bd9a8..c0e2c45dae 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -24,6 +24,7 @@ use common::{ InventoryManip, InventoryUpdateEvent, }, event::{EventBus, LocalEvent}, + grid::Grid, msg::{ validate_chat_msg, world_msg::SiteInfo, ChatMsgValidationError, ClientGeneral, ClientMsg, ClientRegister, ClientType, DisconnectReason, InviteAnswer, Notification, PingMsg, @@ -80,15 +81,15 @@ pub struct Client { /// Just the "base" layer for LOD; currently includes colors and nothing /// else. In the future we'll add more layers, like shadows, rivers, and /// probably foliage, cities, roads, and other structures. - pub lod_base: Vec, + pub lod_base: Grid, /// The "height" layer for LOD; currently includes only land altitudes, but /// in the future should also water depth, and probably other /// information as well. - pub lod_alt: Vec, + pub lod_alt: Grid, /// The "shadow" layer for LOD. Includes east and west horizon angles and /// an approximate max occluder height, which we use to try to /// approximate soft and volumetric shadows. - pub lod_horizon: Vec, + pub lod_horizon: Grid, /// A fully rendered map image for use with the map and minimap; note that /// this can be constructed dynamically by combining the layers of world /// map data (e.g. with shadow map data or river data), but at present @@ -229,11 +230,10 @@ impl Client { let sea_level = world_map.sea_level; let rgba = world_map.rgba; let alt = world_map.alt; - let expected_size = (u32::from(map_size.x) * u32::from(map_size.y)) as usize; - if rgba.len() != expected_size { + if rgba.size() != map_size.map(|e| e as i32) { return Err(Error::Other("Server sent a bad world map image".into())); } - if alt.len() != expected_size { + if rgba.size() != map_size.map(|e| e as i32) { return Err(Error::Other("Server sent a bad altitude map.".into())); } let [west, east] = world_map.horizons; @@ -257,7 +257,7 @@ impl Client { let horizons = [unzip_horizons(&west), unzip_horizons(&east)]; // Redraw map (with shadows this time). - let mut world_map_rgba = vec![0u32; rgba.len()]; + let mut world_map_rgba = vec![0u32; rgba.size().product() as usize]; let mut map_config = common::terrain::map::MapConfig::orthographic( map_size_lg, core::ops::RangeInclusive::new(0.0, max_height), @@ -274,14 +274,14 @@ impl Client { |pos| { let (rgba, alt, downhill_wpos) = if bounds_check(pos) { let posi = pos.y as usize * map_size.x as usize + pos.x as usize; - let [r, g, b, a] = rgba[posi].to_le_bytes(); - let alti = alt[posi]; + let [r, g, b, a] = rgba[pos].to_le_bytes(); + let alti = alt[pos]; // Compute downhill. let downhill = { let mut best = -1; let mut besth = alti; for nposi in neighbors(map_size_lg, posi) { - let nbh = alt[nposi]; + let nbh = alt.raw()[nposi]; if nbh < besth { besth = nbh; best = nposi as isize; @@ -317,8 +317,7 @@ impl Client { |wpos| { let pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, f| e / f as i32); rescale_height(if bounds_check(pos) { - let posi = pos.y as usize * map_size.x as usize + pos.x as usize; - scale_height_big(alt[posi]) + scale_height_big(alt[pos]) } else { 0.0 }) @@ -361,7 +360,7 @@ impl Client { entity, lod_base, lod_alt, - lod_horizon, + Grid::from_raw(map_size.map(|e| e as i32), lod_horizon), (world_map_img, map_size, map_bounds), world_map.sites, recipe_book, diff --git a/world/src/util/grid.rs b/common/src/grid.rs similarity index 68% rename from world/src/util/grid.rs rename to common/src/grid.rs index 7c57cc2050..3901c05ce0 100644 --- a/world/src/util/grid.rs +++ b/common/src/grid.rs @@ -1,11 +1,20 @@ +use serde::{Deserialize, Serialize}; +use std::ops::{Index, IndexMut}; use vek::*; +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Grid { cells: Vec, size: Vec2, } impl Grid { + pub fn from_raw(size: Vec2, raw: impl Into>) -> Self { + let cells = raw.into(); + assert_eq!(size.product() as usize, cells.len()); + Self { cells, size } + } + pub fn populate_from(size: Vec2, mut f: impl FnMut(Vec2) -> T) -> Self { Self { cells: (0..size.y) @@ -81,4 +90,32 @@ impl Grid { }) .flatten() } + + pub fn raw(&self) -> &[T] { &self.cells } +} + +impl Index> for Grid { + type Output = T; + + fn index(&self, index: Vec2) -> &Self::Output { + self.get(index).unwrap_or_else(|| { + panic!( + "Attempted to index grid of size {:?} with index {:?}", + self.size(), + index + ) + }) + } +} + +impl IndexMut> for Grid { + fn index_mut(&mut self, index: Vec2) -> &mut Self::Output { + let size = self.size(); + self.get_mut(index).unwrap_or_else(|| { + panic!( + "Attempted to index grid of size {:?} with index {:?}", + size, index + ) + }) + } } diff --git a/common/src/lib.rs b/common/src/lib.rs index 666fe925cb..610e21ed4d 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -30,6 +30,7 @@ pub mod event; pub mod explosion; pub mod figure; pub mod generation; +pub mod grid; pub mod loadout_builder; pub mod lottery; pub mod metrics; diff --git a/common/src/msg/world_msg.rs b/common/src/msg/world_msg.rs index 5290871b81..d6d2d470f4 100644 --- a/common/src/msg/world_msg.rs +++ b/common/src/msg/world_msg.rs @@ -1,3 +1,4 @@ +use crate::grid::Grid; use serde::{Deserialize, Serialize}; use vek::*; @@ -30,12 +31,12 @@ pub struct WorldMapMsg { pub max_height: f32, /// RGB+A; the alpha channel is currently unused, but will be used in the /// future. Entries are in the usual chunk order. - pub rgba: Vec, + pub rgba: Grid, /// Altitudes: bits 2 to 0 are unused, then bits 15 to 3 are used for /// altitude. The remainder are currently unused, but we have plans to /// use 7 bits for water depth (using an integer f7 encoding), and we /// will find other uses for the remaining 12 bits. - pub alt: Vec, + pub alt: Grid, /// Horizon mapping. This is a variant of shadow mapping that is /// specifically designed for height maps; it takes advantage of their /// regular structure (e.g. no holes) to compress all information needed diff --git a/voxygen/src/scene/lod.rs b/voxygen/src/scene/lod.rs index f241d8fa0d..fdfbf17782 100644 --- a/voxygen/src/scene/lod.rs +++ b/voxygen/src/scene/lod.rs @@ -29,9 +29,9 @@ impl Lod { data: LodData::new( renderer, client.world_map.1, - &client.lod_base, - &client.lod_alt, - &client.lod_horizon, + &client.lod_base.raw(), + &client.lod_alt.raw(), + &client.lod_horizon.raw(), settings.graphics.lod_detail.max(100).min(2500), water_color().into_array().into(), ), diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index d2c465eb0f..9c006fc010 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -36,6 +36,7 @@ use crate::{ }; use common::{ assets, + grid::Grid, msg::WorldMapMsg, store::Id, terrain::{ @@ -1498,8 +1499,8 @@ impl WorldSim { dimensions_lg: self.map_size_lg().vec(), sea_level: CONFIG.sea_level, max_height: self.max_height, - rgba: v, - alt: alts, + rgba: Grid::from_raw(self.get_size().map(|e| e as i32), v), + alt: Grid::from_raw(self.get_size().map(|e| e as i32), alts), horizons, sites: Vec::new(), // Will be substituted later } diff --git a/world/src/util/mod.rs b/world/src/util/mod.rs index de31f42c71..8d20dc2216 100644 --- a/world/src/util/mod.rs +++ b/world/src/util/mod.rs @@ -1,5 +1,4 @@ pub mod fast_noise; -pub mod grid; pub mod map_vec; pub mod random; pub mod sampler; @@ -11,7 +10,6 @@ pub mod unit_chooser; // Reexports pub use self::{ fast_noise::FastNoise, - grid::Grid, map_vec::MapVec, random::{RandomField, RandomPerm}, sampler::{Sampler, SamplerMut}, @@ -20,6 +18,8 @@ pub use self::{ unit_chooser::UnitChooser, }; +pub use common::grid::Grid; + use fxhash::FxHasher32; use hashbrown::{HashMap, HashSet}; use std::hash::BuildHasherDefault;