Improve frustum culling by using AABBs, add related debug information

This commit is contained in:
Yusuf Bera Ertan 2019-11-19 18:13:33 +03:00
parent fd9cc76786
commit e32153e980
8 changed files with 123 additions and 35 deletions

34
Cargo.lock generated
View File

@ -864,6 +864,15 @@ dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dirs"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dirs-sys"
version = "0.3.4"
@ -1055,7 +1064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "frustum_query"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/yusdacra/frustum_query#866b36607a3a80356f0fc7a1cb29c2c59a70fdab"
[[package]]
name = "fsevent"
@ -2974,6 +2983,16 @@ name = "shrev"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "simplelog"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "siphasher"
version = "0.2.3"
@ -3226,6 +3245,15 @@ dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "term"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termcolor"
version = "1.0.5"
@ -3929,6 +3957,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum derivative 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "942ca430eef7a3806595a6737bc388bf51adb888d3fc0dd1b50f1c170167ee3a"
"checksum directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c"
"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
"checksum discord-rpc-sdk 0.1.1 (git+https://github.com/Songtronix/rust-discord-rpc.git)" = "<none>"
"checksum discord-rpc-sys 0.1.0 (git+https://github.com/Songtronix/rust-discord-rpc.git)" = "<none>"
@ -3952,7 +3981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
"checksum frustum_query 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e1771c26abed26b2527d888742fffd27dab86d205bf4846748abf29c06ef5a05"
"checksum frustum_query 0.1.2 (git+https://github.com/yusdacra/frustum_query)" = "<none>"
"checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6"
"checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
@ -4192,6 +4221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
"checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42"
"checksum term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5"
"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"

View File

@ -55,7 +55,7 @@ directories = "2.0.2"
num = "0.2.0"
backtrace = "0.3.40"
rand = "0.7.2"
frustum_query = "0.1.2"
frustum_query = { git = "https://github.com/yusdacra/frustum_query" }
# context for pinning to commit: https://gitlab.com/veloren/veloren/issues/280
rodio = { git = "https://github.com/RustAudio/rodio", rev = "e5474a2"}
cpal = "0.10"

View File

