mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Create (segment, offset) just once per figure.
This commit is contained in:
parent
7e6975d881
commit
4eeb131f4b
@ -273,3 +273,8 @@ impl<'a, T: ReadVol> Iterator for DefaultVolIterator<'a, T> {
|
|||||||
None
|
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) }
|
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> {
|
impl<V: Vox, M, A: Access> ReadVol for Dyna<V, M, A> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn get(&self, pos: Vec3<i32>) -> Result<&V, DynaError> {
|
fn get(&self, pos: Vec3<i32>) -> Result<&V, DynaError> {
|
||||||
|
@ -13,7 +13,6 @@ use common::{
|
|||||||
figure::Cell,
|
figure::Cell,
|
||||||
vol::{BaseVol, ReadVol, SizedVol, Vox},
|
vol::{BaseVol, ReadVol, SizedVol, Vox},
|
||||||
};
|
};
|
||||||
use core::ops::Range;
|
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
type SpriteVertex = <SpritePipeline as render::Pipeline>::Vertex;
|
type SpriteVertex = <SpritePipeline as render::Pipeline>::Vertex;
|
||||||
@ -28,32 +27,26 @@ where
|
|||||||
* &'a V: BaseVol<Vox=Cell>, */
|
* &'a V: BaseVol<Vox=Cell>, */
|
||||||
{
|
{
|
||||||
type Pipeline = TerrainPipeline;
|
type Pipeline = TerrainPipeline;
|
||||||
/// NOTE: The result provides the (roughly) computed bounds for the model,
|
type Result = math::Aabb<f32>;
|
||||||
/// 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 ShadowPipeline = ShadowPipeline;
|
type ShadowPipeline = ShadowPipeline;
|
||||||
|
/// NOTE: bone_idx must be in [0, 15] (may be bumped to [0, 31] at some
|
||||||
|
/// point).
|
||||||
type Supplement = (
|
type Supplement = (
|
||||||
&'b mut GreedyMesh<'a>,
|
&'b mut GreedyMesh<'a>,
|
||||||
&'b mut Mesh<Self::Pipeline>,
|
&'b mut Mesh<Self::Pipeline>,
|
||||||
Vec3<f32>,
|
Vec3<f32>,
|
||||||
Vec3<f32>,
|
Vec3<f32>,
|
||||||
|
u8,
|
||||||
);
|
);
|
||||||
type TranslucentPipeline = FigurePipeline;
|
type TranslucentPipeline = FigurePipeline;
|
||||||
|
|
||||||
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
||||||
fn generate_mesh(
|
fn generate_mesh(
|
||||||
self,
|
self,
|
||||||
(greedy, opaque_mesh, offs, scale): Self::Supplement,
|
(greedy, opaque_mesh, offs, scale, bone_idx): Self::Supplement,
|
||||||
) -> MeshGen<FigurePipeline, &'b mut GreedyMesh<'a>, Self> {
|
) -> 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();
|
let max_size = greedy.max_size();
|
||||||
// NOTE: Required because we steal two bits from the normal in the shadow uint
|
// 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
|
// 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| {
|
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 {
|
greedy.push(GreedyConfig {
|
||||||
data: self,
|
data: self,
|
||||||
draw_delta,
|
draw_delta,
|
||||||
@ -129,14 +121,8 @@ where
|
|||||||
max: math::Vec3::from((upper_bound.as_::<f32>() + offs) * scale),
|
max: math::Vec3::from((upper_bound.as_::<f32>() + offs) * scale),
|
||||||
}
|
}
|
||||||
.made_valid();
|
.made_valid();
|
||||||
let vertex_range = start..opaque_mesh.vertices().len();
|
|
||||||
|
|
||||||
(
|
(Mesh::new(), Mesh::new(), Mesh::new(), bounds)
|
||||||
Mesh::new(),
|
|
||||||
Mesh::new(),
|
|
||||||
Mesh::new(),
|
|
||||||
(bounds, vertex_range),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ use super::{
|
|||||||
shadow, Globals, Light, Shadow,
|
shadow, Globals, Light, Shadow,
|
||||||
};
|
};
|
||||||
use crate::mesh::greedy::GreedyMesh;
|
use crate::mesh::greedy::GreedyMesh;
|
||||||
use core::ops::Range;
|
|
||||||
use gfx::{
|
use gfx::{
|
||||||
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
|
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
|
||||||
gfx_pipeline_inner, state::ColorMask,
|
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]
|
[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 {
|
impl Locals {
|
||||||
|
@ -367,7 +367,11 @@ where
|
|||||||
let slot_ = Arc::clone(&slot);
|
let slot_ = Arc::clone(&slot);
|
||||||
|
|
||||||
thread_pool.execute(move || {
|
thread_pool.execute(move || {
|
||||||
|
// First, load all the base vertex data.
|
||||||
let manifests = &*manifests;
|
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 greedy = FigureModel::make_greedy();
|
||||||
let mut opaque = Mesh::<TerrainPipeline>::new();
|
let mut opaque = Mesh::<TerrainPipeline>::new();
|
||||||
// Choose the most conservative bounds for any LOD model.
|
// Choose the most conservative bounds for any LOD model.
|
||||||
@ -382,31 +386,21 @@ where
|
|||||||
let mut make_model = |generate_mesh: for<'a, 'b> fn(
|
let mut make_model = |generate_mesh: for<'a, 'b> fn(
|
||||||
&mut GreedyMesh<'a>,
|
&mut GreedyMesh<'a>,
|
||||||
&'b mut _,
|
&'b mut _,
|
||||||
|
&'a _,
|
||||||
_,
|
_,
|
||||||
_,
|
_,
|
||||||
)
|
)
|
||||||
-> _| {
|
-> _| {
|
||||||
let vertex_start = opaque.vertices().len();
|
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
|
meshes
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
// NOTE: Cast to u8 is safe because i <= 16.
|
// NOTE: Cast to u8 is safe because i < 16.
|
||||||
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i as u8, bm.clone())))
|
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i as u8, bm)))
|
||||||
.for_each(|(i, (_opaque_mesh, (bounds, vertex_range)))| {
|
.for_each(|(i, (segment, offset))| {
|
||||||
// Update the bone index for all vertices that belong to this
|
// Generate this mesh.
|
||||||
// model.
|
let (_opaque_mesh, bounds) =
|
||||||
opaque
|
generate_mesh(&mut greedy, &mut opaque, segment, *offset, i);
|
||||||
.iter_mut(vertex_range)
|
|
||||||
.for_each(|vert| {
|
|
||||||
vert.set_bone_idx(i);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update the figure bounds to the largest granularity seen so far
|
// Update the figure bounds to the largest granularity seen so far
|
||||||
// (NOTE: this is more than a little imperfect).
|
// (NOTE: this is more than a little imperfect).
|
||||||
@ -442,13 +436,14 @@ where
|
|||||||
fn generate_mesh<'a>(
|
fn generate_mesh<'a>(
|
||||||
greedy: &mut GreedyMesh<'a>,
|
greedy: &mut GreedyMesh<'a>,
|
||||||
opaque_mesh: &mut Mesh<TerrainPipeline>,
|
opaque_mesh: &mut Mesh<TerrainPipeline>,
|
||||||
segment: Segment,
|
segment: &'a Segment,
|
||||||
offset: Vec3<f32>,
|
offset: Vec3<f32>,
|
||||||
|
bone_idx: u8,
|
||||||
) -> BoneMeshes {
|
) -> BoneMeshes {
|
||||||
let (opaque, _, _, bounds) =
|
let (opaque, _, _, bounds) =
|
||||||
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
|
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
|
||||||
segment,
|
segment,
|
||||||
(greedy, opaque_mesh, offset, Vec3::one()),
|
(greedy, opaque_mesh, offset, Vec3::one(), bone_idx),
|
||||||
);
|
);
|
||||||
(opaque, bounds)
|
(opaque, bounds)
|
||||||
}
|
}
|
||||||
@ -456,8 +451,9 @@ where
|
|||||||
fn generate_mesh_lod_mid<'a>(
|
fn generate_mesh_lod_mid<'a>(
|
||||||
greedy: &mut GreedyMesh<'a>,
|
greedy: &mut GreedyMesh<'a>,
|
||||||
opaque_mesh: &mut Mesh<TerrainPipeline>,
|
opaque_mesh: &mut Mesh<TerrainPipeline>,
|
||||||
segment: Segment,
|
segment: &'a Segment,
|
||||||
offset: Vec3<f32>,
|
offset: Vec3<f32>,
|
||||||
|
bone_idx: u8,
|
||||||
) -> BoneMeshes {
|
) -> BoneMeshes {
|
||||||
let lod_scale = 0.6;
|
let lod_scale = 0.6;
|
||||||
let (opaque, _, _, bounds) =
|
let (opaque, _, _, bounds) =
|
||||||
@ -468,6 +464,7 @@ where
|
|||||||
opaque_mesh,
|
opaque_mesh,
|
||||||
offset * lod_scale,
|
offset * lod_scale,
|
||||||
Vec3::one() / lod_scale,
|
Vec3::one() / lod_scale,
|
||||||
|
bone_idx,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
(opaque, bounds)
|
(opaque, bounds)
|
||||||
@ -476,8 +473,9 @@ where
|
|||||||
fn generate_mesh_lod_low<'a>(
|
fn generate_mesh_lod_low<'a>(
|
||||||
greedy: &mut GreedyMesh<'a>,
|
greedy: &mut GreedyMesh<'a>,
|
||||||
opaque_mesh: &mut Mesh<TerrainPipeline>,
|
opaque_mesh: &mut Mesh<TerrainPipeline>,
|
||||||
segment: Segment,
|
segment: &'a Segment,
|
||||||
offset: Vec3<f32>,
|
offset: Vec3<f32>,
|
||||||
|
bone_idx: u8,
|
||||||
) -> BoneMeshes {
|
) -> BoneMeshes {
|
||||||
let lod_scale = 0.3;
|
let lod_scale = 0.3;
|
||||||
let (opaque, _, _, bounds) =
|
let (opaque, _, _, bounds) =
|
||||||
@ -488,6 +486,7 @@ where
|
|||||||
opaque_mesh,
|
opaque_mesh,
|
||||||
offset * lod_scale,
|
offset * lod_scale,
|
||||||
Vec3::one() / lod_scale,
|
Vec3::one() / lod_scale,
|
||||||
|
bone_idx,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
(opaque, bounds)
|
(opaque, bounds)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -50,11 +50,12 @@ fn generate_mesh<'a>(
|
|||||||
mesh: &mut Mesh<TerrainPipeline>,
|
mesh: &mut Mesh<TerrainPipeline>,
|
||||||
segment: Segment,
|
segment: Segment,
|
||||||
offset: Vec3<f32>,
|
offset: Vec3<f32>,
|
||||||
|
bone_idx: u8,
|
||||||
) -> BoneMeshes {
|
) -> BoneMeshes {
|
||||||
let (opaque, _, /* shadow */ _, bounds) =
|
let (opaque, _, /* shadow */ _, bounds) =
|
||||||
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
|
Meshable::<FigurePipeline, &mut GreedyMesh>::generate_mesh(
|
||||||
segment,
|
segment,
|
||||||
(greedy, mesh, offset, Vec3::one()),
|
(greedy, mesh, offset, Vec3::one(), bone_idx),
|
||||||
);
|
);
|
||||||
(opaque /* , shadow */, bounds)
|
(opaque /* , shadow */, bounds)
|
||||||
}
|
}
|
||||||
@ -154,16 +155,14 @@ impl Scene {
|
|||||||
let mut state = FigureState::new(renderer, FixtureSkeleton::default());
|
let mut state = FigureState::new(renderer, FixtureSkeleton::default());
|
||||||
let mut greedy = FigureModel::make_greedy();
|
let mut greedy = FigureModel::make_greedy();
|
||||||
let mut opaque_mesh = Mesh::new();
|
let mut opaque_mesh = Mesh::new();
|
||||||
let (_opaque_mesh, (bounds, range)) = load_mesh(
|
let (segment, offset) = load_mesh(specifier, Vec3::new(-55.0, -49.5, -2.0));
|
||||||
specifier,
|
let (_opaque_mesh, bounds) =
|
||||||
Vec3::new(-55.0, -49.5, -2.0),
|
generate_mesh(&mut greedy, &mut opaque_mesh, segment, offset, 0);
|
||||||
|segment, offset| generate_mesh(&mut greedy, &mut opaque_mesh, segment, offset),
|
|
||||||
);
|
|
||||||
// NOTE: Since MagicaVoxel sizes are limited to 256 × 256 × 256, and there are
|
// NOTE: Since MagicaVoxel sizes are limited to 256 × 256 × 256, and there are
|
||||||
// at most 3 meshed vertices per unique vertex, we know the
|
// 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
|
// total size is bounded by 2^24 * 3 * 1.5 which is bounded by
|
||||||
// 2^27, which fits in a u32.
|
// 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
|
let model = col_lights
|
||||||
.create_figure(renderer, greedy.finalize(), (opaque_mesh, bounds), [range])
|
.create_figure(renderer, greedy.finalize(), (opaque_mesh, bounds), [range])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user