diff --git a/src/map.rs b/src/map.rs index 97e74f5..0a83468 100644 --- a/src/map.rs +++ b/src/map.rs @@ -14,6 +14,7 @@ pub enum Error{ InvalidHeader(binrw::Error), InvalidBlockId(BlockId), InvalidMeshId(model::MeshId), + InvalidModelId(model::ModelId), InvalidTextureId(model::TextureId), InvalidData(binrw::Error), IO(std::io::Error), @@ -168,18 +169,20 @@ struct Region{ //consider including a bvh in the region instead of needing to rebalance the physics bvh on the fly model_count:u32, #[br(count=model_count)] - models:Vec, + models:Vec<(u32,newtypes::model::Model)>, } //code deduplication reused in into_complete_map -fn read_region(file:&mut crate::file::File,block_id:BlockId)->Result,Error>{ +fn read_region(file:&mut crate::file::File,block_id:BlockId)->Result,Error>{ //load region from disk //parse the models and determine what resources need to be loaded //load resources into self.resources //return Region let mut block=file.block_reader(block_id).map_err(Error::File)?; let region:Region=block.read_le().map_err(Error::InvalidData)?; - Ok(region.models.into_iter().map(Into::into).collect()) + Ok(region.models.into_iter().map(|(model_id,model)| + (model::ModelId::new(model_id),model.into()) + ).collect()) } fn read_mesh(file:&mut crate::file::File,block_id:BlockId)->Result{ let mut block=file.block_reader(block_id).map_err(Error::File)?; @@ -251,7 +254,7 @@ impl StreamableMap{ self.bvh.the_tester(aabb,&mut |&block_id|block_ids.push(block_id)); block_ids } - pub fn load_region(&mut self,block_id:BlockId)->Result,Error>{ + pub fn load_region(&mut self,block_id:BlockId)->Result,Error>{ read_region(&mut self.file,block_id) } pub fn load_mesh(&mut self,mesh_id:model::MeshId)->Result{ @@ -263,14 +266,18 @@ impl StreamableMap{ read_texture(&mut self.file,block_id) } pub fn into_complete_map(mut self)->Result{ - let mut block_ids=Vec::new(); - self.bvh.into_visitor(&mut |block_id|block_ids.push(block_id)); //count on reading the file in sequential order being fastest - block_ids.sort(); + let mut block_ids=std::collections::BinaryHeap::new(); + self.bvh.into_visitor(&mut |block_id|block_ids.push(block_id)); //load all regions - let mut models=Vec::new(); + let mut model_pairs=HashMap::new(); for block_id in block_ids{ - models.append(&mut read_region(&mut self.file,block_id)?); + model_pairs.extend(read_region(&mut self.file,block_id)?); + } + let mut models=Vec::with_capacity(model_pairs.len()); + for model_id in 0..model_pairs.len() as u32{ + let model_id=model::ModelId::new(model_id); + models.push(model_pairs.remove(&model_id).ok_or(Error::InvalidModelId(model_id))?); } //load all meshes let mut meshes=Vec::with_capacity(self.resource_blocks.meshes.len()); @@ -302,7 +309,7 @@ fn collect_spacial_blocks( block_location:&mut Vec, block_headers:&mut Vec, sequential_block_data:&mut std::io::Cursor<&mut Vec>, - bvh_node:strafesnet_common::bvh::BvhWeightNode + bvh_node:strafesnet_common::bvh::BvhWeightNode )->Result<(),Error>{ //inspect the node weights top-down. //When a node weighs less than the limit, @@ -311,9 +318,9 @@ fn collect_spacial_blocks( let mut models=Vec::new(); let mut model_count=0; let extents=bvh_node.aabb().clone().into(); - bvh_node.into_visitor(&mut |model|{ + bvh_node.into_visitor(&mut |(model_id,model)|{ model_count+=1; - models.push(model); + models.push((model_id.get(),model)); }); let id=BlockId::new(block_headers.len() as u32+1); block_headers.push(SpacialBlockHeader{ @@ -343,14 +350,14 @@ fn collect_spacial_blocks( /// otherwise sort by distance to start zone pub fn write_map(mut writer:W,map:strafesnet_common::map::CompleteMap)->Result<(),Error>{ //serialize models and make a bvh that knows the file size of the branch - let boxen=map.models.into_iter().map(|model|{ + let boxen=map.models.into_iter().enumerate().map(|(model_id,model)|{ //grow your own aabb let mesh=map.meshes.get(model.mesh.get() as usize).ok_or(Error::InvalidMeshId(model.mesh))?; let mut aabb=strafesnet_common::aabb::Aabb::default(); for &pos in &mesh.unique_pos{ aabb.grow(model.transform.transform_point3(pos)); } - Ok((model.into(),aabb)) + Ok(((model::ModelId::new(model_id as u32),model.into()),aabb)) }).collect::,_>>()?; let bvh=strafesnet_common::bvh::generate_bvh(boxen).weigh_contents(&|_|std::mem::size_of::()); //build blocks