summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-01-07 15:15:19 +0100
committermetamuffin <metamuffin@disroot.org>2025-01-07 15:15:19 +0100
commite32de26dcb5e1498f2b2fa19cacb593bec518ef4 (patch)
tree8a5d3d0e4629d04527e1f8203adbfcbe9d03838a /client
parentd81eebe423fd3e00df5ff035ec24fe7fb37f2c62 (diff)
downloadweareserver-e32de26dcb5e1498f2b2fa19cacb593bec518ef4.tar
weareserver-e32de26dcb5e1498f2b2fa19cacb593bec518ef4.tar.bz2
weareserver-e32de26dcb5e1498f2b2fa19cacb593bec518ef4.tar.zst
camera controller broken
Diffstat (limited to 'client')
-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
9 files changed, 164 insertions, 11 deletions
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() {