diff options
author | metamuffin <metamuffin@disroot.org> | 2025-01-07 15:15:19 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-01-07 15:15:19 +0100 |
commit | e32de26dcb5e1498f2b2fa19cacb593bec518ef4 (patch) | |
tree | 8a5d3d0e4629d04527e1f8203adbfcbe9d03838a /client/src | |
parent | d81eebe423fd3e00df5ff035ec24fe7fb37f2c62 (diff) | |
download | weareserver-e32de26dcb5e1498f2b2fa19cacb593bec518ef4.tar weareserver-e32de26dcb5e1498f2b2fa19cacb593bec518ef4.tar.bz2 weareserver-e32de26dcb5e1498f2b2fa19cacb593bec518ef4.tar.zst |
camera controller broken
Diffstat (limited to 'client/src')
-rw-r--r-- | client/src/camera.rs | 37 | ||||
-rw-r--r-- | client/src/main.rs | 2 | ||||
-rw-r--r-- | client/src/renderer.rs | 7 | ||||
-rw-r--r-- | client/src/scene_prepare.rs | 2 | ||||
-rw-r--r-- | client/src/scene_render.rs | 6 | ||||
-rw-r--r-- | client/src/state.rs | 30 | ||||
-rw-r--r-- | client/src/ui.rs | 54 | ||||
-rw-r--r-- | client/src/window.rs | 35 |
8 files changed, 162 insertions, 11 deletions
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() { |