summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/src/scene_prepare.rs25
-rw-r--r--doc/other.md10
-rw-r--r--doc/protocol.md36
-rw-r--r--doc/resources.md (renamed from a.md)82
-rw-r--r--shared/src/resources.rs207
-rw-r--r--world/src/main.rs8
6 files changed, 240 insertions, 128 deletions
diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs
index 6d50035..e58e77a 100644
--- a/client/src/scene_prepare.rs
+++ b/client/src/scene_prepare.rs
@@ -11,7 +11,7 @@ use std::{
use weareshared::{
Affine3A,
packets::{ReadWrite, Resource},
- resources::{Part, Prefab},
+ resources::{MeshPart, Prefab},
};
use wgpu::{
BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindingResource, Buffer,
@@ -55,12 +55,12 @@ pub struct ScenePreparer {
index_buffers: DemandMap<Resource, (Arc<Buffer>, u32)>,
vertex_buffers: DemandMap<Resource, (Arc<Buffer>, u32)>,
placeholder_vertex_buffers: DemandMap<(u32, bool), Arc<Buffer>>,
- parts: DemandMap<Resource, Arc<RPart>>,
+ mesh_parts: DemandMap<Resource, Arc<RMeshPart>>,
pub prefabs: DemandMap<Resource, Arc<RPrefab>>,
}
-pub struct RPrefab(pub Vec<(Affine3A, Arc<RPart>)>);
-pub struct RPart {
+pub struct RPrefab(pub Vec<(Affine3A, Arc<RMeshPart>)>);
+pub struct RMeshPart {
pub index_count: u32,
pub index: Arc<Buffer>,
pub position: [Arc<Buffer>; 3],
@@ -75,7 +75,7 @@ impl ScenePreparer {
texture_bgl,
index_buffers: DemandMap::new(),
vertex_buffers: DemandMap::new(),
- parts: DemandMap::new(),
+ mesh_parts: DemandMap::new(),
prefabs: DemandMap::new(),
textures: DemandMap::new(),
placeholder_vertex_buffers: DemandMap::new(),
@@ -89,12 +89,12 @@ impl ScenePreparer {
if let Some(buf) = dls.try_get(pres)? {
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.try_get(*partres) {
+ for (aff, partres) in &prefab.mesh {
+ if let Some(part) = self.mesh_parts.try_get(*partres) {
rprefab.0.push((*aff, part.clone()));
}
}
- if rprefab.0.len() == prefab.0.len() {
+ if rprefab.0.len() == prefab.mesh.len() {
self.prefabs.insert(pres, Arc::new(rprefab));
debug!("prefab created ({pres})");
}
@@ -169,9 +169,10 @@ impl ScenePreparer {
);
self.placeholder_textures.insert(pres, tex_bg);
}
- for pres in self.parts.needed.clone() {
+ for pres in self.mesh_parts.needed.clone() {
if let Some(buf) = dls.try_get(pres)? {
- let part = Part::read(&mut buf.as_slice()).context("parsing part")?;
+ let part = MeshPart::read(&mut buf.as_slice()).context("parsing part")?;
+
if let (Some(indexres), Some(positionres)) = (part.index, part.va_position) {
let Some((index, index_count)) = self.index_buffers.try_get(indexres) else {
self.index_buffers.needed.insert(indexres);
@@ -238,9 +239,9 @@ impl ScenePreparer {
&& texture.is_some()
{
debug!("part created ({pres})");
- self.parts.insert(
+ self.mesh_parts.insert(
pres,
- Arc::new(RPart {
+ Arc::new(RMeshPart {
index_count,
index,
texcoord: texcoord.try_into().unwrap(),
diff --git a/doc/other.md b/doc/other.md
new file mode 100644
index 0000000..76c8c37
--- /dev/null
+++ b/doc/other.md
@@ -0,0 +1,10 @@
+
+## Player tree
+
+- LowerTorso (2x leg tilt)
+ - FootL
+ - FootR
+ - UpperTorso (2x arm tilt)
+ - HandL (5x finger, 5x tilt)
+ - HandR (5x finger, 5x tilt)
+ - Head (2x brow, 2x eyelid, 2x eye, 3x mouth)
diff --git a/doc/protocol.md b/doc/protocol.md
new file mode 100644
index 0000000..cd4694e
--- /dev/null
+++ b/doc/protocol.md
@@ -0,0 +1,36 @@
+# Protocol
+
+Default port is 28555 for TCP and UDP transport.
+
+For TCP, packets are concatenated to a stream.
+
+For UDP, game packets are concatenated in groups of at least one to form one UDP
+packet.
+
+## Protocol packets
+
+All packets are preceeded by its length as u32. The next byte indicates the
+type. The following bytes are the parameters.
+
+`Vec<T>` is stored as u32 element count followed by the elements. `Res<T>` is
+used to denote 256-bit resource hash referring to data of type T. `Obj` refers
+128-bit game objects IDs.
+
+```rs
+00 connect(identity: u128)
+ff disconnect()
+01 request_resource(name: Res)
+02 respond_resource(data: Vec<u8>)
+03 add(id: Obj, prefab: Res<Prefab>)
+04 remove(id: Obj)
+05 position(id: Obj, pos: Vec3, rot: Vec3)
+06 pose(id: Obj, params: Vec<f32>)
+07 parent(parent: Obj, child: Obj)
+08 sound(id: Obj, data: Vec<u8>)
+09 prefab_index(res: Res)
+```
+
+## Resources
+
+Resources are reusable things. They are identified by the SHA-256 hash of their
+serialized content. See [resources.md](./resources.md)
diff --git a/a.md b/doc/resources.md
index 22cccd4..3add075 100644
--- a/a.md
+++ b/doc/resources.md
@@ -1,47 +1,31 @@
-## Protocol packets
+# Resource formats
-Vec is stored as `len:u32 *(data:T)`. All packets are preceeded by a u32
-indicating its length.
+## Dictionary format
-```rs
-type Obj = [u8; 16]
-type Res = [u8; 32]
-00 connect(identity: u128)
-ff disconnect()
-01 request_resource(name: Res)
-02 respond_resource(data: Vec<u8>)
-03 add(id: Obj, prefab: Res)
-04 remove(id: Obj)
-05 position(id: Obj, pos: Vec3, rot: Vec3)
-06 pose(id: Obj, params: Vec<f32>)
-07 parent(parent: Obj, child: Obj)
-08 sound(id: Obj, data: Vec<u8>)
-09 prefab_index(res: Res)
```
-
-## Resource formats
-
-### PrefabIndex
-
-```
-PrefabIndex = *(len_key:u16 len_value:u16 *(key:u8) *(value:u8))
+[kkkk vvvv KK... VV...]...
+ ^ ^ ^ ^
+ | | | | value
+ | | | key
+ | | 16-bit kalue length
+ | 16-bit key length
```
-Key is string with model name. Value is prefab resource.
+## PrefabIndex
-### Prefab
+| Key | Value Type |
+| -------- | ---------- |
+| \<Name\> | Resource |
-```
-Prefab = *(pos:f32x3 mat:f32_3x3 part:Res<Part>)
-```
+## Prefab
-### Part
+| Key | Value Type | |
+| ----------- | ----------------------- | --------- |
+| mesh | Matrix3, Vec3, Resource | Multi key |
+| light | Vec3, Resource | Multi key |
+| environment | Resource | |
-```
-Part = *(len_key:u16 len_value:u16 *(key:u8) *(value:u8))
-Attribute = 0x01 constant:f32 / 0x02 buffer:Res / 0x03 texture:Res<Texture>
-NewAttribute = flag:u8 constant:f32 buffer:Res texture:Res<Texture>
-```
+## MeshPart
Combinations of g__, va__ and tex_* are multiplied except normal which is added.
Defaults should be the identity for that operation, so default is 1 / white
@@ -52,9 +36,9 @@ except normals are zero.
| index | Resource | |
| g_metallic | f32 | |
| g_roughness | f32 | |
-| g_albedo | \[f32;3\] | |
+| g_albedo | Vec3 | |
| g_transmission | f32 | |
-| g_emission | \[f32;3\] | |
+| g_emission | Vec3 | |
| va_position | [Resource; 3] | |
| va_normal | [Resource; 3] | |
| va_texcoord | [Resource; 2] | |
@@ -70,20 +54,20 @@ except normals are zero.
| tex_transmission | Resource | Use alpha channel |
| tex_emission | Resource | Use color channels |
-### Texture
+## LightPart
-WebP
+| Key | Value Type |
+| -------- | ---------- |
+| radius | f32 |
+| emission | Vec3 |
-### Shader
+## EnvironmentPart
-glsl source, todo
+| Key | Value Type | |
+| ------ | ---------- | ---------------- |
+| skybox | Resource | |
+| sun | Vec3, Vec3 | Direction, Color |
-## Player tree
+## Texture
-- LowerTorso (2x leg tilt)
- - FootL
- - FootR
- - UpperTorso (2x arm tilt)
- - HandL (5x finger, 5x tilt)
- - HandR (5x finger, 5x tilt)
- - Head (2x brow, 2x eyelid, 2x eye, 3x mouth)
+WebP
diff --git a/shared/src/resources.rs b/shared/src/resources.rs
index 5b2e852..d0094fa 100644
--- a/shared/src/resources.rs
+++ b/shared/src/resources.rs
@@ -8,10 +8,26 @@ use std::{
};
#[derive(Debug, Default, Clone)]
-pub struct Prefab(pub Vec<(Affine3A, Resource)>);
+pub struct Prefab {
+ pub mesh: Vec<(Affine3A, Resource)>,
+ pub light: Vec<(Vec3A, Resource)>,
+ pub environment: Option<EnvironmentPart>,
+}
+
+#[derive(Debug, Default, Clone)]
+pub struct LightPart {
+ emission: Option<Vec3A>,
+ radius: Option<f32>,
+}
#[derive(Debug, Default, Clone)]
-pub struct Part {
+pub struct EnvironmentPart {
+ skybox: Option<Resource>,
+ sun: Option<(Vec3A, Vec3A)>,
+}
+
+#[derive(Debug, Default, Clone)]
+pub struct MeshPart {
pub index: Option<Resource>,
pub g_metallic: Option<f32>,
pub g_roughness: Option<f32>,
@@ -63,58 +79,69 @@ impl ReadWrite for PrefabIndex {
impl ReadWrite for Prefab {
fn write(&self, w: &mut dyn Write) -> Result<()> {
- for (aff, res) in self.0.clone() {
- aff.write(w)?;
- res.write(w)?;
+ for x in &self.mesh {
+ write_kv_opt(w, b"mesh", &Some(*x))?;
+ }
+ for x in &self.light {
+ write_kv_opt(w, b"light", &Some(*x))?;
}
+ write_kv_opt(w, b"environment", &self.environment)?;
Ok(())
}
fn read(r: &mut dyn Read) -> Result<Self> {
- 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(&mut g)?, Resource::read(&mut g)?))
- }
+ let mut s = Self::default();
+ read_kv_iter(r, |k, v| match k {
+ b"mesh" => Ok(s.mesh.push(read_slice(v)?)),
+ b"light" => Ok(s.light.push(read_slice(v)?)),
+ b"environment" => Ok(s.environment = Some(read_slice(v)?)),
+ x => Ok(warn!(
+ "unknown prefab key: {:?}",
+ String::from_utf8_lossy(x)
+ )),
+ })?;
Ok(s)
}
}
-impl ReadWrite for IndexArray {
+impl ReadWrite for LightPart {
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())?;
- }
+ write_kv_opt(w, b"emission", &self.emission)?;
+ write_kv_opt(w, b"radius", &self.radius)?;
Ok(())
}
+
fn read(r: &mut dyn Read) -> Result<Self> {
- let mut s = Self(Vec::new());
- 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))))
- }
+ let mut s = Self::default();
+ read_kv_iter(r, |k, v| match k {
+ b"emission" => Ok(s.emission = Some(read_slice(v)?)),
+ b"radius" => Ok(s.radius = Some(read_slice(v)?)),
+ x => Ok(warn!(
+ "unknown light part key: {:?}",
+ String::from_utf8_lossy(x)
+ )),
+ })?;
Ok(s)
}
}
-impl ReadWrite for AttributeArray {
+impl ReadWrite for EnvironmentPart {
fn write(&self, w: &mut dyn Write) -> Result<()> {
- for x in self.0.clone() {
- w.write_all(&x.to_be_bytes())?;
- }
+ write_kv_opt(w, b"skybox", &self.skybox)?;
+ write_kv_opt(w, b"sun", &self.sun)?;
Ok(())
}
fn read(r: &mut dyn Read) -> Result<Self> {
- let mut s = Self(Vec::new());
- 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)))
- }
+ let mut s = Self::default();
+ read_kv_iter(r, |k, v| match k {
+ b"skybox" => Ok(s.skybox = Some(read_slice(v)?)),
+ b"sun" => Ok(s.sun = Some(read_slice(v)?)),
+ x => Ok(warn!(
+ "unknown environment part key: {:?}",
+ String::from_utf8_lossy(x)
+ )),
+ })?;
Ok(s)
}
}
-impl ReadWrite for Part {
+impl ReadWrite for MeshPart {
fn write(&self, w: &mut dyn Write) -> Result<()> {
write_kv_opt(w, b"index", &self.index)?;
write_kv_opt(w, b"g_metallic", &self.g_metallic)?;
@@ -140,36 +167,32 @@ impl ReadWrite for Part {
}
fn read(r: &mut dyn Read) -> Result<Self> {
let mut s = Self::default();
- 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"index" => s.index = Some(<_ as ReadWrite>::read(&mut v)?),
- b"g_metallic" => s.g_metallic = Some(<_ as ReadWrite>::read(&mut v)?),
- b"g_roughness" => s.g_roughness = Some(<_ as ReadWrite>::read(&mut v)?),
- b"g_albedo" => s.g_albedo = Some(<_ as ReadWrite>::read(&mut v)?),
- b"g_transmission" => s.g_transmission = Some(<_ as ReadWrite>::read(&mut v)?),
- b"g_emission" => s.g_emission = 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_roughness" => s.va_roughness = Some(<_ as ReadWrite>::read(&mut v)?),
- b"va_metallic" => s.va_metallic = Some(<_ as ReadWrite>::read(&mut v)?),
- b"va_albedo" => s.va_albedo = Some(<_ as ReadWrite>::read(&mut v)?),
- b"va_transmission" => s.va_transmission = Some(<_ as ReadWrite>::read(&mut v)?),
- b"va_emission" => s.va_emission = Some(<_ as ReadWrite>::read(&mut v)?),
- b"tex_normal" => s.tex_normal = Some(<_ as ReadWrite>::read(&mut v)?),
- b"tex_roughness" => s.tex_roughness = Some(<_ as ReadWrite>::read(&mut v)?),
- b"tex_metallic" => s.tex_metallic = Some(<_ as ReadWrite>::read(&mut v)?),
- b"tex_albedo" => s.tex_albedo = Some(<_ as ReadWrite>::read(&mut v)?),
- b"tex_transmission" => s.tex_transmission = Some(<_ as ReadWrite>::read(&mut v)?),
- b"tex_emission" => s.tex_emission = Some(<_ as ReadWrite>::read(&mut v)?),
- x => warn!("unknown part key: {:?}", String::from_utf8_lossy(x)),
- }
- }
+ read_kv_iter(r, |k, v| match k {
+ b"index" => Ok(s.index = Some(read_slice(v)?)),
+ b"g_metallic" => Ok(s.g_metallic = Some(read_slice(v)?)),
+ b"g_roughness" => Ok(s.g_roughness = Some(read_slice(v)?)),
+ b"g_albedo" => Ok(s.g_albedo = Some(read_slice(v)?)),
+ b"g_transmission" => Ok(s.g_transmission = Some(read_slice(v)?)),
+ b"g_emission" => Ok(s.g_emission = Some(read_slice(v)?)),
+ b"va_position" => Ok(s.va_position = Some(read_slice(v)?)),
+ b"va_normal" => Ok(s.va_normal = Some(read_slice(v)?)),
+ b"va_texcoord" => Ok(s.va_texcoord = Some(read_slice(v)?)),
+ b"va_roughness" => Ok(s.va_roughness = Some(read_slice(v)?)),
+ b"va_metallic" => Ok(s.va_metallic = Some(read_slice(v)?)),
+ b"va_albedo" => Ok(s.va_albedo = Some(read_slice(v)?)),
+ b"va_transmission" => Ok(s.va_transmission = Some(read_slice(v)?)),
+ b"va_emission" => Ok(s.va_emission = Some(read_slice(v)?)),
+ b"tex_normal" => Ok(s.tex_normal = Some(read_slice(v)?)),
+ b"tex_roughness" => Ok(s.tex_roughness = Some(read_slice(v)?)),
+ b"tex_metallic" => Ok(s.tex_metallic = Some(read_slice(v)?)),
+ b"tex_albedo" => Ok(s.tex_albedo = Some(read_slice(v)?)),
+ b"tex_transmission" => Ok(s.tex_transmission = Some(read_slice(v)?)),
+ b"tex_emission" => Ok(s.tex_emission = Some(read_slice(v)?)),
+ x => Ok(warn!(
+ "unknown mesh part key: {:?}",
+ String::from_utf8_lossy(x)
+ )),
+ })?;
Ok(s)
}
}
@@ -188,6 +211,20 @@ fn read_kv(r: &mut &[u8]) -> Result<(Vec<u8>, Vec<u8>)> {
Ok((key, value))
}
+fn read_kv_iter(r: &mut dyn Read, mut cb: impl FnMut(&[u8], &[u8]) -> Result<()>) -> Result<()> {
+ 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)?;
+ cb(&k, &v)?
+ }
+ Ok(())
+}
+fn read_slice<T: ReadWrite>(mut r: &[u8]) -> Result<T> {
+ T::read(&mut r)
+}
+
fn write_kv_opt(w: &mut dyn Write, key: &[u8], value: &Option<impl ReadWrite>) -> Result<()> {
if let Some(v) = value {
write_kv(w, key, &v.write_alloc())?;
@@ -236,3 +273,47 @@ impl ReadWrite for Affine3A {
Ok(Self::from_cols_array(&[(); 12].try_map(|()| f32::read(r))?))
}
}
+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(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ let mut s = Self(Vec::new());
+ 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 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(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ let mut s = Self(Vec::new());
+ 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<A: ReadWrite, B: ReadWrite> ReadWrite for (A, B) {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ self.0.write(w)?;
+ self.1.write(w)?;
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ Ok((A::read(r)?, B::read(r)?))
+ }
+}
diff --git a/world/src/main.rs b/world/src/main.rs
index 2014996..5f72b01 100644
--- a/world/src/main.rs
+++ b/world/src/main.rs
@@ -15,7 +15,7 @@ use std::{
use weareshared::{
Affine3A, Vec3A,
packets::{Data, Object, Packet, ReadWrite, Resource},
- resources::{AttributeArray, IndexArray, Part, Prefab},
+ resources::{AttributeArray, IndexArray, MeshPart, Prefab},
store::ResourceStore,
vec3a,
};
@@ -241,8 +241,8 @@ fn main() -> Result<()> {
None
};
- let part = store.set(
- &Part {
+ let mesh = store.set(
+ &MeshPart {
g_albedo,
g_transmission,
g_metallic,
@@ -273,7 +273,7 @@ fn main() -> Result<()> {
[mat[2][0], mat[2][1], mat[2][2]],
[mat[3][0], mat[3][1], mat[3][2]],
]);
- prefab.0.push((aff, part))
+ prefab.mesh.push((aff, mesh))
}
}
}