summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock105
-rw-r--r--client/Cargo.toml2
-rw-r--r--client/src/camera.rs37
-rw-r--r--client/src/main.rs2
-rw-r--r--client/src/renderer.rs7
-rw-r--r--client/src/scene_prepare.rs2
-rw-r--r--client/src/scene_render.rs6
-rw-r--r--client/src/state.rs30
-rw-r--r--client/src/ui.rs54
-rw-r--r--client/src/window.rs35
10 files changed, 269 insertions, 11 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1d8744a..904c78a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -376,6 +376,20 @@ name = "bytemuck"
version = "1.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"
+dependencies = [
+ "bytemuck_derive",
+]
+
+[[package]]
+name = "bytemuck_derive"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
[[package]]
name = "byteorder"
@@ -776,12 +790,63 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53"
[[package]]
+name = "ecolor"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d72e9c39f6e11a2e922d04a34ec5e7ef522ea3f5a1acfca7a19d16ad5fe50f5"
+dependencies = [
+ "bytemuck",
+ "emath",
+]
+
+[[package]]
+name = "egui"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "252d52224d35be1535d7fd1d6139ce071fb42c9097773e79f7665604f5596b5e"
+dependencies = [
+ "ahash",
+ "emath",
+ "epaint",
+ "nohash-hasher",
+ "profiling",
+]
+
+[[package]]
+name = "egui-wgpu"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26c1e821d2d8921ef6ce98b258c7e24d9d6aab2ca1f9cdf374eca997e7f67f59"
+dependencies = [
+ "ahash",
+ "bytemuck",
+ "document-features",
+ "egui",
+ "epaint",
+ "log",
+ "profiling",
+ "thiserror",
+ "type-map",
+ "web-time",
+ "wgpu",
+]
+
+[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
+name = "emath"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4fe73c1207b864ee40aa0b0c038d6092af1030744678c60188a05c28553515d"
+dependencies = [
+ "bytemuck",
+]
+
+[[package]]
name = "env_filter"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -805,6 +870,29 @@ dependencies = [
]
[[package]]
+name = "epaint"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5666f8d25236293c966fbb3635eac18b04ad1914e3bab55bc7d44b9980cafcac"
+dependencies = [
+ "ab_glyph",
+ "ahash",
+ "bytemuck",
+ "ecolor",
+ "emath",
+ "epaint_default_fonts",
+ "nohash-hasher",
+ "parking_lot",
+ "profiling",
+]
+
+[[package]]
+name = "epaint_default_fonts"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66f6ddac3e6ac6fd4c3d48bb8b1943472f8da0f43a4303bcd8a18aa594401c80"
+
+[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1523,6 +1611,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
[[package]]
+name = "nohash-hasher"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
+
+[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2634,6 +2728,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
[[package]]
+name = "type-map"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f"
+dependencies = [
+ "rustc-hash",
+]
+
+[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2907,6 +3010,8 @@ dependencies = [
"audiopus",
"clap",
"cpal",
+ "egui",
+ "egui-wgpu",
"env_logger",
"glam",
"image",
diff --git a/client/Cargo.toml b/client/Cargo.toml
index da0f5c6..de8bf01 100644
--- a/client/Cargo.toml
+++ b/client/Cargo.toml
@@ -17,3 +17,5 @@ weareshared = { path = "../shared" }
rand = "0.9.0-beta.1"
glam = "0.29.2"
image = "0.25.5"
+egui-wgpu = "0.30.0"
+egui = "0.30.0"
diff --git a/client/src/camera.rs b/client/src/camera.rs
new file mode 100644
index 0000000..289e773
--- /dev/null
+++ b/client/src/camera.rs
@@ -0,0 +1,37 @@
+use glam::{EulerRot, Mat3, Mat4, Vec2, Vec3};
+
+pub struct Camera {
+ pos: Vec3,
+ rot: Vec3,
+ fov: f32,
+ aspect: f32,
+}
+
+impl Camera {
+ pub fn new() -> Self {
+ Self {
+ aspect: 1.,
+ fov: 0.5,
+ pos: Vec3::Z * 3.,
+ rot: Vec3::ZERO,
+ }
+ }
+ pub fn update(&mut self, input_move: Vec3, input_rot: Vec2, dt: f32) {
+ self.pos += input_move * dt;
+ self.rot.x += input_rot.x * 0.002;
+ self.rot.y += input_rot.y * 0.002;
+ }
+ pub fn to_matrix(&self) -> Mat4 {
+ // let tdir =
+ // Mat3::from_euler(EulerRot::ZXY, self.rot.x, self.rot.y, self.rot.z) * Vec3::NEG_Z;
+ // * Mat4::look_at_rh(self.pos, self.pos + tdir, Vec3::Y)
+
+ Mat4::perspective_infinite_reverse_rh(self.fov, self.aspect, 0.1)
+ * Mat4::from_mat3(Mat3::from_euler(
+ EulerRot::ZXY,
+ self.rot.x,
+ self.rot.y,
+ self.rot.z,
+ ))
+ }
+}
diff --git a/client/src/main.rs b/client/src/main.rs
index 1b615d1..48d9dcb 100644
--- a/client/src/main.rs
+++ b/client/src/main.rs
@@ -6,6 +6,8 @@ pub mod scene_prepare;
pub mod scene_render;
pub mod state;
pub mod window;
+pub mod camera;
+// pub mod ui;
use anyhow::Result;
use clap::Parser;
diff --git a/client/src/renderer.rs b/client/src/renderer.rs
index 3591503..3e06508 100644
--- a/client/src/renderer.rs
+++ b/client/src/renderer.rs
@@ -1,4 +1,4 @@
-use crate::{scene_prepare::ScenePreparer, scene_render::ScenePipeline};
+use crate::{camera::Camera, scene_prepare::ScenePreparer, scene_render::ScenePipeline};
use anyhow::{Result, anyhow};
use log::{info, warn};
use pollster::FutureExt;
@@ -85,7 +85,7 @@ impl<'a> Renderer<'a> {
self.scene_pipeline.resize(&self.device, width, height);
}
- pub fn draw(&mut self, scene: &SceneTree) -> Result<()> {
+ pub fn draw(&mut self, scene: &SceneTree, camera: &Camera) -> Result<()> {
if self.surface_needs_reconfigure {
self.surface
.configure(&self.device, &self.surface_configuration);
@@ -104,11 +104,14 @@ impl<'a> Renderer<'a> {
.device
.create_command_encoder(&CommandEncoderDescriptor { label: None });
+ let projection = camera.to_matrix();
+
self.scene_pipeline.draw(
&mut commands,
&target_view,
scene,
&mut self.scene_prepare.prefabs,
+ projection,
);
let i = self.queue.submit(Some(commands.finish()));
diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs
index f7a5bc8..fcc7932 100644
--- a/client/src/scene_prepare.rs
+++ b/client/src/scene_prepare.rs
@@ -1,6 +1,6 @@
use crate::download::Downloader;
use anyhow::{Context, Result};
-use image::{ImageFormat, ImageReader};
+use image::ImageReader;
use log::debug;
use std::{
collections::{HashMap, HashSet},
diff --git a/client/src/scene_render.rs b/client/src/scene_render.rs
index 8703c9f..7e634df 100644
--- a/client/src/scene_render.rs
+++ b/client/src/scene_render.rs
@@ -1,4 +1,4 @@
-use glam::{EulerRot, Mat3, Mat4, Vec3, vec3};
+use glam::{EulerRot, Mat3, Mat4};
use std::sync::Arc;
use weareshared::{packets::Resource, tree::SceneTree};
use wgpu::{
@@ -149,6 +149,7 @@ impl ScenePipeline {
target: &TextureView,
scene: &SceneTree,
prefabs: &mut DemandMap<Resource, Arc<RPrefab>>,
+ camera: Mat4,
) {
let mut rpass = commands.begin_render_pass(&RenderPassDescriptor {
label: None,
@@ -176,9 +177,6 @@ impl ScenePipeline {
..Default::default()
});
- let camera = Mat4::perspective_infinite_reverse_rh(1., 1., 0.1)
- * Mat4::look_at_rh(vec3(-5., 0., 0.), vec3(0., 0., 0.), Vec3::Y);
-
for ob in scene.objects.values() {
let prefab_projection = camera
* Mat4::from_mat3(Mat3::from_euler(
diff --git a/client/src/state.rs b/client/src/state.rs
index a370264..beac614 100644
--- a/client/src/state.rs
+++ b/client/src/state.rs
@@ -1,7 +1,8 @@
-use crate::{download::Downloader, network::Network, renderer::Renderer};
+use crate::{camera::Camera, download::Downloader, network::Network, renderer::Renderer};
use anyhow::{Context, Result};
+use glam::{Vec2, Vec3};
use log::{info, warn};
-use std::net::TcpStream;
+use std::{net::TcpStream, time::Instant};
use weareshared::{store::ResourceStore, tree::SceneTree};
use winit::window::Window;
@@ -10,19 +11,34 @@ pub struct State<'a> {
pub downloader: Downloader,
pub renderer: Renderer<'a>,
pub tree: SceneTree,
+ pub camera: Camera,
+ pub delta: DeltaState,
}
+
+pub struct DeltaState {
+ time: Instant,
+ pub move_dir: Vec3,
+ pub mouse_acc: Vec2,
+}
+
impl<'a> State<'a> {
pub fn new(conn: TcpStream, window: &'a Window) -> Result<State<'a>> {
info!("new state");
Ok(Self {
+ camera: Camera::new(),
network: Network::new(conn),
tree: SceneTree::default(),
renderer: Renderer::new(window)?,
downloader: Downloader::new(ResourceStore::new_memory()),
+ delta: DeltaState {
+ time: Instant::now(),
+ move_dir: Vec3::ZERO,
+ mouse_acc: Vec2::ZERO,
+ },
})
}
pub fn draw(&mut self) {
- if let Err(e) = self.renderer.draw(&self.tree) {
+ if let Err(e) = self.renderer.draw(&self.tree, &self.camera) {
warn!("draw failed: {e:?}");
}
}
@@ -30,6 +46,14 @@ impl<'a> State<'a> {
self.renderer.resize(width, height);
}
pub fn update(&mut self) -> Result<()> {
+ let now = Instant::now();
+ let dt = (now - self.delta.time).as_secs_f32();
+ self.delta.time = now;
+
+ self.camera
+ .update(self.delta.move_dir, self.delta.mouse_acc, dt);
+ self.delta.mouse_acc = Vec2::ZERO;
+
for p in self.network.packet_recv.try_iter() {
self.downloader.packet(&p)?;
self.tree.packet(&p);
diff --git a/client/src/ui.rs b/client/src/ui.rs
new file mode 100644
index 0000000..2fc5dd7
--- /dev/null
+++ b/client/src/ui.rs
@@ -0,0 +1,54 @@
+use egui::{Context, epaint::Primitive};
+use wgpu::{Buffer, BufferDescriptor, BufferUsages, Device, Queue};
+
+pub struct UiRenderer {
+ ctx: Context,
+}
+
+impl UiRenderer {
+ pub fn new(device: &Device) -> Self {
+ let index = device.create_buffer(&BufferDescriptor {
+ label: None,
+ size: 1,
+ usage: BufferUsages::INDEX | BufferUsages::COPY_DST,
+ mapped_at_creation: false,
+ });
+ let vertex = device.create_buffer(&BufferDescriptor {
+ label: None,
+ size: 1,
+ usage: BufferUsages::VERTEX | BufferUsages::COPY_DST,
+ mapped_at_creation: false,
+ });
+ Self {
+ ctx: Context::default(),
+ index,
+ vertex,
+ }
+ }
+
+ pub fn draw(&self, queue: &Queue) {
+ let raw_input = egui::RawInput::default();
+ let full_output = self.ctx.run(raw_input, |ctx| {
+ egui::CentralPanel::default().show(&ctx, |ui| {
+ ui.label("Hello world!");
+ if ui.button("Click me").clicked() {
+ // take some action here
+ }
+ });
+ });
+
+
+ // handle_platform_output(full_output.platform_output);
+ let clipped_primitives = self
+ .ctx
+ .tessellate(full_output.shapes, full_output.pixels_per_point);
+
+ for p in clipped_primitives {
+ match p.primitive {
+ Primitive::Mesh(mesh) => {}
+ _ => unreachable!(),
+ }
+ }
+ // paint(full_output.textures_delta, clipped_primitives);
+ }
+}
diff --git a/client/src/window.rs b/client/src/window.rs
index 6ee7fa4..ac90f71 100644
--- a/client/src/window.rs
+++ b/client/src/window.rs
@@ -1,10 +1,12 @@
use crate::state::State;
+use glam::Vec3;
use log::{info, warn};
use std::net::TcpStream;
use winit::{
application::ApplicationHandler,
- event::WindowEvent,
+ event::{DeviceEvent, ElementState, WindowEvent},
event_loop::ActiveEventLoop,
+ keyboard::{KeyCode, PhysicalKey},
window::{Window, WindowAttributes, WindowId},
};
@@ -47,6 +49,21 @@ impl ApplicationHandler for WindowState {
sta.draw();
win.request_redraw();
}
+ WindowEvent::KeyboardInput { event, .. } => {
+ if event.repeat {
+ return;
+ }
+ sta.delta.move_dir += match event.physical_key {
+ PhysicalKey::Code(KeyCode::KeyW) => Vec3::X,
+ PhysicalKey::Code(KeyCode::KeyS) => Vec3::NEG_X,
+ PhysicalKey::Code(KeyCode::KeyA) => Vec3::NEG_Z,
+ PhysicalKey::Code(KeyCode::KeyD) => Vec3::Z,
+ _ => Vec3::ZERO,
+ } * match event.state {
+ ElementState::Pressed => 1.,
+ ElementState::Released => -1.,
+ };
+ }
WindowEvent::CloseRequested => {
event_loop.exit();
}
@@ -54,6 +71,22 @@ impl ApplicationHandler for WindowState {
}
}
}
+ fn device_event(
+ &mut self,
+ _event_loop: &ActiveEventLoop,
+ _device_id: winit::event::DeviceId,
+ event: winit::event::DeviceEvent,
+ ) {
+ if let Some((_win, sta)) = &mut self.window {
+ match event {
+ DeviceEvent::MouseMotion { delta } => {
+ sta.delta.mouse_acc.x += delta.0 as f32;
+ sta.delta.mouse_acc.y += delta.1 as f32;
+ }
+ _ => (),
+ }
+ }
+ }
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
if let Some((_win, sta)) = &mut self.window {
if let Err(e) = sta.update() {