Merge branch 'sharp/default-shadows' into 'master'

Create (segment, offset) just once per figure.

See merge request veloren/veloren!1360
This commit is contained in:
Joshua Yanovski 2020-09-04 15:54:55 +00:00
commit 66f49d5386
8 changed files with 389 additions and 1052 deletions

View File

@ -273,3 +273,8 @@ impl<'a, T: ReadVol> Iterator for DefaultVolIterator<'a, T> {
None
}
}
impl<'b, T: ReadVol> ReadVol for &'b T {
#[inline(always)]
fn get<'a>(&'a self, pos: Vec3<i32>) -> Result<&'a Self::Vox, Self::Error> { (*self).get(pos) }
}

View File

@ -59,6 +59,14 @@ impl<V: Vox, M, A: Access> SizedVol for Dyna<V, M, A> {
fn upper_bound(&self) -> Vec3<i32> { self.sz.map(|e| e as i32) }
}
impl<'a, V: Vox, M, A: Access> SizedVol for &'a Dyna<V, M, A> {
#[inline(always)]
fn lower_bound(&self) -> Vec3<i32> { (*self).lower_bound() }
#[inline(always)]
fn upper_bound(&self) -> Vec3<i32> { (*self).upper_bound() }
}
impl<V: Vox, M, A: Access> ReadVol for Dyna<V, M, A> {
#[inline(always)]
fn get(&self, pos: Vec3<i32>) -> Result<&V, DynaError> {

View File

@ -13,7 +13,6 @@ use common::{
figure::Cell,
vol::{BaseVol, ReadVol, SizedVol, Vox},
};
use core::ops::Range;
use vek::*;
type SpriteVertex = <SpritePipeline as render::Pipeline>::Vertex;
@ -28,32 +27,26 @@ where
* &'a V: BaseVol<Vox=Cell>, */
{
type Pipeline = TerrainPipeline;
/// NOTE: The result provides the (roughly) computed bounds for the model,
/// and the vertex range meshed for this model; we return this instead
/// of the full opaque mesh so we can avoid allocating a separate mesh
/// for each bone.
///
/// Later, we can iterate through the bone array and correctly assign bone
/// ids to all vertices in range for each segment.
///
/// FIXME: A refactor of the figure cache to not just return an array of
/// models (thus allowing us to knoe the bone index ahead of time) would
/// avoid needing per-bone information at all.
type Result = (math::Aabb<f32>, Range<usize>);
type Result = math::Aabb<f32>;
type ShadowPipeline = ShadowPipeline;
/// NOTE: bone_idx must be in [0, 15] (may be bumped to [0, 31] at some
/// point).
type Supplement = (
&'b mut GreedyMesh<'a>,
&'b mut Mesh<Self::Pipeline>,
Vec3<f32>,
Vec3<f32>,
u8,
);
type TranslucentPipeline = FigurePipeline;
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
fn generate_mesh(
self,
(greedy, opaque_mesh, offs, scale): Self::Supplement,
(greedy, opaque_mesh, offs, scale, bone_idx): Self::Supplement,
) -> MeshGen<FigurePipeline, &'b mut GreedyMesh<'a>, Self> {
assert!(bone_idx <= 15, "Bone index for figures must be in [0, 15]");
let max_size = greedy.max_size();
// NOTE: Required because we steal two bits from the normal in the shadow uint
// in order to store the bone index. The two bits are instead taken out
@ -98,10 +91,9 @@ where
})
};
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, bone_idx)
};
let start = opaque_mesh.vertices().len();
greedy.push(GreedyConfig {
data: self,
draw_delta,
@ -129,14 +121,8 @@ where
max: math::Vec3::from((upper_bound.as_::<f32>() + offs) * scale),
}
.made_valid();
let vertex_range = start..opaque_mesh.vertices().len();
(
Mesh::new(),
Mesh::new(),
Mesh::new(),
(bounds, vertex_range),
)
(Mesh::new(), Mesh::new(), Mesh::new(), bounds)
}
}

View File

@ -3,7 +3,6 @@ use super::{
shadow, Globals, Light, Shadow,
};
use crate::mesh::greedy::GreedyMesh;
use core::ops::Range;
use gfx::{
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
gfx_pipeline_inner, state::ColorMask,
@ -122,4 +121,4 @@ impl FigureModel {
}
}
pub type BoneMeshes = (Mesh<TerrainPipeline>, (anim::vek::Aabb<f32>, Range<usize>));
pub type BoneMeshes = (Mesh<TerrainPipeline>, anim::vek::Aabb<f32>);

View File

