Fix clippy warnings, part 1.

There aer still a bunch of type too complex and
function takes too many arguments warnings that I'll fix later
(or ignore, since in the one case I did fix a function takes too
many arguments warning I think it made the code *less* readable).
This commit is contained in:
Joshua Yanovski 2020-08-02 20:41:51 +02:00
parent ba54307540
commit a428a3ebba
20 changed files with 280 additions and 281 deletions

View File

@ -316,7 +316,7 @@ impl Client {
// Should not fail if the dimensions are correct. // Should not fail if the dimensions are correct.
let map = let map =
image::ImageBuffer::from_raw(u32::from(map_size.x), u32::from(map_size.y), raw); 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 // Flip the image, since Voxygen uses an orientation where rotation from
// positive x axis to positive y axis is counterclockwise around the z axis. // positive x axis to positive y axis is counterclockwise around the z axis.

View File

@ -142,6 +142,12 @@ pub const MAX_WORLD_BLOCKS_LG: Vec2<u32> = Vec2 { x: 19, y: 19 };
pub struct MapSizeLg(Vec2<u32>); pub struct MapSizeLg(Vec2<u32>);
impl MapSizeLg { 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 /// Construct a new `MapSizeLg`, returning an error if the needed invariants
/// do not hold and the vector otherwise. /// 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 // accurate (though I'm not sure if it can matter for these
// purposes). // purposes).
chunk_idx chunk_idx
.map(|chunk_idx| neighbors(map_size_lg, chunk_idx).chain(iter::once(chunk_idx)))
.into_iter() .into_iter()
.flatten() .flat_map(|chunk_idx| {
neighbors(map_size_lg, chunk_idx).chain(iter::once(chunk_idx))
})
.for_each(|neighbor_posi| { .for_each(|neighbor_posi| {
let neighbor_pos = uniform_idx_as_vec2(map_size_lg, 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 neighbor_wpos = neighbor_pos.map(|e| e as f64) * chunk_size;
let MapSample { connections, .. } = sample_pos(neighbor_pos); let MapSample { connections, .. } = sample_pos(neighbor_pos);
NEIGHBOR_DELTA NEIGHBOR_DELTA
.iter() .iter()
.zip( .zip(connections.iter().flatten())
connections
.as_ref()
.map(|e| e.iter())
.into_iter()
.flatten()
.into_iter(),
)
.for_each(|(&delta, connection)| { .for_each(|(&delta, connection)| {
let connection = if let Some(connection) = connection { let connection = if let Some(connection) = connection {
connection connection

View File

@ -2185,7 +2185,6 @@ impl<'a> Widget for SettingsWindow<'a> {
events.push(Event::ChangeRenderMode(RenderMode { events.push(Event::ChangeRenderMode(RenderMode {
shadow: ShadowMode::Map(ShadowMapMode { shadow: ShadowMode::Map(ShadowMapMode {
resolution: 2.0f32.powf(f32::from(new_val) / 4.0), resolution: 2.0f32.powf(f32::from(new_val) / 4.0),
..shadow_map_mode
}), }),
..render_mode ..render_mode
})); }));

View File

@ -3,6 +3,77 @@ use vek::*;
type TerrainVertex = <TerrainPipeline as render::Pipeline>::Vertex; type TerrainVertex = <TerrainPipeline as render::Pipeline>::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<D, FL, FC, FO, FS, FP> {
pub data: D,
/// The minimum position to mesh, in the coordinate system used
/// for queries against the volume.
pub draw_delta: Vec3<i32>,
/// 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<usize>,
/// 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<usize>,
/// 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. /// A suspended greedy mesh, with enough information to recover color data.
/// ///
/// The reason this exists is that greedy meshing is split into two parts. /// 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> { 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 { pub fn new(max_size: guillotiere::Size) -> Self {
let min_max_dim = max_size.width.min(max_size.height); let min_max_dim = max_size.width.min(max_size.height);
assert!( assert!(
@ -55,45 +140,55 @@ impl<'a> GreedyMesh<'a> {
} }
} }
pub fn push</* S: render::Pipeline, *//*O: render::Pipeline, */ M: PartialEq, D: 'a>( /// 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, &mut self,
data: D, config: GreedyConfig<D, FL, FC, FO, FS, FP>,
draw_delta: Vec3<i32>, ) -> Aabb<u16>
greedy_size: Vec3<usize>, where
greedy_size_cross: Vec3<usize>, FL: for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a,
get_light: impl for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a, FC: for<'r> FnMut(&'r mut D, Vec3<i32>) -> Rgb<u8> + 'a,
get_color: impl for<'r> FnMut(&'r mut D, Vec3<i32>) -> Rgb<u8> + 'a, FO: for<'r> FnMut(&'r mut D, Vec3<i32>) -> bool + 'a,
get_opacity: impl for<'r> FnMut(&'r mut D, Vec3<i32>) -> bool + 'a, FS: for<'r> FnMut(&'r mut D, Vec3<i32>, Vec3<i32>, Vec2<Vec3<i32>>) -> Option<(bool, M)>,
should_draw: impl for<'r> FnMut( FP: FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
&'r mut D, {
Vec3<i32>,
Vec3<i32>,
Vec2<Vec3<i32>>,
) -> Option<(bool, M)>,
// create_shadow: impl for<'r> Fn(Vec3<f32>, Vec3<f32>, &'r M) -> S::Vertex,
// create_opaque: impl for<'r> Fn(Vec2<u16>, Vec3<f32>, Vec3<f32>, &'r M) -> O::Vertex,
push_quad: impl FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
) -> Aabb<u16> {
let (bounds, /* opaque, *//*shadow, */ cont) = greedy_mesh( let (bounds, /* opaque, *//*shadow, */ cont) = greedy_mesh(
&mut self.atlas, &mut self.atlas,
&mut self.col_lights_size, &mut self.col_lights_size,
self.max_size, self.max_size,
data, config,
draw_delta,
greedy_size,
greedy_size_cross,
get_light,
get_color,
get_opacity,
should_draw,
// create_shadow,
// create_opaque,
push_quad,
); );
self.suspended.push(cont); self.suspended.push(cont);
bounds 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 { pub fn finalize(self) -> ColLightInfo {
let cur_size = self.col_lights_size; 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)]; 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 } pub fn max_size(&self) -> guillotiere::Size { self.max_size }
} }
/// Perform greedy meshing on a model, separately producing "pure" model data fn greedy_mesh<'a, M: PartialEq, D: 'a, FL, FC, FO, FS, FP>(
/// (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,
>(
atlas: &mut guillotiere::SimpleAtlasAllocator, atlas: &mut guillotiere::SimpleAtlasAllocator,
col_lights_size: &mut Vec2<u16>, col_lights_size: &mut Vec2<u16>,
max_size: guillotiere::Size, max_size: guillotiere::Size,
mut data: D, GreedyConfig {
draw_delta: Vec3<i32>, mut data,
greedy_size: Vec3<usize>, draw_delta,
greedy_size_cross: Vec3<usize>, greedy_size,
get_light: impl for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a, greedy_size_cross,
get_color: impl for<'r> FnMut(&'r mut D, Vec3<i32>) -> Rgb<u8> + 'a, get_light,
get_opacity: impl for<'r> FnMut(&'r mut D, Vec3<i32>) -> bool + 'a, get_color,
mut should_draw: impl for<'r> FnMut( get_opacity,
&'r mut D, mut should_draw,
Vec3<i32>, mut push_quad,
Vec3<i32>, }: GreedyConfig<D, FL, FC, FO, FS, FP>,
Vec2<Vec3<i32>>,
) -> Option<(bool, M)>,
// create_shadow: impl Fn(Vec3<f32>, Vec3<f32>, &M) -> S::Vertex,
// create_opaque: impl Fn(Vec2<u16>, Vec3<f32>, Vec3<f32>, &M) -> O::Vertex,
mut push_quad: impl FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
) -> ( ) -> (
Aabb<u16>, Aabb<u16>,
// Mesh<O>, // Mesh<O>,
// Mesh<S>, // Mesh<S>,
Box<SuspendedMesh<'a>>, Box<SuspendedMesh<'a>>,
) { )
where
FL: for<'r> FnMut(&'r mut D, Vec3<i32>) -> f32 + 'a,
FC: for<'r> FnMut(&'r mut D, Vec3<i32>) -> Rgb<u8> + 'a,
FO: for<'r> FnMut(&'r mut D, Vec3<i32>) -> bool + 'a,
FS: for<'r> FnMut(&'r mut D, Vec3<i32>, Vec3<i32>, Vec2<Vec3<i32>>) -> Option<(bool, M)>,
FP: FnMut(Vec2<u16>, Vec2<Vec2<u16>>, Vec3<f32>, Vec2<Vec3<f32>>, Vec3<f32>, &M),
{
// let mut opaque_mesh = Mesh::new(); // let mut opaque_mesh = Mesh::new();
// let mut shadow_mesh = Mesh::new(); // let mut shadow_mesh = Mesh::new();

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
mesh::{ mesh::{
greedy::{self, GreedyMesh}, greedy::{self, GreedyConfig, GreedyMesh},
Meshable, Meshable,
}, },
render::{self, FigurePipeline, Mesh, ShadowPipeline, SpritePipeline, TerrainPipeline}, render::{self, FigurePipeline, Mesh, ShadowPipeline, SpritePipeline, TerrainPipeline},
@ -77,30 +77,32 @@ where
vol.get(vox).map(|vox| *vox).unwrap_or(Vox::empty()) 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) TerrainVertex::new_figure(atlas_pos, (pos + offs) * scale, norm, 0)
}; };
let mut opaque_mesh = Mesh::new(); let mut opaque_mesh = Mesh::new();
let bounds = greedy.push( let bounds = greedy.push(
self, GreedyConfig {
draw_delta, data: self,
greedy_size, draw_delta,
greedy_size_cross, greedy_size,
get_light, greedy_size_cross,
get_color, get_light,
get_opacity, get_color,
should_draw, get_opacity,
|atlas_origin, dim, origin, draw_dim, norm, meta| { should_draw,
opaque_mesh.push_quad(greedy::create_quad( push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &()| {
atlas_origin, opaque_mesh.push_quad(greedy::create_quad(
dim, atlas_origin,
origin, dim,
draw_dim, origin,
norm, draw_dim,
meta, norm,
|atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), meta,
)); |atlas_pos, pos, norm, &_meta| create_opaque(atlas_pos, pos, norm),
));
},
}, },
); );
let bounds = bounds.map(f32::from); let bounds = bounds.map(f32::from);
@ -194,24 +196,26 @@ where
let mut opaque_mesh = Mesh::new(); let mut opaque_mesh = Mesh::new();
let _bounds = greedy.push( let _bounds = greedy.push(
self, GreedyConfig {
draw_delta, data: self,
greedy_size, draw_delta,
greedy_size_cross, greedy_size,
get_light, greedy_size_cross,
get_color, get_light,
get_opacity, get_color,
should_draw, get_opacity,
|atlas_origin, dim, origin, draw_dim, norm, meta| { should_draw,
opaque_mesh.push_quad(greedy::create_quad( push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &bool| {
atlas_origin, opaque_mesh.push_quad(greedy::create_quad(
dim, atlas_origin,
origin, dim,
draw_dim, origin,
norm, draw_dim,
meta, norm,
|atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), meta,
)); |atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta),
));
},
}, },
); );

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
mesh::{ mesh::{
greedy::{self, GreedyMesh}, greedy::{self, GreedyConfig, GreedyMesh},
Meshable, Meshable,
}, },
render::{self, ColLightInfo, FluidPipeline, Mesh, ShadowPipeline, TerrainPipeline}, render::{self, ColLightInfo, FluidPipeline, Mesh, ShadowPipeline, TerrainPipeline},
@ -503,8 +503,9 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
let get_color = let get_color =
|_: &mut (), pos: Vec3<i32>| flat_get(pos).get_color().unwrap_or(Rgb::zero()); |_: &mut (), pos: Vec3<i32>| flat_get(pos).get_color().unwrap_or(Rgb::zero());
let get_opacity = |_: &mut (), pos: Vec3<i32>| !flat_get(pos).is_opaque(); let get_opacity = |_: &mut (), pos: Vec3<i32>| !flat_get(pos).is_opaque();
let flat_get = |pos| flat_get(pos);
let should_draw = |_: &mut (), pos: Vec3<i32>, delta: Vec3<i32>, _uv| { let should_draw = |_: &mut (), pos: Vec3<i32>, delta: Vec3<i32>, _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. // 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, // let create_shadow = |pos, norm, meta| ShadowVertex::new(pos + Vec3::new(0.0,
@ -513,45 +514,44 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug>
let create_opaque = |atlas_pos, pos, norm, meta| { let create_opaque = |atlas_pos, pos, norm, meta| {
TerrainVertex::new(atlas_pos, pos + mesh_delta, norm, meta) TerrainVertex::new(atlas_pos, pos + mesh_delta, norm, meta)
}; };
let create_transparent = let create_transparent = |_atlas_pos, pos, norm| FluidVertex::new(pos + mesh_delta, norm);
|_atlas_pos, pos, norm, _meta| FluidVertex::new(pos + mesh_delta, norm);
let mut greedy = GreedyMesh::new(max_size); let mut greedy = GreedyMesh::new(max_size);
let mut opaque_mesh = Mesh::new(); let mut opaque_mesh = Mesh::new();
let mut fluid_mesh = Mesh::new(); let mut fluid_mesh = Mesh::new();
let bounds = greedy.push( let bounds = greedy.push(
(), GreedyConfig {
draw_delta, data: (),
greedy_size, draw_delta,
greedy_size_cross, greedy_size,
get_light, greedy_size_cross,
get_color, get_light,
get_opacity, get_color,
should_draw, get_opacity,
|atlas_origin, dim, origin, draw_dim, norm, meta| match meta { should_draw,
FaceKind::Opaque(meta) => { push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &FaceKind| match meta {
opaque_mesh.push_quad(greedy::create_quad( FaceKind::Opaque(meta) => {
atlas_origin, opaque_mesh.push_quad(greedy::create_quad(
dim, atlas_origin,
origin, dim,
draw_dim, origin,
norm, draw_dim,
meta, norm,
|atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta), meta,
)); |atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta),
}, ));
FaceKind::Fluid => { },
fluid_mesh.push_quad(greedy::create_quad( FaceKind::Fluid => {
atlas_origin, fluid_mesh.push_quad(greedy::create_quad(
dim, atlas_origin,
origin, dim,
draw_dim, origin,
norm, draw_dim,
&(), norm,
|atlas_pos, pos, norm, &meta| { &(),
create_transparent(atlas_pos, pos, norm, meta) |atlas_pos, pos, norm, &_meta| create_transparent(atlas_pos, pos, norm),
}, ));
)); },
}, },
}, },
); );

