diff --git a/client/src/lib.rs b/client/src/lib.rs index 3222c7e51c..55d8b6e2e5 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -316,7 +316,7 @@ impl Client { // Should not fail if the dimensions are correct. let map = image::ImageBuffer::from_raw(u32::from(map_size.x), u32::from(map_size.y), raw); - map.ok_or(Error::Other("Server sent a bad world map image".into()))? + map.ok_or_else(|| Error::Other("Server sent a bad world map image".into()))? }) // Flip the image, since Voxygen uses an orientation where rotation from // positive x axis to positive y axis is counterclockwise around the z axis. diff --git a/common/src/terrain/map.rs b/common/src/terrain/map.rs index 573fee914c..545ca7883a 100644 --- a/common/src/terrain/map.rs +++ b/common/src/terrain/map.rs @@ -142,6 +142,12 @@ pub const MAX_WORLD_BLOCKS_LG: Vec2 = Vec2 { x: 19, y: 19 }; pub struct MapSizeLg(Vec2); impl MapSizeLg { + // FIXME: We cannot use is_some() here because it is not currently marked as a + // `const fn`. Since being able to use conditionals in constant expressions has + // not technically been stabilized yet, Clippy probably doesn't check for this + // case yet. When it can, or when is_some() is stabilized as a `const fn`, + // we should deal with this. + #[allow(clippy::redundant_pattern_matching)] /// Construct a new `MapSizeLg`, returning an error if the needed invariants /// do not hold and the vector otherwise. /// @@ -509,23 +515,17 @@ impl<'a> MapConfig<'a> { // accurate (though I'm not sure if it can matter for these // purposes). chunk_idx - .map(|chunk_idx| neighbors(map_size_lg, chunk_idx).chain(iter::once(chunk_idx))) .into_iter() - .flatten() + .flat_map(|chunk_idx| { + neighbors(map_size_lg, chunk_idx).chain(iter::once(chunk_idx)) + }) .for_each(|neighbor_posi| { let neighbor_pos = uniform_idx_as_vec2(map_size_lg, neighbor_posi); let neighbor_wpos = neighbor_pos.map(|e| e as f64) * chunk_size; let MapSample { connections, .. } = sample_pos(neighbor_pos); NEIGHBOR_DELTA .iter() - .zip( - connections - .as_ref() - .map(|e| e.iter()) - .into_iter() - .flatten() - .into_iter(), - ) + .zip(connections.iter().flatten()) .for_each(|(&delta, connection)| { let connection = if let Some(connection) = connection { connection diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs index a4b512e301..a4722c4a0c 100644 --- a/voxygen/src/hud/settings_window.rs +++ b/voxygen/src/hud/settings_window.rs @@ -2185,7 +2185,6 @@ impl<'a> Widget for SettingsWindow<'a> { events.push(Event::ChangeRenderMode(RenderMode { shadow: ShadowMode::Map(ShadowMapMode { resolution: 2.0f32.powf(f32::from(new_val) / 4.0), - ..shadow_map_mode }), ..render_mode })); diff --git a/voxygen/src/mesh/greedy.rs b/voxygen/src/mesh/greedy.rs index afc7326cd1..51443e1c32 100644 --- a/voxygen/src/mesh/greedy.rs +++ b/voxygen/src/mesh/greedy.rs @@ -3,6 +3,77 @@ use vek::*; type TerrainVertex = ::Vertex; +/// `max_size`: +/// +/// `draw_delta`: +/// +/// `greedy_size`: +/// +/// `greedy_size_cross`: +/// +/// `get_light`: +/// +/// `get_color`: +/// +/// +/// `create_shadow`: +/// Create a shadow vertex (used for both shadow and display rendering) +/// given its position, normal, and meta information. Note that the position +/// received here is relative to `draw_delta`--it still needs to be translated +/// to mesh coordinates. +/// +/// `create_opaque`: +pub struct GreedyConfig { + pub data: D, + /// The minimum position to mesh, in the coordinate system used + /// for queries against the volume. + pub draw_delta: Vec3, + /// For each dimension i, for faces drawn in planes *parallel* to i, + /// represents the number of voxels considered along dimenson i in those + /// planes, starting from `draw_delta`. + pub greedy_size: Vec3, + /// For each dimension i, represents the number of planes considered + /// *orthogonal* to dimension i, starting from `draw_delta`. This should + /// usually be the same as greedy_size. + /// + /// An important exception is during chunk rendering (where vertical faces + /// at chunk boundaries would otherwise be rendered twice, and also + /// force us to use more than 5 bits to represent x and y + /// positions--though there may be a clever way aruond the latter). + /// Thus, for chunk rendering we set the number of *vertical* planes to + /// one less than the chunk size along the x and y dimensions, but keep + /// the number of *horizontal* planes large enough to cover the whole + /// chunk. + pub greedy_size_cross: Vec3, + /// Given a position, return the lighting information for the voxel at that + /// position. + pub get_light: FL, + /// Given a position, return the color information for the voxel at that + /// position. + pub get_color: FC, + /// Given a position, return the opacity information for the voxel at that + /// position. Currently, we don't support real translucent lighting, so the + /// value should either be `false` (for opaque blocks) or `true` + /// (otherwise). + pub get_opacity: FO, + /// Given a position and a normal, should we draw the face between the + /// position and position - normal (i.e. the voxel "below" this vertex)? + /// If so, provide its orientation, together with any other meta + /// information required for the mesh that needs to split up faces. For + /// example, terrain faces currently record a bit indicating whether + /// they are exposed to water or not, so we should not merge faces where + /// one is submerged in water and the other is not, even if they + /// otherwise have the same orientation, dimensions, and are + /// next to each other. + pub should_draw: FS, + /// Create an opauqe quad (used for only display rendering) from its + /// top-left atlas position, the rectangle's dimensions in (2D) atlas + /// space, a world position, the u and v axes of the rectangle in (3D) + /// world space, the normal facing out frmo the rectangle in world + /// space, and meta information common to every voxel in this rectangle. + pub push_quad: FP, +} + /// A suspended greedy mesh, with enough information to recover color data. /// /// The reason this exists is that greedy meshing is split into two parts. @@ -28,6 +99,20 @@ pub struct GreedyMesh<'a> { } impl<'a> GreedyMesh<'a> { + /// Construct a new greedy mesher. + /// + /// Takes as input the maximum allowable size of the texture atlas used to + /// store the light/color data for this mesh. + /// + /// NOTE: It is an error to pass any size > u16::MAX. + /// + /// Even aside from the above limitation, this will not necessarily always + /// be the same as the maximum atlas size supported by the hardware. + /// For instance, since we want to reserve 4 bits for a bone index for + /// figures in their shadow vertex, the atlas parameter for figures has + /// to have at least 2 bits of the normal; thus, it can only take up at + /// most 30 bits total, meaning we are restricted to "only" at most 2^15 + /// × 2^15 atlases even if the hardware supports larger ones. pub fn new(max_size: guillotiere::Size) -> Self { let min_max_dim = max_size.width.min(max_size.height); assert!( @@ -55,45 +140,55 @@ impl<'a> GreedyMesh<'a> { } } - pub fn push( + /// Perform greedy meshing on a model, separately producing "pure" model + /// data (the opaque mesh, ttogether with atlas positions connecting + /// each rectangle with texture information), and raw light and color + /// data ready to be used as a texture (accessible with `finalize`). + /// Texture data built up within the same greedy mesh will be inserted + /// into the same atlas, which can be used to group texture data for + /// things like figures that are the result of meshing multiple models. + /// + /// Returns an estimate of the bounds of the current meshed model. + /// + /// For more information on the config parameter, see [GreedyConfig]. + pub fn push< + M: PartialEq, + D: 'a, + FL, + FC, + FO, + FS, + FP, + >( &mut self, - data: D, - draw_delta: Vec3, - greedy_size: Vec3, - greedy_size_cross: Vec3, - get_light: impl for<'r> FnMut(&'r mut D, Vec3) -> f32 + 'a, - get_color: impl for<'r> FnMut(&'r mut D, Vec3) -> Rgb + 'a, - get_opacity: impl for<'r> FnMut(&'r mut D, Vec3) -> bool + 'a, - should_draw: impl for<'r> FnMut( - &'r mut D, - Vec3, - Vec3, - Vec2>, - ) -> Option<(bool, M)>, - // create_shadow: impl for<'r> Fn(Vec3, Vec3, &'r M) -> S::Vertex, - // create_opaque: impl for<'r> Fn(Vec2, Vec3, Vec3, &'r M) -> O::Vertex, - push_quad: impl FnMut(Vec2, Vec2>, Vec3, Vec2>, Vec3, &M), - ) -> Aabb { + config: GreedyConfig, + ) -> Aabb + where + FL: for<'r> FnMut(&'r mut D, Vec3) -> f32 + 'a, + FC: for<'r> FnMut(&'r mut D, Vec3) -> Rgb + 'a, + FO: for<'r> FnMut(&'r mut D, Vec3) -> bool + 'a, + FS: for<'r> FnMut(&'r mut D, Vec3, Vec3, Vec2>) -> Option<(bool, M)>, + FP: FnMut(Vec2, Vec2>, Vec3, Vec2>, Vec3, &M), + { let (bounds, /* opaque, *//*shadow, */ cont) = greedy_mesh( &mut self.atlas, &mut self.col_lights_size, self.max_size, - data, - draw_delta, - greedy_size, - greedy_size_cross, - get_light, - get_color, - get_opacity, - should_draw, - // create_shadow, - // create_opaque, - push_quad, + config, ); self.suspended.push(cont); bounds } + /// Finalize the mesh, producing texture color data for the whole model. + /// + /// By delaying finalization until the contents of the whole texture atlas + /// are known, we can perform just a single allocation to construct a + /// precisely fitting atlas. This will also let us (in the future) + /// suspend meshing partway through in order to meet frame budget, and + /// potentially use a single staged upload to the GPU. + /// + /// Returns the ColLightsInfo corresponding to the consstructed atlas. pub fn finalize(self) -> ColLightInfo { let cur_size = self.col_lights_size; let col_lights = vec![/*Default::default()*/TerrainVertex::make_col_light(254, Rgb::broadcast(254)); usize::from(cur_size.x) * usize::from(cur_size.y)]; @@ -107,122 +202,34 @@ impl<'a> GreedyMesh<'a> { pub fn max_size(&self) -> guillotiere::Size { self.max_size } } -/// Perform greedy meshing on a model, separately producing "pure" model data -/// (the shadow mesh), raw light and color data ready to be used as a texture -/// (the returned vector of ColLights, together with their width and height), -/// and the atlas positions (the opaque mesh) used to connect the shadow -/// information with the light and color information. -/// -/// The opaque and shadow data are in the same order and it is intended that -/// they be used together as vertex buffers for display purposes. Thus, if you -/// perform further manipulation on the meshes after this function returns, such -/// as merges, please be sure that all those operations preserve this -/// relationship. -/// -/// TODO: Consider supporting shared texture atlases (this might come in handy -/// for mobs or sprites, for instance).a -/// -/// TODO: Add assertions to make this more robust. -/// -/// Parameter description: -/// -/// `max_size`: -/// The maximum allowable size of the texture atlas used to store the -/// light/color data for this mesh. -/// -/// NOTE: It is an error to pass any size > u16::MAX. -/// -/// Even aside from the above limitation, this will not necessarily always be -/// the same as the maximum atlas size supported by the hardware. For instance, -/// since we want to reserve 4 bits for a bone index for figures in their shadow -/// vertex, the atlas parameter for figures has to have at least 2 bits of the -/// normal; thus, it can only take up at most 30 bits total, meaning we are -/// restricted to "only" at most 2^15 × 2^15 atlases even if the hardware -/// supports larger ones. -/// -/// `draw_delta`: The minimum position to mesh, in the coordinate system used -/// for queries against the volume. -/// -/// `greedy_size`: -/// For each dimension i, for faces drawn in planes *parallel* to i, represents -/// the number of voxels considered along dimenson i in those planes, starting -/// from `draw_delta`. -/// -/// `greedy_size_cross`: -/// For each dimension i, represents the number of planes considered -/// *orthogonal* to dimension i, starting from `draw_delta`. This should -/// usually be the same as greedy_size. -/// -/// An important exception is during chunk rendering (where vertical faces at -/// chunk boundaries would otherwise be rendered twice, and also force us to use -/// more than 5 bits to represent x and y positions--though there may be a -/// clever way aruond the latter). Thus, for chunk rendering we set the number -/// of *vertical* planes to one less than the chunk size along the -/// x and y dimensions, but keep the number of *horizontal* planes large enough -/// to cover the whole chunk. -/// -/// `get_light`: -/// Given a position, return the lighting information for the voxel at that -/// position. -/// -/// `get_color`: -/// Given a position, return the color information for the voxel at that -/// position. -/// -/// `get_opacity`: -/// Given a position, return the opacity information for the voxel at that -/// position. Currently, we don't support real translucent lighting, so the -/// value should either be `false` (for opaque blocks) or `true` (otherwise). -/// -/// `should_draw`: -/// Given a position and a normal, should we draw the face between the position -/// and position - normal (i.e. the voxel "below" this vertex)? If so, provide -/// its orientation, together with any other meta information required for the -/// mesh that needs to split up faces. For example, terrain faces currently -/// record a bit indicating whether they are exposed to water or not, so we -/// should not merge faces where one is submerged in water and the other is not, -/// even if they otherwise have the same orientation, dimensions, and are -/// next to each other. -/// -/// `create_shadow`: -/// Create a shadow vertex (used for both shadow and display rendering) -/// given its position, normal, and meta information. Note that the position -/// received here is relative to `draw_delta`--it still needs to be translated -/// to mesh coordinates. -/// -/// `create_opaque`: -/// Create an opauqe vertex (used for only display rendering) from an atlas -/// position, normal, and meta information. -fn greedy_mesh< - 'a, /* , S: render::Pipeline*//*, O: render::Pipeline */ - M: PartialEq, - D: 'a, ->( +fn greedy_mesh<'a, M: PartialEq, D: 'a, FL, FC, FO, FS, FP>( atlas: &mut guillotiere::SimpleAtlasAllocator, col_lights_size: &mut Vec2, max_size: guillotiere::Size, - mut data: D, - draw_delta: Vec3, - greedy_size: Vec3, - greedy_size_cross: Vec3, - get_light: impl for<'r> FnMut(&'r mut D, Vec3) -> f32 + 'a, - get_color: impl for<'r> FnMut(&'r mut D, Vec3) -> Rgb + 'a, - get_opacity: impl for<'r> FnMut(&'r mut D, Vec3) -> bool + 'a, - mut should_draw: impl for<'r> FnMut( - &'r mut D, - Vec3, - Vec3, - Vec2>, - ) -> Option<(bool, M)>, - // create_shadow: impl Fn(Vec3, Vec3, &M) -> S::Vertex, - // create_opaque: impl Fn(Vec2, Vec3, Vec3, &M) -> O::Vertex, - mut push_quad: impl FnMut(Vec2, Vec2>, Vec3, Vec2>, Vec3, &M), + GreedyConfig { + mut data, + draw_delta, + greedy_size, + greedy_size_cross, + get_light, + get_color, + get_opacity, + mut should_draw, + mut push_quad, + }: GreedyConfig, ) -> ( Aabb, // Mesh, // Mesh, Box>, -) { +) +where + FL: for<'r> FnMut(&'r mut D, Vec3) -> f32 + 'a, + FC: for<'r> FnMut(&'r mut D, Vec3) -> Rgb + 'a, + FO: for<'r> FnMut(&'r mut D, Vec3) -> bool + 'a, + FS: for<'r> FnMut(&'r mut D, Vec3, Vec3, Vec2>) -> Option<(bool, M)>, + FP: FnMut(Vec2, Vec2>, Vec3, Vec2>, Vec3, &M), +{ // let mut opaque_mesh = Mesh::new(); // let mut shadow_mesh = Mesh::new(); diff --git a/voxygen/src/mesh/segment.rs b/voxygen/src/mesh/segment.rs index e70ef1bd7a..a14669a06c 100644 --- a/voxygen/src/mesh/segment.rs +++ b/voxygen/src/mesh/segment.rs @@ -1,6 +1,6 @@ use crate::{ mesh::{ - greedy::{self, GreedyMesh}, + greedy::{self, GreedyConfig, GreedyMesh}, Meshable, }, render::{self, FigurePipeline, Mesh, ShadowPipeline, SpritePipeline, TerrainPipeline}, @@ -77,30 +77,32 @@ where vol.get(vox).map(|vox| *vox).unwrap_or(Vox::empty()) }) }; - let create_opaque = |atlas_pos, pos, norm, _meta| { + let create_opaque = |atlas_pos, pos, norm| { TerrainVertex::new_figure(atlas_pos, (pos + offs) * scale, norm, 0) }; let mut opaque_mesh = Mesh::new(); let bounds = greedy.push( - self, - draw_delta, - greedy_size, - greedy_size_cross, - get_light, - get_color, - get_opacity, - should_draw, - |atlas_origin, dim, origin, draw_dim, norm, meta| { - opaque_mesh.push_quad(greedy::create_quad( - atlas_origin, - dim, - origin, - draw_dim, - norm, - meta, - |atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), - )); + GreedyConfig { + data: self, + draw_delta, + greedy_size, + greedy_size_cross, + get_light, + get_color, + get_opacity, + should_draw, + push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &()| { + opaque_mesh.push_quad(greedy::create_quad( + atlas_origin, + dim, + origin, + draw_dim, + norm, + meta, + |atlas_pos, pos, norm, &_meta| create_opaque(atlas_pos, pos, norm), + )); + }, }, ); let bounds = bounds.map(f32::from); @@ -194,24 +196,26 @@ where let mut opaque_mesh = Mesh::new(); let _bounds = greedy.push( - self, - draw_delta, - greedy_size, - greedy_size_cross, - get_light, - get_color, - get_opacity, - should_draw, - |atlas_origin, dim, origin, draw_dim, norm, meta| { - opaque_mesh.push_quad(greedy::create_quad( - atlas_origin, - dim, - origin, - draw_dim, - norm, - meta, - |atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), - )); + GreedyConfig { + data: self, + draw_delta, + greedy_size, + greedy_size_cross, + get_light, + get_color, + get_opacity, + should_draw, + push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &bool| { + opaque_mesh.push_quad(greedy::create_quad( + atlas_origin, + dim, + origin, + draw_dim, + norm, + meta, + |atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), + )); + }, }, ); diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index 12946106e9..607cd80a19 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -1,6 +1,6 @@ use crate::{ mesh::{ - greedy::{self, GreedyMesh}, + greedy::{self, GreedyConfig, GreedyMesh}, Meshable, }, render::{self, ColLightInfo, FluidPipeline, Mesh, ShadowPipeline, TerrainPipeline}, @@ -503,8 +503,9 @@ impl<'a, V: RectRasterableVol + ReadVol + Debug> let get_color = |_: &mut (), pos: Vec3| flat_get(pos).get_color().unwrap_or(Rgb::zero()); let get_opacity = |_: &mut (), pos: Vec3| !flat_get(pos).is_opaque(); + let flat_get = |pos| flat_get(pos); let should_draw = |_: &mut (), pos: Vec3, delta: Vec3, _uv| { - should_draw_greedy(pos, delta, |pos| flat_get(pos)) + should_draw_greedy(pos, delta, flat_get) }; // NOTE: Conversion to f32 is fine since this i32 is actually in bounds for u16. // let create_shadow = |pos, norm, meta| ShadowVertex::new(pos + Vec3::new(0.0, @@ -513,45 +514,44 @@ impl<'a, V: RectRasterableVol + ReadVol + Debug> let create_opaque = |atlas_pos, pos, norm, meta| { TerrainVertex::new(atlas_pos, pos + mesh_delta, norm, meta) }; - let create_transparent = - |_atlas_pos, pos, norm, _meta| FluidVertex::new(pos + mesh_delta, norm); + let create_transparent = |_atlas_pos, pos, norm| FluidVertex::new(pos + mesh_delta, norm); let mut greedy = GreedyMesh::new(max_size); let mut opaque_mesh = Mesh::new(); let mut fluid_mesh = Mesh::new(); let bounds = greedy.push( - (), - draw_delta, - greedy_size, - greedy_size_cross, - get_light, - get_color, - get_opacity, - should_draw, - |atlas_origin, dim, origin, draw_dim, norm, meta| match meta { - FaceKind::Opaque(meta) => { - opaque_mesh.push_quad(greedy::create_quad( - atlas_origin, - dim, - origin, - draw_dim, - norm, - meta, - |atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), - )); - }, - FaceKind::Fluid => { - fluid_mesh.push_quad(greedy::create_quad( - atlas_origin, - dim, - origin, - draw_dim, - norm, - &(), - |atlas_pos, pos, norm, &meta| { - create_transparent(atlas_pos, pos, norm, meta) - }, - )); + GreedyConfig { + data: (), + draw_delta, + greedy_size, + greedy_size_cross, + get_light, + get_color, + get_opacity, + should_draw, + push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &FaceKind| match meta { + FaceKind::Opaque(meta) => { + opaque_mesh.push_quad(greedy::create_quad( + atlas_origin, + dim, + origin, + draw_dim, + norm, + meta, + |atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), + )); + }, + FaceKind::Fluid => { + fluid_mesh.push_quad(greedy::create_quad( + atlas_origin, + dim, + origin, + draw_dim, + norm, + &(), + |atlas_pos, pos, norm, &_meta| create_transparent(atlas_pos, pos, norm), + )); + }, }, }, ); diff --git a/voxygen/src/render/mesh.rs b/voxygen/src/render/mesh.rs index 190c96c9b4..bad7507530 100644 --- a/voxygen/src/render/mesh.rs +++ b/voxygen/src/render/mesh.rs @@ -128,7 +128,7 @@ impl Quad

{ let verts = [self.a, self.b, self.c, self.d]; Self { - a: verts[(0 + n) % 4].clone(), + a: verts[n % 4].clone(), b: verts[(1 + n) % 4].clone(), c: verts[(2 + n) % 4].clone(), d: verts[(3 + n) % 4].clone(), diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 544d25e1c4..e5e5f6b98e 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -163,7 +163,7 @@ impl FigureModel { // in order to store the bone index. The two bits are instead taken out // of the atlas coordinates, which is why we "only" allow 1 << 15 per // coordinate instead of 1 << 16. - let max_size = guillotiere::Size::new(1 << 15 - 1, 1 << 15 - 1); + let max_size = guillotiere::Size::new((1 << 15) - 1, (1 << 15) - 1); GreedyMesh::new(max_size) } } diff --git a/voxygen/src/render/pipelines/shadow.rs b/voxygen/src/render/pipelines/shadow.rs index 8211e089dd..38756b5acf 100644 --- a/voxygen/src/render/pipelines/shadow.rs +++ b/voxygen/src/render/pipelines/shadow.rs @@ -84,8 +84,10 @@ impl Vertex { if norm.x < 0.0 { 0 } else { 1 } } else if norm.y != 0.0 { if norm.y < 0.0 { 2 } else { 3 } + } else if norm.z < 0.0 { + 4 } else { - if norm.z < 0.0 { 4 } else { 5 } + 5 }; // let ao = 0xFFu32; // let light = 0xFFu32; diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index da25362d1d..9281671d9d 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -82,10 +82,7 @@ impl fmt::Display for Vertex { .field("pos", &Vec3::::from(self.pos)) .field( "atlas_pos", - &Vec2::new( - (self.atlas_pos >> 0) & 0xFFFF, - (self.atlas_pos >> 16) & 0xFFFF, - ), + &Vec2::new(self.atlas_pos & 0xFFFF, (self.atlas_pos >> 16) & 0xFFFF), ) .field("norm_ao", &self.norm_ao) .finish() diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index c88d7799f9..8984b4556b 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -58,8 +58,10 @@ impl Vertex { if norm.x < 0.0 { 0 } else { 1 } } else if norm.y != 0.0 { if norm.y < 0.0 { 2 } else { 3 } + } else if norm.z < 0.0 { + 4 } else { - if norm.z < 0.0 { 4 } else { 5 } + 5 }; Self { pos_norm: 0 diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 1361144d50..488e427e42 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -166,7 +166,7 @@ impl Renderer { let shadow_views = Self::create_shadow_views( &mut factory, (dims.0, dims.1), - &ShadowMapMode::try_from(mode.shadow).unwrap_or(ShadowMapMode::default()), + &ShadowMapMode::try_from(mode.shadow).unwrap_or_default(), ) .map_err(|err| { warn!("Could not create shadow map views: {:?}", err); @@ -1192,7 +1192,6 @@ impl Renderer { _alt: &Texture, _horizon: &Texture, ) { - return; /* let (point_shadow_maps, directed_shadow_maps) = if let Some(shadow_map) = &mut self.shadow_map { ( @@ -2222,7 +2221,7 @@ fn create_shadow_pipeline( factory.create_shader_set(vs.as_bytes(), fs.as_bytes())? }; - let result = Ok(GfxPipeline { + Ok(GfxPipeline { pso: factory.create_pipeline_state( &shader_set, gfx::Primitive::TriangleList, @@ -2242,7 +2241,5 @@ fn create_shadow_pipeline( }, pipe, )?, - }); - - result + }) } diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index 2d5786bafa..e0733a4f06 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -59,7 +59,8 @@ where filter_method.unwrap_or(gfx::texture::FilterMethod::Scale), wrap_mode.unwrap_or(gfx::texture::WrapMode::Clamp), ); - sampler_info.border = border.unwrap_or([0.0, 0.0, 0.0, 1.0].into()); + let transparent = [0.0, 0.0, 0.0, 1.0].into(); + sampler_info.border = border.unwrap_or(transparent); Ok(Self { tex, srv, diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 1faa428945..ee0c0c96ee 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -185,7 +185,7 @@ impl FigureMgrStates { } } - fn retain<'a>(&'a mut self, mut f: impl FnMut(&EcsEntity, &mut FigureStateMeta) -> bool) { + fn retain(&mut self, mut f: impl FnMut(&EcsEntity, &mut FigureStateMeta) -> bool) { self.character_states.retain(|k, v| f(k, &mut *v)); self.quadruped_small_states.retain(|k, v| f(k, &mut *v)); self.quadruped_medium_states.retain(|k, v| f(k, &mut *v)); diff --git a/voxygen/src/scene/math.rs b/voxygen/src/scene/math.rs index 86f504d481..c72f9be978 100644 --- a/voxygen/src/scene/math.rs +++ b/voxygen/src/scene/math.rs @@ -53,7 +53,7 @@ pub fn mat_mul_points>( pts: &mut [Vec3], mut do_p: impl FnMut(Vec4) -> Vec3, ) { - pts.into_iter().for_each(|p| { + pts.iter_mut().for_each(|p| { *p = do_p(mat * Vec4::from_point(*p)); }); } @@ -480,12 +480,10 @@ pub fn clip_test(p: T, q: T, (u1, u2): (T, T)) -> O } else { Some((if r > u1 { r } else { u1 }, u2)) } + } else if r < u1 { + None } else { - if r < u1 { - None - } else { - Some((u1, if r < u2 { r } else { u2 })) - } + Some((u1, if r < u2 { r } else { u2 })) } } /*; // println!("clip_test@(p={:?}, q={:?}, (u1, u2)=({:?}. {:?})): diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index b2fdae596c..01f8ec61fa 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -1195,19 +1195,19 @@ impl Scene { let w_p: math::Mat4 = { if /*sin_gamma > EPISLON_GAMMA*/factor > EPSILON_UPSILON { // Projection for y - let n = directed_near;// - near_dist; - let f = directed_far; - let l = -1.0;// bounds0.min.x;//-1.0;// bounds0.min.x - light_focus_pos.x; - let r = 1.0;// bounds0.max.x;//1.0;// bounds0.max.x - light_focus_pos.x; - let b = -1.0;// bounds0.max.z;// bounds0.max.z - light_focus_pos.z; - let t = 1.0;// bounds0.min.z;// bounds0.min.z - light_focus_pos.z; - let s_x = 2.0 * n / (r - l); - let o_x = (r + l) / (r - l); - let s_z = 2.0 * n / (t - b); - let o_z = (t + b) / (t - b); + let near = directed_near;// - near_dist; + let far = directed_far; + let left = -1.0;// bounds0.min.x;//-1.0;// bounds0.min.x - light_focus_pos.x; + let right = 1.0;// bounds0.max.x;//1.0;// bounds0.max.x - light_focus_pos.x; + let bottom = -1.0;// bounds0.max.z;// bounds0.max.z - light_focus_pos.z; + let top = 1.0;// bounds0.min.z;// bounds0.min.z - light_focus_pos.z; + let s_x = 2.0 * near / (right - left); + let o_x = (right + left) / (right - left); + let s_z = 2.0 * near / (top - bottom); + let o_z = (top + bottom) / (top - bottom); - let s_y = (f + n) / (f - n); - let o_y = -2.0 * f * n / (f - n); + let s_y = (far + near) / (far - near); + let o_y = -2.0 * far * near / (far - near); // y(y₀) = s_y y₀ + o_y // = ((f + n)y₀ - 2fn) / (f - n) // y(f) = s_y f + o_y @@ -1337,22 +1337,12 @@ impl Scene { let o_x = -(xmax + xmin) / (xmax - xmin); let o_y = -(ymax + ymin) / (ymax - ymin); let o_z = -(zmax + zmin) / (zmax - zmin); - let directed_proj_mat = if /*sin_gamma > EPISLON_GAMMA*/factor > EPSILON_UPSILON { - // Mat4::identity() - Mat4::new( - s_x, 0.0, 0.0, o_x, - 0.0, s_y, 0.0, o_y, - 0.0, 0.0, /*-*/s_z, /*-*/o_z, - 0.0, 0.0, 0.0, 1.0, - )/*.scaled_3d(Vec3::new(1.0, 1.0, -1.0))*/ - } else { - Mat4::new( - s_x, 0.0, 0.0, o_x, - 0.0, s_y, 0.0, o_y, - 0.0, 0.0, s_z, o_z, - 0.0, 0.0, 0.0, 1.0, - )/*.scaled_3d(Vec3::new(1.0, 1.0, -1.0))*/ - }/*.scaled_3d(Vec3::new(1.0, 1.0, -1.0))*//* * w_p * w_v*//* * l_r*/;//Mat4::identity(); + let directed_proj_mat = Mat4::new( + s_x, 0.0, 0.0, o_x, + 0.0, s_y, 0.0, o_y, + 0.0, 0.0, s_z, o_z, + 0.0, 0.0, 0.0, 1.0, + )/*.scaled_3d(Vec3::new(1.0, 1.0, -1.0))*//* * w_p * w_v*//* * l_r*/;//Mat4::identity(); // println!("proj_mat: {:?}", directed_proj_mat); // println!("all_mat: {:?}", directed_proj_mat * view_mat); // let _w_p_arr = directed_proj_mat.cols.iter().map(|e| (e.x, e.y, e.z, e.w)).collect::>(); diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index f3f3dfe9db..ee27bfb30f 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -525,6 +525,7 @@ impl Terrain { let mut make_models = |(kind, variation), s, offset, lod_axes: Vec3| { let scaled = [1.0, 0.8, 0.6, 0.4, 0.2]; let model = assets::load_expect::(s); + let zero = Vec3::zero(); let model_size = model .models .first() @@ -534,7 +535,7 @@ impl Terrain { .. }| Vec3::new(x, y, z), ) - .unwrap_or(Vec3::zero()); + .unwrap_or(zero); let max_model_size = Vec3::new(15.0, 15.0, 63.0); let model_scale = max_model_size.map2(model_size, |max_sz: f32, cur_sz| { let scale = max_sz / max_sz.max(cur_sz as f32); @@ -2663,7 +2664,7 @@ impl Terrain { // store it. Only pull out one chunk per frame to avoid an unacceptable // amount of blocking lag due to the GPU upload. That still gives us a // 60 chunks / second budget to play with. - if let Some(response) = self.mesh_recv.recv_timeout(Duration::new(0, 0)).ok() { + if let Ok(response) = self.mesh_recv.recv_timeout(Duration::new(0, 0)) { match self.mesh_todo.get(&response.pos) { // It's the mesh we want, insert the newly finished model into the terrain model // data structure (convert the mesh to a model first of course). diff --git a/world/src/lib.rs b/world/src/lib.rs index 5eaefeedb9..6594188e1b 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -6,7 +6,8 @@ const_if_match, const_generics, const_panic, - label_break_value + label_break_value, + or_patterns )] mod all; diff --git a/world/src/sim/map.rs b/world/src/sim/map.rs index 6f1fc7ec1a..5cfa26feec 100644 --- a/world/src/sim/map.rs +++ b/world/src/sim/map.rs @@ -232,7 +232,7 @@ pub fn sample_pos( ); Rgb::new((r * 255.0) as u8, (g * 255.0) as u8, (b * 255.0) as u8) }, - (None, _) | (Some(RiverKind::Lake { .. }), _) | (Some(RiverKind::Ocean), _) => Rgb::new( + (None | Some(RiverKind::Lake { .. } | RiverKind::Ocean), _) => Rgb::new( 0, ((g_water - water_depth * g_water) * 1.0) as u8, ((b_water - water_depth * b_water) * 1.0) as u8, diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index 6214210035..dc6ac1cf6c 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -1440,7 +1440,7 @@ impl WorldSim { /* let z_cache = block_gen.get_z_cache(wpos); sample.alt = alt.max(z_cache.get_z_limits(&mut block_gen).2); */ sample.alt = alt.max(BlockGen::get_cliff_height( - &mut block_gen.column_gen, + &block_gen.column_gen, &mut block_gen.column_cache, wpos.map(|e| e as f32), &sample.close_cliffs, @@ -1719,12 +1719,12 @@ impl WorldSim { } pub fn get_base_z(&self, chunk_pos: Vec2) -> Option { - if !chunk_pos + let in_bounds = chunk_pos .map2(self.map_size_lg().chunks(), |e, sz| { e > 0 && e < sz as i32 - 2 }) - .reduce_and() - { + .reduce_and(); + if !in_bounds { return None; }