Added LoD for figures and reduced update rates for far figures

This commit is contained in:
Joshua Barretto 2020-04-24 19:37:45 +01:00
parent 3e62f7edc3
commit 39b88dbcb1
4 changed files with 725 additions and 644 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -117,7 +117,7 @@ impl FigureMgr {
.get(scene_data.player_entity)
.map_or(Vec3::zero(), |pos| pos.0);
for (
for (i, (
entity,
pos,
interpolated,
@ -129,7 +129,7 @@ impl FigureMgr {
physics,
stats,
loadout,
) in (
)) in (
&ecs.entities(),
&ecs.read_storage::<Pos>(),
ecs.read_storage::<Interpolated>().maybe(),
@ -143,7 +143,20 @@ impl FigureMgr {
ecs.read_storage::<Loadout>().maybe(),
)
.join()
.enumerate()
{
// Maintaining figure data and sending new figure data to the GPU turns out to be a
// very expensive operation. We want to avoid doing it as much as possible, so we
// make the assumption that players don't care so much about the update *rate* for far
// away things. As the entity goes further and further away, we start to 'skip' update
// ticks.
// TODO: Investigate passing the velocity into the shader so we can at least
// interpolate motion
const MIN_PERFECT_RATE_DIST: f32 = 96.0;
if (i as u64 + tick) % 1 + ((pos.0.distance(camera.get_focus_pos()).powf(0.5) - MIN_PERFECT_RATE_DIST.powf(0.5)).max(0.0) / 5.0) as u64 != 0 {
continue;
}
let is_player = scene_data.player_entity == entity;
let (pos, ori) = interpolated
@ -1385,7 +1398,7 @@ impl FigureMgr {
let character_state_storage = state.read_storage::<common::comp::CharacterState>();
let character_state = character_state_storage.get(player_entity);
for (entity, _, _, body, _, loadout, _) in (
for (entity, pos, _, body, _, loadout, _) in (
&ecs.entities(),
&ecs.read_storage::<Pos>(),
ecs.read_storage::<Ori>().maybe(),
@ -1413,6 +1426,7 @@ impl FigureMgr {
body,
loadout,
false,
pos.0,
);
}
}
@ -1434,7 +1448,10 @@ impl FigureMgr {
let character_state_storage = state.read_storage::<common::comp::CharacterState>();
let character_state = character_state_storage.get(player_entity);
if let Some(body) = ecs.read_storage::<Body>().get(player_entity) {
if let (Some(pos), Some(body)) = (
ecs.read_storage::<Pos>().get(player_entity),
ecs.read_storage::<Body>().get(player_entity),
) {
let stats_storage = state.read_storage::<Stats>();
let stats = stats_storage.get(player_entity);
@ -1457,6 +1474,7 @@ impl FigureMgr {
body,
loadout,
true,
pos.0,
);
}
}
@ -1474,6 +1492,7 @@ impl FigureMgr {
body: &Body,
loadout: Option<&Loadout>,
is_player: bool,
pos: Vec3<f32>,
) {
let player_camera_mode = if is_player {
camera.get_mode()
@ -1686,6 +1705,17 @@ impl FigureMgr {
)
}),
} {
const FIGURE_LOD_LOW_DIST: f32 = 150.0;
const FIGURE_LOD_MID_DIST: f32 = 70.0;
let model = if pos.distance_squared(camera.get_focus_pos()) > FIGURE_LOD_LOW_DIST.powf(2.0) {
&model[2]
} else if pos.distance_squared(camera.get_focus_pos()) > FIGURE_LOD_MID_DIST.powf(2.0) {
&model[1]
} else {
&model[0]
};
if is_player {
renderer.render_player(model, globals, locals, bone_consts, lights, shadows);
renderer.render_player_shadow(model, globals, locals, bone_consts, lights, shadows);

View File

@ -7,17 +7,20 @@ use crate::{
render::{
create_pp_mesh, create_skybox_mesh, Consts, FigurePipeline, Globals, Light, Model,
PostProcessLocals, PostProcessPipeline, Renderer, Shadow, SkyboxLocals, SkyboxPipeline,
Mesh,
},
scene::{
camera::{self, Camera, CameraMode},
figure::{load_mesh, FigureModelCache, FigureState},
},
window::{Event, PressState},
mesh::Meshable,
};
use common::{
comp::{humanoid, Body, Loadout},
terrain::BlockKind,
vol::{BaseVol, ReadVol, Vox},
figure::Segment,
};
use log::error;
use vek::*;
@ -40,6 +43,10 @@ impl ReadVol for VoidVol {
fn get<'a>(&'a self, _pos: Vec3<i32>) -> Result<&'a Self::Vox, Self::Error> { Ok(&VoidVox) }
}
fn generate_mesh(segment: &Segment, offset: Vec3<f32>) -> Mesh<FigurePipeline> {
Meshable::<FigurePipeline, FigurePipeline>::generate_mesh(segment, (offset, Vec3::one())).0
}
struct Skybox {
model: Model<SkyboxPipeline>,
locals: Consts<SkyboxLocals>,
@ -107,7 +114,7 @@ impl Scene {
backdrop: backdrop.map(|specifier| {
(
renderer
.create_model(&load_mesh(specifier, Vec3::new(-55.0, -49.5, -2.0)))
.create_model(&load_mesh(specifier, Vec3::new(-55.0, -49.5, -2.0), generate_mesh))
.unwrap(),
FigureState::new(renderer, FixtureSkeleton::new()),
)
@ -229,7 +236,7 @@ impl Scene {
.0;
renderer.render_figure(
model,
&model[0],
&self.globals,
self.figure_state.locals(),
self.figure_state.bone_consts(),