mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
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:
commit
66f49d5386
@ -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) }
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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>);
|
||||
|
@ -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 {
|
||||
|
@ -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
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user