use crate::download::Downloader; use anyhow::{Context, Result}; use std::{ collections::{HashMap, HashSet}, sync::Arc, }; use weareshared::{ Affine3A, packets::{ReadWrite, Resource}, resources::{Attribute, Part, Prefab}, }; use wgpu::Buffer; pub struct ScenePreparer { index_buffers: HashMap, u32)>, index_buffers_needed: HashSet, vertex_buffers: HashMap>, vertex_buffers_needed: HashSet, parts: HashMap>, parts_needed: HashSet, pub prefabs: HashMap, pub prefabs_needed: HashSet, } pub struct RPrefab(pub Vec<(Affine3A, Arc)>); pub struct RPart { pub index_count: u32, pub index: Arc, pub position: [Arc; 3], pub normal: [Arc; 3], pub texcoord: [Arc; 2], } impl ScenePreparer { pub fn new() -> Self { Self { index_buffers: 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(), } } 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()).context("parsing prefab")?; 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.index_buffers_needed { if let Some(buf) = dls.try_get(*pres)? {} } for pres in &self.parts_needed { if let Some(buf) = dls.try_get(*pres)? { let part = Part::read(&mut buf.as_slice()).context("parsing part")?; if let (Some(indexres), Some(positionres), Some(normalres), Some(texcoordres)) = ( part.index, part.va_position, part.va_normal, part.va_texcoord, ) { let Some((index, index_count)) = self.index_buffers.get(&indexres).cloned() else { self.index_buffers_needed.insert(indexres); continue; }; let mut positions = Vec::new(); for vr in positionres { match vr { Attribute::Constant(_) => todo!(), Attribute::Vertex(resource) => { let Some(vertex) = self.vertex_buffers.get(&resource).cloned() else { self.vertex_buffers_needed.insert(indexres); continue; }; positions.push(vertex); } Attribute::Texture(_resource) => todo!(), } } let mut normals = Vec::new(); for vr in normalres { match vr { Attribute::Constant(_) => todo!(), Attribute::Vertex(resource) => { let Some(vertex) = self.vertex_buffers.get(&resource).cloned() else { self.vertex_buffers_needed.insert(indexres); continue; }; normals.push(vertex); } Attribute::Texture(_resource) => todo!(), } } let mut texcoords = Vec::new(); for vr in texcoordres { match vr { Attribute::Constant(_) => todo!(), Attribute::Vertex(resource) => { let Some(vertex) = self.vertex_buffers.get(&resource).cloned() else { self.vertex_buffers_needed.insert(indexres); continue; }; texcoords.push(vertex); } Attribute::Texture(_resource) => todo!(), } } self.parts.insert( *pres, Arc::new(RPart { index_count, index, texcoord: texcoords.try_into().unwrap(), normal: normals.try_into().unwrap(), position: positions.try_into().unwrap(), }), ); } } } Ok(()) } }