summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-01-06 14:28:02 +0100
committermetamuffin <metamuffin@disroot.org>2025-01-06 14:28:02 +0100
commit814cc1cb01692aa934a40636c9226ff7bb911266 (patch)
tree47a50a5dc1861ace4bc1854a9156618b70df3847
parentc2ee65a83838a0ce13402e2c4634bae409d55071 (diff)
downloadweareserver-814cc1cb01692aa934a40636c9226ff7bb911266.tar
weareserver-814cc1cb01692aa934a40636c9226ff7bb911266.tar.bz2
weareserver-814cc1cb01692aa934a40636c9226ff7bb911266.tar.zst
new proto
-rw-r--r--a.md21
-rw-r--r--client/src/main.rs3
-rw-r--r--client/src/network.rs6
-rw-r--r--client/src/renderer.rs113
-rw-r--r--client/src/scene_prepare.rs30
-rw-r--r--client/src/scene_render.rs (renamed from client/src/part.rs)131
-rw-r--r--server/src/main.rs10
-rw-r--r--shared/src/lib.rs2
-rw-r--r--shared/src/packets.rs92
-rw-r--r--shared/src/resources.rs172
-rw-r--r--world/src/main.rs65
11 files changed, 324 insertions, 321 deletions
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<Packet>,
@@ -40,7 +40,7 @@ impl Network {
fn handle_conn_read(sock: TcpStream, tx: Sender<Packet>) -> 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<Packet>) -> 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/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<Resource, Vec<PartData>>,
- prefabs: HashMap<Resource, Vec<PartRenderer>>,
+ scene_pipeline: ScenePipeline,
+ scene_prepare: ScenePreparer,
}
impl<'a> Renderer<'a> {
pub fn new(window: &'a Window) -> Result<Self> {
@@ -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<Resource, Buffer>,
+ vertex_buffers_x3: HashMap<[Resource; 1], Arc<Buffer>>,
+ vertex_buffers_x2: HashMap<[Resource; 2], Arc<Buffer>>,
+ vertex_buffers_x1: HashMap<[Resource; 3], Arc<Buffer>>,
+ parts: HashMap<Resource, Part>,
+}
+
+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::<HashSet<_>>();
+ }
+}
diff --git a/client/src/part.rs b/client/src/scene_render.rs
index 7d02f0c..cc15e3f 100644
--- a/client/src/part.rs
+++ b/client/src/scene_render.rs
@@ -1,86 +1,31 @@
-use crate::download::Downloader;
-use anyhow::Result;
-use weareshared::resources::{Indecies, Part, VertexAttributes};
+use std::collections::HashMap;
+use weareshared::{packets::Resource, tree::SceneTree};
use wgpu::{
- BindGroup, BindGroupDescriptor, BindGroupLayoutDescriptor, BlendState, Buffer, BufferUsages,
+ 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,
- util::{BufferInitDescriptor, DeviceExt},
};
-pub struct PartRenderer {
- vertex: Buffer,
- index: Buffer,
+pub struct ScenePipeline {
pipeline: RenderPipeline,
bind_group: BindGroup,
- n_vertex: u32,
-}
-
-pub struct PrefabData {
-
+ prefabs: HashMap<Resource, RPrefab>,
}
-pub struct PartData {
- target: Part,
- vertex: Vec<Option<VertexAttributes>>,
- index: Option<Indecies>,
-}
-
-impl PartData {
- pub fn update(&mut self, dls: &mut Downloader) -> Result<bool> {
- 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)
- }
+struct RPrefab(Vec<RPart>);
+struct RPart {
+ index_count: u32,
+ index: Buffer,
+ positions: Buffer,
+ normals: Buffer,
}
-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,
- });
-
+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 {
@@ -115,12 +60,19 @@ impl PartRenderer {
entry_point: Some("vs_main"),
buffers: &[VertexBufferLayout {
step_mode: VertexStepMode::Vertex,
- array_stride: 3,
- attributes: &[VertexAttribute {
- format: VertexFormat::Float32x3,
- offset: 0,
- shader_location: 0,
- }],
+ 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(),
},
@@ -136,33 +88,42 @@ impl PartRenderer {
multiview: None,
cache: None,
});
-
Self {
bind_group,
- index,
- vertex,
pipeline,
- n_vertex,
+ prefabs: HashMap::new(),
}
}
- pub fn draw(&self, commands: &mut CommandEncoder, target: &TextureView) {
+ 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,
+ view: target,
resolve_target: None,
ops: Operations {
store: StoreOp::Store,
- load: LoadOp::Load,
+ 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);
- 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);
+
+ 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<Mutex<State>>) -> 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<Packet>) -> 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<u8>),
}
+pub trait ReadWrite: Sized {
+ fn write(&self, w: &mut dyn Write) -> Result<()>;
+ fn read(r: &mut dyn Read) -> Result<Self>;
+
+ fn write_alloc(&self) -> Vec<u8> {
+ 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<Self> {
+}
+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<Self> {
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<u128> {
+fn read_u128(r: &mut dyn Read) -> Result<u128> {
let mut buf = [0; 16];
r.read_exact(&mut buf)?;
Ok(u128::from_be_bytes(buf))
}
-fn read_res(r: &mut impl Read) -> Result<Resource> {
- 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<Self> {
+ let mut s = Self([0; 32]);
+ r.read_exact(&mut s.0)?;
+ Ok(s)
+ }
}
-fn read_data(r: &mut impl Read) -> Result<Vec<u8>> {
+fn read_data(r: &mut dyn Read) -> Result<Vec<u8>> {
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<Vec<u8>> {
r.read_exact(&mut buf)?;
Ok(buf)
}
-fn read_float(r: &mut impl Read) -> Result<f32> {
- let mut buf = [0; 4];
- r.read_exact(&mut buf)?;
- Ok(f32::from_be_bytes(buf))
-}
-fn read_params(r: &mut impl Read) -> Result<Vec<f32>> {
+fn read_params(r: &mut dyn Read) -> Result<Vec<f32>> {
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<Self> {
+ 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<T: ReadWrite, const N: usize> 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<Self> {
+ [(); 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<Resource>);
#[derive(Debug, Default, Clone)]
pub struct Part {
- pub vertex: Vec<Resource>,
pub index: Option<Resource>,
- pub armature: Option<Resource>,
- pub fragment_shader: Option<Resource>,
- pub fragment_shader_data: Option<Resource>,
- pub vertex_shader: Option<Resource>,
- pub vertex_shader_data: Option<Resource>,
- pub texture: Vec<Resource>,
+ pub va_position: Option<[Attribute; 3]>,
+ pub va_normal: Option<[Attribute; 3]>,
+ pub va_texcoord: Option<[Attribute; 2]>,
+ pub va_pbr_roughness: Option<Attribute>,
+ pub va_pbr_metallic: Option<Attribute>,
+ pub va_pbr_albedo: Option<[Attribute; 3]>,
+ pub va_pbr_transmission: Option<Attribute>,
+}
+
+#[derive(Debug, Clone)]
+pub enum Attribute {
+ Constant(f32),
+ Vertex(Resource),
+ Texture(Resource),
}
#[derive(Debug, Default, Clone)]
-pub struct VertexAttributes(pub Vec<f32>);
+pub struct AttributeArray(pub Vec<f32>);
#[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<u8>) -> 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<Self> {
+ fn read(r: &mut dyn Read) -> Result<Self> {
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<u8>) -> 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<Self> {
+ fn read(r: &mut dyn Read) -> Result<Self> {
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<u8>) -> 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<Self> {
+ fn read(r: &mut dyn Read) -> Result<Self> {
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<u8>) -> 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<Self> {
+ fn read(r: &mut dyn Read) -> Result<Self> {
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<Resource> {
- Ok(Resource(
- s.try_into()
- .map_err(|_| anyhow!("resource length incorrect"))?,
- ))
-}
-fn read_kv(r: &mut &[u8]) -> Result<(Vec<u8>, Vec<u8>)> {
+fn read_kv(r: &mut dyn Read) -> Result<(Vec<u8>, Vec<u8>)> {
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<u8>, Vec<u8>)> {
r.read_exact(&mut key)?;
Ok((key, value))
}
-fn write_kv(w: &mut Vec<u8>, 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<Self> {
+ 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::<Vec<_>>();
- let part = Part {
- vertex: attrs
- .into_iter()
- .map(|d| {
- let mut out = Vec::new();
- VertexAttributes(d).serialize(&mut out)?;
- 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();
- 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)?;
}
}
_ => (),