implement map file format

This commit is contained in:
Quaternions 2024-07-23 18:34:28 -07:00
parent 1883c06f12
commit 4f90956e16
2 changed files with 96 additions and 49 deletions

View File

@ -84,6 +84,9 @@ impl<R:BinReaderExt> File<R>{
data:input, data:input,
}) })
} }
pub(crate) fn as_mut(&mut self)->&mut R{
&mut self.data
}
pub(crate) fn block_reader(&mut self,block_id:BlockId)->Result<binrw::io::TakeSeek<&mut R>,Error>{ pub(crate) fn block_reader(&mut self,block_id:BlockId)->Result<binrw::io::TakeSeek<&mut R>,Error>{
if self.header.block_location.len() as u32<=block_id.get(){ if self.header.block_location.len() as u32<=block_id.get(){
return Err(Error::InvalidBlockId(block_id)) return Err(Error::InvalidBlockId(block_id))

View File

@ -1,10 +1,14 @@
//use strafesnet_common::model; use crate::newtypes;
//use strafesnet_common::gameplay_modes; use crate::file::BlockId;
use binrw::{BinReaderExt, binrw}; use binrw::{binrw,BinReaderExt};
use strafesnet_common::model;
use strafesnet_common::aabb::Aabb;
use strafesnet_common::bvh::BvhNode;
use strafesnet_common::gameplay_modes;
pub enum Error{ pub enum Error{
InvalidHeader, InvalidHeader(binrw::Error),
InvalidBvhNodeId(BvhNodeId), InvalidBlockId(BlockId),
InvalidRegion(binrw::Error), InvalidRegion(binrw::Error),
File(crate::file::Error), File(crate::file::Error),
} }
@ -14,10 +18,13 @@ pub enum Error{
BLOCK_MAP_HEADER: BLOCK_MAP_HEADER:
DefaultStyleInfo style_info DefaultStyleInfo style_info
//bvh goes here //bvh goes here
u64 num_nodes u32 num_nodes
u32 num_spacial_blocks
u32 num_resource_blocks
u32 num_resources_external
//node 0 parent node is implied to be None //node 0 parent node is implied to be None
for node_id in 1..num_nodes{ for node_id in 1..num_nodes{
u64 parent_node u32 parent_node
} }
//NOTE: alternate realities are not necessary. //NOTE: alternate realities are not necessary.
@ -26,17 +33,20 @@ for node_id in 1..num_nodes{
//ideally spacial blocks are sorted from distance to start zone //ideally spacial blocks are sorted from distance to start zone
//texture blocks are inserted before the first spacial block they are used in //texture blocks are inserted before the first spacial block they are used in
u64 num_spacial_blocks
for spacial_block_id in 0..num_spacial_blocks{ for spacial_block_id in 0..num_spacial_blocks{
u64 node_id u32 node_id
u64 block_id //data block u32 block_id //data block
Aabb block_extents Aabb extents
} }
//if the map file references external resources, num_resources = 0 //the order of these lists uniquely generates the incremental Ids
u64 num_resources //MeshId, TextureId etc. based on resource type
for resource_id in 0..num_resources{ //the first 8 bits of resource_uuid describe the type (mesh, texture, etc)
u64 block_id //if the map file references only external resources, num_resource_blocks = 0
u128 resource_id for resource_idx in 0..num_resource_blocks{
u32 block_id
}
for resource_idx in 0..num_resources_external{
u128 resource_uuid
} }
BLOCK_MAP_RESOURCE: BLOCK_MAP_RESOURCE:
@ -52,71 +62,105 @@ Resource resource_type
BLOCK_MAP_REGION: BLOCK_MAP_REGION:
u64 num_models u64 num_models
for model_id in 0..num_models{ for model_id in 0..num_models{
u128 model_resource_uuid
ModelInstance mode_instance ModelInstance mode_instance
} }
*/ */
//if you hash the resource itself and set the first 8 bits to this, that's the resource uuid
//error hiding mock code #[binrw]
mod gameplay_modes{ #[brw(little,repr=u8)]
pub struct Modes{} enum Resource{
Mesh,
Image,
Shader,
Sound,
Video,
Animation,
} }
mod model{
pub struct Mesh{}
#[super::binrw]
#[brw(little)]
pub struct Model{}
}
mod image{
pub struct Image{}
}
//serious code
struct ModelUuid(u128);
struct ImageUuid(u128);
#[binrw] #[binrw]
#[brw(little)] #[brw(little)]
#[derive(Clone,Copy,id::Id)] struct SpacialBlockHeader{
pub struct BvhNodeId(u32); id:BlockId,
struct BvhNode{ extents:newtypes::aabb::Aabb,
//aabb
//child
} }
#[binrw]
#[brw(little)]
struct ResourceBlockHeader{
resource:Resource,
id:BlockId,
}
#[binrw]
#[brw(little)]
struct ResourceExternalHeader{
resource_uuid:u128,
}
#[binrw]
#[brw(little)]
struct MapHeader{
num_nodes:u32,
num_spacial_blocks:u32,
num_resource_blocks:u32,
num_resources_external:u32,
num_modes:u32,
#[br(count=num_nodes)]
nodes:Vec<u32>,
#[br(count=num_spacial_blocks)]
spacial_blocks:Vec<SpacialBlockHeader>,
#[br(count=num_resource_blocks)]
resource_blocks:Vec<ResourceBlockHeader>,
#[br(count=num_resources_external)]
external_resources:Vec<ResourceExternalHeader>,
#[br(count=num_modes)]
modes:Vec<newtypes::gameplay_modes::Mode>,
}
#[binrw] #[binrw]
#[brw(little)] #[brw(little)]
struct Region{ struct Region{
//consider including a bvh in the region instead of needing to rebalance the physics bvh on the fly //consider including a bvh in the region instead of needing to rebalance the physics bvh on the fly
model_count:u32, model_count:u32,
#[br(count=model_count)] #[br(count=model_count)]
models:Vec<model::Model>, models:Vec<newtypes::model::Model>,
} }
pub struct StreamableMap<R:BinReaderExt>{ pub struct StreamableMap<R:BinReaderExt>{
file:crate::file::File<R>, file:crate::file::File<R>,
//this includes every platform... move the unconstrained datas to their appropriate data block? //this includes every platform... move the unconstrained datas to their appropriate data block?
modes:gameplay_modes::Modes, modes:gameplay_modes::Modes,
bvh:BvhNode, bvh:BvhNode<BlockId>,
node_id_to_block_id:Vec<crate::file::BlockId>,
} }
impl<R:BinReaderExt> StreamableMap<R>{ impl<R:BinReaderExt> StreamableMap<R>{
pub(crate) fn new(file:crate::file::File<R>)->Result<Self,Error>{ pub(crate) fn new(mut file:crate::file::File<R>)->Result<Self,Error>{
Err(Error::InvalidHeader) //assume the file seek is in the right place to start reading a map header
let header:MapHeader=file.as_mut().read_le().map_err(Error::InvalidHeader)?;
let modes=header.modes.into_iter().map(Into::into).collect();
let bvh=header.spacial_blocks.into_iter().map(|spacial_block|
(spacial_block.id,spacial_block.extents.into())
).collect();
Ok(Self{
file,
modes:strafesnet_common::gameplay_modes::Modes::new(modes),
bvh:strafesnet_common::bvh::generate_bvh(bvh),
})
} }
pub fn load_node(&mut self,node_id:BvhNodeId)->Result<Vec<model::Model>,Error>{ pub fn get_intersecting_region_block_ids(&self,aabb:&Aabb)->Vec<BlockId>{
let mut block_ids=Vec::new();
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<Vec<model::Model>,Error>{
//load region from disk //load region from disk
//parse the models and determine what resources need to be loaded //parse the models and determine what resources need to be loaded
//load resources into self.resources //load resources into self.resources
//return Region //return Region
let block_id=*self.node_id_to_block_id.get(node_id.get() as usize).ok_or(Error::InvalidBvhNodeId(node_id))?;
let mut block=self.file.block_reader(block_id).map_err(Error::File)?; let mut block=self.file.block_reader(block_id).map_err(Error::File)?;
let region:Region=block.read_le().map_err(Error::InvalidRegion)?; let region:Region=block.read_le().map_err(Error::InvalidRegion)?;
Ok(region.models) Ok(region.models.into_iter().map(Into::into).collect())
} }
// pub fn load_resource(&mut self,resource_id:ResourceId)->Resource{ // pub fn load_resource(&mut self,resource_id:ResourceId)->Resource{
// // // //
// } // }
} }