@ -119,6 +119,8 @@ widget_ids! {
loaded_distance,
time,
entity_count,
num_chunks,
num_figures,
// Game Version
version,
@ -172,6 +174,10 @@ pub struct DebugInfo {
pub ping_ms: f64,
pub coordinates: Option<comp::Pos>,
pub velocity: Option<comp::Vel>,
pub num_chunks: u32,
pub num_visible_chunks: u32,
pub num_figures: u32,
pub num_figures_visible: u32,
}
pub enum Event {
@ -979,6 +985,7 @@ impl Hud {
.font_id(self.fonts.cyri)
.font_size(14)
.set(self.ids.time, ui_widgets);
// Number of entities
let entity_count = client.state().ecs().entities().join().count();
Text::new(&format!("Entity count: {}", entity_count))
@ -987,11 +994,33 @@ impl Hud {
.font_id(self.fonts.cyri)
.font_size(14)
.set(self.ids.entity_count, ui_widgets);
// Number of chunks
Text::new(&format!(
"Chunks: {} ({} visible)",
debug_info.num_chunks, debug_info.num_visible_chunks,
))
.color(TEXT_COLOR)
.down_from(self.ids.entity_count, 5.0)
.font_id(self.fonts.cyri)
.font_size(14)
.set(self.ids.num_chunks, ui_widgets);
// Number of figures
Text::new(&format!(
"Figures: {} ({} visible)",
debug_info.num_figures, debug_info.num_figures_visible,
))
.color(TEXT_COLOR)
.down_from(self.ids.num_chunks, 5.0)
.font_id(self.fonts.cyri)
.font_size(14)
.set(self.ids.num_figures, ui_widgets);
// Help Window
Text::new("Press 'F1' to show Keybindings")
.color(TEXT_COLOR)
.down_from(self.ids.entity_count, 5.0)
.down_from(self.ids.num_figures, 5.0)
.font_id(self.fonts.cyri)
.font_size(14)
.set(self.ids.help_info, ui_widgets);

View File

@ -103,10 +103,7 @@ impl Camera {
pub fn frustum(&self, client: &Client) -> Frustum {
let (view_mat, proj_mat, _) = self.compute_dependents(client);
Frustum::from_modelview_and_projection(
&view_mat.into_col_array(),
&proj_mat.into_col_array(),
)
Frustum::from_modelview_projection((proj_mat * view_mat).into_col_arrays())
}
/// Rotate the camera about its focus by the given delta, limiting the input accordingly.

View File

@ -43,6 +43,8 @@ pub struct FigureMgr {
fish_small_states: HashMap<EcsEntity, FigureState<FishSmallSkeleton>>,
biped_large_states: HashMap<EcsEntity, FigureState<BipedLargeSkeleton>>,
object_states: HashMap<EcsEntity, FigureState<ObjectSkeleton>>,
figure_count: usize,
visible_figure_count: usize,
}
impl FigureMgr {
@ -59,6 +61,8 @@ impl FigureMgr {
fish_small_states: HashMap::new(),
biped_large_states: HashMap::new(),
object_states: HashMap::new(),
figure_count: 0,
visible_figure_count: 0,
}
}
@ -78,6 +82,8 @@ impl FigureMgr {
.get(client.entity())
.map_or(Vec3::zero(), |pos| pos.0);
self.figure_count = 0;
for (entity, pos, ori, scale, body, character, last_character, stats) in (
&ecs.entities(),
&ecs.read_storage::<Pos>(),
@ -90,6 +96,7 @@ impl FigureMgr {
)
.join()
{
self.figure_count += 1;
// Don't process figures outside the vd
let vd_frac = Vec2::from(pos.0 - player_pos)
.map2(TerrainChunk::RECT_SIZE, |d: f32, sz| {
@ -823,6 +830,8 @@ impl FigureMgr {
.read_storage::<common::comp::CharacterState>();
let character_state = character_state_storage.get(client.entity());
self.visible_figure_count = 0;
for (entity, _, _, body, stats, _) in (
&ecs.entities(),
&ecs.read_storage::<Pos>(),
@ -835,15 +844,14 @@ impl FigureMgr {
// Don't render figures outside of frustum (camera viewport, max draw distance is farplane)
.filter(|(_, pos, _, _, _, scale)| {
frustum.sphere_intersecting(
&pos.0.x,
&pos.0.y,
&pos.0.z,
&(scale.unwrap_or(&Scale(1.0)).0 * 2.0),
pos.0.into_array(),
scale.unwrap_or(&Scale(1.0)).0 * 2.0,
)
})
// Don't render dead entities
.filter(|(_, _, _, _, stats, _)| stats.map_or(true, |s| !s.is_dead))
{
self.visible_figure_count += 1;
if let Some((locals, bone_consts)) = match body {
Body::Humanoid(_) => self
.character_states
@ -912,6 +920,14 @@ impl FigureMgr {
}
}
}
pub fn figure_count(&self) -> usize {
self.figure_count
}
pub fn figure_count_visible(&self) -> usize {
self.visible_figure_count
}
}
pub struct FigureState<S: Skeleton> {

View File

@ -94,7 +94,7 @@ impl Scene {
}
}
/// Get a reference to the scene's globals
/// Get a reference to the scene's globals.
pub fn globals(&self) -> &Consts<Globals> {
&self.globals
}
@ -104,6 +104,16 @@ impl Scene {
&self.camera
}
/// Get a reference to the scene's terrain.
pub fn terrain(&self) -> &Terrain<TerrainChunk> {
&self.terrain
}
/// Get a reference to the scene's figure manager.
pub fn figure_mgr(&self) -> &FigureMgr {
&self.figure_mgr
}
/// Get a mutable reference to the scene's camera.
pub fn camera_mut(&mut self) -> &mut Camera {
&mut self.camera

View File

@ -1035,10 +1035,7 @@ impl<V: RectRasterableVol> Terrain<V> {
}
// Construct view frustum
let frustum = Frustum::from_modelview_and_projection(
&view_mat.into_col_array(),
&proj_mat.into_col_array(),
);
let frustum = Frustum::from_modelview_projection((proj_mat * view_mat).into_col_arrays());
// Update chunk visibility
let chunk_sz = V::RECT_SIZE.x as f32;
@ -1050,28 +1047,33 @@ impl<V: RectRasterableVol> Terrain<V> {
let in_range = Vec2::<f32>::from(focus_pos).distance_squared(nearest_in_chunk)
< loaded_distance.powf(2.0);
// Ensure the chunk is within the view frustrum
let chunk_mid = Vec3::new(
chunk_pos.x + chunk_sz / 2.0,
chunk_pos.y + chunk_sz / 2.0,
(chunk.z_bounds.0 + chunk.z_bounds.1) * 0.5,
);
let chunk_radius = ((chunk.z_bounds.1 - chunk.z_bounds.0) / 2.0)
.max(chunk_sz / 2.0)
.powf(2.0)
.mul(2.0)
.sqrt();
let in_frustum = frustum.sphere_intersecting(
&chunk_mid.x,
&chunk_mid.y,
&chunk_mid.z,
&chunk_radius,
);
if !in_range {
chunk.visible = in_range;
continue;
}
chunk.visible = in_range && in_frustum;
// Ensure the chunk is within the view frustum
let chunk_min = [chunk_pos.x, chunk_pos.y, chunk.z_bounds.0];
let chunk_max = [
chunk_pos.x + chunk_sz,
chunk_pos.y + chunk_sz,
chunk.z_bounds.1,
];
let in_frustum = frustum.aabb_intersecting(chunk_min, chunk_max);
chunk.visible = in_frustum;
}
}
pub fn chunk_count(&self) -> usize {
self.chunks.len()
}
pub fn visible_chunk_count(&self) -> usize {
self.chunks.iter().filter(|(_, c)| c.visible).count()
}
pub fn render(
&self,
renderer: &mut Renderer,

View File

@ -385,6 +385,10 @@ impl PlayState for SessionState {
.read_storage::<Vel>()
.get(self.client.borrow().entity())
.cloned(),
num_chunks: self.scene.terrain().chunk_count() as u32,
num_visible_chunks: self.scene.terrain().visible_chunk_count() as u32,
num_figures: self.scene.figure_mgr().figure_count() as u32,
num_figures_visible: self.scene.figure_mgr().figure_count_visible() as u32,
},
&self.scene.camera(),
clock.get_last_delta(),