View File

@ -128,7 +128,7 @@ impl<P: Pipeline> Quad<P> {
let verts = [self.a, self.b, self.c, self.d]; let verts = [self.a, self.b, self.c, self.d];
Self { Self {
a: verts[(0 + n) % 4].clone(), a: verts[n % 4].clone(),
b: verts[(1 + n) % 4].clone(), b: verts[(1 + n) % 4].clone(),
c: verts[(2 + n) % 4].clone(), c: verts[(2 + n) % 4].clone(),
d: verts[(3 + n) % 4].clone(), d: verts[(3 + n) % 4].clone(),

View File

@ -163,7 +163,7 @@ impl FigureModel {
// in order to store the bone index. The two bits are instead taken out // 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 // of the atlas coordinates, which is why we "only" allow 1 << 15 per
// coordinate instead of 1 << 16. // 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) GreedyMesh::new(max_size)
} }
} }

View File

@ -84,8 +84,10 @@ impl Vertex {
if norm.x < 0.0 { 0 } else { 1 } if norm.x < 0.0 { 0 } else { 1 }
} else if norm.y != 0.0 { } else if norm.y != 0.0 {
if norm.y < 0.0 { 2 } else { 3 } if norm.y < 0.0 { 2 } else { 3 }
} else if norm.z < 0.0 {
4
} else { } else {
if norm.z < 0.0 { 4 } else { 5 } 5
}; };
// let ao = 0xFFu32; // let ao = 0xFFu32;
// let light = 0xFFu32; // let light = 0xFFu32;

