mirror of
https://codeberg.org/icewind/vbspview.git
synced 2026-06-03 18:24:09 +02:00
upgrade dependencies
This commit is contained in:
parent
d892adca58
commit
6765cc267f
9 changed files with 1053 additions and 1546 deletions
2149
Cargo.lock
generated
2149
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
22
Cargo.toml
22
Cargo.toml
|
|
@ -6,23 +6,23 @@ authors = ["Robin Appelman <robin@icewind.nl>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
[dependencies]
|
[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" }
|
vbsp = { version = "0.1.0", git = "https://github.com/icewind1991/vbsp" }
|
||||||
miette = { version = "4.2.1", features = ["fancy"] }
|
miette = { version = "5.5.0", features = ["fancy"] }
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.37"
|
||||||
delaunator = "1.0.1"
|
delaunator = "1.0.1"
|
||||||
itertools = "0.10.3"
|
itertools = "0.10.5"
|
||||||
steamlocate = "1.0.1"
|
steamlocate = "1.1.0"
|
||||||
vpk = { version = "0.1.4", git = "https://github.com/icewind1991/vpk-rs", branch = "perf" }
|
vpk = { version = "0.1.4", git = "https://github.com/icewind1991/vpk-rs", branch = "perf" }
|
||||||
vmdl = { version = "*", git = "https://github.com/icewind1991/vmdl" }
|
vmdl = { version = "*", git = "https://github.com/icewind1991/vmdl" }
|
||||||
tracing = "0.1.29"
|
tracing = "0.1.37"
|
||||||
tracing-subscriber = { version = "0.3.3", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
|
||||||
tracing-tree = "0.2.0"
|
tracing-tree = "0.2.2"
|
||||||
cgmath = "0.18.0"
|
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"
|
steamid-ng = "1.0.0"
|
||||||
clap = { version = "3.1.8", features = ["derive"] }
|
clap = { version = "4.0.29", features = ["derive"] }
|
||||||
splines = { version = "4.1.0", features = ["cgmath"] }
|
splines = { version = "4.1.1", features = ["cgmath"] }
|
||||||
|
|
||||||
[profile.dev.package."*"]
|
[profile.dev.package."*"]
|
||||||
opt-level = 2
|
opt-level = 2
|
||||||
|
|
|
||||||
24
flake.nix
24
flake.nix
|
|
@ -16,7 +16,29 @@
|
||||||
in rec {
|
in rec {
|
||||||
# `nix develop`
|
# `nix develop`
|
||||||
devShell = pkgs.mkShell {
|
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])}";
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
50
src/bsp.rs
50
src/bsp.rs
|
|
@ -1,38 +1,38 @@
|
||||||
use crate::{Error, Loader};
|
use crate::{Error, Loader};
|
||||||
use cgmath::{vec4, Matrix, SquareMatrix};
|
use cgmath::{vec4, Matrix, SquareMatrix};
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
use three_d::{CPUMesh, Indices, Mat4};
|
use three_d::{CpuMesh, Indices, Mat4, Positions, Vec3};
|
||||||
use vbsp::{Bsp, Handle, StaticPropLump};
|
use vbsp::{Bsp, Handle, StaticPropLump};
|
||||||
use vmdl::mdl::Mdl;
|
use vmdl::mdl::Mdl;
|
||||||
use vmdl::vtx::Vtx;
|
use vmdl::vtx::Vtx;
|
||||||
use vmdl::vvd::Vvd;
|
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)?;
|
let (cpu_mesh, bsp) = load_world(data)?;
|
||||||
loader.set_pack(bsp.pack.clone());
|
loader.set_pack(bsp.pack.clone());
|
||||||
let merged_props = load_props(loader, bsp.static_props())?;
|
let merged_props = load_props(loader, bsp.static_props())?;
|
||||||
Ok(vec![cpu_mesh, merged_props])
|
Ok(vec![cpu_mesh, merged_props])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_transform(coord: [f32; 3], transform: Mat4) -> [f32; 3] {
|
fn apply_transform<C: Into<Vec3>>(coord: C, transform: Mat4) -> Vec3 {
|
||||||
let coord = (transform * vec4(coord[0], coord[1], coord[2], 1.0)).truncate();
|
let coord = coord.into();
|
||||||
[coord.x, coord.y, coord.z]
|
(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();
|
let vec = vec.into();
|
||||||
[
|
Vec3 {
|
||||||
vec[1] * UNIT_SCALE,
|
x: vec.y * UNIT_SCALE,
|
||||||
vec[2] * UNIT_SCALE,
|
y: vec.z * UNIT_SCALE,
|
||||||
vec[0] * UNIT_SCALE,
|
z: vec.x * UNIT_SCALE,
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1 hammer unit is ~1.905cm
|
// 1 hammer unit is ~1.905cm
|
||||||
pub const UNIT_SCALE: f32 = 1.0 / (1.905 * 100.0);
|
pub const UNIT_SCALE: f32 = 1.0 / (1.905 * 100.0);
|
||||||
|
|
||||||
fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CPUMesh {
|
fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CpuMesh {
|
||||||
let positions: Vec<f32> = model
|
let positions: Vec<Vec3> = model
|
||||||
.faces()
|
.faces()
|
||||||
.filter(|face| face.is_visible())
|
.filter(|face| face.is_visible())
|
||||||
.flat_map(|face| {
|
.flat_map(|face| {
|
||||||
|
|
@ -41,11 +41,11 @@ fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CPUMesh {
|
||||||
.map(Either::Left)
|
.map(Either::Left)
|
||||||
.unwrap_or_else(|| Either::Right(face.triangulate().flatten()))
|
.unwrap_or_else(|| Either::Right(face.triangulate().flatten()))
|
||||||
})
|
})
|
||||||
.flat_map(map_coords)
|
.map(|c| map_coords(c).into())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut mesh = CPUMesh {
|
let mut mesh = CpuMesh {
|
||||||
positions,
|
positions: Positions::F32(positions),
|
||||||
..Default::default()
|
..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>>>(
|
fn load_props<'a, I: Iterator<Item = Handle<'a, StaticPropLump>>>(
|
||||||
loader: &Loader,
|
loader: &Loader,
|
||||||
props: I,
|
props: I,
|
||||||
) -> Result<CPUMesh, Error> {
|
) -> Result<CpuMesh, Error> {
|
||||||
merge_models(props.map(|prop| {
|
merge_models(props.map(|prop| {
|
||||||
let model = load_prop(loader, prop.model())?;
|
let model = load_prop(loader, prop.model())?;
|
||||||
let transform =
|
let transform =
|
||||||
|
|
@ -80,7 +80,7 @@ struct ModelData {
|
||||||
transform: Mat4,
|
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 positions = Vec::new();
|
||||||
let mut normals = Vec::new();
|
let mut normals = Vec::new();
|
||||||
let mut indices = 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 normal_transform = transform.invert().unwrap().transpose() * -1.0;
|
||||||
let model = prop.model;
|
let model = prop.model;
|
||||||
|
|
||||||
let offset = positions.len() as u32 / 3;
|
let offset = positions.len() as u32;
|
||||||
|
|
||||||
positions.extend(
|
positions.extend(
|
||||||
model
|
model
|
||||||
.vertices()
|
.vertices()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| map_coords(v.position))
|
.map(|v| map_coords(v.position))
|
||||||
.flat_map(|v| apply_transform(v, transform)),
|
.map(|v| apply_transform(v, transform)),
|
||||||
);
|
);
|
||||||
normals.extend(
|
normals.extend(
|
||||||
model
|
model
|
||||||
.vertices()
|
.vertices()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| map_coords(v.normal))
|
.map(|v| map_coords(v.normal))
|
||||||
.flat_map(|v| apply_transform(v, normal_transform)),
|
.map(|v| apply_transform(v, normal_transform)),
|
||||||
);
|
);
|
||||||
indices.extend(
|
indices.extend(
|
||||||
model
|
model
|
||||||
|
|
@ -115,15 +115,15 @@ fn merge_models<I: Iterator<Item = Result<ModelData, Error>>>(props: I) -> Resul
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(CPUMesh {
|
Ok(CpuMesh {
|
||||||
positions,
|
positions: Positions::F32(positions),
|
||||||
normals: Some(normals),
|
normals: Some(normals),
|
||||||
indices: Some(Indices::U32(indices)),
|
indices: Indices::U32(indices),
|
||||||
..Default::default()
|
..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 bsp = Bsp::read(data)?;
|
||||||
let world_model = bsp.models().next().ok_or(Error::Other("No world model"))?;
|
let world_model = bsp.models().next().ok_or(Error::Other("No world model"))?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ pub trait Control {
|
||||||
events: &mut [Event],
|
events: &mut [Event],
|
||||||
elapsed_time: f64,
|
elapsed_time: f64,
|
||||||
accumulated_time: f64,
|
accumulated_time: f64,
|
||||||
) -> ThreeDResult<bool>;
|
) -> bool;
|
||||||
|
|
||||||
fn ui(&mut self, _ui: &mut Ui) {}
|
fn ui(&mut self, _ui: &mut Ui) {}
|
||||||
|
|
||||||
|
|
@ -33,8 +33,8 @@ impl Control for FirstPerson {
|
||||||
events: &mut [Event],
|
events: &mut [Event],
|
||||||
_elapsed_time: f64,
|
_elapsed_time: f64,
|
||||||
_accumulated_time: f64,
|
_accumulated_time: f64,
|
||||||
) -> ThreeDResult<bool> {
|
) -> bool {
|
||||||
let change = self.control.handle_events(camera, events)?;
|
let change = self.control.handle_events(camera, events);
|
||||||
for event in events.iter_mut() {
|
for event in events.iter_mut() {
|
||||||
match event {
|
match event {
|
||||||
Event::KeyPress { kind, .. } => {
|
Event::KeyPress { kind, .. } => {
|
||||||
|
|
@ -48,19 +48,19 @@ impl Control for FirstPerson {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.keys[0] {
|
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] {
|
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] {
|
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] {
|
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],
|
events: &mut [Event],
|
||||||
_elapsed_time: f64,
|
_elapsed_time: f64,
|
||||||
_accumulated_time: f64,
|
_accumulated_time: f64,
|
||||||
) -> ThreeDResult<bool> {
|
) -> bool {
|
||||||
for event in events.iter_mut() {
|
for event in events.iter_mut() {
|
||||||
match event {
|
match event {
|
||||||
Event::Text(text) => {
|
Event::Text(text) => {
|
||||||
if text == "`" {
|
if text == "`" {
|
||||||
self.enabled = !self.enabled;
|
self.enabled = !self.enabled;
|
||||||
return Ok(true);
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(false)
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,7 +158,7 @@ impl Control for DemoCamera {
|
||||||
events: &mut [Event],
|
events: &mut [Event],
|
||||||
_elapsed_time: f64,
|
_elapsed_time: f64,
|
||||||
accumulated_time: f64,
|
accumulated_time: f64,
|
||||||
) -> ThreeDResult<bool> {
|
) -> bool {
|
||||||
let mut change = false;
|
let mut change = false;
|
||||||
for event in events.iter_mut() {
|
for event in events.iter_mut() {
|
||||||
match event {
|
match event {
|
||||||
|
|
@ -198,7 +198,7 @@ impl Control for DemoCamera {
|
||||||
self.force_update = false;
|
self.force_update = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.playing | change)
|
self.playing | change
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui(&mut self, ui: &mut Ui) {
|
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 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 angle_transform = Mat4::from_angle_y(degrees(yaw)) * Mat4::from_angle_x(degrees(pitch));
|
||||||
let target = position + (angle_transform * forward).truncate();
|
let target = position + (angle_transform * forward).truncate();
|
||||||
camera
|
camera.set_view(position, target, vec3(0.0, 1.0, 0.0))
|
||||||
.set_view(position, target, vec3(0.0, 1.0, 0.0))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tick_range(&self) -> RangeInclusive<u32> {
|
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) {
|
fn set_tick(&mut self, tick: u32, time: f64) {
|
||||||
|
|
@ -277,40 +275,36 @@ impl DemoCamera {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_camera_action(
|
fn apply_camera_action(camera: &mut Camera, control_type: CameraAction, x: f64) -> bool {
|
||||||
camera: &mut Camera,
|
|
||||||
control_type: CameraAction,
|
|
||||||
x: f64,
|
|
||||||
) -> ThreeDResult<bool> {
|
|
||||||
match control_type {
|
match control_type {
|
||||||
CameraAction::Pitch { speed } => {
|
CameraAction::Pitch { speed } => {
|
||||||
camera.pitch(radians(speed * x as f32))?;
|
camera.pitch(radians(speed * x as f32));
|
||||||
}
|
}
|
||||||
CameraAction::OrbitUp { speed, target } => {
|
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 } => {
|
CameraAction::Yaw { speed } => {
|
||||||
camera.yaw(radians(speed * x as f32))?;
|
camera.yaw(radians(speed * x as f32));
|
||||||
}
|
}
|
||||||
CameraAction::OrbitLeft { speed, target } => {
|
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 } => {
|
CameraAction::Roll { speed } => {
|
||||||
camera.roll(radians(speed * x as f32))?;
|
camera.roll(radians(speed * x as f32));
|
||||||
}
|
}
|
||||||
CameraAction::Left { speed } => {
|
CameraAction::Left { speed } => {
|
||||||
let change = -camera.right_direction() * x as f32 * speed;
|
let change = -camera.right_direction() * x as f32 * speed;
|
||||||
camera.translate(&change)?;
|
camera.translate(&change);
|
||||||
}
|
}
|
||||||
CameraAction::Up { speed } => {
|
CameraAction::Up { speed } => {
|
||||||
let right = camera.right_direction();
|
let right = camera.right_direction();
|
||||||
let up = right.cross(camera.view_direction());
|
let up = right.cross(camera.view_direction());
|
||||||
let change = up * x as f32 * speed;
|
let change = up * x as f32 * speed;
|
||||||
camera.translate(&change)?;
|
camera.translate(&change);
|
||||||
}
|
}
|
||||||
CameraAction::Forward { speed } => {
|
CameraAction::Forward { speed } => {
|
||||||
let change = camera.view_direction() * speed * x as f32;
|
let change = camera.view_direction() * speed * x as f32;
|
||||||
camera.translate(&change)?;
|
camera.translate(&change);
|
||||||
}
|
}
|
||||||
CameraAction::Zoom {
|
CameraAction::Zoom {
|
||||||
target,
|
target,
|
||||||
|
|
@ -318,11 +312,11 @@ fn apply_camera_action(
|
||||||
min,
|
min,
|
||||||
max,
|
max,
|
||||||
} => {
|
} => {
|
||||||
camera.zoom_towards(&target, speed * x as f32, min, max)?;
|
camera.zoom_towards(&target, speed * x as f32, min, max);
|
||||||
}
|
}
|
||||||
CameraAction::None => {}
|
CameraAction::None => {}
|
||||||
}
|
}
|
||||||
Ok(control_type != CameraAction::None)
|
control_type != CameraAction::None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
|
|
||||||
61
src/demo.rs
61
src/demo.rs
|
|
@ -4,7 +4,7 @@ use crate::Error;
|
||||||
use splines::{Interpolation, Key};
|
use splines::{Interpolation, Key};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
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::header::Header;
|
||||||
use tf_demo_parser::demo::message::packetentities::EntityId;
|
use tf_demo_parser::demo::message::packetentities::EntityId;
|
||||||
use tf_demo_parser::demo::message::Message;
|
use tf_demo_parser::demo::message::Message;
|
||||||
|
|
@ -20,7 +20,7 @@ pub struct DemoInfo {
|
||||||
pub ticks: u32,
|
pub ticks: u32,
|
||||||
pub map: String,
|
pub map: String,
|
||||||
pub positions: Positions,
|
pub positions: Positions,
|
||||||
pub start_tick: u32,
|
pub start_tick: DemoTick,
|
||||||
pub time_per_tick: f64,
|
pub time_per_tick: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,15 +55,15 @@ struct PovAnalyzer {
|
||||||
positions: Positions,
|
positions: Positions,
|
||||||
name: String,
|
name: String,
|
||||||
player: Option<EntityId>,
|
player: Option<EntityId>,
|
||||||
start_tick: u32,
|
start_tick: DemoTick,
|
||||||
pov_name: String,
|
pov_name: String,
|
||||||
is_pov: bool,
|
is_pov: bool,
|
||||||
last_tick: u32,
|
last_tick: DemoTick,
|
||||||
last_pov_tick: u32,
|
last_pov_tick: DemoTick,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageHandler for PovAnalyzer {
|
impl MessageHandler for PovAnalyzer {
|
||||||
type Output = (Positions, u32, f32);
|
type Output = (Positions, DemoTick, f32);
|
||||||
|
|
||||||
fn does_handle(message_type: MessageType) -> bool {
|
fn does_handle(message_type: MessageType) -> bool {
|
||||||
matches!(message_type, MessageType::PacketEntities)
|
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 {
|
if tick > self.last_tick {
|
||||||
self.last_tick = tick;
|
self.last_tick = tick;
|
||||||
const NON_LOCAL_ORIGIN: SendPropIdentifier =
|
const NON_LOCAL_ORIGIN: SendPropIdentifier =
|
||||||
|
|
@ -113,14 +113,14 @@ impl MessageHandler for PovAnalyzer {
|
||||||
}
|
}
|
||||||
NON_LOCAL_PITCH_ANGLES => {
|
NON_LOCAL_PITCH_ANGLES => {
|
||||||
self.positions.pitch.push(Key::new(
|
self.positions.pitch.push(Key::new(
|
||||||
tick as f32,
|
u32::from(tick) as f32,
|
||||||
Wrapping(f32::try_from(&prop.value).unwrap_or_default()),
|
Wrapping(f32::try_from(&prop.value).unwrap_or_default()),
|
||||||
Interpolation::Linear,
|
Interpolation::Linear,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
NON_LOCAL_YAW_ANGLES => {
|
NON_LOCAL_YAW_ANGLES => {
|
||||||
self.positions.yaw.push(Key::new(
|
self.positions.yaw.push(Key::new(
|
||||||
tick as f32,
|
u32::from(tick) as f32,
|
||||||
Wrapping(f32::try_from(&prop.value).unwrap_or_default()),
|
Wrapping(f32::try_from(&prop.value).unwrap_or_default()),
|
||||||
Interpolation::Linear,
|
Interpolation::Linear,
|
||||||
));
|
));
|
||||||
|
|
@ -137,9 +137,9 @@ impl MessageHandler for PovAnalyzer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.last_position != old_pos || old_offset != self.view_offset) && !self.is_pov {
|
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(
|
self.positions.positions.push(Key::new(
|
||||||
tick as f32,
|
u32::from(tick) as f32,
|
||||||
vec3(pos[0], pos[1] + self.view_offset, pos[2]),
|
vec3(pos[0], pos[1] + self.view_offset, pos[2]),
|
||||||
Interpolation::CatmullRom,
|
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() {
|
if table == "userinfo" && self.player.is_none() {
|
||||||
let _ = self.parse_user_info(
|
let _ = self.parse_user_info(
|
||||||
|
index as u16,
|
||||||
entry.text.as_ref().map(|s| s.as_ref()),
|
entry.text.as_ref().map(|s| s.as_ref()),
|
||||||
entry.extra_data.as_ref().map(|data| data.data.clone()),
|
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 {
|
if tick != self.last_pov_tick {
|
||||||
self.last_pov_tick = tick;
|
self.last_pov_tick = tick;
|
||||||
if self.is_pov {
|
if self.is_pov {
|
||||||
self.positions.pitch.push(Key::new(
|
self.positions.pitch.push(Key::new(
|
||||||
tick as f32,
|
u32::from(tick) as f32,
|
||||||
Wrapping(meta.view_angles[0].local_angles.y),
|
Wrapping(meta.view_angles[0].local_angles.y),
|
||||||
Interpolation::Linear,
|
Interpolation::Linear,
|
||||||
));
|
));
|
||||||
self.positions.yaw.push(Key::new(
|
self.positions.yaw.push(Key::new(
|
||||||
tick as f32,
|
u32::from(tick) as f32,
|
||||||
Wrapping(meta.view_angles[0].local_angles.x),
|
Wrapping(meta.view_angles[0].local_angles.x),
|
||||||
Interpolation::Linear,
|
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(
|
self.positions.positions.push(Key::new(
|
||||||
tick as f32,
|
u32::from(tick) as f32,
|
||||||
vec3(pos[0], pos[1] + self.view_offset, pos[2]),
|
vec3(pos[0], pos[1] + self.view_offset, pos[2]),
|
||||||
Interpolation::CatmullRom,
|
Interpolation::CatmullRom,
|
||||||
));
|
));
|
||||||
|
|
@ -197,16 +209,21 @@ impl PovAnalyzer {
|
||||||
positions: Positions::default(),
|
positions: Positions::default(),
|
||||||
name,
|
name,
|
||||||
player: None,
|
player: None,
|
||||||
start_tick: 0,
|
start_tick: DemoTick::default(),
|
||||||
pov_name: String::new(),
|
pov_name: String::new(),
|
||||||
is_pov: false,
|
is_pov: false,
|
||||||
last_tick: 0,
|
last_tick: DemoTick::default(),
|
||||||
last_pov_tick: 0,
|
last_pov_tick: DemoTick::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_user_info(&mut self, text: Option<&str>, data: Option<Stream>) -> ReadResult<()> {
|
fn parse_user_info(
|
||||||
if let Some(user_info) = UserInfo::parse_from_string_table(text, data)? {
|
&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
|
if user_info
|
||||||
.player_info
|
.player_info
|
||||||
.name
|
.name
|
||||||
|
|
|
||||||
18
src/main.rs
18
src/main.rs
|
|
@ -47,6 +47,10 @@ pub enum Error {
|
||||||
Demo(#[from] tf_demo_parser::ParseError),
|
Demo(#[from] tf_demo_parser::ParseError),
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Other(&'static str),
|
Other(&'static str),
|
||||||
|
#[error(transparent)]
|
||||||
|
Window(#[from] WindowError),
|
||||||
|
#[error(transparent)]
|
||||||
|
Render(#[from] RendererError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&'static str> for Error {
|
impl From<&'static str> for Error {
|
||||||
|
|
@ -98,10 +102,10 @@ fn main() -> Result<(), Error> {
|
||||||
fn play<C: Control + 'static>(
|
fn play<C: Control + 'static>(
|
||||||
window: Window,
|
window: Window,
|
||||||
control: C,
|
control: C,
|
||||||
meshes: Vec<CPUMesh>,
|
meshes: Vec<CpuMesh>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut renderer = Renderer::new(&window, control)?;
|
let mut renderer = Renderer::new(&window, control);
|
||||||
let material = PhysicalMaterial {
|
let material = CpuMaterial {
|
||||||
albedo: Color {
|
albedo: Color {
|
||||||
r: 128,
|
r: 128,
|
||||||
g: 128,
|
g: 128,
|
||||||
|
|
@ -113,10 +117,14 @@ fn play<C: Control + 'static>(
|
||||||
|
|
||||||
renderer.models = meshes
|
renderer.models = meshes
|
||||||
.into_iter()
|
.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<_, _>>()?;
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
window.render_loop(move |frame_input| renderer.render(frame_input).unwrap())?;
|
window.render_loop(move |frame_input| renderer.render(frame_input));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
179
src/renderer.rs
179
src/renderer.rs
|
|
@ -1,86 +1,78 @@
|
||||||
use crate::control::{Control, DebugToggle};
|
use crate::control::{Control, DebugToggle};
|
||||||
|
use crate::ui::DebugType;
|
||||||
use crate::DebugUI;
|
use crate::DebugUI;
|
||||||
use three_d::*;
|
use three_d::*;
|
||||||
|
|
||||||
pub struct Renderer<C: Control> {
|
pub struct Renderer<C: Control> {
|
||||||
gui: DebugUI,
|
gui: DebugUI,
|
||||||
pub models: Vec<Model<PhysicalMaterial>>,
|
pub models: Vec<Model<PhysicalMaterial>>,
|
||||||
lights: Lights,
|
ambient_lights: Vec<AmbientLight>,
|
||||||
|
directional_lights: Vec<DirectionalLight>,
|
||||||
pub context: Context,
|
pub context: Context,
|
||||||
pipeline: ForwardPipeline,
|
|
||||||
control: C,
|
control: C,
|
||||||
debug_toggle: DebugToggle,
|
debug_toggle: DebugToggle,
|
||||||
pub camera: Camera,
|
pub camera: Camera,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Control> Renderer<C> {
|
impl<C: Control> Renderer<C> {
|
||||||
pub fn new(window: &Window, control: C) -> ThreeDResult<Self> {
|
pub fn new(window: &Window, control: C) -> Self {
|
||||||
let context = window.gl().unwrap();
|
let context = window.gl();
|
||||||
let forward_pipeline = ForwardPipeline::new(&context).unwrap();
|
|
||||||
let camera = Camera::new_perspective(
|
let camera = Camera::new_perspective(
|
||||||
&context,
|
window.viewport(),
|
||||||
window.viewport().unwrap(),
|
|
||||||
vec3(9.0, 4.0, 5.0),
|
vec3(9.0, 4.0, 5.0),
|
||||||
vec3(0.0, 0.0, 0.0),
|
vec3(0.0, 0.0, 0.0),
|
||||||
vec3(0.0, 1.0, 0.0),
|
vec3(0.0, 1.0, 0.0),
|
||||||
degrees(60.0),
|
degrees(60.0),
|
||||||
0.1,
|
0.1,
|
||||||
30.0,
|
30.0,
|
||||||
)?;
|
);
|
||||||
|
|
||||||
let lights = Lights {
|
let ambient_lights = vec![AmbientLight {
|
||||||
ambient: Some(AmbientLight {
|
|
||||||
color: Color::WHITE,
|
color: Color::WHITE,
|
||||||
intensity: 0.2,
|
intensity: 0.2,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}];
|
||||||
directional: vec![
|
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)),
|
||||||
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 control = FirstPerson::new(0.1);
|
// let control = FirstPerson::new(0.1);
|
||||||
|
|
||||||
Ok(Self {
|
Self {
|
||||||
models: Vec::new(),
|
models: Vec::new(),
|
||||||
gui: DebugUI::new(&context)?,
|
gui: DebugUI::new(&context),
|
||||||
pipeline: forward_pipeline,
|
ambient_lights,
|
||||||
lights,
|
directional_lights,
|
||||||
context,
|
context,
|
||||||
control,
|
control,
|
||||||
debug_toggle: DebugToggle::new(),
|
debug_toggle: DebugToggle::new(),
|
||||||
camera,
|
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) =
|
let (ui_change, _panel_width) =
|
||||||
self.gui
|
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;
|
let change = frame_input.first_frame || ui_change;
|
||||||
if change {
|
if change {
|
||||||
if self.gui.shadows_enabled {
|
if self.gui.shadows_enabled {
|
||||||
self.lights.directional[0]
|
self.directional_lights[0]
|
||||||
.generate_shadow_map(4.0, 1024, 1024, &self.models)
|
.generate_shadow_map(1024, self.models.iter().flat_map(|model| model.iter()));
|
||||||
.unwrap();
|
self.directional_lights[1]
|
||||||
self.lights.directional[1]
|
.generate_shadow_map(1024, self.models.iter().flat_map(|model| model.iter()));
|
||||||
.generate_shadow_map(4.0, 1024, 1024, &self.models)
|
|
||||||
.unwrap();
|
|
||||||
} else {
|
} else {
|
||||||
self.lights.directional[0].clear_shadow_map();
|
self.directional_lights[0].clear_shadow_map();
|
||||||
self.lights.directional[1].clear_shadow_map();
|
self.directional_lights[1].clear_shadow_map();
|
||||||
}
|
}
|
||||||
self.lights.directional[0].set_intensity(self.gui.directional_intensity);
|
self.directional_lights[0].intensity = self.gui.directional_intensity;
|
||||||
self.lights.directional[1].set_intensity(self.gui.directional_intensity);
|
self.directional_lights[1].intensity = self.gui.directional_intensity;
|
||||||
self.lights.ambient.as_mut().unwrap().intensity = self.gui.ambient_intensity;
|
self.ambient_lights[0].intensity = self.gui.ambient_intensity;
|
||||||
self.camera
|
self.camera.set_perspective_projection(
|
||||||
.set_perspective_projection(
|
|
||||||
degrees(self.gui.fov),
|
degrees(self.gui.fov),
|
||||||
self.camera.z_near(),
|
self.camera.z_near(),
|
||||||
self.camera.z_far(),
|
self.camera.z_far(),
|
||||||
)
|
);
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let viewport = Viewport {
|
let viewport = Viewport {
|
||||||
|
|
@ -89,89 +81,74 @@ impl<C: Control> Renderer<C> {
|
||||||
width: frame_input.viewport.width,
|
width: frame_input.viewport.width,
|
||||||
height: frame_input.viewport.height,
|
height: frame_input.viewport.height,
|
||||||
};
|
};
|
||||||
self.camera.set_viewport(viewport).unwrap();
|
self.camera.set_viewport(viewport);
|
||||||
self.control
|
self.control.handle(
|
||||||
.handle(
|
|
||||||
&mut self.camera,
|
&mut self.camera,
|
||||||
&mut frame_input.events,
|
&mut frame_input.events,
|
||||||
frame_input.elapsed_time,
|
frame_input.elapsed_time,
|
||||||
frame_input.accumulated_time,
|
frame_input.accumulated_time,
|
||||||
)
|
);
|
||||||
.unwrap();
|
self.debug_toggle.handle(
|
||||||
self.debug_toggle
|
|
||||||
.handle(
|
|
||||||
&mut self.camera,
|
&mut self.camera,
|
||||||
&mut frame_input.events,
|
&mut frame_input.events,
|
||||||
frame_input.elapsed_time,
|
frame_input.elapsed_time,
|
||||||
frame_input.accumulated_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
|
// 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 {
|
match self.gui.debug_type {
|
||||||
DebugType::NORMAL => {
|
DebugType::NORMAL => target.render_with_material(
|
||||||
for model in &self.models {
|
&NormalMaterial::default(),
|
||||||
model.render_with_material(
|
|
||||||
&NormalMaterial::from_physical_material(&model.material),
|
|
||||||
&self.camera,
|
&self.camera,
|
||||||
&self.lights,
|
geometries,
|
||||||
)?;
|
lights,
|
||||||
}
|
),
|
||||||
}
|
|
||||||
DebugType::DEPTH => {
|
DebugType::DEPTH => {
|
||||||
let depth_material = DepthMaterial {
|
let mut depth_material = DepthMaterial::default();
|
||||||
max_distance: Some(self.gui.depth_max),
|
depth_material.max_distance = Some(self.gui.depth_max);
|
||||||
..DepthMaterial::default()
|
target.render_with_material(&depth_material, &self.camera, geometries, lights)
|
||||||
};
|
|
||||||
for model in &self.models {
|
|
||||||
model.render_with_material(&depth_material, &self.camera, &self.lights)?;
|
|
||||||
}
|
}
|
||||||
}
|
DebugType::ORM => target.render_with_material(
|
||||||
DebugType::ORM => {
|
&ORMMaterial::default(),
|
||||||
for model in &self.models {
|
|
||||||
model.render_with_material(
|
|
||||||
&ORMMaterial::from_physical_material(&model.material),
|
|
||||||
&self.camera,
|
&self.camera,
|
||||||
&self.lights,
|
geometries,
|
||||||
)?;
|
lights,
|
||||||
}
|
),
|
||||||
}
|
|
||||||
DebugType::POSITION => {
|
DebugType::POSITION => {
|
||||||
for model in &self.models {
|
|
||||||
let position_material = PositionMaterial::default();
|
let position_material = PositionMaterial::default();
|
||||||
model.render_with_material(
|
target.render_with_material(&position_material, &self.camera, geometries, lights)
|
||||||
&position_material,
|
}
|
||||||
|
DebugType::COLOR => target.render_with_material(
|
||||||
|
&ColorMaterial::default(),
|
||||||
&self.camera,
|
&self.camera,
|
||||||
&self.lights,
|
geometries,
|
||||||
)?;
|
lights,
|
||||||
}
|
),
|
||||||
}
|
DebugType::NONE => target.render(
|
||||||
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),
|
|
||||||
&self.camera,
|
&self.camera,
|
||||||
&self.lights,
|
self.models.iter().flat_map(|model| model.iter()),
|
||||||
)?;
|
lights,
|
||||||
}
|
),
|
||||||
}
|
|
||||||
DebugType::NONE => {
|
|
||||||
self.pipeline
|
|
||||||
.render_pass(&self.camera, &self.models, &self.lights)?
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.debug_toggle.enabled {
|
if self.debug_toggle.enabled {
|
||||||
self.gui.render()?;
|
target.write(|| self.gui.render());
|
||||||
}
|
}
|
||||||
Ok(())
|
FrameOutput::default()
|
||||||
})?;
|
|
||||||
Ok(FrameOutput::default())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
40
src/ui.rs
40
src/ui.rs
|
|
@ -1,6 +1,17 @@
|
||||||
use crate::Control;
|
use crate::Control;
|
||||||
use three_d::egui::*;
|
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 {
|
pub struct DebugUI {
|
||||||
ui: GUI,
|
ui: GUI,
|
||||||
|
|
@ -13,16 +24,16 @@ pub struct DebugUI {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugUI {
|
impl DebugUI {
|
||||||
pub fn new(context: &Context) -> ThreeDResult<Self> {
|
pub fn new(context: &Context) -> Self {
|
||||||
Ok(DebugUI {
|
DebugUI {
|
||||||
ui: three_d::GUI::new(context)?,
|
ui: three_d::GUI::new(context),
|
||||||
shadows_enabled: false,
|
shadows_enabled: false,
|
||||||
directional_intensity: 1.0,
|
directional_intensity: 1.0,
|
||||||
ambient_intensity: 0.2,
|
ambient_intensity: 0.2,
|
||||||
depth_max: 30.0,
|
depth_max: 30.0,
|
||||||
fov: 60.0,
|
fov: 60.0,
|
||||||
debug_type: DebugType::NORMAL,
|
debug_type: DebugType::NORMAL,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update<C: Control>(
|
pub fn update<C: Control>(
|
||||||
|
|
@ -30,16 +41,22 @@ impl DebugUI {
|
||||||
frame_input: &mut FrameInput,
|
frame_input: &mut FrameInput,
|
||||||
camera: &Camera,
|
camera: &Camera,
|
||||||
control: &mut C,
|
control: &mut C,
|
||||||
) -> ThreeDResult<(bool, u32)> {
|
) -> (bool, u32) {
|
||||||
let mut panel_width = 0;
|
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| {
|
SidePanel::left("side_panel").show(gui_context, |ui| {
|
||||||
ui.heading("Debug Panel");
|
ui.heading("Debug Panel");
|
||||||
ui.label(" toggle panel with <`>");
|
ui.label(" toggle panel with <`>");
|
||||||
|
|
||||||
ui.label("Light options");
|
ui.label("Light options");
|
||||||
ui.add(
|
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(
|
ui.add(
|
||||||
Slider::new(&mut self.directional_intensity, 0.0..=1.0)
|
Slider::new(&mut self.directional_intensity, 0.0..=1.0)
|
||||||
|
|
@ -67,12 +84,13 @@ impl DebugUI {
|
||||||
control.ui(ui);
|
control.ui(ui);
|
||||||
});
|
});
|
||||||
panel_width = gui_context.used_size().x as u32;
|
panel_width = gui_context.used_size().x as u32;
|
||||||
})?;
|
},
|
||||||
|
);
|
||||||
control.post_ui(frame_input.accumulated_time);
|
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()
|
self.ui.render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue