diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | a.md | 5 | ||||
-rw-r--r-- | client/src/download.rs | 4 | ||||
-rw-r--r-- | client/src/scene_prepare.rs | 64 | ||||
-rw-r--r-- | client/src/scene_render.rs | 10 | ||||
-rw-r--r-- | server/src/main.rs | 106 | ||||
-rw-r--r-- | server/src/network.rs | 191 | ||||
-rw-r--r-- | shared/src/lib.rs | 2 | ||||
-rw-r--r-- | shared/src/packets.rs | 62 | ||||
-rw-r--r-- | shared/src/tree.rs | 10 | ||||
-rw-r--r-- | world/Cargo.toml | 1 | ||||
-rw-r--r-- | world/src/main.rs | 75 |
12 files changed, 396 insertions, 135 deletions
@@ -2474,6 +2474,7 @@ dependencies = [ "env_logger", "gltf", "log", + "rand", "weareshared", ] @@ -5,6 +5,8 @@ Vec is stored as `len:u8 *(data:T)` ```rs type Obj = [u8; 16] type Res = [u8; 32] +len 00 connect(identity: u128) +len ff disconnect() len 01 request_resource(name: Res) len 02 respond_resource(data: Vec<u8>) len 03 add(id: Obj, prefab: Res) @@ -27,7 +29,8 @@ Prefab = *(pos:f32x3 mat:f32_3x3 part:Res<Part>) ``` Part = *(len_key:u16 len_value:u16 *(key:u8) *(value:u8)) -Attribute = 0x01 value:f32 / 0x02 buffer:Res / 0x03 texture:Res<Texture> +Attribute = 0x01 constant:f32 / 0x02 buffer:Res / 0x03 texture:Res<Texture> +NewAttribute = flag:u8 constant:f32 buffer:Res texture:Res<Texture> ``` | Key | Value Type | diff --git a/client/src/download.rs b/client/src/download.rs index dfd7ff0..8e1686a 100644 --- a/client/src/download.rs +++ b/client/src/download.rs @@ -34,8 +34,8 @@ impl Downloader { pub fn packet(&mut self, p: &Packet) -> Result<()> { match p { Packet::RespondResource(d) => { - let key = Resource(sha256(&d)); - self.store.set(&d)?; + let key = Resource(sha256(&d.0)); + self.store.set(&d.0)?; self.need.remove(&key); self.pending.remove(&key); if self.have.insert(key) { diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs index 30c1742..5376145 100644 --- a/client/src/scene_prepare.rs +++ b/client/src/scene_prepare.rs @@ -1,28 +1,28 @@ +use crate::download::Downloader; use anyhow::Result; use std::{ collections::{HashMap, HashSet}, sync::Arc, }; use weareshared::{ + Affine3A, packets::{ReadWrite, Resource}, - resources::Prefab, - tree::SceneTree, + resources::{Attribute, Part, Prefab}, }; use wgpu::Buffer; -use crate::download::Downloader; - pub struct ScenePreparer { index_buffers: HashMap<Resource, Arc<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>>, + index_buffers_needed: HashSet<Resource>, + vertex_buffers: HashMap<Resource, Arc<Buffer>>, + vertex_buffers_needed: HashSet<Resource>, parts: HashMap<Resource, Arc<RPart>>, + parts_needed: HashSet<Resource>, prefabs: HashMap<Resource, RPrefab>, prefabs_needed: HashSet<Resource>, } -pub struct RPrefab(pub Vec<Arc<RPart>>); +pub struct RPrefab(pub Vec<(Affine3A, Arc<RPart>)>); pub struct RPart { pub index_count: u32, pub index: Arc<Buffer>, @@ -34,19 +34,57 @@ 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(), + vertex_buffers: HashMap::new(), + vertex_buffers_needed: HashSet::new(), parts: HashMap::new(), + parts_needed: HashSet::new(), prefabs: HashMap::new(), prefabs_needed: HashSet::new(), + index_buffers_needed: HashSet::new(), } } - fn update(&mut self, dls: &mut Downloader) -> Result<()> { + pub fn update(&mut self, dls: &mut Downloader) -> Result<()> { + let mut done = Vec::new(); for pres in &self.prefabs_needed { if let Some(buf) = dls.try_get(*pres)? { let prefab = Prefab::read(&mut buf.as_slice())?; - + let mut rprefab = RPrefab(Vec::new()); + for (aff, partres) in &prefab.0 { + if let Some(part) = self.parts.get(partres) { + rprefab.0.push((*aff, part.clone())); + } else { + self.parts_needed.insert(*partres); + } + } + if rprefab.0.len() == prefab.0.len() { + self.prefabs.insert(*pres, rprefab); + done.push(*pres); + } + } + } + for pres in &self.parts_needed { + if let Some(buf) = dls.try_get(*pres)? { + let part = Part::read(&mut buf.as_slice())?; + if let Some(indexres) = part.index { + if let Some(vertexres) = part.va_position { + let Some(index) = self.index_buffers.get(&indexres) else { + self.index_buffers_needed.insert(indexres); + continue; + }; + for vr in vertexres { + match vr { + Attribute::Constant(_) => todo!(), + Attribute::Vertex(resource) => { + let Some(vertex) = self.index_buffers.get(&resource) else { + self.index_buffers_needed.insert(indexres); + continue; + }; + } + Attribute::Texture(resource) => todo!(), + } + } + } + } } } Ok(()) diff --git a/client/src/scene_render.rs b/client/src/scene_render.rs index f80f6c2..68d0c49 100644 --- a/client/src/scene_render.rs +++ b/client/src/scene_render.rs @@ -5,9 +5,9 @@ use wgpu::{ 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, + RenderPassDescriptor, RenderPipeline, RenderPipelineDescriptor, ShaderStages, StoreOp, + TextureFormat, TextureView, VertexAttribute, VertexBufferLayout, VertexFormat, VertexState, + VertexStepMode, include_wgsl, }; use crate::scene_prepare::RPrefab; @@ -113,7 +113,9 @@ impl ScenePipeline { for ob in scene.objects.values() { if let Some(prefab) = self.prefabs.get(&ob.res) { - for part in &prefab.0 { + for (affine, part) in &prefab.0 { + let affine = affine.to_cols_array().map(|v| v.to_le_bytes()); + rpass.set_push_constants(ShaderStages::VERTEX, 0, affine.as_flattened()); 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(..)); diff --git a/server/src/main.rs b/server/src/main.rs index 6b2911f..a8473c6 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,18 +1,12 @@ +pub mod network; + use anyhow::Result; use clap::Parser; -use log::{debug, info}; -use std::{ - collections::HashMap, - io::{BufReader, BufWriter, Write}, - net::{IpAddr, TcpListener, TcpStream}, - sync::{ - Arc, Mutex, - mpsc::{Receiver, Sender, channel}, - }, - thread::spawn, -}; +use log::warn; +use network::ServerNetwork; +use std::net::{IpAddr, SocketAddr}; use weareshared::{ - packets::{Packet, ReadWrite}, + packets::{Data, Packet}, store::ResourceStore, tree::SceneTree, }; @@ -26,7 +20,6 @@ struct Args { } struct State { - tx: HashMap<usize, Sender<Packet>>, store: ResourceStore, tree: SceneTree, } @@ -35,101 +28,64 @@ fn main() -> Result<()> { env_logger::init_from_env("LOG"); let args = Args::parse(); - let listener = TcpListener::bind((args.bind_addr, args.port))?; - info!("bound to {}", listener.local_addr()?); - let state = Arc::new(Mutex::new(State::new()?)); - for conn in 0.. { - let (sock, addr) = listener.accept()?; - info!("{addr} connected"); - let (tx, rx) = channel(); - let state2 = state.clone(); - let sock2 = sock.try_clone().unwrap(); - spawn(move || { - for p in state2.lock().unwrap().tree.prime_client() { - tx.send(p).unwrap(); - } - state2.lock().unwrap().tx.insert(conn, tx); - let _ = handle_conn_read(conn, sock, state2.clone()); - info!("{addr} disconnected"); - state2.lock().unwrap().tx.remove(&conn); - }); - spawn(move || { - let _ = handle_conn_write(conn, sock2, rx); - }); - } - Ok(()) -} + let net = ServerNetwork::new(SocketAddr::new(args.bind_addr, args.port))?; + let mut state = State::new()?; -fn handle_conn_read(conn: usize, sock: TcpStream, state: Arc<Mutex<State>>) -> Result<()> { - let mut sock = BufReader::new(sock); - loop { - let packet = Packet::read(&mut sock)?; - debug!("{conn} <- {packet:?}"); - state.lock().unwrap().handle_packet(conn, packet)?; - } -} -fn handle_conn_write(conn: usize, sock: TcpStream, rx: Receiver<Packet>) -> Result<()> { - let mut sock = BufWriter::new(sock); - for packet in rx { - debug!("{conn} -> {packet:?}"); - packet.write(&mut sock)?; - sock.flush()?; + while let Ok((conn, packet)) = net.recv.recv() { + if let Err(e) = state.handle_packet(conn, packet, &net) { + warn!("state handler error: ({conn}) {e}"); + } } + Ok(()) } + impl State { pub fn new() -> Result<Self> { Ok(Self { - tx: HashMap::new(), store: ResourceStore::new_persistent( &xdg::BaseDirectories::with_prefix("weareserver")?.place_cache_file("resources")?, )?, tree: SceneTree::default(), }) } - pub fn broadcast(&self, packet: Packet) -> Result<()> { - for tx in self.tx.values() { - tx.send(packet.clone())?; - } - Ok(()) - } - pub fn send(&self, conn: usize, packet: Packet) -> Result<()> { - if let Some(tx) = self.tx.get(&conn) { - tx.send(packet)?; - } - Ok(()) - } - pub fn handle_packet(&mut self, conn: usize, packet: Packet) -> Result<()> { + pub fn handle_packet(&mut self, conn: u128, packet: Packet, net: &ServerNetwork) -> Result<()> { self.tree.update(&packet); match packet { + Packet::Connect(_) => { + for p in self.tree.prime_client() { + net.send(conn, p, true); + } + } + Packet::Disconnect => {} Packet::RequestResource(resource) => { if let Some(r) = self.store.get(resource)? { - self.send(conn, Packet::RespondResource(r))?; + net.send(conn, Packet::RespondResource(Data(r)), true); } else { - self.broadcast(Packet::RequestResource(resource))?; + net.broadcast(Packet::RequestResource(resource), true); } } Packet::RespondResource(data) => { - self.store.set(&data)?; - self.broadcast(Packet::RespondResource(data))?; + self.store.set(&data.0)?; + net.broadcast(Packet::RespondResource(data), true); } Packet::Add(object, resource) => { - self.broadcast(Packet::Add(object, resource))?; + net.broadcast(Packet::Add(object, resource), true); } Packet::Remove(object) => { - self.broadcast(Packet::Remove(object))?; + net.broadcast(Packet::Remove(object), true); } Packet::Position(object, pos, rot) => { - self.broadcast(Packet::Position(object, pos, rot))?; + net.broadcast(Packet::Position(object, pos, rot), true); } Packet::Pose(object, vec) => { - self.broadcast(Packet::Pose(object, vec))?; + net.broadcast(Packet::Pose(object, vec), true); } Packet::Parent(parent, child) => { - self.broadcast(Packet::Parent(parent, child))?; + net.broadcast(Packet::Parent(parent, child), true); } Packet::Sound(object, vec) => { - self.broadcast(Packet::Sound(object, vec))?; + net.broadcast(Packet::Sound(object, vec), true); } } Ok(()) diff --git a/server/src/network.rs b/server/src/network.rs new file mode 100644 index 0000000..22cbc65 --- /dev/null +++ b/server/src/network.rs @@ -0,0 +1,191 @@ +use anyhow::Result; +use log::{debug, error, info, warn}; +use std::{ + collections::HashMap, + io::{BufReader, BufWriter, Write}, + net::{SocketAddr, TcpListener, TcpStream, UdpSocket}, + sync::{ + Arc, Mutex, + mpsc::{Receiver, Sender, SyncSender, channel, sync_channel}, + }, + thread::spawn, + time::Instant, +}; +use weareshared::packets::{Packet, ReadWrite}; + +pub struct ServerNetwork { + conns: Arc<Mutex<HashMap<u128, (SyncSender<Arc<Vec<u8>>>, Option<SocketAddr>)>>>, + udp_sock: Arc<UdpSocket>, + pub recv: Receiver<(u128, Packet)>, +} +impl ServerNetwork { + pub fn new(addr: SocketAddr) -> Result<Self> { + let (recv_tx, recv_rx) = channel(); + let conns = Arc::new(Mutex::new(HashMap::new())); + + let tcp_listener = TcpListener::bind(addr)?; + info!("tcp bound to {}", tcp_listener.local_addr()?); + let udp_sock = Arc::new(UdpSocket::bind(addr)?); + info!("udp bound to {}", udp_sock.local_addr()?); + + let s = Self { + conns: conns.clone(), + recv: recv_rx, + udp_sock: udp_sock.clone(), + }; + let recv_tx2 = recv_tx.clone(); + let conns2 = conns.clone(); + spawn(move || { + info!("tcp listener thread started"); + loop { + let (mut sock, addr) = match tcp_listener.accept() { + Ok(x) => x, + Err(e) => { + warn!("cannot accept tcp: {e}"); + continue; + } + }; + info!("TCP connected {addr}"); + + let conns = conns.clone(); + let recv_tx = recv_tx.clone(); + spawn(move || { + let conn = match Packet::read(&mut sock) { + Ok(Packet::Connect(x)) => x, + Ok(_) => { + warn!("client send non-connect packet first"); + return; + } + Err(e) => { + warn!("client handshake failed: {e}"); + return; + } + }; + let (send_tx, send_rx) = sync_channel(128); + conns.lock().unwrap().insert(conn, (send_tx, None)); + + let sock2 = match sock.try_clone() { + Ok(x) => x, + Err(e) => { + error!("cannot duplicate client socket: {e}"); + return; + } + }; + spawn(move || { + if let Err(e) = handle_conn_write(conn, sock2, send_rx) { + warn!("client outbound error: {e}"); + } + }); + if let Err(e) = handle_conn_read(conn, sock, recv_tx) { + warn!("client inbound error: {e}"); + } + conns.lock().unwrap().remove(&conn); + }); + } + }); + spawn(move || { + info!("udp listener thread started"); + let mut buf = [0u8; 8096]; + struct CState { + last_ack: Instant, + conn_id: u128, + } + let mut cstates = HashMap::new(); + let mut last_check = Instant::now(); + loop { + let (size, addr) = match udp_sock.recv_from(&mut buf) { + Err(e) => { + warn!("udp recv failed: {e}"); + continue; + } + Ok(s) => s, + }; + + let mut packet = &buf[..size]; + let packet = match Packet::read(&mut packet) { + Ok(p) => p, + Err(e) => { + warn!("invalid packet from {e}"); + continue; + } + }; + if let Packet::Connect(id) = &packet { + if let Some((_send, udp_addr)) = conns2.lock().unwrap().get_mut(id) { + *udp_addr = Some(addr); + cstates.insert(addr, CState { + conn_id: *id, + last_ack: Instant::now(), + }); + } + } + if let Some(conn) = cstates.get(&addr) { + let cid = conn.conn_id; + if let Packet::Disconnect = &packet { + cstates.remove(&addr); + } + recv_tx2.send((cid, packet)).unwrap(); + } + + if last_check.elapsed().as_secs() > 10 { + cstates.retain(|addr, state| { + if state.last_ack.elapsed().as_secs() > 30 { + warn!("client dropped: {addr}"); + recv_tx2.send((state.conn_id, Packet::Disconnect)).unwrap(); + false + } else { + true + } + }); + last_check = Instant::now(); + } + } + }); + Ok(s) + } + pub fn broadcast(&self, packet: Packet, reliable: bool) { + let ser = Arc::new(packet.write_alloc()); + for (cid, (tcp, udp)) in self.conns.lock().unwrap().iter() { + if !reliable { + if let Some(addr) = udp { + self.udp_sock.send_to(&ser, addr).unwrap(); + continue; + } + } + if let Err(_) = tcp.send(ser.clone()) { + warn!("{cid}: queue full, packet dropped") + } + } + } + pub fn send(&self, conn: u128, packet: Packet, reliable: bool) { + let ser = Arc::new(packet.write_alloc()); + if let Some((tcp, udp)) = self.conns.lock().unwrap().get(&conn) { + if !reliable { + if let Some(addr) = udp { + self.udp_sock.send_to(&ser, addr).unwrap(); + return; + } + } + if let Err(_) = tcp.send(ser.clone()) { + warn!("{conn}: queue full, packet dropped") + } + } + } +} + +fn handle_conn_read(conn: u128, sock: TcpStream, tx: Sender<(u128, Packet)>) -> Result<()> { + let mut sock = BufReader::new(sock); + loop { + let packet = Packet::read(&mut sock)?; + debug!("{conn} <- {packet:?}"); + tx.send((conn, packet)).unwrap(); + } +} +fn handle_conn_write(conn: u128, sock: TcpStream, rx: Receiver<Arc<Vec<u8>>>) -> Result<()> { + let mut sock = BufWriter::new(sock); + for packet in rx { + debug!("{conn} -> {packet:?}"); + sock.write_all(&packet)?; + sock.flush()?; + } + Ok(()) +} diff --git a/shared/src/lib.rs b/shared/src/lib.rs index 56c1fe4..b1da612 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -5,4 +5,4 @@ pub mod resources; pub mod store; pub mod tree; -pub use glam::{Affine3A, Mat3A, Vec3A}; +pub use glam::{Affine3A, Mat3A, Vec3A, vec3a}; diff --git a/shared/src/packets.rs b/shared/src/packets.rs index 0ceed73..a1636cd 100644 --- a/shared/src/packets.rs +++ b/shared/src/packets.rs @@ -1,5 +1,5 @@ use anyhow::{Result, bail}; -use glam::Vec3; +use glam::Vec3A; use std::{ fmt::{Debug, Display}, io::{Read, Write}, @@ -10,16 +10,21 @@ pub struct Resource(pub [u8; 32]); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Object(pub u128); +#[derive(Clone)] +pub struct Data(pub Vec<u8>); + #[derive(Debug, Clone)] pub enum Packet { + Connect(u128), + Disconnect, RequestResource(Resource), - RespondResource(Vec<u8>), + RespondResource(Data), Add(Object, Resource), Remove(Object), - Position(Object, Vec3, Vec3), + Position(Object, Vec3A, Vec3A), Pose(Object, Vec<f32>), Parent(Object, Object), - Sound(Object, Vec<u8>), + Sound(Object, Data), } pub trait ReadWrite: Sized { @@ -41,14 +46,20 @@ impl Object { impl Packet { fn serialize_inner(&self, w: &mut impl Write) -> Result<()> { match self { + Packet::Connect(id) => { + w.write_all(&[0x00])?; + w.write_all(&id.to_be_bytes())?; + } + Packet::Disconnect => { + w.write_all(&[0xff])?; + } Packet::RequestResource(resource) => { w.write_all(&[0x01])?; w.write_all(&resource.0)?; } Packet::RespondResource(data) => { w.write_all(&[0x02])?; - w.write_all(&(data.len() as u16).to_be_bytes())?; - w.write_all(&data)?; + data.write(w)?; } Packet::Add(object, resource) => { w.write_all(&[0x03])?; @@ -79,10 +90,10 @@ impl Packet { w.write_all(&parent.0.to_be_bytes())?; w.write_all(&child.0.to_be_bytes())?; } - Packet::Sound(object, vec) => { + Packet::Sound(object, data) => { w.write_all(&[0x08])?; w.write_all(&object.0.to_be_bytes())?; - w.write_all(&(vec.len() as u16).to_be_bytes())?; + data.write(w)?; } } Ok(()) @@ -100,18 +111,19 @@ impl ReadWrite for Packet { let mut size_tag = [0u8; 3]; r.read_exact(&mut size_tag)?; Ok(match size_tag[2] { + 0x00 => Packet::Connect(read_u128(r)?), 0x01 => Packet::RequestResource(Resource::read(r)?), - 0x02 => Packet::RespondResource(read_data(r)?), + 0x02 => Packet::RespondResource(Data::read(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(f32::read(r)?, f32::read(r)?, f32::read(r)?), - Vec3::new(f32::read(r)?, f32::read(r)?, f32::read(r)?), + Vec3A::new(f32::read(r)?, f32::read(r)?, f32::read(r)?), + Vec3A::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)?)), - 0x08 => Packet::Sound(Object(read_u128(r)?), read_data(r)?), + 0x08 => Packet::Sound(Object(read_u128(r)?), Data::read(r)?), _ => { for _ in 0..u16::from_be_bytes([size_tag[0], size_tag[1]]) - 1 { r.read_exact(&mut [0])?; @@ -138,13 +150,20 @@ impl ReadWrite for Resource { Ok(s) } } -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); - let mut buf = vec![0; size as usize]; - r.read_exact(&mut buf)?; - Ok(buf) +impl ReadWrite for Data { + fn write(&self, w: &mut dyn Write) -> Result<()> { + w.write_all(&(self.0.len() as u16).to_be_bytes())?; + w.write_all(&self.0)?; + Ok(()) + } + fn read(r: &mut dyn Read) -> Result<Self> { + let mut size = [0; 2]; + r.read_exact(&mut size)?; + let size = u16::from_be_bytes(size); + let mut buf = vec![0; size as usize]; + r.read_exact(&mut buf)?; + Ok(Data(buf)) + } } fn read_params(r: &mut dyn Read) -> Result<Vec<f32>> { let mut size = [0; 2]; @@ -200,3 +219,8 @@ impl<T: ReadWrite, const N: usize> ReadWrite for [T; N] { [(); N].try_map(|()| T::read(r)) } } +impl Debug for Data { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("Data").finish_non_exhaustive() + } +} diff --git a/shared/src/tree.rs b/shared/src/tree.rs index 4cb7abc..d8d2bfd 100644 --- a/shared/src/tree.rs +++ b/shared/src/tree.rs @@ -1,13 +1,13 @@ use crate::packets::{Object, Packet, Resource}; -use glam::Vec3; +use glam::Vec3A; use std::collections::HashMap; pub struct SceneTree { pub objects: HashMap<Object, ObjectData>, } pub struct ObjectData { - pub pos: Vec3, - pub rot: Vec3, + pub pos: Vec3A, + pub rot: Vec3A, pub parent: Object, pub pose: Vec<f32>, pub res: Resource, @@ -25,8 +25,8 @@ impl SceneTree { Packet::Add(object, res) => { self.objects.insert(*object, ObjectData { parent: Object(0), - pos: Vec3::ZERO, - rot: Vec3::ZERO, + pos: Vec3A::ZERO, + rot: Vec3A::ZERO, pose: Vec::new(), res: *res, }); diff --git a/world/Cargo.toml b/world/Cargo.toml index ee74e2b..bdfc1f1 100644 --- a/world/Cargo.toml +++ b/world/Cargo.toml @@ -10,3 +10,4 @@ env_logger = "0.11.6" gltf = { version = "1.4.1", features = ["extras", "names"] } log = "0.4.22" weareshared = { path = "../shared" } +rand = "0.9.0-beta.1"
\ No newline at end of file diff --git a/world/src/main.rs b/world/src/main.rs index fe71e79..4f433ba 100644 --- a/world/src/main.rs +++ b/world/src/main.rs @@ -1,21 +1,28 @@ #![feature(iter_array_chunks)] use anyhow::Result; use clap::Parser; +use rand::random; use std::{ + io::Write, net::{SocketAddr, TcpStream}, path::PathBuf, + thread::{self, sleep}, + time::Duration, }; use weareshared::{ - Affine3A, Mat3A, Vec3A, - packets::{Object, Packet, ReadWrite}, + Affine3A, Vec3A, + packets::{Data, Object, Packet, ReadWrite}, resources::{Attribute, AttributeArray, IndexArray, Part, Prefab}, store::ResourceStore, + vec3a, }; #[derive(Parser)] struct Args { address: SocketAddr, scene: PathBuf, + #[arg(short, long)] + push: bool, } fn main() -> Result<()> { @@ -25,6 +32,8 @@ fn main() -> Result<()> { let mut sock = TcpStream::connect(args.address)?; let store = ResourceStore::new_memory(); + Packet::Connect(random()).write(&mut sock)?; + let (gltf, buffers, _) = gltf::import(args.scene)?; let mut prefab = Prefab::default(); @@ -38,6 +47,8 @@ fn main() -> Result<()> { 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]); @@ -48,6 +59,10 @@ fn main() -> Result<()> { 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 index = reader .read_indices() .unwrap() @@ -56,6 +71,8 @@ fn main() -> Result<()> { .array_chunks::<3>() .collect::<Vec<_>>(); + if let Some(tex) = p.material().pbr_metallic_roughness().base_color_texture() {} + let part = store.set( &Part { va_position: Some([ @@ -68,6 +85,15 @@ fn main() -> Result<()> { Attribute::Vertex(store.set(&AttributeArray(norm_y).write_alloc())?), Attribute::Vertex(store.set(&AttributeArray(norm_z).write_alloc())?), ]), + va_texcoord: Some([ + Attribute::Vertex(store.set(&AttributeArray(uv_x).write_alloc())?), + Attribute::Vertex(store.set(&AttributeArray(uv_y).write_alloc())?), + ]), + va_pbr_albedo: Some([ + Attribute::Constant(0.9), + Attribute::Constant(0.1), + Attribute::Constant(0.1), + ]), index: Some(store.set(&IndexArray(index).write_alloc())?), ..Part::default() } @@ -86,23 +112,42 @@ fn main() -> Result<()> { } } - Packet::Add(Object::new(), store.set(&prefab.write_alloc())?).write(&mut sock)?; + let ob = Object::new(); + Packet::Add(ob, store.set(&prefab.write_alloc())?).write(&mut sock)?; - store.iter(|d| { - Packet::RespondResource(d.to_vec()) - .write(&mut sock) - .unwrap(); - })?; + let mut sock2 = sock.try_clone().unwrap(); + thread::spawn(move || { + let mut x = 0.; + loop { + Packet::Position(ob, Vec3A::ZERO, vec3a(x, x * 0.3, x * 0.1)) + .write(&mut sock2) + .unwrap(); + sock2.flush().unwrap(); + x += 0.1; + sleep(Duration::from_millis(50)); + } + }); - loop { - let packet = Packet::read(&mut sock)?; - match packet { - Packet::RequestResource(hash) => { - if let Some(d) = store.get(hash)? { - Packet::RespondResource(d).write(&mut sock)?; + if args.push { + store.iter(|d| { + Packet::RespondResource(Data(d.to_vec())) + .write(&mut sock) + .unwrap(); + })?; + sock.flush()?; + } else { + loop { + let packet = Packet::read(&mut sock)?; + match packet { + Packet::RequestResource(hash) => { + if let Some(d) = store.get(hash)? { + Packet::RespondResource(Data(d)).write(&mut sock)?; + sock.flush()?; + } } + _ => (), } - _ => (), } } + Ok(()) } |