diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | a.md | 8 | ||||
-rw-r--r-- | client/Cargo.toml | 1 | ||||
-rw-r--r-- | client/src/main.rs | 3 | ||||
-rw-r--r-- | client/src/part.rs | 157 | ||||
-rw-r--r-- | shared/src/store.rs | 9 | ||||
-rw-r--r-- | world/src/main.rs | 22 |
7 files changed, 196 insertions, 5 deletions
@@ -2435,6 +2435,7 @@ dependencies = [ "env_logger", "log", "pollster", + "weareshared", "wgpu", "winit", ] @@ -1,7 +1,9 @@ ## Protocol packets +Vec is stored as `len:u8 *(data:T)` + ```rs -type Obj = u128 +type Obj = [u8; 16] type Res = [u8; 32] 01 request_resource(name: Res) 02 respond_resource(data: Vec<u8>) @@ -18,13 +20,13 @@ type Res = [u8; 32] ### Prefab ``` -([part])* +Prefab = *(part) ``` ### Part ``` -([len_key:u8] [len_value:u8] ([key:u8])* ([value:u8])*)* +Part = *(len_key:u8 len_value:u8 *(key:u8) *(value:u8)) ``` - vertex (mult): `[Res<[f32]>]` diff --git a/client/Cargo.toml b/client/Cargo.toml index b0ba84a..ffa40e4 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -13,3 +13,4 @@ log = "0.4.22" pollster = "0.4.0" wgpu = "23.0.1" winit = "0.30.8" +weareshared = { path = "../shared" } diff --git a/client/src/main.rs b/client/src/main.rs index 1aa05db..543db6d 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,5 +1,6 @@ -pub mod window; pub mod renderer; +pub mod window; +pub mod part; use anyhow::Result; use clap::Parser; diff --git a/client/src/part.rs b/client/src/part.rs new file mode 100644 index 0000000..15835d0 --- /dev/null +++ b/client/src/part.rs @@ -0,0 +1,157 @@ +use anyhow::Result; +use weareshared::{ + packets::Resource, + 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 RenderPart { + vertex: Buffer, + index: Buffer, + pipeline: RenderPipeline, + bind_group: BindGroup, + n_vertex: u32, +} +pub struct PartData { + target: Part, + vertex: Vec<Option<VertexAttributes>>, + index: Option<Indecies>, +} + +impl PartData { + pub fn update(&mut self, hash: Resource, data: &[u8]) -> Result<bool> { + if Some(hash) == self.target.index { + self.index = Some(Indecies::deserialize(data)?) + } + for (thash, tdata) in self.target.vertex.iter().zip(self.vertex.iter_mut()) { + if hash == *thash { + *tdata = Some(VertexAttributes::deserialize(data)?) + } + } + Ok(self.vertex.iter().all(|v| v.is_some()) && self.index.is_some()) + } +} + +impl RenderPart { + pub fn new(device: Device, data: PartData, format: TextureFormat) -> Self { + let mut vertex = Vec::new(); + let mut index = Vec::new(); + let attrs = data.vertex.unwrap(); + for i in 0..data.vertex[0].as_ref().unwrap().0.len() { + vertex.extend(attrs[0].0[i].to_le_bytes()); + vertex.extend(attrs[1].0[i].to_le_bytes()); + vertex.extend(attrs[2].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/shared/src/store.rs b/shared/src/store.rs index 7130021..702ed87 100644 --- a/shared/src/store.rs +++ b/shared/src/store.rs @@ -46,6 +46,15 @@ impl ResourceStore { } Ok(key) } + pub fn iter(&self, mut cb: impl FnMut(&[u8])) -> Result<()> { + match self { + ResourceStore::Redb(_database) => todo!(), + ResourceStore::Memory(mutex) => { + mutex.lock().unwrap().values().for_each(|v| cb(v)); + Ok(()) + } + } + } } pub fn sha256(x: &[u8]) -> [u8; 32] { diff --git a/world/src/main.rs b/world/src/main.rs index 28a4ec4..fd354b3 100644 --- a/world/src/main.rs +++ b/world/src/main.rs @@ -1,3 +1,4 @@ +#![feature(iter_array_chunks)] use anyhow::Result; use clap::Parser; use std::{ @@ -6,7 +7,7 @@ use std::{ }; use weareshared::{ packets::{Object, Packet}, - resources::{Part, Prefab, VertexAttributes}, + resources::{Indecies, Part, Prefab, VertexAttributes}, store::ResourceStore, }; @@ -36,6 +37,14 @@ fn main() -> Result<()> { attrs[1].push(p[1]); attrs[2].push(p[2]); } + let index = reader + .read_indices() + .unwrap() + .into_u32() + .map(|e| e as u16) + .array_chunks::<3>() + .collect::<Vec<_>>(); + let part = Part { vertex: attrs .into_iter() @@ -45,6 +54,11 @@ fn main() -> Result<()> { store.set(&out) }) .collect::<Result<Vec<_>, _>>()?, + index: Some({ + let mut out = Vec::new(); + Indecies(index).serialize(&mut out)?; + store.set(&out)? + }), ..Part::default() }; let mut out = Vec::new(); @@ -60,6 +74,12 @@ fn main() -> Result<()> { Packet::Add(Object::new(), prefab).serialize(&mut sock)?; + store.iter(|d| { + Packet::RespondResource(d.to_vec()) + .serialize(&mut sock) + .unwrap(); + })?; + loop { let packet = Packet::deserialize(&mut sock)?; match packet { |