From 814cc1cb01692aa934a40636c9226ff7bb911266 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Mon, 6 Jan 2025 14:28:02 +0100 Subject: new proto --- a.md | 21 +++--- client/src/main.rs | 3 +- client/src/network.rs | 6 +- client/src/part.rs | 168 ------------------------------------------- client/src/renderer.rs | 113 ++++------------------------- client/src/scene_prepare.rs | 30 ++++++++ client/src/scene_render.rs | 129 +++++++++++++++++++++++++++++++++ server/src/main.rs | 10 ++- shared/src/lib.rs | 2 +- shared/src/packets.rs | 92 +++++++++++++++++------- shared/src/resources.rs | 172 +++++++++++++++++++++++++++----------------- world/src/main.rs | 65 +++++++++-------- 12 files changed, 407 insertions(+), 404 deletions(-) delete mode 100644 client/src/part.rs create mode 100644 client/src/scene_prepare.rs create mode 100644 client/src/scene_render.rs diff --git a/a.md b/a.md index 5539e14..30c1f86 100644 --- a/a.md +++ b/a.md @@ -27,18 +27,19 @@ Prefab = *(part) ``` Part = *(len_key:u16 len_value:u16 *(key:u8) *(value:u8)) +Attribute = 0x01 value:f32 / 0x02 buffer:Res / 0x03 texture:Res ``` -| Key | Value Type | -| -------------------- | ----------------- | -| vertex (mult) | `Res<[f32]>` | -| index | `Res<[[u16; 3]]>` | -| armature | ???? | -| fragment_shader | Shader | -| fragment_shader_data | `Res<[f32]>` | -| vertex_shader | Shader | -| vertex_shader_data | `Res<[f32]>` | -| texture (mult) | Texture | +| Key | Value Type | +| ------------------- | ----------------- | +| index | `Res<[[u16; 3]]>` | +| va_position | `[Attribute; 3]` | +| va_normal | `[Attribute; 3]` | +| va_texcoord | `[Attribute; 2]` | +| va_pbr_roughness | `Attribute` | +| va_pbr_metallic | `Attribute` | +| va_pbr_albedo | `[Attribute; 3]` | +| va_pbr_transmission | `Attribute` | ### Texture diff --git a/client/src/main.rs b/client/src/main.rs index b90d26b..e1f556f 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,9 +1,10 @@ pub mod download; pub mod network; -pub mod part; +pub mod scene_render; pub mod renderer; pub mod state; pub mod window; +pub mod scene_prepare; use anyhow::Result; use clap::Parser; diff --git a/client/src/network.rs b/client/src/network.rs index e542c7e..e54ecf7 100644 --- a/client/src/network.rs +++ b/client/src/network.rs @@ -7,7 +7,7 @@ use std::{ use anyhow::Result; use log::{debug, info, warn}; -use weareshared::packets::Packet; +use weareshared::packets::{Packet, ReadWrite}; pub struct Network { pub packet_recv: Receiver, @@ -40,7 +40,7 @@ impl Network { fn handle_conn_read(sock: TcpStream, tx: Sender) -> Result<()> { let mut sock = BufReader::new(sock); loop { - let packet = Packet::deserialize(&mut sock)?; + let packet = Packet::read(&mut sock)?; debug!("<- {packet:?}"); tx.send(packet)?; } @@ -49,7 +49,7 @@ fn handle_conn_write(sock: TcpStream, rx: Receiver) -> Result<()> { let mut sock = BufWriter::new(sock); for packet in rx { debug!("-> {packet:?}"); - packet.serialize(&mut sock)?; + packet.write(&mut sock)?; sock.flush()?; } Ok(()) diff --git a/client/src/part.rs b/client/src/part.rs deleted file mode 100644 index 7d02f0c..0000000 --- a/client/src/part.rs +++ /dev/null @@ -1,168 +0,0 @@ -use crate::download::Downloader; -use anyhow::Result; -use weareshared::resources::{Indecies, Part, VertexAttributes}; -use wgpu::{ - BindGroup, BindGroupDescriptor, BindGroupLayoutDescriptor, BlendState, Buffer, BufferUsages, - ColorTargetState, ColorWrites, CommandEncoder, Device, FragmentState, FrontFace, IndexFormat, - LoadOp, MultisampleState, Operations, PipelineCompilationOptions, PipelineLayoutDescriptor, - PolygonMode, PrimitiveState, PrimitiveTopology, RenderPassColorAttachment, - RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor, StoreOp, TextureFormat, - TextureView, VertexAttribute, VertexBufferLayout, VertexFormat, VertexState, VertexStepMode, - include_wgsl, - util::{BufferInitDescriptor, DeviceExt}, -}; - -pub struct PartRenderer { - vertex: Buffer, - index: Buffer, - pipeline: RenderPipeline, - bind_group: BindGroup, - n_vertex: u32, -} - -pub struct PrefabData { - -} - -pub struct PartData { - target: Part, - vertex: Vec>, - index: Option, -} - -impl PartData { - pub fn update(&mut self, dls: &mut Downloader) -> Result { - let mut ready = true; - if self.index.is_none() { - ready = false; - if let Some(hash) = self.target.index { - if let Some(data) = dls.try_get(hash)? { - self.index = Some(Indecies::deserialize(data.as_slice())?) - } - } - } - for (hash, slot) in self.target.vertex.iter().zip(self.vertex.iter_mut()) { - if slot.is_none() { - ready = false; - if let Some(data) = dls.try_get(*hash)? { - *slot = Some(VertexAttributes::deserialize(data.as_slice())?) - } - } - } - Ok(ready) - } -} - -impl PartRenderer { - pub fn new(device: Device, data: PartData, format: TextureFormat) -> Self { - let mut vertex = Vec::new(); - let mut index = Vec::new(); - for i in 0..data.vertex[0].as_ref().unwrap().0.len() { - vertex.extend(data.vertex[0].as_ref().unwrap().0[i].to_le_bytes()); - vertex.extend(data.vertex[1].as_ref().unwrap().0[i].to_le_bytes()); - vertex.extend(data.vertex[2].as_ref().unwrap().0[i].to_le_bytes()); - } - let mut n_vertex = 0; - for ind in data.index.unwrap().0 { - index.extend(ind[0].to_le_bytes()); - index.extend(ind[1].to_le_bytes()); - index.extend(ind[2].to_le_bytes()); - n_vertex += 3; - } - - let vertex = device.create_buffer_init(&BufferInitDescriptor { - label: None, - contents: &vertex, - usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, - }); - let index = device.create_buffer_init(&BufferInitDescriptor { - label: None, - contents: &index, - usage: BufferUsages::INDEX | BufferUsages::COPY_DST, - }); - - let module = device.create_shader_module(include_wgsl!("shader.wgsl")); - - let bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDescriptor { - entries: &[], - label: None, - }); - let bind_group = device.create_bind_group(&BindGroupDescriptor { - label: None, - layout: &bind_group_layout, - entries: &[], - }); - let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor { - label: None, - bind_group_layouts: &[&bind_group_layout], - push_constant_ranges: &[], - }); - let pipeline = device.create_render_pipeline(&RenderPipelineDescriptor { - label: None, - layout: Some(&pipeline_layout), - fragment: Some(FragmentState { - module: &module, - entry_point: Some("fs_main"), - targets: &[Some(ColorTargetState { - blend: Some(BlendState::PREMULTIPLIED_ALPHA_BLENDING), - format, - write_mask: ColorWrites::all(), - })], - compilation_options: PipelineCompilationOptions::default(), - }), - vertex: VertexState { - module: &module, - entry_point: Some("vs_main"), - buffers: &[VertexBufferLayout { - step_mode: VertexStepMode::Vertex, - array_stride: 3, - attributes: &[VertexAttribute { - format: VertexFormat::Float32x3, - offset: 0, - shader_location: 0, - }], - }], - compilation_options: PipelineCompilationOptions::default(), - }, - primitive: PrimitiveState { - topology: PrimitiveTopology::TriangleList, - front_face: FrontFace::Ccw, - cull_mode: None, //Some(Face::Back), - polygon_mode: PolygonMode::Fill, - ..Default::default() - }, - depth_stencil: Default::default(), - multisample: MultisampleState::default(), - multiview: None, - cache: None, - }); - - Self { - bind_group, - index, - vertex, - pipeline, - n_vertex, - } - } - pub fn draw(&self, commands: &mut CommandEncoder, target: &TextureView) { - let mut rpass = commands.begin_render_pass(&RenderPassDescriptor { - label: None, - color_attachments: &[Some(RenderPassColorAttachment { - view: &target, - resolve_target: None, - ops: Operations { - store: StoreOp::Store, - load: LoadOp::Load, - }, - })], - ..Default::default() - }); - - rpass.set_bind_group(0, &self.bind_group, &[]); - rpass.set_pipeline(&self.pipeline); - rpass.set_vertex_buffer(0, self.vertex.slice(..)); - rpass.set_index_buffer(self.index.slice(..), IndexFormat::Uint16); - rpass.draw(0..self.n_vertex, 0..1); - } -} diff --git a/client/src/renderer.rs b/client/src/renderer.rs index 35bc0ef..1cbc3cc 100644 --- a/client/src/renderer.rs +++ b/client/src/renderer.rs @@ -1,31 +1,22 @@ -use crate::part::{PartData, PartRenderer}; +use crate::{scene_prepare::ScenePreparer, scene_render::ScenePipeline}; use anyhow::{Result, anyhow}; -use log::info; +use log::{info, warn}; use pollster::FutureExt; -use std::collections::HashMap; -use weareshared::{packets::Resource, tree::SceneTree}; +use weareshared::tree::SceneTree; use wgpu::{ - Backends, BindGroup, BindGroupDescriptor, BindGroupLayoutDescriptor, BlendState, Color, - ColorTargetState, ColorWrites, CommandEncoderDescriptor, Device, DeviceDescriptor, Features, - FragmentState, FrontFace, Instance, InstanceDescriptor, Limits, LoadOp, MaintainBase, - MultisampleState, Operations, PipelineCompilationOptions, PipelineLayoutDescriptor, - PolygonMode, PowerPreference, PrimitiveState, PrimitiveTopology, Queue, - RenderPassColorAttachment, RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor, - RequestAdapterOptions, StoreOp, Surface, SurfaceConfiguration, TextureViewDescriptor, - VertexState, include_wgsl, + Backends, CommandEncoderDescriptor, Device, DeviceDescriptor, Features, Instance, + InstanceDescriptor, Limits, MaintainBase, PowerPreference, Queue, RequestAdapterOptions, + Surface, SurfaceConfiguration, TextureViewDescriptor, }; use winit::window::Window; pub struct Renderer<'a> { surface: Surface<'a>, - pipeline: RenderPipeline, - bind_group: BindGroup, queue: Queue, device: Device, surface_configuration: SurfaceConfiguration, - - prefabs_loading: HashMap>, - prefabs: HashMap>, + scene_pipeline: ScenePipeline, + scene_prepare: ScenePreparer, } impl<'a> Renderer<'a> { pub fn new(window: &'a Window) -> Result { @@ -60,65 +51,15 @@ impl<'a> Renderer<'a> { .get_default_config(&adapter, 256, 256) .ok_or(anyhow!("no default config"))?; - let module = device.create_shader_module(include_wgsl!("shader.wgsl")); - - let bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDescriptor { - entries: &[], - label: None, - }); - let bind_group = device.create_bind_group(&BindGroupDescriptor { - label: None, - layout: &bind_group_layout, - entries: &[], - }); - let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor { - label: None, - bind_group_layouts: &[&bind_group_layout], - push_constant_ranges: &[], - }); - let pipeline = device.create_render_pipeline(&RenderPipelineDescriptor { - label: None, - layout: Some(&pipeline_layout), - fragment: Some(FragmentState { - module: &module, - entry_point: Some("fs_main"), - targets: &[Some(ColorTargetState { - blend: Some(BlendState::PREMULTIPLIED_ALPHA_BLENDING), - format: surface_configuration.format, - write_mask: ColorWrites::all(), - })], - compilation_options: PipelineCompilationOptions::default(), - }), - vertex: VertexState { - module: &module, - entry_point: Some("vs_main"), - buffers: &[], - compilation_options: PipelineCompilationOptions::default(), - }, - primitive: PrimitiveState { - topology: PrimitiveTopology::TriangleList, - front_face: FrontFace::Ccw, - cull_mode: None, //Some(Face::Back), - polygon_mode: PolygonMode::Fill, - ..Default::default() - }, - depth_stencil: Default::default(), - multisample: MultisampleState::default(), - multiview: None, - cache: None, - }); - surface.configure(&device, &surface_configuration); Ok(Self { + scene_pipeline: ScenePipeline::new(&device, surface_configuration.format), + scene_prepare: ScenePreparer::new(), surface, - pipeline, - bind_group, device, queue, surface_configuration, - prefabs: HashMap::new(), - prefabs_loading: HashMap::new(), }) } @@ -131,6 +72,9 @@ impl<'a> Renderer<'a> { pub fn draw(&mut self, scene: &SceneTree) -> Result<()> { let target = self.surface.get_current_texture()?; + if target.suboptimal { + warn!("suboptimal swapchain texture") + } let target_view = target .texture .create_view(&TextureViewDescriptor::default()); @@ -139,38 +83,11 @@ impl<'a> Renderer<'a> { .device .create_command_encoder(&CommandEncoderDescriptor { label: None }); - { - let mut rpass = commands.begin_render_pass(&RenderPassDescriptor { - label: None, - color_attachments: &[Some(RenderPassColorAttachment { - view: &target_view, - resolve_target: None, - ops: Operations { - store: StoreOp::Store, - load: LoadOp::Clear(Color::BLUE), - }, - })], - ..Default::default() - }); - - rpass.set_bind_group(0, &self.bind_group, &[]); - rpass.set_pipeline(&self.pipeline); - rpass.draw(0..3, 0..1); - } - - for data in scene.objects.values() { - if let Some(ob) = self.prefabs.get(&data.res) { - for p in ob { - p.draw(&mut commands, &target_view); - } - } else { - let loading = self.prefabs_loading.entry(data.res).or_default(); - - } - } + self.scene_pipeline.draw(&mut commands, &target_view, scene); let i = self.queue.submit(Some(commands.finish())); self.device.poll(MaintainBase::WaitForSubmissionIndex(i)); + target.present(); Ok(()) diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs new file mode 100644 index 0000000..8d52f49 --- /dev/null +++ b/client/src/scene_prepare.rs @@ -0,0 +1,30 @@ +use anyhow::Result; +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, +}; +use weareshared::{packets::Resource, resources::Part, tree::SceneTree}; +use wgpu::Buffer; + +pub struct ScenePreparer { + index_buffers: HashMap, + vertex_buffers_x3: HashMap<[Resource; 1], Arc>, + vertex_buffers_x2: HashMap<[Resource; 2], Arc>, + vertex_buffers_x1: HashMap<[Resource; 3], Arc>, + parts: HashMap, +} + +impl ScenePreparer { + pub fn new() -> Self { + Self { + index_buffers: HashMap::new(), + vertex_buffers_x3: HashMap::new(), + vertex_buffers_x2: HashMap::new(), + vertex_buffers_x1: HashMap::new(), + parts: HashMap::new(), + } + } + fn update(&mut self, tree: &SceneTree) -> Result<()> { + let x = tree.objects.values().map(|o| o.res).collect::>(); + } +} diff --git a/client/src/scene_render.rs b/client/src/scene_render.rs new file mode 100644 index 0000000..cc15e3f --- /dev/null +++ b/client/src/scene_render.rs @@ -0,0 +1,129 @@ +use std::collections::HashMap; +use weareshared::{packets::Resource, tree::SceneTree}; +use wgpu::{ + BindGroup, BindGroupDescriptor, BindGroupLayoutDescriptor, BlendState, Buffer, Color, + ColorTargetState, ColorWrites, CommandEncoder, Device, FragmentState, FrontFace, IndexFormat, + LoadOp, MultisampleState, Operations, PipelineCompilationOptions, PipelineLayoutDescriptor, + PolygonMode, PrimitiveState, PrimitiveTopology, RenderPassColorAttachment, + RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor, StoreOp, TextureFormat, + TextureView, VertexAttribute, VertexBufferLayout, VertexFormat, VertexState, VertexStepMode, + include_wgsl, +}; + +pub struct ScenePipeline { + pipeline: RenderPipeline, + bind_group: BindGroup, + prefabs: HashMap, +} + +struct RPrefab(Vec); +struct RPart { + index_count: u32, + index: Buffer, + positions: Buffer, + normals: Buffer, +} + +impl ScenePipeline { + pub fn new(device: &Device, format: TextureFormat) -> Self { + let module = device.create_shader_module(include_wgsl!("shader.wgsl")); + + let bind_group_layout = device.create_bind_group_layout(&BindGroupLayoutDescriptor { + entries: &[], + label: None, + }); + let bind_group = device.create_bind_group(&BindGroupDescriptor { + label: None, + layout: &bind_group_layout, + entries: &[], + }); + let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor { + label: None, + bind_group_layouts: &[&bind_group_layout], + push_constant_ranges: &[], + }); + let pipeline = device.create_render_pipeline(&RenderPipelineDescriptor { + label: None, + layout: Some(&pipeline_layout), + fragment: Some(FragmentState { + module: &module, + entry_point: Some("fs_main"), + targets: &[Some(ColorTargetState { + blend: Some(BlendState::PREMULTIPLIED_ALPHA_BLENDING), + format, + write_mask: ColorWrites::all(), + })], + compilation_options: PipelineCompilationOptions::default(), + }), + vertex: VertexState { + module: &module, + entry_point: Some("vs_main"), + buffers: &[VertexBufferLayout { + step_mode: VertexStepMode::Vertex, + array_stride: 2 * 4 * 3, + attributes: &[ + VertexAttribute { + format: VertexFormat::Float32x3, + offset: 0, + shader_location: 0, + }, + VertexAttribute { + format: VertexFormat::Float32x3, + offset: 3 * 4, + shader_location: 1, + }, + ], + }], + compilation_options: PipelineCompilationOptions::default(), + }, + primitive: PrimitiveState { + topology: PrimitiveTopology::TriangleList, + front_face: FrontFace::Ccw, + cull_mode: None, //Some(Face::Back), + polygon_mode: PolygonMode::Fill, + ..Default::default() + }, + depth_stencil: Default::default(), + multisample: MultisampleState::default(), + multiview: None, + cache: None, + }); + Self { + bind_group, + pipeline, + prefabs: HashMap::new(), + } + } + pub fn draw(&self, commands: &mut CommandEncoder, target: &TextureView, scene: &SceneTree) { + let mut rpass = commands.begin_render_pass(&RenderPassDescriptor { + label: None, + color_attachments: &[Some(RenderPassColorAttachment { + view: target, + resolve_target: None, + ops: Operations { + store: StoreOp::Store, + load: LoadOp::Clear(Color { + r: 0.1, + g: 0.1, + b: 0.1, + a: 1., + }), + }, + })], + ..Default::default() + }); + rpass.set_bind_group(0, &self.bind_group, &[]); + rpass.set_pipeline(&self.pipeline); + + for ob in scene.objects.values() { + if let Some(prefab) = self.prefabs.get(&ob.res) { + for part in &prefab.0 { + 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.draw_indexed(0..part.index_count, 0, 0..1); + } + } + } + } +} diff --git a/server/src/main.rs b/server/src/main.rs index cc55488..6b2911f 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -11,7 +11,11 @@ use std::{ }, thread::spawn, }; -use weareshared::{packets::Packet, store::ResourceStore, tree::SceneTree}; +use weareshared::{ + packets::{Packet, ReadWrite}, + store::ResourceStore, + tree::SceneTree, +}; #[derive(Parser, Debug)] struct Args { @@ -59,7 +63,7 @@ fn main() -> Result<()> { fn handle_conn_read(conn: usize, sock: TcpStream, state: Arc>) -> Result<()> { let mut sock = BufReader::new(sock); loop { - let packet = Packet::deserialize(&mut sock)?; + let packet = Packet::read(&mut sock)?; debug!("{conn} <- {packet:?}"); state.lock().unwrap().handle_packet(conn, packet)?; } @@ -68,7 +72,7 @@ fn handle_conn_write(conn: usize, sock: TcpStream, rx: Receiver) -> Resu let mut sock = BufWriter::new(sock); for packet in rx { debug!("{conn} -> {packet:?}"); - packet.serialize(&mut sock)?; + packet.write(&mut sock)?; sock.flush()?; } Ok(()) diff --git a/shared/src/lib.rs b/shared/src/lib.rs index fadbc35..45b31da 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(iter_array_chunks)] +#![feature(iter_array_chunks, array_try_map)] pub mod packets; pub mod resources; diff --git a/shared/src/packets.rs b/shared/src/packets.rs index 626da07..0ceed73 100644 --- a/shared/src/packets.rs +++ b/shared/src/packets.rs @@ -22,21 +22,24 @@ pub enum Packet { Sound(Object, Vec), } +pub trait ReadWrite: Sized { + fn write(&self, w: &mut dyn Write) -> Result<()>; + fn read(r: &mut dyn Read) -> Result; + + fn write_alloc(&self) -> Vec { + let mut buf = Vec::new(); + self.write(&mut buf).unwrap(); + buf + } +} + impl Object { pub fn new() -> Self { Self(rand::random()) } } - impl Packet { - pub fn serialize(&self, w: &mut impl Write) -> Result<()> { - let mut buf = Vec::new(); - self.serialize_inner(&mut buf)?; - w.write_all(&(buf.len() as u16).to_be_bytes())?; - w.write_all(&buf)?; - Ok(()) - } - pub fn serialize_inner(&self, w: &mut impl Write) -> Result<()> { + fn serialize_inner(&self, w: &mut impl Write) -> Result<()> { match self { Packet::RequestResource(resource) => { w.write_all(&[0x01])?; @@ -84,18 +87,27 @@ impl Packet { } Ok(()) } - pub fn deserialize(r: &mut impl Read) -> Result { +} +impl ReadWrite for Packet { + fn write(&self, w: &mut dyn Write) -> Result<()> { + let mut buf = Vec::new(); + self.serialize_inner(&mut buf)?; + w.write_all(&(buf.len() as u16).to_be_bytes())?; + w.write_all(&buf)?; + Ok(()) + } + fn read(r: &mut dyn Read) -> Result { let mut size_tag = [0u8; 3]; r.read_exact(&mut size_tag)?; Ok(match size_tag[2] { - 0x01 => Packet::RequestResource(read_res(r)?), + 0x01 => Packet::RequestResource(Resource::read(r)?), 0x02 => Packet::RespondResource(read_data(r)?), - 0x03 => Packet::Add(Object(read_u128(r)?), read_res(r)?), + 0x03 => Packet::Add(Object(read_u128(r)?), Resource::read(r)?), 0x04 => Packet::Remove(Object(read_u128(r)?)), 0x05 => Packet::Position( Object(read_u128(r)?), - Vec3::new(read_float(r)?, read_float(r)?, read_float(r)?), - Vec3::new(read_float(r)?, read_float(r)?, read_float(r)?), + Vec3::new(f32::read(r)?, f32::read(r)?, f32::read(r)?), + Vec3::new(f32::read(r)?, f32::read(r)?, f32::read(r)?), ), 0x06 => Packet::Pose(Object(read_u128(r)?), read_params(r)?), 0x07 => Packet::Parent(Object(read_u128(r)?), Object(read_u128(r)?)), @@ -110,17 +122,23 @@ impl Packet { } } -fn read_u128(r: &mut impl Read) -> Result { +fn read_u128(r: &mut dyn Read) -> Result { let mut buf = [0; 16]; r.read_exact(&mut buf)?; Ok(u128::from_be_bytes(buf)) } -fn read_res(r: &mut impl Read) -> Result { - let mut buf = [0; 32]; - r.read_exact(&mut buf)?; - Ok(Resource(buf)) +impl ReadWrite for Resource { + fn write(&self, w: &mut dyn Write) -> Result<()> { + w.write_all(&self.0)?; + Ok(()) + } + fn read(r: &mut dyn Read) -> Result { + let mut s = Self([0; 32]); + r.read_exact(&mut s.0)?; + Ok(s) + } } -fn read_data(r: &mut impl Read) -> Result> { +fn read_data(r: &mut dyn Read) -> Result> { let mut size = [0; 2]; r.read_exact(&mut size)?; let size = u16::from_be_bytes(size); @@ -128,22 +146,29 @@ fn read_data(r: &mut impl Read) -> Result> { r.read_exact(&mut buf)?; Ok(buf) } -fn read_float(r: &mut impl Read) -> Result { - let mut buf = [0; 4]; - r.read_exact(&mut buf)?; - Ok(f32::from_be_bytes(buf)) -} -fn read_params(r: &mut impl Read) -> Result> { +fn read_params(r: &mut dyn Read) -> Result> { let mut size = [0; 2]; r.read_exact(&mut size)?; let size = u16::from_be_bytes(size); let mut v = Vec::with_capacity(size as usize); for _ in 0..size { - v.push(read_float(r)?); + v.push(f32::read(r)?); } Ok(v) } +impl ReadWrite for f32 { + fn write(&self, w: &mut dyn Write) -> Result<()> { + w.write_all(&self.to_be_bytes())?; + Ok(()) + } + fn read(r: &mut dyn Read) -> Result { + let mut buf = [0; 4]; + r.read_exact(&mut buf)?; + Ok(f32::from_be_bytes(buf)) + } +} + impl Display for Resource { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( @@ -162,3 +187,16 @@ impl Debug for Resource { write!(f, "{}", self) } } + +impl ReadWrite for [T; N] { + fn write(&self, w: &mut dyn Write) -> Result<()> { + for e in self { + e.write(w)?; + } + Ok(()) + } + + fn read(r: &mut dyn Read) -> Result { + [(); N].try_map(|()| T::read(r)) + } +} diff --git a/shared/src/resources.rs b/shared/src/resources.rs index a677755..cdf53bd 100644 --- a/shared/src/resources.rs +++ b/shared/src/resources.rs @@ -1,5 +1,5 @@ -use crate::packets::Resource; -use anyhow::{Result, anyhow}; +use crate::packets::{ReadWrite, Resource}; +use anyhow::{Result, bail}; use log::warn; use std::io::{Read, Write}; @@ -8,120 +8,130 @@ pub struct Prefab(pub Vec); #[derive(Debug, Default, Clone)] pub struct Part { - pub vertex: Vec, pub index: Option, - pub armature: Option, - pub fragment_shader: Option, - pub fragment_shader_data: Option, - pub vertex_shader: Option, - pub vertex_shader_data: Option, - pub texture: Vec, + pub va_position: Option<[Attribute; 3]>, + pub va_normal: Option<[Attribute; 3]>, + pub va_texcoord: Option<[Attribute; 2]>, + pub va_pbr_roughness: Option, + pub va_pbr_metallic: Option, + pub va_pbr_albedo: Option<[Attribute; 3]>, + pub va_pbr_transmission: Option, +} + +#[derive(Debug, Clone)] +pub enum Attribute { + Constant(f32), + Vertex(Resource), + Texture(Resource), } #[derive(Debug, Default, Clone)] -pub struct VertexAttributes(pub Vec); +pub struct AttributeArray(pub Vec); #[derive(Debug, Default, Clone)] -pub struct Indecies(pub Vec<[u16; 3]>); +pub struct IndexArray(pub Vec<[u16; 3]>); -impl Prefab { - pub fn serialize(&self, w: &mut Vec) -> Result<()> { +impl ReadWrite for Prefab { + fn write(&self, w: &mut dyn Write) -> Result<()> { for x in self.0.clone() { w.write_all(&x.0)?; } Ok(()) } - pub fn deserialize(r: &[u8]) -> Result { + fn read(r: &mut dyn Read) -> Result { let mut s = Prefab::default(); - for x in r.iter().array_chunks::<32>() { + let mut g = Vec::new(); + r.read_to_end(&mut g)?; + for x in g.iter().array_chunks::<32>() { s.0.push(Resource(x.map(|x| *x))) } Ok(s) } } -impl Indecies { - pub fn serialize(&self, w: &mut Vec) -> Result<()> { +impl ReadWrite for IndexArray { + fn write(&self, w: &mut dyn Write) -> Result<()> { for x in self.0.clone() { w.write_all(x.map(|x| x.to_be_bytes()).as_flattened())?; } Ok(()) } - pub fn deserialize(r: &[u8]) -> Result { + fn read(r: &mut dyn Read) -> Result { let mut s = Self(Vec::new()); - for x in r.iter().array_chunks::<2>().array_chunks::<3>() { + let mut g = Vec::new(); + r.read_to_end(&mut g)?; + for x in g.iter().array_chunks::<2>().array_chunks::<3>() { s.0.push(x.map(|x| u16::from_be_bytes(x.map(|x| *x)))) } Ok(s) } } -impl VertexAttributes { - pub fn serialize(&self, w: &mut Vec) -> Result<()> { +impl ReadWrite for AttributeArray { + fn write(&self, w: &mut dyn Write) -> Result<()> { for x in self.0.clone() { w.write_all(&x.to_be_bytes())?; } Ok(()) } - pub fn deserialize(r: &[u8]) -> Result { + fn read(r: &mut dyn Read) -> Result { let mut s = Self(Vec::new()); - for x in r.iter().array_chunks::<4>() { + let mut g = Vec::new(); + r.read_to_end(&mut g)?; + for x in g.iter().array_chunks::<4>() { s.0.push(f32::from_be_bytes(x.map(|x| *x))) } Ok(s) } } -impl Part { - pub fn serialize(&self, w: &mut Vec) -> Result<()> { - for x in &self.vertex { - write_kv(w, b"vertex", &x.0); +impl ReadWrite for Part { + fn write(&self, w: &mut dyn Write) -> Result<()> { + if let Some(a) = &self.index { + write_kv(w, b"index", &a.write_alloc())?; } - if let Some(x) = &self.index { - write_kv(w, b"index", &x.0); + if let Some(a) = &self.va_position { + write_kv(w, b"va_position", &a.write_alloc())?; } - if let Some(x) = &self.armature { - write_kv(w, b"armature", &x.0); + if let Some(a) = &self.va_normal { + write_kv(w, b"va_normal", &a.write_alloc())?; } - if let Some(x) = &self.fragment_shader { - write_kv(w, b"fragment_shader", &x.0); + if let Some(a) = &self.va_texcoord { + write_kv(w, b"va_texcoord", &a.write_alloc())?; } - if let Some(x) = &self.fragment_shader_data { - write_kv(w, b"fragment_shader_data", &x.0); + if let Some(a) = &self.va_pbr_roughness { + write_kv(w, b"va_pbr_roughness", &a.write_alloc())?; } - if let Some(x) = &self.vertex_shader { - write_kv(w, b"vertex_shader", &x.0); + if let Some(a) = &self.va_pbr_metallic { + write_kv(w, b"va_pbr_metallic", &a.write_alloc())?; } - if let Some(x) = &self.vertex_shader_data { - write_kv(w, b"vertex_shader_data", &x.0); - } - for x in &self.vertex { - write_kv(w, b"texture", &x.0); + if let Some(a) = &self.va_pbr_albedo { + write_kv(w, b"va_pbr_albedo", &a.write_alloc())?; } Ok(()) } - pub fn deserialize(mut r: &[u8]) -> Result { + fn read(r: &mut dyn Read) -> Result { let mut s = Self::default(); - while !r.is_empty() { - let (k, v) = read_kv(&mut r)?; + let mut g = Vec::new(); + r.read_to_end(&mut g)?; + let mut g = g.as_slice(); + while !g.is_empty() { + let (k, v) = read_kv(&mut g)?; + let mut v = v.as_slice(); match k.as_slice() { - b"vertex" => s.vertex.push(slice_to_res(&v)?), - b"index" => s.index = Some(slice_to_res(&v)?), - b"armature" => s.armature = Some(slice_to_res(&v)?), - b"fragment_shader" => s.fragment_shader = Some(slice_to_res(&v)?), - b"fragment_shader_data" => s.fragment_shader_data = Some(slice_to_res(&v)?), - b"vertex_shader" => s.vertex_shader = Some(slice_to_res(&v)?), - b"vertex_shader_data" => s.vertex_shader_data = Some(slice_to_res(&v)?), - b"texture" => s.texture.push(slice_to_res(&v)?), + b"index" => s.index = Some(<_ as ReadWrite>::read(&mut v)?), + b"va_position" => s.va_position = Some(<_ as ReadWrite>::read(&mut v)?), + b"va_normal" => s.va_normal = Some(<_ as ReadWrite>::read(&mut v)?), + b"va_texcoord" => s.va_texcoord = Some(<_ as ReadWrite>::read(&mut v)?), + b"va_pbr_roughness" => s.va_pbr_roughness = Some(<_ as ReadWrite>::read(&mut v)?), + b"va_pbr_metallic" => s.va_pbr_metallic = Some(<_ as ReadWrite>::read(&mut v)?), + b"va_pbr_albedo" => s.va_pbr_albedo = Some(<_ as ReadWrite>::read(&mut v)?), + b"va_pbr_transmission" => { + s.va_pbr_transmission = Some(<_ as ReadWrite>::read(&mut v)?) + } _ => warn!("unknown part key"), } } Ok(s) } } -fn slice_to_res(s: &[u8]) -> Result { - Ok(Resource( - s.try_into() - .map_err(|_| anyhow!("resource length incorrect"))?, - )) -} -fn read_kv(r: &mut &[u8]) -> Result<(Vec, Vec)> { +fn read_kv(r: &mut dyn Read) -> Result<(Vec, Vec)> { let mut key_size = [0; 2]; let mut value_size = [0; 2]; r.read_exact(&mut key_size)?; @@ -134,9 +144,41 @@ fn read_kv(r: &mut &[u8]) -> Result<(Vec, Vec)> { r.read_exact(&mut key)?; Ok((key, value)) } -fn write_kv(w: &mut Vec, key: &[u8], value: &[u8]) { - w.extend(&(key.len() as u16).to_be_bytes()); - w.extend(&(value.len() as u16).to_be_bytes()); - w.extend(key); - w.extend(value); + +fn write_kv(w: &mut dyn Write, key: &[u8], value: &[u8]) -> Result<()> { + w.write_all(&(key.len() as u16).to_be_bytes())?; + w.write_all(&(value.len() as u16).to_be_bytes())?; + w.write_all(key)?; + w.write_all(value)?; + Ok(()) +} + +impl ReadWrite for Attribute { + fn write(&self, w: &mut dyn Write) -> Result<()> { + match self { + Attribute::Constant(v) => { + w.write_all(&[0x01])?; + w.write_all(&v.to_be_bytes())?; + } + Attribute::Vertex(resource) => { + w.write_all(&[0x02])?; + resource.write(w)?; + } + Attribute::Texture(resource) => { + w.write_all(&[0x03])?; + resource.write(w)?; + } + } + Ok(()) + } + fn read(r: &mut dyn Read) -> Result { + let mut tag = [0u8; 1]; + r.read_exact(&mut tag)?; + Ok(match tag[0] { + 0x01 => Self::Constant(f32::read(r)?), + 0x02 => Self::Vertex(Resource::read(r)?), + 0x03 => Self::Texture(Resource::read(r)?), + _ => bail!("unknown attribute tag"), + }) + } } diff --git a/world/src/main.rs b/world/src/main.rs index 4f641c3..772c87d 100644 --- a/world/src/main.rs +++ b/world/src/main.rs @@ -6,8 +6,8 @@ use std::{ path::PathBuf, }; use weareshared::{ - packets::{Object, Packet}, - resources::{Indecies, Part, Prefab, VertexAttributes}, + packets::{Object, Packet, ReadWrite}, + resources::{Attribute, AttributeArray, IndexArray, Part}, store::ResourceStore, }; @@ -30,11 +30,21 @@ fn main() -> Result<()> { if let Some(mesh) = node.mesh() { for p in mesh.primitives() { let reader = p.reader(|buf| Some(&buffers[buf.index()])); - let mut attrs = vec![vec![]; 3]; + let mut pos_x = vec![]; + let mut pos_y = vec![]; + let mut pos_z = vec![]; + let mut norm_x = vec![]; + let mut norm_y = vec![]; + let mut norm_z = vec![]; for p in reader.read_positions().unwrap() { - attrs[0].push(p[0]); - attrs[1].push(p[1]); - attrs[2].push(p[2]); + pos_x.push(p[0]); + pos_y.push(p[1]); + pos_z.push(p[2]); + } + for p in reader.read_normals().unwrap() { + norm_x.push(p[0]); + norm_y.push(p[1]); + norm_z.push(p[2]); } let index = reader .read_indices() @@ -44,41 +54,40 @@ fn main() -> Result<()> { .array_chunks::<3>() .collect::>(); - let part = Part { - vertex: attrs - .into_iter() - .map(|d| { - let mut out = Vec::new(); - VertexAttributes(d).serialize(&mut out)?; - store.set(&out) - }) - .collect::, _>>()?, - index: Some({ - let mut out = Vec::new(); - Indecies(index).serialize(&mut out)?; - store.set(&out)? - }), - ..Part::default() - }; - let mut out = Vec::new(); - part.serialize(&mut out)?; - Packet::Add(Object::new(), store.set(&out)?).serialize(&mut sock)?; + let part = store.set( + &Part { + va_position: Some([ + Attribute::Vertex(store.set(&AttributeArray(pos_x).write_alloc())?), + Attribute::Vertex(store.set(&AttributeArray(pos_y).write_alloc())?), + Attribute::Vertex(store.set(&AttributeArray(pos_z).write_alloc())?), + ]), + va_normal: Some([ + Attribute::Vertex(store.set(&AttributeArray(norm_x).write_alloc())?), + Attribute::Vertex(store.set(&AttributeArray(norm_y).write_alloc())?), + Attribute::Vertex(store.set(&AttributeArray(norm_z).write_alloc())?), + ]), + index: Some(store.set(&IndexArray(index).write_alloc())?), + ..Part::default() + } + .write_alloc(), + )?; + Packet::Add(Object::new(), part).write(&mut sock)?; } } } store.iter(|d| { Packet::RespondResource(d.to_vec()) - .serialize(&mut sock) + .write(&mut sock) .unwrap(); })?; loop { - let packet = Packet::deserialize(&mut sock)?; + let packet = Packet::read(&mut sock)?; match packet { Packet::RequestResource(hash) => { if let Some(d) = store.get(hash)? { - Packet::RespondResource(d).serialize(&mut sock)?; + Packet::RespondResource(d).write(&mut sock)?; } } _ => (), -- cgit v1.2.3-70-g09d2