diff --git a/client/src/lib.rs b/client/src/lib.rs index 112a04c2db..fbc95e1905 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -311,6 +311,8 @@ pub struct Client { flashing_lights_enabled: bool, + pub debug_vectors_enabled: bool, + /// Terrrain view distance server_view_distance_limit: Option, view_distance: Option, @@ -987,6 +989,7 @@ impl Client { dt_adjustment: 1.0, connected_server_constants: server_constants, + debug_vectors_enabled: false, }) } diff --git a/voxygen/egui/src/lib.rs b/voxygen/egui/src/lib.rs index 5a8a279e38..330d1c2647 100644 --- a/voxygen/egui/src/lib.rs +++ b/voxygen/egui/src/lib.rs @@ -96,6 +96,7 @@ pub struct EguiInnerState { selected_entity_cylinder_height: f32, frame_times: Vec, windows: EguiWindows, + debug_vectors_enabled: bool, } #[derive(Clone, Default)] @@ -118,6 +119,7 @@ impl Default for EguiInnerState { selected_entity_cylinder_height: 10.0, frame_times: Vec::new(), windows: EguiWindows::default(), + debug_vectors_enabled: false, } } } @@ -142,6 +144,7 @@ pub enum EguiAction { }, DebugShape(EguiDebugShapeAction), SetExperimentalShader(String, bool), + SetShowDebugVector(bool), } #[derive(Default)] @@ -225,6 +228,7 @@ pub fn maintain_egui_inner( let mut max_entity_distance = egui_state.max_entity_distance; let mut selected_entity_cylinder_height = egui_state.selected_entity_cylinder_height; let mut windows = egui_state.windows.clone(); + let mut debug_vectors_enabled_mut = egui_state.debug_vectors_enabled; // If a debug cylinder was added in the last frame, store it against the // selected entity @@ -261,6 +265,7 @@ pub fn maintain_egui_inner( ui.checkbox(&mut windows.ecs_entities, "ECS Entities"); ui.checkbox(&mut windows.frame_time, "Frame Time"); ui.checkbox(&mut windows.experimental_shaders, "Experimental Shaders"); + ui.checkbox(&mut debug_vectors_enabled_mut, "Show Debug Vectors"); }); }); @@ -510,6 +515,12 @@ pub fn maintain_egui_inner( } } }; + if debug_vectors_enabled_mut != egui_state.debug_vectors_enabled { + egui_actions + .actions + .push(EguiAction::SetShowDebugVector(debug_vectors_enabled_mut)); + egui_state.debug_vectors_enabled = debug_vectors_enabled_mut; + } egui_state.max_entity_distance = max_entity_distance; egui_state.selected_entity_cylinder_height = selected_entity_cylinder_height; diff --git a/voxygen/src/scene/debug.rs b/voxygen/src/scene/debug.rs index bfb94015bb..412ef5e48b 100644 --- a/voxygen/src/scene/debug.rs +++ b/voxygen/src/scene/debug.rs @@ -9,7 +9,8 @@ use vek::*; #[derive(Debug, PartialEq)] pub enum DebugShape { - Line([Vec3; 2]), + /// [Start, End], width + Line([Vec3; 2], f32), Cylinder { radius: f32, height: f32, @@ -96,13 +97,13 @@ impl DebugShape { }; match self { - DebugShape::Line([a, b]) => { + DebugShape::Line([a, b], width) => { //let h = Vec3::new(0.0, 1.0, 0.0); //mesh.push_quad(quad(*a, a + h, b + h, *b)); box_along_line( LineSegment3 { start: *a, end: *b }, - 0.1, - 0.1, + *width, + *width, [1.0; 4], &mut mesh, ); diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index c87821d971..af2eb453b2 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -27,6 +27,7 @@ use crate::{ GlobalsBindGroup, Light, Model, PointLightMatrix, PostProcessLocals, RainOcclusionLocals, Renderer, Shadow, ShadowLocals, SkyboxVertex, }, + session::PlayerDebugLines, settings::Settings, window::{AnalogGameInput, Event}, }; @@ -39,8 +40,9 @@ use common::{ }, outcome::Outcome, resources::{DeltaTime, TimeScale}, - terrain::{BlockKind, TerrainChunk, TerrainGrid}, + terrain::{BlockKind, CoordinateConversions, TerrainChunk, TerrainGrid, NEIGHBOR_DELTA}, vol::ReadVol, + weather::WeatherGrid, }; use common_base::{prof_span, span}; use common_state::State; @@ -1541,7 +1543,7 @@ impl Scene { for line in chunk.meta().debug_lines().iter() { let shape_id = self .debug - .add_shape(DebugShape::Line([line.start, line.end])); + .add_shape(DebugShape::Line([line.start, line.end], 0.1)); ret.push(shape_id); self.debug .set_context(shape_id, [0.0; 4], [1.0; 4], [0.0, 0.0, 0.0, 1.0]); @@ -1638,4 +1640,77 @@ impl Scene { keep }); } + + pub fn maintain_debug_vectors(&mut self, client: &Client, lines: &mut PlayerDebugLines) { + lines + .chunk_normal + .take() + .map(|id| self.debug.remove_shape(id)); + lines.fluid_vel.take().map(|id| self.debug.remove_shape(id)); + lines.wind.take().map(|id| self.debug.remove_shape(id)); + lines.vel.take().map(|id| self.debug.remove_shape(id)); + if client.debug_vectors_enabled { + let ecs = client.state().ecs(); + + let vels = &ecs.read_component::(); + let Some(vel) = vels.get(client.entity()) else { return; }; + + let phys_states = &ecs.read_component::(); + let Some(phys) = phys_states.get(client.entity()) else {return;}; + + let positions = &ecs.read_component::(); + let Some(pos) = positions.get(client.entity()) else {return;}; + + let weather = ecs.read_resource::(); + // take id and remove to delete the previous lines. + + const LINE_WIDTH: f32 = 0.05; + // Fluid Velocity + { + let Some(fluid) = phys.in_fluid else { return;}; + let shape = DebugShape::Line([pos.0, pos.0 + fluid.flow_vel().0 / 2.], LINE_WIDTH); + let id = self.debug.add_shape(shape); + lines.fluid_vel = Some(id); + self.debug + .set_context(id, [0.0; 4], [0.18, 0.72, 0.87, 0.8], [0.0, 0.0, 0.0, 1.0]); + } + // Chunk Terrain Normal Vector + { + let Some(chunk) = client.current_chunk() else { return;}; + let shape = DebugShape::Line( + [ + pos.0, + pos.0 + + chunk + .meta() + .approx_chunk_terrain_normal() + .unwrap_or(Vec3::unit_z()) + * 2.5, + ], + LINE_WIDTH, + ); + let id = self.debug.add_shape(shape); + lines.chunk_normal = Some(id); + self.debug + .set_context(id, [0.0; 4], [0.22, 0.63, 0.1, 0.8], [0.0, 0.0, 0.0, 1.0]); + } + // Wind + { + let wind = weather.get_interpolated(pos.0.xy()).wind_vel(); + let shape = DebugShape::Line([pos.0, pos.0 + wind * 5.0], LINE_WIDTH); + let id = self.debug.add_shape(shape); + lines.wind = Some(id); + self.debug + .set_context(id, [0.0; 4], [0.76, 0.76, 0.76, 0.8], [0.0, 0.0, 0.0, 1.0]); + } + // Player Vel + { + let shape = DebugShape::Line([pos.0, pos.0 + vel.0 / 2.0], LINE_WIDTH); + let id = self.debug.add_shape(shape); + lines.vel = Some(id); + self.debug + .set_context(id, [0.0; 4], [0.98, 0.76, 0.01, 0.8], [0.0, 0.0, 0.0, 1.0]); + } + } + } } diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 8b1295e86d..b8d3c01d39 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -89,6 +89,14 @@ enum TickAction { Disconnect, } +#[derive(Default)] +pub struct PlayerDebugLines { + pub chunk_normal: Option, + pub wind: Option, + pub fluid_vel: Option, + pub vel: Option, +} + pub struct SessionState { scene: Scene, pub(crate) client: Rc>, @@ -113,6 +121,7 @@ pub struct SessionState { #[cfg(not(target_os = "macos"))] mumble_link: SharedLink, hitboxes: HashMap, + lines: PlayerDebugLines, tracks: HashMap, Vec>, } @@ -186,6 +195,7 @@ impl SessionState { hitboxes: HashMap::new(), metadata, tracks: HashMap::new(), + lines: Default::default(), } } @@ -237,6 +247,7 @@ impl SessionState { &mut self.hitboxes, &mut self.tracks, ); + self.scene.maintain_debug_vectors(&client, &mut self.lines); // All this camera code is just to determine if it's underwater for the sfx // filter diff --git a/voxygen/src/ui/egui/mod.rs b/voxygen/src/ui/egui/mod.rs index efdd9b18f4..2e440b12a9 100644 --- a/voxygen/src/ui/egui/mod.rs +++ b/voxygen/src/ui/egui/mod.rs @@ -102,6 +102,9 @@ impl EguiState { } } }, + EguiAction::SetShowDebugVector(enabled) => { + client.debug_vectors_enabled = enabled; + }, }); new_render_mode.map(|rm| SettingsChange::Graphics(Graphics::ChangeRenderMode(Box::new(rm))))