diff --git a/src/map.rs b/src/map.rs index 5a97e8d..2df530f 100644 --- a/src/map.rs +++ b/src/map.rs @@ -135,15 +135,12 @@ struct ResourceExternalHeader{ #[binrw] #[brw(little)] struct MapHeader{ - num_nodes:u32, num_spacial_blocks:u32, num_resource_blocks:u32, num_resources_external:u32, num_modes:u32, num_attributes:u32, num_render_configs:u32, - #[br(count=num_nodes)] - nodes:Vec, #[br(count=num_spacial_blocks)] spacial_blocks:Vec, #[br(count=num_resource_blocks)] @@ -244,7 +241,7 @@ impl StreamableMap{ } pub fn get_intersecting_region_block_ids(&self,aabb:&Aabb)->Vec{ let mut block_ids=Vec::new(); - self.bvh.the_tester(aabb,&mut |block_id|block_ids.push(block_id)); + 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>{ @@ -285,11 +282,75 @@ impl StreamableMap{ } } +const BVH_NODE_MAX_WEIGHT:usize=64*1024;//64 kB +fn collect_spacial_blocks(block_headers:&mut Vec,block_datas:&mut Vec>,bvh_node:strafesnet_common::bvh::BvhWeightNode>){ + //inspect the node weights top-down. + //When a node weighs less than the limit, + //serialize its entire contents into a region block + if *bvh_node.weight(){ + for bvh_node in bvh_node_list{ + collect_spacial_blocks(block_headers,block_datas,bvh_node); + } + }, + strafesnet_common::bvh::RecursiveContent::Leaf(_)=>panic!(),//bvh branches are 20 leaves minimum + } + } +} + /// TODO: Optionally provide a bot that describes the path through the map /// 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|{ + //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)); + } + let serializable_model:newtypes::model::Model=model.into(); + let mut data=Vec::new(); + binrw::BinWrite::write_le(&serializable_model,&mut std::io::Cursor::new(&mut data)).map_err(Error::InvalidData)?; + Ok((data,aabb)) + }).collect::,_>>()?; + let bvh=strafesnet_common::bvh::generate_bvh(boxen).weigh_contents(&|model|model.len()); //build blocks + let mut spacial_blocks=Vec::new(); + let mut spacial_blocks_data=Vec::new(); + collect_spacial_blocks(&mut spacial_blocks,&mut spacial_blocks_data,bvh); + let resource_blocks=Vec::new(); + //let resource_blocks_data=Vec::new(); //build header + let header=MapHeader{ + num_spacial_blocks:spacial_blocks.len() as u32, + num_resource_blocks:resource_blocks.len() as u32, + num_resources_external:0, + num_modes:map.modes.modes.len() as u32, + num_attributes:map.attributes.len() as u32, + num_render_configs:map.render_configs.len() as u32, + spacial_blocks, + resource_blocks, + external_resources:Vec::new(), + modes:map.modes.modes.into_iter().map(Into::into).collect(), + attributes:map.attributes.into_iter().map(Into::into).collect(), + render_configs:map.render_configs.into_iter().map(Into::into).collect(), + }; //write header //write blocks Ok(())