@ -105,11 +105,6 @@ impl Vertex {
{
[col.r, col.g, col.b, light]
}
/// Set the bone_idx for an existing figure vertex.
pub fn set_bone_idx(&mut self, bone_idx: u8) {
self.pos_norm = (self.pos_norm & !(0xF << 27)) | ((bone_idx as u32 & 0xF) << 27);
}
}
impl Locals {

View File

@ -367,7 +367,11 @@ where
let slot_ = Arc::clone(&slot);
thread_pool.execute(move || {
// First, load all the base vertex data.
let manifests = &*manifests;
let meshes = <Skel::Body as BodySpec>::bone_meshes(&key, &*manifests);
// Then, set up meshing context.
let mut greedy = FigureModel::make_greedy();
let mut opaque = Mesh::<TerrainPipeline>::new();
// Choose the most conservative bounds for any LOD model.
@ -382,31 +386,21 @@ where
let mut make_model = |generate_mesh: for<'a, 'b> fn(
&mut GreedyMesh<'a>,
&'b mut _,
&'a _,
_,
_,
)
-> _| {
let vertex_start = opaque.vertices().len();
let meshes = <Skel::Body as BodySpec>::bone_meshes(
&key,
&*manifests,
|segment, offset| {
generate_mesh(&mut greedy, &mut opaque, segment, offset)
},
);
meshes
.iter()
.enumerate()
// NOTE: Cast to u8 is safe because i <= 16.
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i as u8, bm.clone())))
.for_each(|(i, (_opaque_mesh, (bounds, vertex_range)))| {
// Update the bone index for all vertices that belong to this
// model.
opaque
.iter_mut(vertex_range)
.for_each(|vert| {
vert.set_bone_idx(i);
});
// NOTE: Cast to u8 is safe because i < 16.
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i as u8, bm)))
.for_each(|(i, (segment, offset))| {
// Generate this mesh.
let (_opaque_mesh, bounds) =
generate_mesh(&mut greedy, &mut opaque, segment, *offset, i);
// Update the figure bounds to the largest granularity seen so far
// (NOTE: this is more than a little imperfect).
@ -442,13 +436,14 @@ where
fn generate_mesh<'a>(
greedy: &mut GreedyMesh<'a>,
opaque_mesh: &mut Mesh<TerrainPipeline>,
segment: Segment,
segment: &'a Segment,
offset: Vec3<f32>,
bone_idx: u8,
) -> BoneMeshes {
let (opaque, _, _, bounds) =
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
segment,
(greedy, opaque_mesh, offset, Vec3::one()),
(greedy, opaque_mesh, offset, Vec3::one(), bone_idx),
);
(opaque, bounds)
}
@ -456,8 +451,9 @@ where
fn generate_mesh_lod_mid<'a>(
greedy: &mut GreedyMesh<'a>,
opaque_mesh: &mut Mesh<TerrainPipeline>,
segment: Segment,
segment: &'a Segment,
offset: Vec3<f32>,
bone_idx: u8,
) -> BoneMeshes {
let lod_scale = 0.6;
let (opaque, _, _, bounds) =
@ -468,6 +464,7 @@ where
opaque_mesh,
offset * lod_scale,
Vec3::one() / lod_scale,
bone_idx,
),
);
(opaque, bounds)
@ -476,8 +473,9 @@ where
fn generate_mesh_lod_low<'a>(
greedy: &mut GreedyMesh<'a>,
opaque_mesh: &mut Mesh<TerrainPipeline>,
segment: Segment,
segment: &'a Segment,
offset: Vec3<f32>,
bone_idx: u8,
) -> BoneMeshes {
let lod_scale = 0.3;
let (opaque, _, _, bounds) =
@ -488,6 +486,7 @@ where
opaque_mesh,
offset * lod_scale,
Vec3::one() / lod_scale,
bone_idx,
),
);
(opaque, bounds)

File diff suppressed because it is too large Load Diff

View File

@ -50,11 +50,12 @@ fn generate_mesh<'a>(
mesh: &mut Mesh<TerrainPipeline>,
segment: Segment,
offset: Vec3<f32>,
bone_idx: u8,
) -> BoneMeshes {
let (opaque, _, /* shadow */ _, bounds) =
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
segment,
(greedy, mesh, offset, Vec3::one()),
(greedy, mesh, offset, Vec3::one(), bone_idx),
);
(opaque /* , shadow */, bounds)
}
@ -154,16 +155,14 @@ impl Scene {
let mut state = FigureState::new(renderer, FixtureSkeleton::default());
let mut greedy = FigureModel::make_greedy();
let mut opaque_mesh = Mesh::new();
let (_opaque_mesh, (bounds, range)) = load_mesh(
specifier,
Vec3::new(-55.0, -49.5, -2.0),
|segment, offset| generate_mesh(&mut greedy, &mut opaque_mesh, segment, offset),
);
let (segment, offset) = load_mesh(specifier, Vec3::new(-55.0, -49.5, -2.0));
let (_opaque_mesh, bounds) =
generate_mesh(&mut greedy, &mut opaque_mesh, segment, offset, 0);
// NOTE: Since MagicaVoxel sizes are limited to 256 × 256 × 256, and there are
// at most 3 meshed vertices per unique vertex, we know the
// total size is bounded by 2^24 * 3 * 1.5 which is bounded by
// 2^27, which fits in a u32.
let range = range.start as u32..range.end as u32;
let range = 0..opaque_mesh.vertices().len() as u32;
let model = col_lights
.create_figure(renderer, greedy.finalize(), (opaque_mesh, bounds), [range])
.unwrap();