diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | client/Cargo.toml | 1 | ||||
-rw-r--r-- | client/src/download.rs | 3 | ||||
-rw-r--r-- | client/src/main.rs | 15 | ||||
-rw-r--r-- | client/src/renderer.rs | 14 | ||||
-rw-r--r-- | client/src/scene_prepare.rs | 99 | ||||
-rw-r--r-- | client/src/scene_render.rs | 27 | ||||
-rw-r--r-- | client/src/state.rs | 19 | ||||
-rw-r--r-- | client/src/window.rs | 9 | ||||
-rw-r--r-- | server/src/main.rs | 2 | ||||
-rw-r--r-- | server/src/network.rs | 4 | ||||
-rw-r--r-- | shared/src/resources.rs | 5 | ||||
-rw-r--r-- | shared/src/tree.rs | 2 | ||||
-rw-r--r-- | world/src/main.rs | 24 |
14 files changed, 159 insertions, 66 deletions
@@ -2435,6 +2435,7 @@ dependencies = [ "env_logger", "log", "pollster", + "rand", "weareshared", "wgpu", "winit", diff --git a/client/Cargo.toml b/client/Cargo.toml index ffa40e4..3289cfd 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -14,3 +14,4 @@ pollster = "0.4.0" wgpu = "23.0.1" winit = "0.30.8" weareshared = { path = "../shared" } +rand = "0.9.0-beta.1" diff --git a/client/src/download.rs b/client/src/download.rs index 8e1686a..48c38dc 100644 --- a/client/src/download.rs +++ b/client/src/download.rs @@ -46,7 +46,7 @@ impl Downloader { } Ok(()) } - pub fn update(&mut self, network: &mut Network) { + pub fn update(&mut self, network: &mut Network) -> Result<()> { let mut new_pending = Vec::new(); for n in self.need.difference(&self.pending) { network @@ -57,5 +57,6 @@ impl Downloader { new_pending.push(*n); } self.pending.extend(new_pending); + Ok(()) } } diff --git a/client/src/main.rs b/client/src/main.rs index e1f556f..cfbd052 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,15 +1,20 @@ pub mod download; pub mod network; -pub mod scene_render; pub mod renderer; +pub mod scene_prepare; +pub mod scene_render; pub mod state; pub mod window; -pub mod scene_prepare; use anyhow::Result; use clap::Parser; use log::info; -use std::net::{SocketAddr, TcpStream}; +use rand::random; +use std::{ + io::Write, + net::{SocketAddr, TcpStream}, +}; +use weareshared::packets::{Packet, ReadWrite}; use window::WindowState; use winit::event_loop::EventLoop; @@ -23,7 +28,9 @@ fn main() -> Result<()> { let args = Args::parse(); info!("connecting..."); - let sock = TcpStream::connect(args.address)?; + let mut sock = TcpStream::connect(args.address)?; + Packet::Connect(random()).write(&mut sock)?; + sock.flush()?; info!("connection established"); let evloop = EventLoop::new()?; evloop.run_app(&mut WindowState::new(sock))?; diff --git a/client/src/renderer.rs b/client/src/renderer.rs index 1cbc3cc..7116a20 100644 --- a/client/src/renderer.rs +++ b/client/src/renderer.rs @@ -1,5 +1,5 @@ -use crate::{scene_prepare::ScenePreparer, scene_render::ScenePipeline}; -use anyhow::{Result, anyhow}; +use crate::{download::Downloader, scene_prepare::ScenePreparer, scene_render::ScenePipeline}; +use anyhow::{Context, Result, anyhow}; use log::{info, warn}; use pollster::FutureExt; use weareshared::tree::SceneTree; @@ -16,7 +16,7 @@ pub struct Renderer<'a> { device: Device, surface_configuration: SurfaceConfiguration, scene_pipeline: ScenePipeline, - scene_prepare: ScenePreparer, + pub scene_prepare: ScenePreparer, } impl<'a> Renderer<'a> { pub fn new(window: &'a Window) -> Result<Self> { @@ -83,7 +83,13 @@ impl<'a> Renderer<'a> { .device .create_command_encoder(&CommandEncoderDescriptor { label: None }); - self.scene_pipeline.draw(&mut commands, &target_view, scene); + self.scene_pipeline.draw( + &mut commands, + &target_view, + scene, + &self.scene_prepare.prefabs, + &mut self.scene_prepare.prefabs_needed, + ); let i = self.queue.submit(Some(commands.finish())); self.device.poll(MaintainBase::WaitForSubmissionIndex(i)); diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs index 5376145..8d50fc3 100644 --- a/client/src/scene_prepare.rs +++ b/client/src/scene_prepare.rs @@ -1,5 +1,5 @@ use crate::download::Downloader; -use anyhow::Result; +use anyhow::{Context, Result}; use std::{ collections::{HashMap, HashSet}, sync::Arc, @@ -12,22 +12,23 @@ use weareshared::{ use wgpu::Buffer; pub struct ScenePreparer { - index_buffers: HashMap<Resource, Arc<Buffer>>, + index_buffers: HashMap<Resource, (Arc<Buffer>, u32)>, index_buffers_needed: HashSet<Resource>, vertex_buffers: HashMap<Resource, Arc<Buffer>>, vertex_buffers_needed: HashSet<Resource>, parts: HashMap<Resource, Arc<RPart>>, parts_needed: HashSet<Resource>, - prefabs: HashMap<Resource, RPrefab>, - prefabs_needed: HashSet<Resource>, + pub prefabs: HashMap<Resource, RPrefab>, + pub prefabs_needed: HashSet<Resource>, } pub struct RPrefab(pub Vec<(Affine3A, Arc<RPart>)>); pub struct RPart { pub index_count: u32, pub index: Arc<Buffer>, - pub positions: Arc<Buffer>, - pub normals: Arc<Buffer>, + pub position: [Arc<Buffer>; 3], + pub normal: [Arc<Buffer>; 3], + pub texcoord: [Arc<Buffer>; 2], } impl ScenePreparer { @@ -47,7 +48,7 @@ impl ScenePreparer { let mut done = Vec::new(); for pres in &self.prefabs_needed { if let Some(buf) = dls.try_get(*pres)? { - let prefab = Prefab::read(&mut buf.as_slice())?; + let prefab = Prefab::read(&mut buf.as_slice()).context("parsing prefab")?; let mut rprefab = RPrefab(Vec::new()); for (aff, partres) in &prefab.0 { if let Some(part) = self.parts.get(partres) { @@ -62,28 +63,78 @@ impl ScenePreparer { } } } + for pres in &self.index_buffers_needed { + if let Some(buf) = dls.try_get(*pres)? {} + } for pres in &self.parts_needed { if let Some(buf) = dls.try_get(*pres)? { - let part = Part::read(&mut buf.as_slice())?; - if let Some(indexres) = part.index { - if let Some(vertexres) = part.va_position { - let Some(index) = self.index_buffers.get(&indexres) else { - self.index_buffers_needed.insert(indexres); - continue; - }; - for vr in vertexres { - match vr { - Attribute::Constant(_) => todo!(), - Attribute::Vertex(resource) => { - let Some(vertex) = self.index_buffers.get(&resource) else { - self.index_buffers_needed.insert(indexres); - continue; - }; - } - Attribute::Texture(resource) => todo!(), + let part = Part::read(&mut buf.as_slice()).context("parsing part")?; + if let (Some(indexres), Some(positionres), Some(normalres), Some(texcoordres)) = ( + part.index, + part.va_position, + part.va_normal, + part.va_texcoord, + ) { + let Some((index, index_count)) = self.index_buffers.get(&indexres).cloned() + else { + self.index_buffers_needed.insert(indexres); + continue; + }; + let mut positions = Vec::new(); + for vr in positionres { + match vr { + Attribute::Constant(_) => todo!(), + Attribute::Vertex(resource) => { + let Some(vertex) = self.vertex_buffers.get(&resource).cloned() + else { + self.vertex_buffers_needed.insert(indexres); + continue; + }; + positions.push(vertex); + } + Attribute::Texture(_resource) => todo!(), + } + } + let mut normals = Vec::new(); + for vr in normalres { + match vr { + Attribute::Constant(_) => todo!(), + Attribute::Vertex(resource) => { + let Some(vertex) = self.vertex_buffers.get(&resource).cloned() + else { + self.vertex_buffers_needed.insert(indexres); + continue; + }; + normals.push(vertex); + } + Attribute::Texture(_resource) => todo!(), + } + } + let mut texcoords = Vec::new(); + for vr in texcoordres { + match vr { + Attribute::Constant(_) => todo!(), + Attribute::Vertex(resource) => { + let Some(vertex) = self.vertex_buffers.get(&resource).cloned() + else { + self.vertex_buffers_needed.insert(indexres); + continue; + }; + texcoords.push(vertex); } + Attribute::Texture(_resource) => todo!(), } } + self.parts.insert( + *pres, + Arc::new(RPart { + index_count, + index, + texcoord: texcoords.try_into().unwrap(), + normal: normals.try_into().unwrap(), + position: positions.try_into().unwrap(), + }), + ); } } } diff --git a/client/src/scene_render.rs b/client/src/scene_render.rs index 68d0c49..366b956 100644 --- a/client/src/scene_render.rs +++ b/client/src/scene_render.rs @@ -15,8 +15,6 @@ use crate::scene_prepare::RPrefab; pub struct ScenePipeline { pipeline: RenderPipeline, bind_group: BindGroup, - prefabs: HashMap<Resource, RPrefab>, - prefabs_needed: HashSet<Resource>, } impl ScenePipeline { @@ -86,11 +84,16 @@ impl ScenePipeline { Self { bind_group, pipeline, - prefabs_needed: HashSet::new(), - prefabs: HashMap::new(), } } - pub fn draw(&mut self, commands: &mut CommandEncoder, target: &TextureView, scene: &SceneTree) { + pub fn draw( + &mut self, + commands: &mut CommandEncoder, + target: &TextureView, + scene: &SceneTree, + prefabs: &HashMap<Resource, RPrefab>, + prefabs_needed: &mut HashSet<Resource>, + ) { let mut rpass = commands.begin_render_pass(&RenderPassDescriptor { label: None, color_attachments: &[Some(RenderPassColorAttachment { @@ -112,17 +115,23 @@ impl ScenePipeline { rpass.set_pipeline(&self.pipeline); for ob in scene.objects.values() { - if let Some(prefab) = self.prefabs.get(&ob.res) { + if let Some(prefab) = prefabs.get(&ob.res) { for (affine, part) in &prefab.0 { let affine = affine.to_cols_array().map(|v| v.to_le_bytes()); rpass.set_push_constants(ShaderStages::VERTEX, 0, affine.as_flattened()); rpass.set_index_buffer(part.index.slice(..), IndexFormat::Uint16); - rpass.set_vertex_buffer(0, part.positions.slice(..)); - rpass.set_vertex_buffer(1, part.normals.slice(..)); + rpass.set_vertex_buffer(0, part.position[0].slice(..)); + rpass.set_vertex_buffer(1, part.position[1].slice(..)); + rpass.set_vertex_buffer(2, part.position[2].slice(..)); + rpass.set_vertex_buffer(3, part.normal[0].slice(..)); + rpass.set_vertex_buffer(4, part.normal[1].slice(..)); + rpass.set_vertex_buffer(5, part.normal[2].slice(..)); + rpass.set_vertex_buffer(6, part.texcoord[0].slice(..)); + rpass.set_vertex_buffer(7, part.texcoord[1].slice(..)); rpass.draw_indexed(0..part.index_count, 0, 0..1); } } else { - self.prefabs_needed.insert(ob.res); + prefabs_needed.insert(ob.res); } } } diff --git a/client/src/state.rs b/client/src/state.rs index ef68b85..e8188d8 100644 --- a/client/src/state.rs +++ b/client/src/state.rs @@ -1,6 +1,6 @@ use crate::{download::Downloader, network::Network, renderer::Renderer}; -use anyhow::Result; -use log::info; +use anyhow::{Context, Result}; +use log::{info, warn}; use std::net::TcpStream; use weareshared::{store::ResourceStore, tree::SceneTree}; use winit::window::Window; @@ -21,12 +21,23 @@ impl<'a> State<'a> { downloader: Downloader::new(ResourceStore::new_memory()), }) } - + pub fn draw(&mut self) { + if let Err(e) = self.renderer.draw(&self.tree) { + warn!("draw failed: {e:?}"); + } + } pub fn update(&mut self) -> Result<()> { for p in self.network.packet_recv.try_iter() { self.downloader.packet(&p)?; + self.tree.packet(&p); } - self.downloader.update(&mut self.network); + self.downloader + .update(&mut self.network) + .context("downloader state")?; + self.renderer + .scene_prepare + .update(&mut self.downloader) + .context("scene preparation")?; Ok(()) } diff --git a/client/src/window.rs b/client/src/window.rs index 2219bbc..2430479 100644 --- a/client/src/window.rs +++ b/client/src/window.rs @@ -38,12 +38,15 @@ impl ApplicationHandler for WindowState { _window_id: WindowId, event: WindowEvent, ) { - if let Some((_win, sta)) = &mut self.window { + if let Some((win, sta)) = &mut self.window { match event { WindowEvent::Resized(size) => { sta.renderer.resize(size.width, size.height); } - WindowEvent::RedrawRequested => sta.renderer.draw(&sta.tree).unwrap(), + WindowEvent::RedrawRequested => { + sta.draw(); + win.request_redraw(); + } WindowEvent::CloseRequested => { event_loop.exit(); } @@ -54,7 +57,7 @@ impl ApplicationHandler for WindowState { fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) { if let Some((_win, sta)) = &mut self.window { if let Err(e) = sta.update() { - warn!("update failed: {e}") + warn!("update failed: {e:#}") } } } diff --git a/server/src/main.rs b/server/src/main.rs index a8473c6..58c3cb2 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -50,7 +50,7 @@ impl State { }) } pub fn handle_packet(&mut self, conn: u128, packet: Packet, net: &ServerNetwork) -> Result<()> { - self.tree.update(&packet); + self.tree.packet(&packet); match packet { Packet::Connect(_) => { for p in self.tree.prime_client() { diff --git a/server/src/network.rs b/server/src/network.rs index 22cbc65..211d0bc 100644 --- a/server/src/network.rs +++ b/server/src/network.rs @@ -63,6 +63,7 @@ impl ServerNetwork { }; let (send_tx, send_rx) = sync_channel(128); conns.lock().unwrap().insert(conn, (send_tx, None)); + recv_tx.send((conn, Packet::Connect(conn))).unwrap(); let sock2 = match sock.try_clone() { Ok(x) => x, @@ -143,6 +144,7 @@ impl ServerNetwork { Ok(s) } pub fn broadcast(&self, packet: Packet, reliable: bool) { + debug!("* -> {packet:?}"); let ser = Arc::new(packet.write_alloc()); for (cid, (tcp, udp)) in self.conns.lock().unwrap().iter() { if !reliable { @@ -165,6 +167,7 @@ impl ServerNetwork { return; } } + debug!("{conn} -> {packet:?}"); if let Err(_) = tcp.send(ser.clone()) { warn!("{conn}: queue full, packet dropped") } @@ -183,7 +186,6 @@ fn handle_conn_read(conn: u128, sock: TcpStream, tx: Sender<(u128, Packet)>) -> fn handle_conn_write(conn: u128, sock: TcpStream, rx: Receiver<Arc<Vec<u8>>>) -> Result<()> { let mut sock = BufWriter::new(sock); for packet in rx { - debug!("{conn} -> {packet:?}"); sock.write_all(&packet)?; sock.flush()?; } diff --git a/shared/src/resources.rs b/shared/src/resources.rs index 6741936..f93de65 100644 --- a/shared/src/resources.rs +++ b/shared/src/resources.rs @@ -43,8 +43,9 @@ impl ReadWrite for Prefab { let mut s = Prefab::default(); let mut g = Vec::new(); r.read_to_end(&mut g)?; + let mut g = g.as_slice(); while !g.is_empty() { - s.0.push((Affine3A::read(r)?, Resource::read(r)?)) + s.0.push((Affine3A::read(&mut g)?, Resource::read(&mut g)?)) } Ok(s) } @@ -127,7 +128,7 @@ impl ReadWrite for Part { b"va_pbr_transmission" => { s.va_pbr_transmission = Some(<_ as ReadWrite>::read(&mut v)?) } - _ => warn!("unknown part key"), + x => warn!("unknown part key: {:?}", String::from_utf8_lossy(x)), } } Ok(s) diff --git a/shared/src/tree.rs b/shared/src/tree.rs index d8d2bfd..2ecfa3d 100644 --- a/shared/src/tree.rs +++ b/shared/src/tree.rs @@ -20,7 +20,7 @@ impl Default for SceneTree { } } impl SceneTree { - pub fn update(&mut self, p: &Packet) { + pub fn packet(&mut self, p: &Packet) { match p { Packet::Add(object, res) => { self.objects.insert(*object, ObjectData { diff --git a/world/src/main.rs b/world/src/main.rs index 4f433ba..d7272fe 100644 --- a/world/src/main.rs +++ b/world/src/main.rs @@ -115,18 +115,18 @@ fn main() -> Result<()> { let ob = Object::new(); Packet::Add(ob, store.set(&prefab.write_alloc())?).write(&mut sock)?; - let mut sock2 = sock.try_clone().unwrap(); - thread::spawn(move || { - let mut x = 0.; - loop { - Packet::Position(ob, Vec3A::ZERO, vec3a(x, x * 0.3, x * 0.1)) - .write(&mut sock2) - .unwrap(); - sock2.flush().unwrap(); - x += 0.1; - sleep(Duration::from_millis(50)); - } - }); + // let mut sock2 = sock.try_clone().unwrap(); + // thread::spawn(move || { + // let mut x = 0.; + // loop { + // Packet::Position(ob, Vec3A::ZERO, vec3a(x, x * 0.3, x * 0.1)) + // .write(&mut sock2) + // .unwrap(); + // sock2.flush().unwrap(); + // x += 0.1; + // sleep(Duration::from_millis(50)); + // } + // }); if args.push { store.iter(|d| { |