upgrade dependencies

This commit is contained in:
Robin Appelman 2022-12-06 16:36:19 +01:00
commit 6765cc267f
9 changed files with 1053 additions and 1546 deletions

2149
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -6,23 +6,23 @@ authors = ["Robin Appelman <robin@icewind.nl>"]
license = "MIT"
[dependencies]
three-d = "0.10.2"
three-d = { version = "0.14.0", features = ["egui-gui"] }
vbsp = { version = "0.1.0", git = "https://github.com/icewind1991/vbsp" }
miette = { version = "4.2.1", features = ["fancy"] }
thiserror = "1.0.30"
miette = { version = "5.5.0", features = ["fancy"] }
thiserror = "1.0.37"
delaunator = "1.0.1"
itertools = "0.10.3"
steamlocate = "1.0.1"
itertools = "0.10.5"
steamlocate = "1.1.0"
vpk = { version = "0.1.4", git = "https://github.com/icewind1991/vpk-rs", branch = "perf" }
vmdl = { version = "*", git = "https://github.com/icewind1991/vmdl" }
tracing = "0.1.29"
tracing-subscriber = { version = "0.3.3", features = ["env-filter"] }
tracing-tree = "0.2.0"
tracing = "0.1.37"
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
tracing-tree = "0.2.2"
cgmath = "0.18.0"
tf-demo-parser = { version = "0.4.0", path = "../demostf/tf-demo-parser" }
tf-demo-parser = { version = "0.4.0", git = "https://github.com/demostf/parser" }
steamid-ng = "1.0.0"
clap = { version = "3.1.8", features = ["derive"] }
splines = { version = "4.1.0", features = ["cgmath"] }
clap = { version = "4.0.29", features = ["derive"] }
splines = { version = "4.1.1", features = ["cgmath"] }
[profile.dev.package."*"]
opt-level = 2

View file

@ -16,7 +16,29 @@
in rec {
# `nix develop`
devShell = pkgs.mkShell {
nativeBuildInputs = with pkgs; [rustc cargo bacon cargo-edit cargo-outdated clippy cargo-audit cargo-msrv];
nativeBuildInputs = with pkgs; [
rustc
cargo
bacon
cargo-edit
cargo-outdated
clippy
cargo-audit
cargo-msrv
freetype
pkgconfig
cmake
fontconfig
xorg.libX11
xorg.libXcursor
xorg.libXrandr
xorg.libXi
glew-egl
egl-wayland
libGL
];
LD_LIBRARY_PATH = with pkgs; "/run/opengl-driver/lib/:${lib.makeLibraryPath ([libGL libGLU])}";
};
});
}

View file

