diff --git a/src/file.rs b/src/file.rs index 6f22cf9..d1fd674 100644 --- a/src/file.rs +++ b/src/file.rs @@ -51,19 +51,19 @@ pub(crate) enum FourCC{ } #[binrw] #[brw(little)] -struct Header{ +pub struct Header{ /// Type of file - fourcc:FourCC, - /// Type version - version:u32, + pub fourcc:FourCC, + /// File format version + pub version:u32, /// Minimum data required to know the location of all streamable resources for this specific file - priming:u64, + pub priming:u64, /// uuid for this file - resource:u128, + pub resource:u128, //don't need try_calc: the struct will force field initialization anyways and it can be calculated there - block_count:u32, + pub block_count:u32, #[br(count=block_count+1)] - block_location:Vec, + pub block_location:Vec, } #[binrw] diff --git a/src/map.rs b/src/map.rs index 8b2d91d..12fd577 100644 --- a/src/map.rs +++ b/src/map.rs @@ -284,6 +284,7 @@ impl StreamableMap{ const BVH_NODE_MAX_WEIGHT:usize=64*1024;//64 kB 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 @@ -309,11 +310,12 @@ fn collect_spacial_blocks( models, }; binrw::BinWrite::write_le(®ion,sequential_block_data).map_err(Error::InvalidData)?; + block_location.push(sequential_block_data.position()); }else{ match bvh_node.into_content(){ strafesnet_common::bvh::RecursiveContent::Branch(bvh_node_list)=>{ for bvh_node in bvh_node_list{ - collect_spacial_blocks(block_headers,sequential_block_data,bvh_node)?; + collect_spacial_blocks(block_location,block_headers,sequential_block_data,bvh_node)?; } }, strafesnet_common::bvh::RecursiveContent::Leaf(_)=>panic!(),//bvh branches are 20 leaves minimum @@ -337,33 +339,36 @@ pub fn write_map(mut writer:W,map:strafesnet_common::map::Comple }).collect::,_>>()?; let bvh=strafesnet_common::bvh::generate_bvh(boxen).weigh_contents(&|_|std::mem::size_of::()); //build blocks - let mut spacial_blocks=Vec::new();//for header + let mut block_location=vec![0];//for file header + let mut spacial_blocks=Vec::new();//for map header let mut sequential_block_data=Vec::new(); let mut cursor_to_data=std::io::Cursor::new(&mut sequential_block_data); - collect_spacial_blocks(&mut spacial_blocks,&mut cursor_to_data,bvh)?; - let mut block_id=spacial_blocks.len() as u32;//continue block id - let mut resource_blocks=Vec::new();//for header + collect_spacial_blocks(&mut block_location,&mut spacial_blocks,&mut cursor_to_data,bvh)?; + let mut block_count=spacial_blocks.len() as u32;//continue block id + let mut resource_blocks=Vec::new();//for map header //meshes for mesh in map.meshes.into_iter(){ resource_blocks.push(ResourceBlockHeader{ resource:ResourceType::Mesh, - id:BlockId::new(block_id), + id:BlockId::new(block_count), }); - block_id+=1; + block_count+=1; let serializable_mesh:newtypes::model::Mesh=mesh.into(); binrw::BinWrite::write_le(&serializable_mesh,&mut cursor_to_data).map_err(Error::InvalidData)?; + block_location.push(cursor_to_data.position()); } //textures for mut texture in map.textures.into_iter(){ resource_blocks.push(ResourceBlockHeader{ resource:ResourceType::Texture, - id:BlockId::new(block_id), + id:BlockId::new(block_count), }); - block_id+=1; + block_count+=1; sequential_block_data.append(&mut texture); + block_location.push(sequential_block_data.len() as u64); } //build header - let header=MapHeader{ + let map_header=MapHeader{ num_spacial_blocks:spacial_blocks.len() as u32, num_resource_blocks:resource_blocks.len() as u32, num_resources_external:0, @@ -377,8 +382,31 @@ pub fn write_map(mut writer:W,map:strafesnet_common::map::Comple attributes:map.attributes.into_iter().map(Into::into).collect(), render_configs:map.render_configs.into_iter().map(Into::into).collect(), }; - //write header - writer.write_le(&header).map_err(Error::InvalidData)?; + let mut file_header=crate::file::Header{ + fourcc:crate::file::FourCC::Map, + version:0, + priming:0,//TODO + resource:0, + block_count, + block_location, + }; + //probe header lengths + let mut file_header_data=Vec::new(); + binrw::BinWrite::write_le(&file_header,&mut std::io::Cursor::new(&mut file_header_data)).map_err(Error::InvalidData)?; + let mut map_header_data=Vec::new(); + binrw::BinWrite::write_le(&map_header,&mut std::io::Cursor::new(&mut map_header_data)).map_err(Error::InvalidData)?; + + //update file header according to probe data + let offset=file_header_data.len() as u64+map_header_data.len() as u64; + file_header.priming=offset; + for position in &mut file_header.block_location{ + *position+=offset; + } + + //write file header + writer.write_le(&file_header).map_err(Error::InvalidData)?; + //write map header + writer.write(&map_header_data).map_err(Error::IO)?; //write blocks writer.write(&sequential_block_data).map_err(Error::IO)?; Ok(())