diff options
author | metamuffin <metamuffin@disroot.org> | 2025-01-07 16:50:44 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-01-07 16:50:44 +0100 |
commit | 0a0abfe7b093d91447fb7070820a0e6d56d6c22d (patch) | |
tree | 17cdfd63bce8d717cd35d4d88646b837fbffc594 | |
parent | d0d8c07e1915b47610bf91176d908c9b46a5ab54 (diff) | |
download | weareserver-0a0abfe7b093d91447fb7070820a0e6d56d6c22d.tar weareserver-0a0abfe7b093d91447fb7070820a0e6d56d6c22d.tar.bz2 weareserver-0a0abfe7b093d91447fb7070820a0e6d56d6c22d.tar.zst |
normal texture
-rw-r--r-- | a.md | 11 | ||||
-rw-r--r-- | client/src/camera.rs | 7 | ||||
-rw-r--r-- | client/src/window.rs | 10 | ||||
-rw-r--r-- | server/src/main.rs | 4 | ||||
-rw-r--r-- | shared/src/resources.rs | 38 | ||||
-rw-r--r-- | world/src/main.rs | 174 |
6 files changed, 178 insertions, 66 deletions
@@ -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") + } + } +} |