mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Improve figure meshing.
This commit is contained in:
parent
053941e16a
commit
ae77c1814c
@ -25,6 +25,12 @@ impl CellData {
|
||||
}
|
||||
|
||||
pub fn is_hollow(&self) -> bool { self.attr.get() & HOLLOW != 0 }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_glowy(&self) -> bool { self.attr.get() & GLOWY != 0 }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_shiny(&self) -> bool { self.attr.get() & SHINY != 0 }
|
||||
}
|
||||
|
||||
impl Default for CellData {
|
||||
@ -73,8 +79,10 @@ impl Cell {
|
||||
}
|
||||
|
||||
impl Vox for Cell {
|
||||
#[inline(always)]
|
||||
fn empty() -> Self { Cell::Empty }
|
||||
|
||||
#[inline(always)]
|
||||
fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
Cell::Filled(_) => false,
|
||||
|
@ -160,13 +160,13 @@ pub struct ColumnAccess;
|
||||
|
||||
impl Access for ColumnAccess {
|
||||
fn idx(pos: Vec3<i32>, sz: Vec3<u32>) -> usize {
|
||||
(pos.x * sz.y as i32 * sz.z as i32 + pos.y * sz.z as i32 + pos.z) as usize
|
||||
((pos.z * sz.y as i32 + pos.y) * sz.x as i32 + pos.x) as usize
|
||||
}
|
||||
|
||||
fn pos(idx: usize, sz: Vec3<u32>) -> Vec3<i32> {
|
||||
let z = idx as u32 % sz.z;
|
||||
let y = (idx as u32 / sz.z) % sz.y;
|
||||
let x = idx as u32 / (sz.y * sz.z);
|
||||
let x = idx as u32 % sz.x;
|
||||
let y = (idx as u32 / sz.x) % sz.y;
|
||||
let z = idx as u32 / (sz.y * sz.x);
|
||||
Vec3::new(x, y, z).map(|e| e as i32)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#![deny(unsafe_code)]
|
||||
#![feature(bool_to_option)]
|
||||
#![recursion_limit = "2048"]
|
||||
|
||||
#[cfg(all(
|
||||
|
@ -49,46 +49,89 @@ where
|
||||
assert!(greedy_size.x <= 512 && greedy_size.y <= 512 && greedy_size.z <= 512);
|
||||
// NOTE: Cast to usize is safe because of previous check, since all values fit
|
||||
// into u16 which is safe to cast to usize.
|
||||
|
||||
let (flat, flat_get) = {
|
||||
let (w_, h_, d_) = greedy_size.into_tuple();
|
||||
let (w, h, d) = (w_ + 2, h_ + 2, d_ + 2);
|
||||
let wh = w * h;
|
||||
let flat = {
|
||||
let mut flat_ = vec![Cell::empty(); (d * wh) as usize];
|
||||
let flat = &mut flat_[0..(d * wh) as usize];
|
||||
// NOTE: We can skip the outside edges because we know they're already empty.
|
||||
flat.chunks_exact_mut(wh as usize).skip(1).take(d_ as usize).enumerate().for_each(|(z, flat)| {
|
||||
let z = z as i32;
|
||||
flat.chunks_exact_mut(w as usize).skip(1).take(h_ as usize).enumerate().for_each(|(y, flat)| {
|
||||
let y = y as i32;
|
||||
flat.into_iter().skip(1).take(w_ as usize).enumerate().for_each(|(x, flat)| {
|
||||
let x = x as i32;
|
||||
*flat = vol.get(Vec3::new(x, y, z)).copied().unwrap_or_else(|_| Cell::empty());
|
||||
});
|
||||
});
|
||||
});
|
||||
/* for z in -1..greedy_size.z + 1 {
|
||||
for y in -1..greedy_size.y + 1 {
|
||||
for x in -1..greedy_size.x + 1 {
|
||||
let wpos = lower_bound + Vec3::new(x, y, z);
|
||||
let block = vol.get(wpos).map(|b| *b).unwrap_or_else(|_| Cell::empty());
|
||||
flat[i] = block;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
} */
|
||||
flat_
|
||||
};
|
||||
|
||||
let wh = w * h;
|
||||
// let offset = wh + w + 1;
|
||||
let flat_get = #[inline(always)] move |flat: &Vec<Cell>, Vec3 { x, y, z }| /* match flat
|
||||
.get((x * hd + y * d + z) as usize)
|
||||
.copied()
|
||||
{
|
||||
Some(b) => b,
|
||||
None => panic!("x {} y {} z {} d {} h {}", x, y, z, d, h),
|
||||
}*/flat[(/*offset + */z * wh + y * w + x) as usize];
|
||||
|
||||
(flat, flat_get)
|
||||
};
|
||||
|
||||
let greedy_size = greedy_size.as_::<usize>();
|
||||
let greedy_size_cross = greedy_size;
|
||||
let draw_delta = lower_bound;
|
||||
let draw_delta = lower_bound + 1;
|
||||
|
||||
let get_light = |vol: &mut V, pos: Vec3<i32>| {
|
||||
if vol.get(pos).map(|vox| vox.is_empty()).unwrap_or(true) {
|
||||
let get_light = #[inline(always)] move |flat: &mut _, pos: Vec3<i32>| {
|
||||
if flat_get(flat, pos).is_empty() {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
};
|
||||
let get_glow = |_vol: &mut V, _pos: Vec3<i32>| 0.0;
|
||||
let get_opacity = |vol: &mut V, pos: Vec3<i32>| vol.get(pos).map_or(true, |vox| vox.is_empty());
|
||||
let should_draw = |vol: &mut V, pos: Vec3<i32>, from: Cell, to: Cell, /*delta: Vec3<i32>, */uv| {
|
||||
let get_glow = #[inline(always)] |_flat: &mut _, _pos: Vec3<i32>| 0.0;
|
||||
let get_opacity = #[inline(always)] move |flat: &mut _, pos: Vec3<i32>| flat_get(flat, pos).is_empty();
|
||||
let should_draw = #[inline(always)] |_flat: &mut _, pos: Vec3<i32>, from: Cell, to: Cell, /*delta: Vec3<i32>, */uv| {
|
||||
should_draw_greedy(pos, from, to,/* delta, */uv/*, |vox| {
|
||||
vol.get(vox)
|
||||
.map(|vox| *vox)
|
||||
.unwrap_or_else(|_| Cell::empty())
|
||||
} */)
|
||||
};
|
||||
let create_opaque = |atlas_pos, pos, norm| {
|
||||
let create_opaque = #[inline(always)] |atlas_pos, pos, norm| {
|
||||
TerrainVertex::new_figure(atlas_pos, (pos + offs) * scale, norm, bone_idx)
|
||||
};
|
||||
|
||||
greedy.push(GreedyConfig {
|
||||
data: vol,
|
||||
data: flat,
|
||||
draw_delta,
|
||||
greedy_size,
|
||||
greedy_size_cross,
|
||||
get_vox: |vol: &mut V, vox| {
|
||||
vol.get(vox)
|
||||
.map(|vox| *vox)
|
||||
.unwrap_or_else(|_| Cell::empty())
|
||||
get_vox: #[inline(always)] move |flat: &mut _, vox| {
|
||||
flat_get(flat, vox)
|
||||
},
|
||||
get_ao: |_: &mut V, _: Vec3<i32>| 1.0,
|
||||
get_ao: #[inline(always)] |_: &mut _, _: Vec3<i32>| 1.0,
|
||||
get_light,
|
||||
get_glow,
|
||||
get_opacity,
|
||||
should_draw,
|
||||
push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &()| {
|
||||
push_quad: #[inline(always)] |atlas_origin, dim, origin, draw_dim, norm, meta: &()| {
|
||||
opaque_mesh.push_quad(greedy::create_quad(
|
||||
atlas_origin,
|
||||
dim,
|
||||
@ -99,14 +142,14 @@ where
|
||||
|atlas_pos, pos, norm, &_meta| create_opaque(atlas_pos, pos, norm),
|
||||
));
|
||||
},
|
||||
make_face_texel: |vol: &mut V, pos, light, _, _| {
|
||||
let cell = vol.get(pos).ok();
|
||||
let (glowy, shiny) = cell
|
||||
.map(|c| (c.is_glowy(), c.is_shiny()))
|
||||
.unwrap_or_default();
|
||||
let col = cell
|
||||
.and_then(|vox| vox.get_color())
|
||||
.unwrap_or_else(Rgb::zero);
|
||||
make_face_texel: #[inline(always)] move |flat: &mut _, pos, light, _, _| {
|
||||
let cell = match flat_get(flat, pos) {
|
||||
Cell::Filled(c) => c,
|
||||
_ => unreachable!("Face texels cannot be empty"),
|
||||
};
|
||||
let glowy = cell.is_glowy();
|
||||
let shiny = cell.is_shiny();
|
||||
let col = cell.col;
|
||||
TerrainVertex::make_col_light_figure(light, glowy, shiny, col)
|
||||
},
|
||||
});
|
||||
@ -162,30 +205,44 @@ where
|
||||
);
|
||||
|
||||
let (flat, flat_get) = {
|
||||
let (w, h, d) = (greedy_size + 2).into_tuple();
|
||||
let (w_, h_, d_) = greedy_size.into_tuple();
|
||||
let (w, h, d) = (w_ + 2, h_ + 2, d_ + 2);
|
||||
let wh = w * h;
|
||||
let flat = {
|
||||
let mut flat = vec![Cell::empty(); (w * h * d) as usize];
|
||||
let mut i = 0;
|
||||
for x in -1..greedy_size.x + 1 {
|
||||
let mut flat_ = vec![Cell::empty(); (d * wh) as usize];
|
||||
let flat = &mut flat_[0..(d * wh) as usize];
|
||||
// NOTE: We can skip the outside edges because we know they're already empty.
|
||||
flat.chunks_exact_mut(wh as usize).skip(1).take(d_ as usize).enumerate().for_each(|(z, flat)| {
|
||||
let z = z as i32;
|
||||
flat.chunks_exact_mut(w as usize).skip(1).take(h_ as usize).enumerate().for_each(|(y, flat)| {
|
||||
let y = y as i32;
|
||||
flat.into_iter().skip(1).take(w_ as usize).enumerate().for_each(|(x, flat)| {
|
||||
let x = x as i32;
|
||||
*flat = vol.get(Vec3::new(x, y, z)).copied().unwrap_or_else(|_| Cell::empty());
|
||||
});
|
||||
});
|
||||
});
|
||||
/* for z in -1..greedy_size.z + 1 {
|
||||
for y in -1..greedy_size.y + 1 {
|
||||
for z in -1..greedy_size.z + 1 {
|
||||
for x in -1..greedy_size.x + 1 {
|
||||
let wpos = lower_bound + Vec3::new(x, y, z);
|
||||
let block = vol.get(wpos).map(|b| *b).unwrap_or_else(|_| Cell::empty());
|
||||
flat[i] = block;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
flat
|
||||
} */
|
||||
flat_
|
||||
};
|
||||
|
||||
let flat_get = move |flat: &Vec<Cell>, Vec3 { x, y, z }| match flat
|
||||
.get((x * h * d + y * d + z) as usize)
|
||||
let wh = w * h;
|
||||
let flat_get = #[inline(always)] move |flat: &Vec<Cell>, Vec3 { x, y, z }| /* match flat
|
||||
.get((x * hd + y * d + z) as usize)
|
||||
.copied()
|
||||
{
|
||||
Some(b) => b,
|
||||
None => panic!("x {} y {} z {} d {} h {}", x, y, z, d, h),
|
||||
};
|
||||
}*/flat[(z * wh + y * w + x) as usize];
|
||||
|
||||
(flat, flat_get)
|
||||
};
|
||||
@ -197,25 +254,25 @@ where
|
||||
let greedy_size_cross = greedy_size;
|
||||
let draw_delta = Vec3::new(1, 1, 1);
|
||||
|
||||
let get_light = move |flat: &mut _, pos: Vec3<i32>| {
|
||||
let get_light = #[inline(always)] move |flat: &mut _, pos: Vec3<i32>| {
|
||||
if flat_get(flat, pos).is_empty() {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
};
|
||||
let get_glow = |_flat: &mut _, _pos: Vec3<i32>| 0.0;
|
||||
let get_color = move |flat: &mut _, pos: Vec3<i32>| {
|
||||
let get_glow = #[inline(always)] |_flat: &mut _, _pos: Vec3<i32>| 0.0;
|
||||
let get_color = #[inline(always)] move |flat: &mut _, pos: Vec3<i32>| {
|
||||
flat_get(flat, pos).get_color().unwrap_or_else(Rgb::zero)
|
||||
};
|
||||
let get_opacity = move |flat: &mut _, pos: Vec3<i32>| flat_get(flat, pos).is_empty();
|
||||
let should_draw = move |flat: &mut _, pos: Vec3<i32>, from: Cell, to: Cell, /*delta: Vec3<i32>, */uv| {
|
||||
let get_opacity = #[inline(always)] move |flat: &mut _, pos: Vec3<i32>| flat_get(flat, pos).is_empty();
|
||||
let should_draw = #[inline(always)] move |_flat: &mut _, pos: Vec3<i32>, from: Cell, to: Cell, /*delta: Vec3<i32>, */uv| {
|
||||
should_draw_greedy_ao(vertical_stripes, pos, from, to,/* delta, */uv/* , |vox| flat_get(flat, vox) */)
|
||||
};
|
||||
// NOTE: Fits in i16 (much lower actually) so f32 is no problem (and the final
|
||||
// position, pos + mesh_delta, is guaranteed to fit in an f32).
|
||||
let mesh_delta = lower_bound.as_::<f32>();
|
||||
let create_opaque = |atlas_pos, pos: Vec3<f32>, norm, _meta| {
|
||||
let create_opaque = #[inline(always)] |atlas_pos, pos: Vec3<f32>, norm, _meta| {
|
||||
SpriteVertex::new(atlas_pos, pos + mesh_delta, norm)
|
||||
};
|
||||
|
||||
@ -224,13 +281,13 @@ where
|
||||
draw_delta,
|
||||
greedy_size,
|
||||
greedy_size_cross,
|
||||
get_vox: move |flat: &mut _, vox| flat_get(flat, vox),
|
||||
get_ao: |_: &mut _, _: Vec3<i32>| 1.0,
|
||||
get_vox: #[inline(always)] move |flat: &mut _, vox| flat_get(flat, vox),
|
||||
get_ao: #[inline(always)] |_: &mut _, _: Vec3<i32>| 1.0,
|
||||
get_light,
|
||||
get_glow,
|
||||
get_opacity,
|
||||
should_draw,
|
||||
push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &bool| {
|
||||
push_quad: #[inline(always)] |atlas_origin, dim, origin, draw_dim, norm, meta: &bool| {
|
||||
opaque_mesh.push_quad(greedy::create_quad(
|
||||
atlas_origin,
|
||||
dim,
|
||||
@ -241,7 +298,7 @@ where
|
||||
|atlas_pos, pos, norm, &meta| create_opaque(atlas_pos, pos, norm, meta),
|
||||
));
|
||||
},
|
||||
make_face_texel: move |flat: &mut _, pos, light, glow, ao| {
|
||||
make_face_texel: #[inline(always)] move |flat: &mut _, pos, light, glow, ao| {
|
||||
TerrainVertex::make_col_light(light, glow, get_color(flat, pos), ao)
|
||||
},
|
||||
});
|
||||
@ -283,29 +340,29 @@ where
|
||||
let greedy_size_cross = greedy_size;
|
||||
let draw_delta = lower_bound;
|
||||
|
||||
let get_light = |vol: &mut V, pos: Vec3<i32>| {
|
||||
let get_light = #[inline(always)] |vol: &mut V, pos: Vec3<i32>| {
|
||||
if vol.get(pos).map(|vox| vox.is_empty()).unwrap_or(true) {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
};
|
||||
let get_glow = |_vol: &mut V, _pos: Vec3<i32>| 0.0;
|
||||
let get_color = |vol: &mut V, pos: Vec3<i32>| {
|
||||
let get_glow = #[inline(always)] |_vol: &mut V, _pos: Vec3<i32>| 0.0;
|
||||
let get_color = #[inline(always)] |vol: &mut V, pos: Vec3<i32>| {
|
||||
vol.get(pos)
|
||||
.ok()
|
||||
.and_then(|vox| vox.get_color())
|
||||
.unwrap_or_else(Rgb::zero)
|
||||
};
|
||||
let get_opacity = |vol: &mut V, pos: Vec3<i32>| vol.get(pos).map_or(true, |vox| vox.is_empty());
|
||||
let should_draw = |vol: &mut V, pos: Vec3<i32>, from: Cell, to: Cell, /*delta: Vec3<i32>, */uv| {
|
||||
let get_opacity = #[inline(always)] |vol: &mut V, pos: Vec3<i32>| vol.get(pos).map_or(true, |vox| vox.is_empty());
|
||||
let should_draw = #[inline(always)] |vol: &mut V, pos: Vec3<i32>, from: Cell, to: Cell, /*delta: Vec3<i32>, */uv| {
|
||||
should_draw_greedy(pos, from, to,/* delta, */uv/*, |vox| {
|
||||
vol.get(vox)
|
||||
.map(|vox| *vox)
|
||||
.unwrap_or_else(|_| Cell::empty())
|
||||
}*/)
|
||||
};
|
||||
let create_opaque = |_atlas_pos, pos: Vec3<f32>, norm| ParticleVertex::new(pos, norm);
|
||||
let create_opaque = #[inline(always)] |_atlas_pos, pos: Vec3<f32>, norm| ParticleVertex::new(pos, norm);
|
||||
|
||||
let mut opaque_mesh = Mesh::new();
|
||||
greedy.push(GreedyConfig {
|
||||
@ -313,17 +370,17 @@ where
|
||||
draw_delta,
|
||||
greedy_size,
|
||||
greedy_size_cross,
|
||||
get_vox: |vol: &mut V, vox| {
|
||||
get_vox: #[inline(always)] |vol: &mut V, vox| {
|
||||
vol.get(vox)
|
||||
.map(|vox| *vox)
|
||||
.unwrap_or_else(|_| Cell::empty())
|
||||
},
|
||||
get_ao: |_: &mut V, _: Vec3<i32>| 1.0,
|
||||
get_ao: #[inline(always)] |_: &mut V, _: Vec3<i32>| 1.0,
|
||||
get_light,
|
||||
get_glow,
|
||||
get_opacity,
|
||||
should_draw,
|
||||
push_quad: |atlas_origin, dim, origin, draw_dim, norm, meta: &()| {
|
||||
push_quad: #[inline(always)] |atlas_origin, dim, origin, draw_dim, norm, meta: &()| {
|
||||
opaque_mesh.push_quad(greedy::create_quad(
|
||||
atlas_origin,
|
||||
dim,
|
||||
@ -334,7 +391,7 @@ where
|
||||
|atlas_pos, pos, norm, &_meta| create_opaque(atlas_pos, pos, norm),
|
||||
));
|
||||
},
|
||||
make_face_texel: move |vol: &mut V, pos, light, glow, ao| {
|
||||
make_face_texel: #[inline(always)] move |vol: &mut V, pos, light, glow, ao| {
|
||||
TerrainVertex::make_col_light(light, glow, get_color(vol, pos), ao)
|
||||
},
|
||||
});
|
||||
|
@ -16,6 +16,7 @@ use common::{
|
||||
},
|
||||
vol::ReadVol,
|
||||
};
|
||||
use common_base::prof_span;
|
||||
use lazy_static::lazy_static;
|
||||
use probability::{
|
||||
prelude::{source, Gaussian, Inverse},
|
||||
@ -113,6 +114,7 @@ pub fn apply_trees_to(
|
||||
dynamic_rng: &mut impl Rng,
|
||||
/* calendar: Option<&Calendar>, */
|
||||
) {
|
||||
prof_span!("apply_trees_to");
|
||||
// TODO: Get rid of this
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
enum TreeModel {
|
||||
|
@ -16,6 +16,7 @@ use common::{
|
||||
},
|
||||
vol::ReadVol,
|
||||
};
|
||||
use common_base::prof_span;
|
||||
use fxhash::FxHasher64;
|
||||
use hashbrown::{/*hash_map::Entry, */HashMap};
|
||||
use noisy_float::types::n32;
|
||||
@ -2858,8 +2859,8 @@ impl Painter<'_> {
|
||||
let aabb = Self::get_bounds(cache, tree, prim);
|
||||
/*if !(aabb.size().w > 8 || aabb.size().h > 8 || aabb.size().d > 16) */{
|
||||
let mut do_segment = || {
|
||||
let distance = segment.end - segment.start;
|
||||
let distance_proj = distance / distance.magnitude_squared();
|
||||
let distance = segment.start - segment.end;
|
||||
let distance_proj = -distance / distance.magnitude_squared();
|
||||
let segment_start = segment.start - 0.5;
|
||||
if r0 == r1 {
|
||||
let radius_2 = r0 * r0;
|
||||
@ -2873,7 +2874,7 @@ impl Painter<'_> {
|
||||
let pos = pos.as_::<f32>();
|
||||
let length = pos - segment_start;
|
||||
let t = length.dot(distance_proj).clamped(0.0, 1.0);
|
||||
let diff = distance * t - length;
|
||||
let diff = distance * t + length;
|
||||
diff.magnitude_squared() < radius_2
|
||||
},
|
||||
hit,
|
||||
@ -2888,7 +2889,7 @@ impl Painter<'_> {
|
||||
let pos = pos.as_::<f32>();
|
||||
let length = pos - segment_start;
|
||||
let t = length.dot(distance_proj).clamped(0.0, 1.0);
|
||||
let mut diff = distance * t - length;
|
||||
let mut diff = distance * t + length;
|
||||
diff.z *= z_scale;
|
||||
diff.magnitude_squared() < radius_2
|
||||
},
|
||||
@ -2905,7 +2906,7 @@ impl Painter<'_> {
|
||||
let pos = pos.as_::<f32>();
|
||||
let length = pos - segment_start;
|
||||
let t = length.dot(distance_proj).clamped(0.0, 1.0);
|
||||
let diff = distance * t - length;
|
||||
let diff = distance * t + length;
|
||||
let radius = Lerp::lerp_unclamped(r0, r1, t);
|
||||
diff.magnitude_squared() < radius * radius
|
||||
},
|
||||
@ -2921,7 +2922,7 @@ impl Painter<'_> {
|
||||
let pos = pos.as_::<f32>();
|
||||
let length = pos - segment_start;
|
||||
let t = length.dot(distance_proj).clamped(0.0, 1.0);
|
||||
let mut diff = distance * t - length;
|
||||
let mut diff = distance * t + length;
|
||||
diff.z *= z_scale;
|
||||
let radius = Lerp::lerp_unclamped(r0, r1, t);
|
||||
diff.magnitude_squared() < radius * radius
|
||||
@ -5698,6 +5699,7 @@ pub fn render_collect<'b, 'c, F: Filler + 'c, Render: FnOnce(&Painter<'b>, &mut
|
||||
fill.sample_at(arena, &mut bounds_cache, prim, prim_tree, render_area, &info, filler)
|
||||
}; */
|
||||
|
||||
prof_span!("render");
|
||||
render(&painter, &mut fill_fn);
|
||||
/* (
|
||||
painter.prims.into_inner(),
|
||||
|
Loading…
Reference in New Issue
Block a user