summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/Cargo.toml1
-rw-r--r--client/src/download.rs3
-rw-r--r--client/src/main.rs15
-rw-r--r--client/src/renderer.rs14
-rw-r--r--client/src/scene_prepare.rs99
-rw-r--r--client/src/scene_render.rs27
-rw-r--r--client/src/state.rs19
-rw-r--r--client/src/window.rs9
8 files changed, 138 insertions, 49 deletions
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:#}")
}
}
}