#![feature(iter_array_chunks)] use anyhow::Result; use clap::Parser; use log::info; use rand::random; use std::{ io::Write, net::{SocketAddr, TcpStream}, path::PathBuf, thread::{self, sleep}, time::Duration, }; use weareshared::{ Affine3A, Vec3A, packets::{Data, Object, Packet, ReadWrite}, resources::{AttributeArray, IndexArray, Part, Prefab}, store::ResourceStore, vec3a, }; #[derive(Parser)] struct Args { address: SocketAddr, scene: PathBuf, #[arg(short, long)] push: bool, #[arg(short, long)] spin: bool, } fn main() -> Result<()> { env_logger::init_from_env("LOG"); let args = Args::parse(); 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(); 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 index = reader .read_indices() .unwrap() .into_u32() .map(|e| e as u16) .array_chunks::<3>() .collect::>(); 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)?); } } 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())?, ]), tex_albedo, index: Some(store.set(&IndexArray(index).write_alloc())?), ..Part::default() } .write_alloc(), )?; let mat = node.transform().matrix(); let aff = Affine3A::from_cols_array_2d(&[ [mat[0][0], mat[0][1], mat[0][2]], [mat[1][0], mat[1][1], mat[1][2]], [mat[2][0], mat[2][1], mat[2][2]], [mat[3][0], mat[3][1], mat[3][2]], ]); prefab.0.push((aff, part)) } } } let ob = Object::new(); Packet::Add(ob, store.set(&prefab.write_alloc())?).write(&mut sock)?; if args.spin { 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)); } }); } 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(()) }