impl deferred_loader::Loader for rbx_loader
This commit is contained in:
parent
c356a9d654
commit
a594f77453
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2389,8 +2389,10 @@ dependencies = [
|
|||||||
"rbx_mesh",
|
"rbx_mesh",
|
||||||
"rbx_reflection_database",
|
"rbx_reflection_database",
|
||||||
"rbx_xml",
|
"rbx_xml",
|
||||||
|
"rbxassetid",
|
||||||
"roblox_emulator",
|
"roblox_emulator",
|
||||||
"strafesnet_common",
|
"strafesnet_common",
|
||||||
|
"strafesnet_deferred_loader",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -18,5 +18,7 @@ rbx_dom_weak = { version = "2.7.0", registry = "strafesnet" }
|
|||||||
rbx_mesh = "0.1.2"
|
rbx_mesh = "0.1.2"
|
||||||
rbx_reflection_database = { version = "0.2.10", registry = "strafesnet" }
|
rbx_reflection_database = { version = "0.2.10", registry = "strafesnet" }
|
||||||
rbx_xml = { version = "0.13.3", registry = "strafesnet" }
|
rbx_xml = { version = "0.13.3", registry = "strafesnet" }
|
||||||
|
rbxassetid = { version = "0.1.0", path = "../rbxassetid" }
|
||||||
roblox_emulator = { path = "../roblox_emulator", registry = "strafesnet" }
|
roblox_emulator = { path = "../roblox_emulator", registry = "strafesnet" }
|
||||||
strafesnet_common = { path = "../common", registry = "strafesnet" }
|
strafesnet_common = { path = "../common", registry = "strafesnet" }
|
||||||
|
strafesnet_deferred_loader = { version = "0.5.0", path = "../deferred_loader" }
|
||||||
|
@ -3,6 +3,7 @@ use rbx_dom_weak::WeakDom;
|
|||||||
|
|
||||||
mod rbx;
|
mod rbx;
|
||||||
mod mesh;
|
mod mesh;
|
||||||
|
pub mod loader;
|
||||||
mod primitives;
|
mod primitives;
|
||||||
|
|
||||||
pub mod data{
|
pub mod data{
|
||||||
@ -94,14 +95,4 @@ pub fn read<R:Read>(input:R)->Result<Model,ReadError>{
|
|||||||
|
|
||||||
//ConvertError
|
//ConvertError
|
||||||
|
|
||||||
pub fn convert<AcquireRenderConfigId,AcquireMeshId>(
|
pub use rbx::convert;
|
||||||
dom:impl AsRef<WeakDom>,
|
|
||||||
acquire_render_config_id:AcquireRenderConfigId,
|
|
||||||
acquire_mesh_id:AcquireMeshId
|
|
||||||
)->rbx::PartialMap1
|
|
||||||
where
|
|
||||||
AcquireRenderConfigId:FnMut(Option<&str>)->strafesnet_common::model::RenderConfigId,
|
|
||||||
AcquireMeshId:FnMut(&str)->strafesnet_common::model::MeshId,
|
|
||||||
{
|
|
||||||
rbx::convert(&dom.as_ref(),acquire_render_config_id,acquire_mesh_id)
|
|
||||||
}
|
|
||||||
|
102
lib/rbx_loader/src/loader.rs
Normal file
102
lib/rbx_loader/src/loader.rs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
use std::io::Read;
|
||||||
|
use rbxassetid::{RobloxAssetId,RobloxAssetIdParseErr};
|
||||||
|
use strafesnet_common::model::Mesh;
|
||||||
|
use strafesnet_deferred_loader::{loader::Loader,texture::Texture};
|
||||||
|
|
||||||
|
use crate::data::RobloxMeshBytes;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TextureError{
|
||||||
|
Io(std::io::Error),
|
||||||
|
RobloxAssetIdParse(RobloxAssetIdParseErr),
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for TextureError{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for TextureError{}
|
||||||
|
impl From<std::io::Error> for TextureError{
|
||||||
|
fn from(value:std::io::Error)->Self{
|
||||||
|
Self::Io(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<RobloxAssetIdParseErr> for TextureError{
|
||||||
|
fn from(value:RobloxAssetIdParseErr)->Self{
|
||||||
|
Self::RobloxAssetIdParse(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TextureLoader<'a>(std::marker::PhantomData<&'a ()>);
|
||||||
|
impl TextureLoader<'_>{
|
||||||
|
pub fn new()->Self{
|
||||||
|
Self(std::marker::PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> Loader for TextureLoader<'a>{
|
||||||
|
type Error=TextureError;
|
||||||
|
type Index=&'a str;
|
||||||
|
type Resource=Texture;
|
||||||
|
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)?;
|
||||||
|
Ok(Texture::ImageDDS(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MeshError{
|
||||||
|
Io(std::io::Error),
|
||||||
|
RobloxAssetIdParse(RobloxAssetIdParseErr),
|
||||||
|
Mesh(crate::mesh::Error)
|
||||||
|
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for MeshError{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for MeshError{}
|
||||||
|
impl From<std::io::Error> for MeshError{
|
||||||
|
fn from(value:std::io::Error)->Self{
|
||||||
|
Self::Io(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<RobloxAssetIdParseErr> for MeshError{
|
||||||
|
fn from(value:RobloxAssetIdParseErr)->Self{
|
||||||
|
Self::RobloxAssetIdParse(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<crate::mesh::Error> for MeshError{
|
||||||
|
fn from(value:crate::mesh::Error)->Self{
|
||||||
|
Self::Mesh(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MeshLoader<'a>(std::marker::PhantomData<&'a ()>);
|
||||||
|
impl MeshLoader<'_>{
|
||||||
|
pub fn new()->Self{
|
||||||
|
Self(std::marker::PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> Loader for MeshLoader<'a>{
|
||||||
|
type Error=MeshError;
|
||||||
|
type Index=&'a str;
|
||||||
|
type Resource=Mesh;
|
||||||
|
fn load(&mut self,index:Self::Index)->Result<Self::Resource,Self::Error>{
|
||||||
|
let RobloxAssetId(asset_id)=index.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))?;
|
||||||
|
Ok(mesh)
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,9 @@ use strafesnet_common::gameplay_attributes as attr;
|
|||||||
use strafesnet_common::integer::{self,vec3,Planar64,Planar64Vec3,Planar64Mat3,Planar64Affine3};
|
use strafesnet_common::integer::{self,vec3,Planar64,Planar64Vec3,Planar64Mat3,Planar64Affine3};
|
||||||
use strafesnet_common::model::RenderConfigId;
|
use strafesnet_common::model::RenderConfigId;
|
||||||
use strafesnet_common::updatable::Updatable;
|
use strafesnet_common::updatable::Updatable;
|
||||||
|
use strafesnet_deferred_loader::deferred_loader::{RenderConfigDeferredLoader,MeshDeferredLoader};
|
||||||
|
use strafesnet_deferred_loader::mesh::Meshes;
|
||||||
|
use strafesnet_deferred_loader::texture::{RenderConfigs,Texture};
|
||||||
|
|
||||||
fn class_is_a(class: &str, superclass: &str) -> bool {
|
fn class_is_a(class: &str, superclass: &str) -> bool {
|
||||||
if class==superclass {
|
if class==superclass {
|
||||||
@ -432,23 +435,18 @@ struct GetAttributesArgs{
|
|||||||
can_collide:bool,
|
can_collide:bool,
|
||||||
velocity:Planar64Vec3,
|
velocity:Planar64Vec3,
|
||||||
}
|
}
|
||||||
pub fn convert<AcquireRenderConfigId,AcquireMeshId>(
|
pub fn convert<'a>(
|
||||||
dom:&rbx_dom_weak::WeakDom,
|
dom:&'a rbx_dom_weak::WeakDom,
|
||||||
mut acquire_render_config_id:AcquireRenderConfigId,
|
render_config_deferred_loader:&mut RenderConfigDeferredLoader<&'a str>,
|
||||||
mut acquire_mesh_id:AcquireMeshId,
|
mesh_deferred_loader:&mut MeshDeferredLoader<&'a str>,
|
||||||
)->PartialMap1
|
)->PartialMap1{
|
||||||
where
|
|
||||||
AcquireRenderConfigId:FnMut(Option<&str>)->model::RenderConfigId,
|
|
||||||
AcquireMeshId:FnMut(&str)->model::MeshId,
|
|
||||||
{
|
|
||||||
|
|
||||||
let mut deferred_models_deferred_attributes=Vec::new();
|
let mut deferred_models_deferred_attributes=Vec::new();
|
||||||
let mut primitive_models_deferred_attributes=Vec::new();
|
let mut primitive_models_deferred_attributes=Vec::new();
|
||||||
let mut primitive_meshes=Vec::new();
|
let mut primitive_meshes=Vec::new();
|
||||||
let mut mesh_id_from_description=HashMap::new();
|
let mut mesh_id_from_description=HashMap::new();
|
||||||
|
|
||||||
//just going to leave it like this for now instead of reworking the data structures for this whole thing
|
//just going to leave it like this for now instead of reworking the data structures for this whole thing
|
||||||
let textureless_render_group=acquire_render_config_id(None);
|
let textureless_render_group=render_config_deferred_loader.acquire_render_config_id(None);
|
||||||
|
|
||||||
let mut object_refs=Vec::new();
|
let mut object_refs=Vec::new();
|
||||||
let mut temp_objects=Vec::new();
|
let mut temp_objects=Vec::new();
|
||||||
@ -529,7 +527,7 @@ where
|
|||||||
decal.properties.get("Color3"),
|
decal.properties.get("Color3"),
|
||||||
decal.properties.get("Transparency"),
|
decal.properties.get("Transparency"),
|
||||||
) {
|
) {
|
||||||
let render_id=acquire_render_config_id(Some(content.as_ref()));
|
let render_id=render_config_deferred_loader.acquire_render_config_id(Some(content.as_ref()));
|
||||||
let normal_id=normalid.to_u32();
|
let normal_id=normalid.to_u32();
|
||||||
if normal_id<6{
|
if normal_id<6{
|
||||||
let (roblox_texture_color,roblox_texture_transform)=if decal.class=="Texture"{
|
let (roblox_texture_color,roblox_texture_transform)=if decal.class=="Texture"{
|
||||||
@ -691,8 +689,8 @@ where
|
|||||||
object.properties.get("TextureID"),
|
object.properties.get("TextureID"),
|
||||||
){
|
){
|
||||||
(
|
(
|
||||||
MeshAvailability::Deferred(acquire_render_config_id(Some(texture_asset_id.as_ref()))),
|
MeshAvailability::Deferred(render_config_deferred_loader.acquire_render_config_id(Some(texture_asset_id.as_ref()))),
|
||||||
acquire_mesh_id(mesh_asset_id.as_ref()),
|
mesh_deferred_loader.acquire_mesh_id(mesh_asset_id.as_ref()),
|
||||||
)
|
)
|
||||||
}else{
|
}else{
|
||||||
panic!("Mesh has no Mesh or Texture");
|
panic!("Mesh has no Mesh or Texture");
|
||||||
@ -736,7 +734,7 @@ pub struct PartialMap1{
|
|||||||
impl PartialMap1{
|
impl PartialMap1{
|
||||||
pub fn add_meshpart_meshes_and_calculate_attributes(
|
pub fn add_meshpart_meshes_and_calculate_attributes(
|
||||||
mut self,
|
mut self,
|
||||||
meshpart_meshes:impl IntoIterator<Item=(model::MeshId,crate::data::RobloxMeshBytes)>,
|
meshpart_meshes:Meshes,
|
||||||
)->PartialMap2{
|
)->PartialMap2{
|
||||||
//calculate attributes
|
//calculate attributes
|
||||||
let mut modes_builder=ModesBuilder::default();
|
let mut modes_builder=ModesBuilder::default();
|
||||||
@ -749,24 +747,16 @@ impl PartialMap1{
|
|||||||
//decode roblox meshes
|
//decode roblox meshes
|
||||||
//generate mesh_id_map based on meshes that failed to load
|
//generate mesh_id_map based on meshes that failed to load
|
||||||
let loaded_meshes:HashMap<model::MeshId,MeshWithAabb>=
|
let loaded_meshes:HashMap<model::MeshId,MeshWithAabb>=
|
||||||
meshpart_meshes.into_iter().flat_map(|(old_mesh_id,roblox_mesh_bytes)|
|
meshpart_meshes.consume().map(|(old_mesh_id,mesh)|{
|
||||||
match crate::mesh::convert(roblox_mesh_bytes){
|
let mut aabb=strafesnet_common::aabb::Aabb::default();
|
||||||
Ok(mesh)=>{
|
for &pos in &mesh.unique_pos{
|
||||||
let mut aabb=strafesnet_common::aabb::Aabb::default();
|
aabb.grow(pos);
|
||||||
for &pos in &mesh.unique_pos{
|
|
||||||
aabb.grow(pos);
|
|
||||||
}
|
|
||||||
Some((old_mesh_id,MeshWithAabb{
|
|
||||||
mesh,
|
|
||||||
aabb,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
Err(e)=>{
|
|
||||||
println!("Error converting mesh: {e:?}");
|
|
||||||
None
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
).collect();
|
(old_mesh_id,MeshWithAabb{
|
||||||
|
mesh,
|
||||||
|
aabb,
|
||||||
|
})
|
||||||
|
}).collect();
|
||||||
|
|
||||||
let mut mesh_id_from_render_config_id=HashMap::new();
|
let mut mesh_id_from_render_config_id=HashMap::new();
|
||||||
//ignore meshes that fail to load completely for now
|
//ignore meshes that fail to load completely for now
|
||||||
@ -879,11 +869,11 @@ pub struct PartialMap2{
|
|||||||
impl PartialMap2{
|
impl PartialMap2{
|
||||||
pub fn add_render_configs_and_textures(
|
pub fn add_render_configs_and_textures(
|
||||||
self,
|
self,
|
||||||
render_configs:impl IntoIterator<Item=(model::RenderConfigId,model::RenderConfig)>,
|
render_configs:RenderConfigs,
|
||||||
textures:impl IntoIterator<Item=(model::TextureId,Vec<u8>)>,
|
|
||||||
)->map::CompleteMap{
|
)->map::CompleteMap{
|
||||||
|
let (textures,render_configs)=render_configs.consume();
|
||||||
let (textures,texture_id_map):(Vec<Vec<u8>>,HashMap<model::TextureId,model::TextureId>)
|
let (textures,texture_id_map):(Vec<Vec<u8>>,HashMap<model::TextureId,model::TextureId>)
|
||||||
=textures.into_iter().enumerate().map(|(new_texture_id,(old_texture_id,texture))|{
|
=textures.into_iter().enumerate().map(|(new_texture_id,(old_texture_id,Texture::ImageDDS(texture)))|{
|
||||||
(texture,(old_texture_id,model::TextureId::new(new_texture_id as u32)))
|
(texture,(old_texture_id,model::TextureId::new(new_texture_id as u32)))
|
||||||
}).unzip();
|
}).unzip();
|
||||||
let render_configs=render_configs.into_iter().map(|(_render_config_id,mut render_config)|{
|
let render_configs=render_configs.into_iter().map(|(_render_config_id,mut render_config)|{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user