summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-01-07 16:50:44 +0100
committermetamuffin <metamuffin@disroot.org>2025-01-07 16:50:44 +0100
commit0a0abfe7b093d91447fb7070820a0e6d56d6c22d (patch)
tree17cdfd63bce8d717cd35d4d88646b837fbffc594
parentd0d8c07e1915b47610bf91176d908c9b46a5ab54 (diff)
downloadweareserver-0a0abfe7b093d91447fb7070820a0e6d56d6c22d.tar
weareserver-0a0abfe7b093d91447fb7070820a0e6d56d6c22d.tar.bz2
weareserver-0a0abfe7b093d91447fb7070820a0e6d56d6c22d.tar.zst
normal texture
-rw-r--r--a.md11
-rw-r--r--client/src/camera.rs7
-rw-r--r--client/src/window.rs10
-rw-r--r--server/src/main.rs4
-rw-r--r--shared/src/resources.rs38
-rw-r--r--world/src/main.rs174
6 files changed, 178 insertions, 66 deletions
diff --git a/a.md b/a.md
index 8498b6c..a320e6d 100644
--- a/a.md
+++ b/a.md
@@ -16,10 +16,19 @@ ff disconnect()
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))
+```
+
+Key is string with model name. Value is prefab resource.
+
### Prefab
```
@@ -34,7 +43,7 @@ Attribute = 0x01 constant:f32 / 0x02 buffer:Res / 0x03 texture:Res<Texture>
NewAttribute = flag:u8 constant:f32 buffer:Res texture:Res<Texture>
```
-Combinations of g_*, va_* and tex_* are multiplied except normal which is added.
+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
except normals are zero.
diff --git a/client/src/camera.rs b/client/src/camera.rs
index 289e773..1471a48 100644
--- a/client/src/camera.rs
+++ b/client/src/camera.rs
@@ -18,8 +18,8 @@ impl Camera {
}
pub fn update(&mut self, input_move: Vec3, input_rot: Vec2, dt: f32) {
self.pos += input_move * dt;
- self.rot.x += input_rot.x * 0.002;
- self.rot.y += input_rot.y * 0.002;
+ self.rot.x += input_rot.y * 0.002;
+ self.rot.y += input_rot.x * 0.002;
}
pub fn to_matrix(&self) -> Mat4 {
// let tdir =
@@ -28,10 +28,11 @@ impl Camera {
Mat4::perspective_infinite_reverse_rh(self.fov, self.aspect, 0.1)
* Mat4::from_mat3(Mat3::from_euler(
- EulerRot::ZXY,
+ EulerRot::YXZ,
self.rot.x,
self.rot.y,
self.rot.z,
))
+ * Mat4::from_translation(-self.pos)
}
}
diff --git a/client/src/window.rs b/client/src/window.rs
index 8b3ee9e..fb9f375 100644
--- a/client/src/window.rs
+++ b/client/src/window.rs
@@ -13,12 +13,14 @@ use winit::{
pub struct WindowState {
init: Option<TcpStream>,
window: Option<(Window, State<'static>)>,
+ lock: bool,
}
impl WindowState {
pub fn new(init: TcpStream) -> Self {
Self {
window: None,
init: Some(init),
+ lock: false,
}
}
}
@@ -56,7 +58,13 @@ impl ApplicationHandler for WindowState {
if event.state == ElementState::Pressed {
match event.physical_key {
PhysicalKey::Code(KeyCode::Escape) => {
- win.set_cursor_grab(CursorGrabMode::Locked).unwrap();
+ win.set_cursor_grab(if self.lock {
+ CursorGrabMode::None
+ } else {
+ CursorGrabMode::Locked
+ })
+ .unwrap();
+ self.lock = !self.lock;
}
_ => (),
}
diff --git a/server/src/main.rs b/server/src/main.rs
index 5216b41..b355d09 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -2,7 +2,7 @@ pub mod network;
use anyhow::Result;
use clap::Parser;
-use log::warn;
+use log::{debug, warn};
use network::ServerNetwork;
use std::net::{IpAddr, SocketAddr};
use weareshared::{
@@ -60,8 +60,10 @@ impl State {
Packet::Disconnect => {}
Packet::RequestResource(resource) => {
if let Some(r) = self.store.get(resource)? {
+ debug!("resource is cached");
net.send(conn, Packet::RespondResource(Data(r)), true);
} else {
+ debug!("resource not cached, request is broadcast");
net.broadcast(Packet::RequestResource(resource), true);
}
}
diff --git a/shared/src/resources.rs b/shared/src/resources.rs
index 512e161..c312531 100644
--- a/shared/src/resources.rs
+++ b/shared/src/resources.rs
@@ -2,13 +2,14 @@ use crate::packets::{ReadWrite, Resource};
use anyhow::Result;
use glam::{Affine3A, Vec3A};
use log::warn;
-use std::io::{Read, Write};
+use std::{
+ collections::HashMap,
+ io::{Read, Write},
+};
#[derive(Debug, Default, Clone)]
pub struct Prefab(pub Vec<(Affine3A, Resource)>);
-/// Combinations of va_* and tex_* are multiplied except normal which is added.
-/// Defaults should be the identity for that operation, so default is 1 (or white) except normals are Vec3::ZERO.
#[derive(Debug, Default, Clone)]
pub struct Part {
pub index: Option<Resource>,
@@ -30,11 +31,33 @@ pub struct Part {
pub tex_transmission: Option<Resource>,
}
+pub struct PrefabIndex(pub HashMap<String, Resource>);
+
#[derive(Debug, Default, Clone)]
pub struct AttributeArray(pub Vec<f32>);
#[derive(Debug, Default, Clone)]
pub struct IndexArray(pub Vec<[u16; 3]>);
+impl ReadWrite for PrefabIndex {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ for (k, v) in &self.0 {
+ write_kv(w, k.as_bytes(), &v.0)?;
+ }
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ let mut s = Self(HashMap::new());
+ 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)?;
+ s.0.insert(String::from_utf8(k)?, Resource::read(&mut v.as_slice())?);
+ }
+ Ok(s)
+ }
+}
+
impl ReadWrite for Prefab {
fn write(&self, w: &mut dyn Write) -> Result<()> {
for (aff, res) in self.0.clone() {
@@ -107,7 +130,6 @@ impl ReadWrite for Part {
write_kv_opt(w, b"tex_metallic", &self.tex_metallic)?;
write_kv_opt(w, b"tex_albedo", &self.tex_albedo)?;
write_kv_opt(w, b"tex_transmission", &self.tex_transmission)?;
-
Ok(())
}
fn read(r: &mut dyn Read) -> Result<Self> {
@@ -130,16 +152,12 @@ impl ReadWrite for Part {
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_transmission" => s.va_transmission = 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_transmission" => s.tex_transmission = Some(<_ as ReadWrite>::read(&mut v)?),
x => warn!("unknown part key: {:?}", String::from_utf8_lossy(x)),
}
}
diff --git a/world/src/main.rs b/world/src/main.rs
index b68b287..517f1e9 100644
--- a/world/src/main.rs
+++ b/world/src/main.rs
@@ -1,18 +1,20 @@
#![feature(iter_array_chunks)]
-use anyhow::Result;
+use anyhow::{Result, bail};
use clap::Parser;
-use log::info;
+use gltf::image::Source;
+use log::{info, warn};
use rand::random;
use std::{
- io::Write,
+ fs::File,
+ io::{Read, Write},
net::{SocketAddr, TcpStream},
- path::PathBuf,
+ path::{Path, PathBuf},
thread::{self, sleep},
time::Duration,
};
use weareshared::{
Affine3A, Vec3A,
- packets::{Data, Object, Packet, ReadWrite},
+ packets::{Data, Object, Packet, ReadWrite, Resource},
resources::{AttributeArray, IndexArray, Part, Prefab},
store::ResourceStore,
vec3a,
@@ -37,35 +39,71 @@ fn main() -> Result<()> {
Packet::Connect(random()).write(&mut sock)?;
- let (gltf, buffers, _) = gltf::import(args.scene)?;
+ let (gltf, buffers, _) = gltf::import(&args.scene)?;
+ let path_base = args.scene.parent().unwrap();
let mut prefab = Prefab::default();
for node in gltf.nodes() {
if let Some(mesh) = node.mesh() {
for p in mesh.primitives() {
let reader = p.reader(|buf| Some(&buffers[buf.index()]));
- 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![];
- let mut uv_x = vec![];
- let mut uv_y = vec![];
- for p in reader.read_positions().unwrap() {
- 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]);
- }
- for p in reader.read_tex_coords(0).unwrap().into_f32() {
- uv_x.push(p[0]);
- uv_y.push(p[1]);
- }
+
+ let va_position = reader
+ .read_positions()
+ .map(|iter| {
+ let mut pos_x = vec![];
+ let mut pos_y = vec![];
+ let mut pos_z = vec![];
+ for p in iter {
+ pos_x.push(p[0]);
+ pos_y.push(p[1]);
+ pos_z.push(p[2]);
+ }
+ info!("vertex positions");
+ Ok::<_, anyhow::Error>([
+ store.set(&AttributeArray(pos_x).write_alloc())?,
+ store.set(&AttributeArray(pos_y).write_alloc())?,
+ store.set(&AttributeArray(pos_z).write_alloc())?,
+ ])
+ })
+ .transpose()?;
+
+ let va_normal = reader
+ .read_normals()
+ .map(|iter| {
+ let mut normal_x = vec![];
+ let mut normal_y = vec![];
+ let mut normal_z = vec![];
+ for p in iter {
+ normal_x.push(p[0]);
+ normal_y.push(p[1]);
+ normal_z.push(p[2]);
+ }
+ info!("vertex normals");
+ Ok::<_, anyhow::Error>([
+ store.set(&AttributeArray(normal_x).write_alloc())?,
+ store.set(&AttributeArray(normal_y).write_alloc())?,
+ store.set(&AttributeArray(normal_z).write_alloc())?,
+ ])
+ })
+ .transpose()?;
+ let va_texcoord = reader
+ .read_tex_coords(0)
+ .map(|iter| {
+ let mut texcoord_u = vec![];
+ let mut texcoord_v = vec![];
+ for p in iter.into_f32() {
+ texcoord_u.push(p[0]);
+ texcoord_v.push(p[1]);
+ }
+ info!("vertex texture coordinates");
+ Ok::<_, anyhow::Error>([
+ store.set(&AttributeArray(texcoord_u).write_alloc())?,
+ store.set(&AttributeArray(texcoord_v).write_alloc())?,
+ ])
+ })
+ .transpose()?;
+
let index = reader
.read_indices()
.unwrap()
@@ -73,36 +111,42 @@ fn main() -> Result<()> {
.map(|e| e as u16)
.array_chunks::<3>()
.collect::<Vec<_>>();
+ let index = Some(store.set(&IndexArray(index).write_alloc())?);
let mut tex_albedo = None;
if let Some(tex) = p.material().pbr_metallic_roughness().base_color_texture() {
- let s = tex.texture().source().source();
- if let gltf::image::Source::View { view, mime_type } = s {
- info!("albedo texture is of type {mime_type:?}");
- let buf = &buffers[view.buffer().index()].0
- [view.offset()..view.offset() + view.length()];
- tex_albedo = Some(store.set(buf)?);
- }
+ tex_albedo = Some(load_texture(
+ "albedo",
+ &store,
+ path_base,
+ &buffers,
+ &tex.texture().source().source(),
+ )?);
+ }
+ let mut tex_normal = None;
+ if let Some(tex) = p.material().normal_texture() {
+ tex_normal = Some(load_texture(
+ "normal",
+ &store,
+ path_base,
+ &buffers,
+ &tex.texture().source().source(),
+ )?);
}
+ let g_metallic = Some(p.material().pbr_metallic_roughness().metallic_factor());
+ let g_roughness = Some(p.material().pbr_metallic_roughness().roughness_factor());
+
let part = store.set(
&Part {
- va_position: Some([
- store.set(&AttributeArray(pos_x).write_alloc())?,
- store.set(&AttributeArray(pos_y).write_alloc())?,
- store.set(&AttributeArray(pos_z).write_alloc())?,
- ]),
- va_normal: Some([
- store.set(&AttributeArray(norm_x).write_alloc())?,
- store.set(&AttributeArray(norm_y).write_alloc())?,
- store.set(&AttributeArray(norm_z).write_alloc())?,
- ]),
- va_texcoord: Some([
- store.set(&AttributeArray(uv_x).write_alloc())?,
- store.set(&AttributeArray(uv_y).write_alloc())?,
- ]),
+ g_metallic,
+ g_roughness,
+ va_position,
+ va_normal,
+ va_texcoord,
tex_albedo,
- index: Some(store.set(&IndexArray(index).write_alloc())?),
+ tex_normal,
+ index,
..Part::default()
}
.write_alloc(),
@@ -160,3 +204,33 @@ fn main() -> Result<()> {
}
Ok(())
}
+
+fn load_texture(
+ name: &str,
+ store: &ResourceStore,
+ path: &Path,
+ buffers: &[gltf::buffer::Data],
+ source: &Source,
+) -> Result<Resource> {
+ match source {
+ gltf::image::Source::View { view, mime_type } => {
+ info!("{name} texture is embedded and of type {mime_type:?}");
+ let buf =
+ &buffers[view.buffer().index()].0[view.offset()..view.offset() + view.length()];
+ return Ok(store.set(buf)?);
+ }
+ gltf::image::Source::Uri {
+ uri,
+ mime_type: Some(mime_type),
+ } => {
+ info!("{name} texture is at {uri:?} and of type {mime_type:?}");
+ let path = path.join(uri);
+ let mut buf = Vec::new();
+ File::open(path)?.read_to_end(&mut buf)?;
+ return Ok(store.set(&buf)?);
+ }
+ _ => {
+ bail!("texture is external and has no mime type")
+ }
+ }
+}