Began using Grid<T> for LoD data

This commit is contained in:
Joshua Barretto 2020-11-25 14:59:28 +00:00
parent 20b45a1202
commit e5ebbd31fa
7 changed files with 61 additions and 22 deletions

View File

@ -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<u32>,
pub lod_base: Grid<u32>,
/// 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<u32>,
pub lod_alt: Grid<u32>,
/// 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<u32>,
pub lod_horizon: Grid<u32>,
/// 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,

View File

@ -1,11 +1,20 @@
use serde::{Deserialize, Serialize};
use std::ops::{Index, IndexMut};
use vek::*;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Grid<T> {
cells: Vec<T>,
size: Vec2<i32>,
}
impl<T> Grid<T> {
pub fn from_raw(size: Vec2<i32>, raw: impl Into<Vec<T>>) -> Self {
let cells = raw.into();
assert_eq!(size.product() as usize, cells.len());
Self { cells, size }
}
pub fn populate_from(size: Vec2<i32>, mut f: impl FnMut(Vec2<i32>) -> T) -> Self {
Self {
cells: (0..size.y)
@ -81,4 +90,32 @@ impl<T> Grid<T> {
})
.flatten()
}
pub fn raw(&self) -> &[T] { &self.cells }
}
impl<T> Index<Vec2<i32>> for Grid<T> {
type Output = T;
fn index(&self, index: Vec2<i32>) -> &Self::Output {
self.get(index).unwrap_or_else(|| {
panic!(
"Attempted to index grid of size {:?} with index {:?}",
self.size(),
index
)
})
}
}
impl<T> IndexMut<Vec2<i32>> for Grid<T> {
fn index_mut(&mut self, index: Vec2<i32>) -> &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
)
})
}
}

View File

@ -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;

View File

@ -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<u32>,
pub rgba: Grid<u32>,
/// 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<u32>,
pub alt: Grid<u32>,
/// 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

View File

@ -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(),
),

View File

@ -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
}

View File

@ -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;