@ -1,38 +1,38 @@
use crate::{Error, Loader};
use cgmath::{vec4, Matrix, SquareMatrix};
use itertools::Either;
use three_d::{CPUMesh, Indices, Mat4};
use three_d::{CpuMesh, Indices, Mat4, Positions, Vec3};
use vbsp::{Bsp, Handle, StaticPropLump};
use vmdl::mdl::Mdl;
use vmdl::vtx::Vtx;
use vmdl::vvd::Vvd;
pub fn load_map(data: &[u8], loader: &mut Loader) -> Result<Vec<CPUMesh>, Error> {
pub fn load_map(data: &[u8], loader: &mut Loader) -> Result<Vec<CpuMesh>, Error> {
let (cpu_mesh, bsp) = load_world(data)?;
loader.set_pack(bsp.pack.clone());
let merged_props = load_props(loader, bsp.static_props())?;
Ok(vec![cpu_mesh, merged_props])
}
fn apply_transform(coord: [f32; 3], transform: Mat4) -> [f32; 3] {
let coord = (transform * vec4(coord[0], coord[1], coord[2], 1.0)).truncate();
[coord.x, coord.y, coord.z]
fn apply_transform<C: Into<Vec3>>(coord: C, transform: Mat4) -> Vec3 {
let coord = coord.into();
(transform * vec4(coord.x, coord.y, coord.z, 1.0)).truncate()
}
pub fn map_coords<C: Into<[f32; 3]>>(vec: C) -> [f32; 3] {
pub fn map_coords<C: Into<Vec3>>(vec: C) -> Vec3 {
let vec = vec.into();
[
vec[1] * UNIT_SCALE,
vec[2] * UNIT_SCALE,
vec[0] * UNIT_SCALE,
]
Vec3 {
x: vec.y * UNIT_SCALE,
y: vec.z * UNIT_SCALE,
z: vec.x * UNIT_SCALE,
}
}
// 1 hammer unit is ~1.905cm
pub const UNIT_SCALE: f32 = 1.0 / (1.905 * 100.0);
fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CPUMesh {
let positions: Vec<f32> = model
fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CpuMesh {
let positions: Vec<Vec3> = model
.faces()
.filter(|face| face.is_visible())
.flat_map(|face| {
@ -41,11 +41,11 @@ fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CPUMesh {
.map(Either::Left)
.unwrap_or_else(|| Either::Right(face.triangulate().flatten()))
})
.flat_map(map_coords)
.map(|c| map_coords(c).into())
.collect();
let mut mesh = CPUMesh {
positions,
let mut mesh = CpuMesh {
positions: Positions::F32(positions),
..Default::default()
};
@ -57,7 +57,7 @@ fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CPUMesh {
fn load_props<'a, I: Iterator<Item = Handle<'a, StaticPropLump>>>(
loader: &Loader,
props: I,
) -> Result<CPUMesh, Error> {
) -> Result<CpuMesh, Error> {
merge_models(props.map(|prop| {
let model = load_prop(loader, prop.model())?;
let transform =
@ -80,7 +80,7 @@ struct ModelData {
transform: Mat4,
}
fn merge_models<I: Iterator<Item = Result<ModelData, Error>>>(props: I) -> Result<CPUMesh, Error> {
fn merge_models<I: Iterator<Item = Result<ModelData, Error>>>(props: I) -> Result<CpuMesh, Error> {
let mut positions = Vec::new();
let mut normals = Vec::new();
let mut indices = Vec::new();
@ -91,21 +91,21 @@ fn merge_models<I: Iterator<Item = Result<ModelData, Error>>>(props: I) -> Resul
let normal_transform = transform.invert().unwrap().transpose() * -1.0;
let model = prop.model;
let offset = positions.len() as u32 / 3;
let offset = positions.len() as u32;
positions.extend(
model
.vertices()
.iter()
.map(|v| map_coords(v.position))
.flat_map(|v| apply_transform(v, transform)),
.map(|v| apply_transform(v, transform)),
);
normals.extend(
model
.vertices()
.iter()
.map(|v| map_coords(v.normal))
.flat_map(|v| apply_transform(v, normal_transform)),
.map(|v| apply_transform(v, normal_transform)),
);
indices.extend(
model
@ -115,15 +115,15 @@ fn merge_models<I: Iterator<Item = Result<ModelData, Error>>>(props: I) -> Resul
);
}
Ok(CPUMesh {
positions,
Ok(CpuMesh {
positions: Positions::F32(positions),
normals: Some(normals),
indices: Some(Indices::U32(indices)),
indices: Indices::U32(indices),
..Default::default()
})
}
fn load_world(data: &[u8]) -> Result<(CPUMesh, Bsp), Error> {
fn load_world(data: &[u8]) -> Result<(CpuMesh, Bsp), Error> {
let bsp = Bsp::read(data)?;
let world_model = bsp.models().next().ok_or(Error::Other("No world model"))?;

View file

@ -13,7 +13,7 @@ pub trait Control {
events: &mut [Event],
elapsed_time: f64,
accumulated_time: f64,
) -> ThreeDResult<bool>;
) -> bool;
fn ui(&mut self, _ui: &mut Ui) {}
@ -33,8 +33,8 @@ impl Control for FirstPerson {
events: &mut [Event],
_elapsed_time: f64,
_accumulated_time: f64,
) -> ThreeDResult<bool> {
let change = self.control.handle_events(camera, events)?;
) -> bool {
let change = self.control.handle_events(camera, events);
for event in events.iter_mut() {
match event {
Event::KeyPress { kind, .. } => {
@ -48,19 +48,19 @@ impl Control for FirstPerson {
}
if self.keys[0] {
apply_camera_action(camera, CameraAction::Forward { speed: self.speed }, 1.0)?;
apply_camera_action(camera, CameraAction::Forward { speed: self.speed }, 1.0);
}
if self.keys[1] {
apply_camera_action(camera, CameraAction::Forward { speed: self.speed }, -1.0)?;
apply_camera_action(camera, CameraAction::Forward { speed: self.speed }, -1.0);
}
if self.keys[2] {
apply_camera_action(camera, CameraAction::Left { speed: self.speed }, 1.0)?;
apply_camera_action(camera, CameraAction::Left { speed: self.speed }, 1.0);
}
if self.keys[3] {
apply_camera_action(camera, CameraAction::Left { speed: self.speed }, -1.0)?;
apply_camera_action(camera, CameraAction::Left { speed: self.speed }, -1.0);
}
Ok(self.keys.iter().fold(change, |change, key| change && *key))
self.keys.iter().fold(change, |change, key| change && *key)
}
}
@ -113,20 +113,20 @@ impl Control for DebugToggle {
events: &mut [Event],
_elapsed_time: f64,
_accumulated_time: f64,
) -> ThreeDResult<bool> {
) -> bool {
for event in events.iter_mut() {
match event {
Event::Text(text) => {
if text == "`" {
self.enabled = !self.enabled;
return Ok(true);
return true;
}
}
_ => {}
};
}
Ok(false)
false
}
}
@ -158,7 +158,7 @@ impl Control for DemoCamera {
events: &mut [Event],
_elapsed_time: f64,
accumulated_time: f64,
) -> ThreeDResult<bool> {
) -> bool {
let mut change = false;
for event in events.iter_mut() {
match event {
@ -198,7 +198,7 @@ impl Control for DemoCamera {
self.force_update = false;
}
Ok(self.playing | change)
self.playing | change
}
fn ui(&mut self, ui: &mut Ui) {
@ -248,13 +248,11 @@ impl DemoCamera {
let forward = vec4(0.0, 0.0, 1.0, 1.0);
let angle_transform = Mat4::from_angle_y(degrees(yaw)) * Mat4::from_angle_x(degrees(pitch));
let target = position + (angle_transform * forward).truncate();
camera
.set_view(position, target, vec3(0.0, 1.0, 0.0))
.unwrap();
camera.set_view(position, target, vec3(0.0, 1.0, 0.0))
}
fn tick_range(&self) -> RangeInclusive<u32> {
self.demo.start_tick..=self.demo.ticks + self.demo.start_tick
u32::from(self.demo.start_tick)..=self.demo.ticks + u32::from(self.demo.start_tick)
}
fn set_tick(&mut self, tick: u32, time: f64) {
@ -277,40 +275,36 @@ impl DemoCamera {
}
}
fn apply_camera_action(
camera: &mut Camera,
control_type: CameraAction,
x: f64,
) -> ThreeDResult<bool> {
fn apply_camera_action(camera: &mut Camera, control_type: CameraAction, x: f64) -> bool {
match control_type {
CameraAction::Pitch { speed } => {
camera.pitch(radians(speed * x as f32))?;
camera.pitch(radians(speed * x as f32));
}
CameraAction::OrbitUp { speed, target } => {
camera.rotate_around_with_fixed_up(&target, 0.0, speed * x as f32)?;
camera.rotate_around_with_fixed_up(&target, 0.0, speed * x as f32);
}
CameraAction::Yaw { speed } => {
camera.yaw(radians(speed * x as f32))?;
camera.yaw(radians(speed * x as f32));
}
CameraAction::OrbitLeft { speed, target } => {
camera.rotate_around_with_fixed_up(&target, speed * x as f32, 0.0)?;
camera.rotate_around_with_fixed_up(&target, speed * x as f32, 0.0);
}
CameraAction::Roll { speed } => {
camera.roll(radians(speed * x as f32))?;
camera.roll(radians(speed * x as f32));
}
CameraAction::Left { speed } => {
let change = -camera.right_direction() * x as f32 * speed;
camera.translate(&change)?;
camera.translate(&change);
}
CameraAction::Up { speed } => {
let right = camera.right_direction();
let up = right.cross(camera.view_direction());
let change = up * x as f32 * speed;
camera.translate(&change)?;
camera.translate(&change);
}
CameraAction::Forward { speed } => {
let change = camera.view_direction() * speed * x as f32;
camera.translate(&change)?;
camera.translate(&change);
}
CameraAction::Zoom {
target,
@ -318,11 +312,11 @@ fn apply_camera_action(
min,
max,
} => {
camera.zoom_towards(&target, speed * x as f32, min, max)?;
camera.zoom_towards(&target, speed * x as f32, min, max);
}
CameraAction::None => {}
}
Ok(control_type != CameraAction::None)
control_type != CameraAction::None
}
#[derive(Copy, Clone, Debug)]

View file

@ -4,7 +4,7 @@ use crate::Error;
use splines::{Interpolation, Key};
use std::fs;
use std::path::Path;
use tf_demo_parser::demo::data::UserInfo;
use tf_demo_parser::demo::data::{DemoTick, UserInfo};
use tf_demo_parser::demo::header::Header;
use tf_demo_parser::demo::message::packetentities::EntityId;
use tf_demo_parser::demo::message::Message;
@ -20,7 +20,7 @@ pub struct DemoInfo {
pub ticks: u32,
pub map: String,
pub positions: Positions,
pub start_tick: u32,
pub start_tick: DemoTick,
pub time_per_tick: f64,
}
@ -55,15 +55,15 @@ struct PovAnalyzer {
positions: Positions,
name: String,
player: Option<EntityId>,
start_tick: u32,
start_tick: DemoTick,
pov_name: String,
is_pov: bool,
last_tick: u32,
last_pov_tick: u32,
last_tick: DemoTick,
last_pov_tick: DemoTick,
}
impl MessageHandler for PovAnalyzer {
type Output = (Positions, u32, f32);
type Output = (Positions, DemoTick, f32);
fn does_handle(message_type: MessageType) -> bool {
matches!(message_type, MessageType::PacketEntities)
@ -76,7 +76,7 @@ impl MessageHandler for PovAnalyzer {
}
}
fn handle_message(&mut self, message: &Message, tick: u32) {
fn handle_message(&mut self, message: &Message, tick: DemoTick, _state: &ParserState) {
if tick > self.last_tick {
self.last_tick = tick;
const NON_LOCAL_ORIGIN: SendPropIdentifier =
@ -113,14 +113,14 @@ impl MessageHandler for PovAnalyzer {
}
NON_LOCAL_PITCH_ANGLES => {
self.positions.pitch.push(Key::new(
tick as f32,
u32::from(tick) as f32,
Wrapping(f32::try_from(&prop.value).unwrap_or_default()),
Interpolation::Linear,
));
}
NON_LOCAL_YAW_ANGLES => {
self.positions.yaw.push(Key::new(
tick as f32,
u32::from(tick) as f32,
Wrapping(f32::try_from(&prop.value).unwrap_or_default()),
Interpolation::Linear,
));
@ -137,9 +137,9 @@ impl MessageHandler for PovAnalyzer {
}
if (self.last_position != old_pos || old_offset != self.view_offset) && !self.is_pov {
let pos = map_coords(self.last_position);
let pos = map_coords(<[f32; 3]>::from(self.last_position));
self.positions.positions.push(Key::new(
tick as f32,
u32::from(tick) as f32,
vec3(pos[0], pos[1] + self.view_offset, pos[2]),
Interpolation::CatmullRom,
));
@ -147,32 +147,44 @@ impl MessageHandler for PovAnalyzer {
}
}
fn handle_string_entry(&mut self, table: &str, _index: usize, entry: &StringTableEntry) {
fn handle_string_entry(
&mut self,
table: &str,
index: usize,
entry: &StringTableEntry,
_state: &ParserState,
) {
if table == "userinfo" && self.player.is_none() {
let _ = self.parse_user_info(
index as u16,
entry.text.as_ref().map(|s| s.as_ref()),
entry.extra_data.as_ref().map(|data| data.data.clone()),
);
}
}
fn handle_packet_meta(&mut self, tick: u32, meta: &MessagePacketMeta) {
fn handle_packet_meta(
&mut self,
tick: DemoTick,
meta: &MessagePacketMeta,
_state: &ParserState,
) {
if tick != self.last_pov_tick {
self.last_pov_tick = tick;
if self.is_pov {
self.positions.pitch.push(Key::new(
tick as f32,
u32::from(tick) as f32,
Wrapping(meta.view_angles[0].local_angles.y),
Interpolation::Linear,
));
self.positions.yaw.push(Key::new(
tick as f32,
u32::from(tick) as f32,
Wrapping(meta.view_angles[0].local_angles.x),
Interpolation::Linear,
));
let pos = map_coords(meta.view_angles[0].origin);
let pos = map_coords(<[f32; 3]>::from(meta.view_angles[0].origin));
self.positions.positions.push(Key::new(
tick as f32,
u32::from(tick) as f32,
vec3(pos[0], pos[1] + self.view_offset, pos[2]),
Interpolation::CatmullRom,
));
@ -197,16 +209,21 @@ impl PovAnalyzer {
positions: Positions::default(),
name,
player: None,
start_tick: 0,
start_tick: DemoTick::default(),
pov_name: String::new(),
is_pov: false,
last_tick: 0,
last_pov_tick: 0,
last_tick: DemoTick::default(),
last_pov_tick: DemoTick::default(),
}
}
fn parse_user_info(&mut self, text: Option<&str>, data: Option<Stream>) -> ReadResult<()> {
if let Some(user_info) = UserInfo::parse_from_string_table(text, data)? {
fn parse_user_info(
&mut self,
index: u16,
text: Option<&str>,
data: Option<Stream>,
) -> ReadResult<()> {
if let Some(user_info) = UserInfo::parse_from_string_table(index, text, data)? {
if user_info
.player_info
.name

View file

@ -47,6 +47,10 @@ pub enum Error {
Demo(#[from] tf_demo_parser::ParseError),
#[error("{0}")]
Other(&'static str),
#[error(transparent)]
Window(#[from] WindowError),
#[error(transparent)]
Render(#[from] RendererError),
}
impl From<&'static str> for Error {
@ -98,10 +102,10 @@ fn main() -> Result<(), Error> {
fn play<C: Control + 'static>(
window: Window,
control: C,
meshes: Vec<CPUMesh>,
meshes: Vec<CpuMesh>,
) -> Result<(), Error> {
let mut renderer = Renderer::new(&window, control)?;
let material = PhysicalMaterial {
let mut renderer = Renderer::new(&window, control);
let material = CpuMaterial {
albedo: Color {
r: 128,
g: 128,
@ -113,10 +117,14 @@ fn play<C: Control + 'static>(
renderer.models = meshes
.into_iter()
.map(|mesh| Model::new_with_material(&renderer.context, &mesh, material.clone()))
.map(|mesh| CpuModel {
geometries: vec![mesh],
materials: vec![material.clone()],
})
.map(|model| Model::new(&renderer.context, &model))
.collect::<Result<_, _>>()?;
window.render_loop(move |frame_input| renderer.render(frame_input).unwrap())?;
window.render_loop(move |frame_input| renderer.render(frame_input));
Ok(())
}

View file

@ -1,86 +1,78 @@
use crate::control::{Control, DebugToggle};
use crate::ui::DebugType;
use crate::DebugUI;
use three_d::*;
pub struct Renderer<C: Control> {
gui: DebugUI,
pub models: Vec<Model<PhysicalMaterial>>,
lights: Lights,
ambient_lights: Vec<AmbientLight>,
directional_lights: Vec<DirectionalLight>,
pub context: Context,
pipeline: ForwardPipeline,
control: C,
debug_toggle: DebugToggle,
pub camera: Camera,
}
impl<C: Control> Renderer<C> {
pub fn new(window: &Window, control: C) -> ThreeDResult<Self> {
let context = window.gl().unwrap();
let forward_pipeline = ForwardPipeline::new(&context).unwrap();
pub fn new(window: &Window, control: C) -> Self {
let context = window.gl();
let camera = Camera::new_perspective(
&context,
window.viewport().unwrap(),
window.viewport(),
vec3(9.0, 4.0, 5.0),
vec3(0.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
degrees(60.0),
0.1,
30.0,
)?;
);
let lights = Lights {
ambient: Some(AmbientLight {
let ambient_lights = vec![AmbientLight {
color: Color::WHITE,
intensity: 0.2,
..Default::default()
}),
directional: vec![
DirectionalLight::new(&context, 1.0, Color::WHITE, &vec3(0.0, -1.0, 0.0))?,
DirectionalLight::new(&context, 1.0, Color::WHITE, &vec3(0.0, 1.0, 0.0))?,
],
..Default::default()
};
}];
let directional_lights = vec![
DirectionalLight::new(&context, 1.0, Color::WHITE, &vec3(0.0, -1.0, 0.0)),
DirectionalLight::new(&context, 1.0, Color::WHITE, &vec3(0.0, 1.0, 0.0)),
];
// let control = FirstPerson::new(0.1);
Ok(Self {
Self {
models: Vec::new(),
gui: DebugUI::new(&context)?,
pipeline: forward_pipeline,
lights,
gui: DebugUI::new(&context),
ambient_lights,
directional_lights,
context,
control,
debug_toggle: DebugToggle::new(),
camera,
})
}
}
pub fn render(&mut self, mut frame_input: FrameInput) -> ThreeDResult<FrameOutput> {
pub fn render(&mut self, mut frame_input: FrameInput) -> FrameOutput {
let (ui_change, _panel_width) =
self.gui
.update(&mut frame_input, &self.camera, &mut self.control)?;
.update(&mut frame_input, &self.camera, &mut self.control);
let change = frame_input.first_frame || ui_change;
if change {
if self.gui.shadows_enabled {
self.lights.directional[0]
.generate_shadow_map(4.0, 1024, 1024, &self.models)
.unwrap();
self.lights.directional[1]
.generate_shadow_map(4.0, 1024, 1024, &self.models)
.unwrap();
self.directional_lights[0]
.generate_shadow_map(1024, self.models.iter().flat_map(|model| model.iter()));
self.directional_lights[1]
.generate_shadow_map(1024, self.models.iter().flat_map(|model| model.iter()));
} else {
self.lights.directional[0].clear_shadow_map();
self.lights.directional[1].clear_shadow_map();
self.directional_lights[0].clear_shadow_map();
self.directional_lights[1].clear_shadow_map();
}
self.lights.directional[0].set_intensity(self.gui.directional_intensity);
self.lights.directional[1].set_intensity(self.gui.directional_intensity);
self.lights.ambient.as_mut().unwrap().intensity = self.gui.ambient_intensity;
self.camera
.set_perspective_projection(
self.directional_lights[0].intensity = self.gui.directional_intensity;
self.directional_lights[1].intensity = self.gui.directional_intensity;
self.ambient_lights[0].intensity = self.gui.ambient_intensity;
self.camera.set_perspective_projection(
degrees(self.gui.fov),
self.camera.z_near(),
self.camera.z_far(),
)
.unwrap();
);
}
let viewport = Viewport {
@ -89,89 +81,74 @@ impl<C: Control> Renderer<C> {
width: frame_input.viewport.width,
height: frame_input.viewport.height,
};
self.camera.set_viewport(viewport).unwrap();
self.control
.handle(
self.camera.set_viewport(viewport);
self.control.handle(
&mut self.camera,
&mut frame_input.events,
frame_input.elapsed_time,
frame_input.accumulated_time,
)
.unwrap();
self.debug_toggle
.handle(
);
self.debug_toggle.handle(
&mut self.camera,
&mut frame_input.events,
frame_input.elapsed_time,
frame_input.accumulated_time,
)
.unwrap();
);
let lights = &[
&self.ambient_lights[0] as &dyn Light,
&self.directional_lights[0],
&self.directional_lights[1],
];
// Light pass
Screen::write(&self.context, ClearState::default(), || {
let target = frame_input.screen();
target.clear(ClearState::default());
let geometries = self
.models
.iter()
.flat_map(|model| model.iter())
.map(|gm| &gm.geometry);
match self.gui.debug_type {
DebugType::NORMAL => {
for model in &self.models {
model.render_with_material(
&NormalMaterial::from_physical_material(&model.material),
DebugType::NORMAL => target.render_with_material(
&NormalMaterial::default(),
&self.camera,
&self.lights,
)?;
}
}
geometries,
lights,
),
DebugType::DEPTH => {
let depth_material = DepthMaterial {
max_distance: Some(self.gui.depth_max),
..DepthMaterial::default()
};
for model in &self.models {
model.render_with_material(&depth_material, &self.camera, &self.lights)?;
let mut depth_material = DepthMaterial::default();
depth_material.max_distance = Some(self.gui.depth_max);
target.render_with_material(&depth_material, &self.camera, geometries, lights)
}
}
DebugType::ORM => {
for model in &self.models {
model.render_with_material(
&ORMMaterial::from_physical_material(&model.material),
DebugType::ORM => target.render_with_material(
&ORMMaterial::default(),
&self.camera,
&self.lights,
)?;
}
}
geometries,
lights,
),
DebugType::POSITION => {
for model in &self.models {
let position_material = PositionMaterial::default();
model.render_with_material(
&position_material,
target.render_with_material(&position_material, &self.camera, geometries, lights)
}
DebugType::COLOR => target.render_with_material(
&ColorMaterial::default(),
&self.camera,
&self.lights,
)?;
}
}
DebugType::UV => {
for model in &self.models {
let uv_material = UVMaterial::default();
model.render_with_material(&uv_material, &self.camera, &self.lights)?;
}
}
DebugType::COLOR => {
for model in &self.models {
model.render_with_material(
&ColorMaterial::from_physical_material(&model.material),
geometries,
lights,
),
DebugType::NONE => target.render(
&self.camera,
&self.lights,
)?;
}
}
DebugType::NONE => {
self.pipeline
.render_pass(&self.camera, &self.models, &self.lights)?
}
self.models.iter().flat_map(|model| model.iter()),
lights,
),
};
if self.debug_toggle.enabled {
self.gui.render()?;
target.write(|| self.gui.render());
}
Ok(())
})?;
Ok(FrameOutput::default())
FrameOutput::default()
}
}

View file

@ -1,6 +1,17 @@
use crate::Control;
use three_d::egui::*;
use three_d::{Camera, Context, DebugType, FrameInput, ThreeDResult, GUI};
use three_d::{Camera, Context, FrameInput, GUI};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum DebugType {
POSITION,
NORMAL,
COLOR,
DEPTH,
ORM,
NONE,
}
pub struct DebugUI {
ui: GUI,
@ -13,16 +24,16 @@ pub struct DebugUI {
}
impl DebugUI {
pub fn new(context: &Context) -> ThreeDResult<Self> {
Ok(DebugUI {
ui: three_d::GUI::new(context)?,
pub fn new(context: &Context) -> Self {
DebugUI {
ui: three_d::GUI::new(context),
shadows_enabled: false,
directional_intensity: 1.0,
ambient_intensity: 0.2,
depth_max: 30.0,
fov: 60.0,
debug_type: DebugType::NORMAL,
})
}
}
pub fn update<C: Control>(
@ -30,16 +41,22 @@ impl DebugUI {
frame_input: &mut FrameInput,
camera: &Camera,
control: &mut C,
) -> ThreeDResult<(bool, u32)> {
) -> (bool, u32) {
let mut panel_width = 0;
let change = self.ui.update(frame_input, |gui_context| {
let change = self.ui.update(
&mut frame_input.events,
frame_input.accumulated_time,
frame_input.viewport,
frame_input.device_pixel_ratio,
|gui_context| {
SidePanel::left("side_panel").show(gui_context, |ui| {
ui.heading("Debug Panel");
ui.label(" toggle panel with <`>");
ui.label("Light options");
ui.add(
Slider::new(&mut self.ambient_intensity, 0.0..=1.0).text("Ambient intensity"),
Slider::new(&mut self.ambient_intensity, 0.0..=1.0)
.text("Ambient intensity"),
);
ui.add(
Slider::new(&mut self.directional_intensity, 0.0..=1.0)
@ -67,12 +84,13 @@ impl DebugUI {
control.ui(ui);
});
panel_width = gui_context.used_size().x as u32;
})?;
},
);
control.post_ui(frame_input.accumulated_time);
Ok((change, panel_width))
(change, panel_width)
}
pub fn render(&mut self) -> ThreeDResult<()> {
pub fn render(&mut self) -> () {
self.ui.render()
}
}