diff --git a/lib/rbx_loader/src/loader.rs b/lib/rbx_loader/src/loader.rs index 099a080..eb804ce 100644 --- a/lib/rbx_loader/src/loader.rs +++ b/lib/rbx_loader/src/loader.rs @@ -5,6 +5,13 @@ use strafesnet_deferred_loader::{loader::Loader,texture::Texture}; use crate::data::RobloxMeshBytes; +fn read_entire_file(path:impl AsRef<std::path::Path>)->Result<Vec<u8>,std::io::Error>{ + let mut file=std::fs::File::open(path)?; + let mut data=Vec::new(); + file.read_to_end(&mut data)?; + Ok(data) +} + #[allow(dead_code)] #[derive(Debug)] pub enum TextureError{ @@ -41,9 +48,7 @@ impl<'a> Loader for TextureLoader<'a>{ fn load(&mut self,index:Self::Index)->Result<Self::Resource,Self::Error>{ let RobloxAssetId(asset_id)=index.parse()?; let file_name=format!("textures/{}.dds",asset_id); - let mut file=std::fs::File::open(file_name)?; - let mut data=Vec::new(); - file.read_to_end(&mut data)?; + let data=read_entire_file(file_name)?; Ok(Texture::ImageDDS(data)) } } @@ -53,7 +58,8 @@ impl<'a> Loader for TextureLoader<'a>{ pub enum MeshError{ Io(std::io::Error), RobloxAssetIdParse(RobloxAssetIdParseErr), - Mesh(crate::mesh::Error) + Mesh(crate::mesh::Error), + Union(crate::union::Error), } impl std::fmt::Display for MeshError{ @@ -77,6 +83,43 @@ impl From<crate::mesh::Error> for MeshError{ Self::Mesh(value) } } +impl From<crate::union::Error> for MeshError{ + fn from(value:crate::union::Error)->Self{ + Self::Union(value) + } +} + +#[derive(Hash,Eq,PartialEq)] +pub enum MeshType<'a>{ + FileMesh, + Union{ + mesh_data:&'a [u8], + physics_data:&'a [u8], + }, +} +#[derive(Hash,Eq,PartialEq)] +pub struct MeshIndex<'a>{ + mesh_type:MeshType<'a>, + content:&'a str, +} +impl MeshIndex<'_>{ + pub fn file_mesh(content:&str)->MeshIndex{ + MeshIndex{ + mesh_type:MeshType::FileMesh, + content, + } + } + pub fn union<'a>( + content:&'a str, + mesh_data:&'a [u8], + physics_data:&'a [u8], + )->MeshIndex<'a>{ + MeshIndex{ + mesh_type:MeshType::Union{mesh_data,physics_data}, + content, + } + } +} pub struct MeshLoader<'a>(std::marker::PhantomData<&'a ()>); impl MeshLoader<'_>{ @@ -86,17 +129,18 @@ impl MeshLoader<'_>{ } impl<'a> Loader for MeshLoader<'a>{ type Error=MeshError; - type Index=&'a str; + type Index=MeshIndex<'a>; type Resource=Mesh; fn load(&mut self,index:Self::Index)->Result<Self::Resource,Self::Error>{ - let RobloxAssetId(asset_id)=index.parse()?; + let RobloxAssetId(asset_id)=index.content.parse()?; let file_name=format!("meshes/{}",asset_id); - let mut file=std::fs::File::open(file_name)?; // reading the entire file is way faster than // round tripping to disk every read from the parser - let mut data=Vec::new(); - file.read_to_end(&mut data)?; - let mesh=crate::mesh::convert(RobloxMeshBytes::new(data))?; + let data=read_entire_file(file_name)?; + let mesh=match index.mesh_type{ + MeshType::FileMesh=>crate::mesh::convert(RobloxMeshBytes::new(data))?, + MeshType::Union{physics_data,mesh_data}=>crate::union::convert(physics_data,mesh_data)?, + }; Ok(mesh) } } diff --git a/lib/rbx_loader/src/rbx.rs b/lib/rbx_loader/src/rbx.rs index 37e3881..0b69776 100644 --- a/lib/rbx_loader/src/rbx.rs +++ b/lib/rbx_loader/src/rbx.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use crate::loader::MeshIndex; use crate::primitives; use strafesnet_common::map; use strafesnet_common::model; @@ -487,31 +488,24 @@ enum Shape{ MeshPart, PhysicsData, } -enum MeshAvailability<'a>{ +enum MeshAvailability{ Immediate, DeferredMesh(RenderConfigId), - DeferredUnion(RobloxPartDescription,UnionDeferredAttributes<'a>), + DeferredUnion(RobloxPartDescription), } -struct DeferredModelDeferredAttributes{ +struct DeferredModelDeferredAttributes<'a>{ render:RenderConfigId, - model:ModelDeferredAttributes, + model:ModelDeferredAttributes<'a>, } -struct ModelDeferredAttributes{ +struct ModelDeferredAttributes<'a>{ mesh:model::MeshId, - deferred_attributes:GetAttributesArgs, + deferred_attributes:GetAttributesArgs<'a>, color:model::Color4,//transparency is in here transform:Planar64Affine3, } struct DeferredUnionDeferredAttributes<'a>{ render:RobloxPartDescription, - model:ModelDeferredAttributes, - union:UnionDeferredAttributes<'a>, -} -#[derive(Hash)] -struct UnionDeferredAttributes<'a>{ - asset_id:Option<&'a str>, - mesh_data:Option<&'a [u8]>, - physics_data:Option<&'a [u8]>, + model:ModelDeferredAttributes<'a>, } struct ModelOwnedAttributes{ mesh:model::MeshId, @@ -519,17 +513,18 @@ struct ModelOwnedAttributes{ color:model::Color4,//transparency is in here transform:Planar64Affine3, } -struct GetAttributesArgs{ - name:Box<str>, +struct GetAttributesArgs<'a>{ + name:&'a str, can_collide:bool, velocity:Planar64Vec3, } pub fn convert<'a>( dom:&'a rbx_dom_weak::WeakDom, render_config_deferred_loader:&mut RenderConfigDeferredLoader<&'a str>, - mesh_deferred_loader:&mut MeshDeferredLoader<&'a str>, + mesh_deferred_loader:&mut MeshDeferredLoader<MeshIndex<'a>>, )->PartialMap1<'a>{ let mut deferred_models_deferred_attributes=Vec::new(); + let mut deferred_unions_deferred_attributes=Vec::new(); let mut primitive_models_deferred_attributes=Vec::new(); let mut primitive_meshes=Vec::new(); let mut mesh_id_from_description=HashMap::new(); @@ -600,7 +595,7 @@ pub fn convert<'a>( let (availability,mesh_id)=match shape{ Shape::Primitive(primitive_shape)=>{ //TODO: TAB TAB - let part_texture_description=get_texture_description(&mut temp_objects,&mut render_config_deferred_loader,dom,object,size); + let part_texture_description=get_texture_description(&mut temp_objects,render_config_deferred_loader,dom,object,size); //obscure rust syntax "slice pattern" let [ f0,//Cube::Right @@ -714,7 +709,7 @@ pub fn convert<'a>( ){ ( MeshAvailability::DeferredMesh(render_config_deferred_loader.acquire_render_config_id(Some(texture_asset_id.as_ref()))), - mesh_deferred_loader.acquire_mesh_id(mesh_asset_id.as_ref()), + mesh_deferred_loader.acquire_mesh_id(MeshIndex::file_mesh(mesh_asset_id.as_ref())), ) }else{ panic!("Mesh has no Mesh or Texture"); @@ -723,34 +718,22 @@ pub fn convert<'a>( //The union mesh is sized already model_transform=planar64_affine3_from_roblox(cf,&rbx_dom_weak::types::Vector3{x:2.0,y:2.0,z:2.0}); - let mut asset_id=None; - let mut mesh_data=None; - let mut physics_data=None; - if let Some(rbx_dom_weak::types::Variant::Content(content))=object.properties.get("AssetId"){ - let value:&str=content.as_ref(); - if !value.is_empty(){ - asset_id=Some(value); - } + let mut content=""; + let mut mesh_data:&[u8]=&[]; + let mut physics_data:&[u8]=&[]; + if let Some(rbx_dom_weak::types::Variant::Content(asset_id))=object.properties.get("AssetId"){ + content=asset_id.as_ref(); } if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=object.properties.get("MeshData"){ - let value:&[u8]=data.as_ref(); - if !value.is_empty(){ - mesh_data=Some(value); - } + mesh_data=data.as_ref(); } if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=object.properties.get("PhysicsData"){ - let value:&[u8]=data.as_ref(); - if !value.is_empty(){ - physics_data=Some(value); - } + physics_data=data.as_ref(); } - let part_texture_description=get_texture_description(&mut temp_objects,&mut render_config_deferred_loader,dom,object,size); - let union_deferred_attributes=UnionDeferredAttributes{ - asset_id, - mesh_data, - physics_data, - }; - (MeshAvailability::DeferredUnion(part_texture_description,union_deferred_attributes),mesh_id) + let part_texture_description=get_texture_description(&mut temp_objects,render_config_deferred_loader,dom,object,size); + let mesh_index=MeshIndex::union(content,mesh_data,physics_data); + let mesh_id=mesh_deferred_loader.acquire_mesh_id(mesh_index); + (MeshAvailability::DeferredUnion(part_texture_description),mesh_id) }, }; let model_deferred_attributes=ModelDeferredAttributes{ @@ -758,7 +741,7 @@ pub fn convert<'a>( transform:model_transform, color:glam::vec4(color3.r as f32/255f32, color3.g as f32/255f32, color3.b as f32/255f32, 1.0-*transparency), deferred_attributes:GetAttributesArgs{ - name:object.name.as_str().into(), + name:object.name.as_str(), can_collide:*can_collide, velocity:vec3::try_from_f32_array([velocity.x,velocity.y,velocity.z]).unwrap(), }, @@ -769,10 +752,9 @@ pub fn convert<'a>( render, model:model_deferred_attributes }), - MeshAvailability::DeferredUnion(part_texture_description,union_deferred_attributes)=>deferred_unions_deferred_attributes.push(DeferredUnionDeferredAttributes{ + MeshAvailability::DeferredUnion(part_texture_description)=>deferred_unions_deferred_attributes.push(DeferredUnionDeferredAttributes{ render:part_texture_description, model:model_deferred_attributes, - union:union_deferred_attributes, }), } } @@ -782,6 +764,7 @@ pub fn convert<'a>( primitive_meshes, primitive_models_deferred_attributes, deferred_models_deferred_attributes, + deferred_unions_deferred_attributes, } } struct MeshWithAabb{ @@ -790,11 +773,11 @@ struct MeshWithAabb{ } pub struct PartialMap1<'a>{ primitive_meshes:Vec<model::Mesh>, - primitive_models_deferred_attributes:Vec<ModelDeferredAttributes>, - deferred_models_deferred_attributes:Vec<DeferredModelDeferredAttributes>, - deferred_union_deferred_attributes:Vec<DeferredModelDeferredAttributes>, + primitive_models_deferred_attributes:Vec<ModelDeferredAttributes<'a>>, + deferred_models_deferred_attributes:Vec<DeferredModelDeferredAttributes<'a>>, + deferred_unions_deferred_attributes:Vec<DeferredUnionDeferredAttributes<'a>>, } -impl PartialMap1{ +impl PartialMap1<'_>{ pub fn add_meshpart_meshes_and_calculate_attributes( mut self, meshpart_meshes:Meshes, diff --git a/lib/rbx_loader/src/union.rs b/lib/rbx_loader/src/union.rs index 8124275..5ba7f13 100644 --- a/lib/rbx_loader/src/union.rs +++ b/lib/rbx_loader/src/union.rs @@ -33,7 +33,7 @@ pub fn convert(roblox_physics_data:&[u8],roblox_mesh_data:&[u8])->Result<model:: std::io::Cursor::new(roblox_mesh_data) ).map_err(Error::RobloxMeshData)?; let graphics_mesh=match mesh_data{ - rbx_mesh::mesh_data::CSGPHS::CSGK(csgk)=>return Err(Error::NotSupposedToHappen), + rbx_mesh::mesh_data::CSGPHS::CSGK(_)=>return Err(Error::NotSupposedToHappen), rbx_mesh::mesh_data::CSGPHS::CSGPHS2(mesh_data2)=>mesh_data2.mesh, rbx_mesh::mesh_data::CSGPHS::CSGPHS4(mesh_data4)=>mesh_data4.mesh, }; @@ -47,8 +47,7 @@ pub fn convert(roblox_physics_data:&[u8],roblox_mesh_data:&[u8])->Result<model:: // have not seen this format in practice |rbx_mesh::physics_data::PhysicsData::CSGPHS(rbx_mesh::physics_data::CSGPHS::Block) =>return Err(Error::NotSupposedToHappen), - rbx_mesh::physics_data::PhysicsData::CSGPHS(rbx_mesh::physics_data::CSGPHS::Meshes3(meshes)) - |rbx_mesh::physics_data::PhysicsData::CSGPHS(rbx_mesh::physics_data::CSGPHS::Meshes5(meshes)) + rbx_mesh::physics_data::PhysicsData::CSGPHS(rbx_mesh::physics_data::CSGPHS::Meshes(meshes)) =>meshes.meshes, rbx_mesh::physics_data::PhysicsData::CSGPHS(rbx_mesh::physics_data::CSGPHS::PhysicsInfoMesh(pim)) =>vec![pim.mesh],