View File

@ -82,10 +82,7 @@ impl fmt::Display for Vertex {
.field("pos", &Vec3::<f32>::from(self.pos)) .field("pos", &Vec3::<f32>::from(self.pos))
.field( .field(
"atlas_pos", "atlas_pos",
&Vec2::new( &Vec2::new(self.atlas_pos & 0xFFFF, (self.atlas_pos >> 16) & 0xFFFF),
(self.atlas_pos >> 0) & 0xFFFF,
(self.atlas_pos >> 16) & 0xFFFF,
),
) )
.field("norm_ao", &self.norm_ao) .field("norm_ao", &self.norm_ao)
.finish() .finish()

View File

@ -58,8 +58,10 @@ impl Vertex {
if norm.x < 0.0 { 0 } else { 1 } if norm.x < 0.0 { 0 } else { 1 }
} else if norm.y != 0.0 { } else if norm.y != 0.0 {
if norm.y < 0.0 { 2 } else { 3 } if norm.y < 0.0 { 2 } else { 3 }
} else if norm.z < 0.0 {
4
} else { } else {
if norm.z < 0.0 { 4 } else { 5 } 5
}; };
Self { Self {
pos_norm: 0 pos_norm: 0

View File

@ -166,7 +166,7 @@ impl Renderer {
let shadow_views = Self::create_shadow_views( let shadow_views = Self::create_shadow_views(
&mut factory, &mut factory,
(dims.0, dims.1), (dims.0, dims.1),
&ShadowMapMode::try_from(mode.shadow).unwrap_or(ShadowMapMode::default()), &ShadowMapMode::try_from(mode.shadow).unwrap_or_default(),
) )
.map_err(|err| { .map_err(|err| {
warn!("Could not create shadow map views: {:?}", err); warn!("Could not create shadow map views: {:?}", err);
@ -1192,7 +1192,6 @@ impl Renderer {
_alt: &Texture<LodAltFmt>, _alt: &Texture<LodAltFmt>,
_horizon: &Texture<LodTextureFmt>, _horizon: &Texture<LodTextureFmt>,
) { ) {
return;
/* let (point_shadow_maps, directed_shadow_maps) = /* let (point_shadow_maps, directed_shadow_maps) =
if let Some(shadow_map) = &mut self.shadow_map { if let Some(shadow_map) = &mut self.shadow_map {
( (
@ -2222,7 +2221,7 @@ fn create_shadow_pipeline<P: gfx::pso::PipelineInit>(
factory.create_shader_set(vs.as_bytes(), fs.as_bytes())? factory.create_shader_set(vs.as_bytes(), fs.as_bytes())?
}; };
let result = Ok(GfxPipeline { Ok(GfxPipeline {
pso: factory.create_pipeline_state( pso: factory.create_pipeline_state(
&shader_set, &shader_set,
gfx::Primitive::TriangleList, gfx::Primitive::TriangleList,
@ -2242,7 +2241,5 @@ fn create_shadow_pipeline<P: gfx::pso::PipelineInit>(
}, },
pipe, pipe,
)?, )?,
}); })
result
} }

View File

@ -59,7 +59,8 @@ where
filter_method.unwrap_or(gfx::texture::FilterMethod::Scale), filter_method.unwrap_or(gfx::texture::FilterMethod::Scale),
wrap_mode.unwrap_or(gfx::texture::WrapMode::Clamp), 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 { Ok(Self {
tex, tex,
srv, srv,

View File

@ -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.character_states.retain(|k, v| f(k, &mut *v));
self.quadruped_small_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)); self.quadruped_medium_states.retain(|k, v| f(k, &mut *v));

View File

@ -53,7 +53,7 @@ pub fn mat_mul_points<T: Float + MulAdd<T, T, Output = T>>(
pts: &mut [Vec3<T>], pts: &mut [Vec3<T>],
mut do_p: impl FnMut(Vec4<T>) -> Vec3<T>, mut do_p: impl FnMut(Vec4<T>) -> Vec3<T>,
) { ) {
pts.into_iter().for_each(|p| { pts.iter_mut().for_each(|p| {
*p = do_p(mat * Vec4::from_point(*p)); *p = do_p(mat * Vec4::from_point(*p));
}); });
} }
@ -480,12 +480,10 @@ pub fn clip_test<T: Float + core::fmt::Debug>(p: T, q: T, (u1, u2): (T, T)) -> O
} else { } else {
Some((if r > u1 { r } else { u1 }, u2)) Some((if r > u1 { r } else { u1 }, u2))
} }
} else if r < u1 {
None
} else { } else {
if r < u1 { Some((u1, if r < u2 { r } else { u2 }))
None
} else {
Some((u1, if r < u2 { r } else { u2 }))
}
} }
} /*; } /*;
// println!("clip_test@(p={:?}, q={:?}, (u1, u2)=({:?}. {:?})): // println!("clip_test@(p={:?}, q={:?}, (u1, u2)=({:?}. {:?})):

View File

@ -1195,19 +1195,19 @@ impl Scene {
let w_p: math::Mat4<f32> = { let w_p: math::Mat4<f32> = {
if /*sin_gamma > EPISLON_GAMMA*/factor > EPSILON_UPSILON { if /*sin_gamma > EPISLON_GAMMA*/factor > EPSILON_UPSILON {
// Projection for y // Projection for y
let n = directed_near;// - near_dist; let near = directed_near;// - near_dist;
let f = directed_far; let far = directed_far;
let l = -1.0;// bounds0.min.x;//-1.0;// bounds0.min.x - light_focus_pos.x; let left = -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 right = 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 bottom = -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 top = 1.0;// bounds0.min.z;// bounds0.min.z - light_focus_pos.z;
let s_x = 2.0 * n / (r - l); let s_x = 2.0 * near / (right - left);
let o_x = (r + l) / (r - l); let o_x = (right + left) / (right - left);
let s_z = 2.0 * n / (t - b); let s_z = 2.0 * near / (top - bottom);
let o_z = (t + b) / (t - b); let o_z = (top + bottom) / (top - bottom);
let s_y = (f + n) / (f - n); let s_y = (far + near) / (far - near);
let o_y = -2.0 * f * n / (f - n); let o_y = -2.0 * far * near / (far - near);
// y(y₀) = s_y y₀ + o_y // y(y₀) = s_y y₀ + o_y
// = ((f + n)y₀ - 2fn) / (f - n) // = ((f + n)y₀ - 2fn) / (f - n)
// y(f) = s_y f + o_y // y(f) = s_y f + o_y
@ -1337,22 +1337,12 @@ impl Scene {
let o_x = -(xmax + xmin) / (xmax - xmin); let o_x = -(xmax + xmin) / (xmax - xmin);
let o_y = -(ymax + ymin) / (ymax - ymin); let o_y = -(ymax + ymin) / (ymax - ymin);
let o_z = -(zmax + zmin) / (zmax - zmin); let o_z = -(zmax + zmin) / (zmax - zmin);
let directed_proj_mat = if /*sin_gamma > EPISLON_GAMMA*/factor > EPSILON_UPSILON { let directed_proj_mat = Mat4::new(
// Mat4::identity() s_x, 0.0, 0.0, o_x,
Mat4::new( 0.0, s_y, 0.0, o_y,
s_x, 0.0, 0.0, o_x, 0.0, 0.0, s_z, o_z,
0.0, s_y, 0.0, o_y, 0.0, 0.0, 0.0, 1.0,
0.0, 0.0, /*-*/s_z, /*-*/o_z, )/*.scaled_3d(Vec3::new(1.0, 1.0, -1.0))*//* * w_p * w_v*//* * l_r*/;//Mat4::identity();
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();
// println!("proj_mat: {:?}", directed_proj_mat); // println!("proj_mat: {:?}", directed_proj_mat);
// println!("all_mat: {:?}", directed_proj_mat * view_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::<Vec<_>>(); // let _w_p_arr = directed_proj_mat.cols.iter().map(|e| (e.x, e.y, e.z, e.w)).collect::<Vec<_>>();

View File

@ -525,6 +525,7 @@ impl<V: RectRasterableVol> Terrain<V> {
let mut make_models = |(kind, variation), s, offset, lod_axes: Vec3<f32>| { let mut make_models = |(kind, variation), s, offset, lod_axes: Vec3<f32>| {
let scaled = [1.0, 0.8, 0.6, 0.4, 0.2]; let scaled = [1.0, 0.8, 0.6, 0.4, 0.2];
let model = assets::load_expect::<DotVoxData>(s); let model = assets::load_expect::<DotVoxData>(s);
let zero = Vec3::zero();
let model_size = model let model_size = model
.models .models
.first() .first()
@ -534,7 +535,7 @@ impl<V: RectRasterableVol> Terrain<V> {
.. ..
}| Vec3::new(x, y, z), }| 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 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 model_scale = max_model_size.map2(model_size, |max_sz: f32, cur_sz| {
let scale = max_sz / max_sz.max(cur_sz as f32); let scale = max_sz / max_sz.max(cur_sz as f32);
@ -2663,7 +2664,7 @@ impl<V: RectRasterableVol> Terrain<V> {
// store it. Only pull out one chunk per frame to avoid an unacceptable // 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 // amount of blocking lag due to the GPU upload. That still gives us a
// 60 chunks / second budget to play with. // 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) { match self.mesh_todo.get(&response.pos) {
// It's the mesh we want, insert the newly finished model into the terrain model // 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). // data structure (convert the mesh to a model first of course).

View File

@ -6,7 +6,8 @@
const_if_match, const_if_match,
const_generics, const_generics,
const_panic, const_panic,
label_break_value label_break_value,
or_patterns
)] )]
mod all; mod all;

View File

@ -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) 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, 0,
((g_water - water_depth * g_water) * 1.0) as u8, ((g_water - water_depth * g_water) * 1.0) as u8,
((b_water - water_depth * b_water) * 1.0) as u8, ((b_water - water_depth * b_water) * 1.0) as u8,

View File

@ -1440,7 +1440,7 @@ impl WorldSim {
/* let z_cache = block_gen.get_z_cache(wpos); /* 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(z_cache.get_z_limits(&mut block_gen).2); */
sample.alt = alt.max(BlockGen::get_cliff_height( sample.alt = alt.max(BlockGen::get_cliff_height(
&mut block_gen.column_gen, &block_gen.column_gen,
&mut block_gen.column_cache, &mut block_gen.column_cache,
wpos.map(|e| e as f32), wpos.map(|e| e as f32),
&sample.close_cliffs, &sample.close_cliffs,
@ -1719,12 +1719,12 @@ impl WorldSim {
} }
pub fn get_base_z(&self, chunk_pos: Vec2<i32>) -> Option<f32> { pub fn get_base_z(&self, chunk_pos: Vec2<i32>) -> Option<f32> {
if !chunk_pos let in_bounds = chunk_pos
.map2(self.map_size_lg().chunks(), |e, sz| { .map2(self.map_size_lg().chunks(), |e, sz| {
e > 0 && e < sz as i32 - 2 e > 0 && e < sz as i32 - 2
}) })
.reduce_and() .reduce_and();
{ if !in_bounds {
return None; return None;
} }