use std::{borrow::Cow, io::Read}; use strafesnet_common::model::Mesh; use strafesnet_deferred_loader::{loader::Loader,texture::Texture}; use crate::{Bsp,Vpk}; #[allow(dead_code)] #[derive(Debug)] pub enum TextureError{ Io(std::io::Error), } 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) } } 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=Cow<'a,str>; type Resource=Texture; fn load(&mut self,index:Self::Index)->Result<Self::Resource,Self::Error>{ let file_name=format!("textures/{}.dds",index); 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), VMDL(vmdl::ModelError), VBSP(vbsp::BspError), MissingMdl(String), MissingVtx, MissingVvd, } 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<vmdl::ModelError> for MeshError{ fn from(value:vmdl::ModelError)->Self{ Self::VMDL(value) } } impl From<vbsp::BspError> for MeshError{ fn from(value:vbsp::BspError)->Self{ Self::VBSP(value) } } #[derive(Clone,Copy)] pub struct BspFinder<'bsp,'vpk>{ pub bsp:&'bsp Bsp, pub vpks:&'vpk [Vpk], } impl<'bsp,'vpk> BspFinder<'bsp,'vpk>{ pub fn find<'a>(&self,path:&str)->Result<Option<Cow<'a,[u8]>>,vbsp::BspError> where 'bsp:'a, 'vpk:'a, { // search bsp if let Some(data)=self.bsp.pack_get(path)?{ return Ok(Some(Cow::Owned(data))); } //search each vpk for vpk in self.vpks{ if let Some(vpk_entry)=vpk.tree_get(path){ return Ok(Some(vpk_entry.get()?)); } } Ok(None) } } pub struct ModelLoader<'bsp,'vpk,'a>{ finder:BspFinder<'bsp,'vpk>, life:core::marker::PhantomData<&'a ()>, } impl ModelLoader<'_,'_,'_>{ #[inline] pub const fn new<'bsp,'vpk,'a>( finder:BspFinder<'bsp,'vpk>, )->ModelLoader<'bsp,'vpk,'a>{ ModelLoader{ finder, life:core::marker::PhantomData, } } } impl<'bsp,'vpk,'a> Loader for ModelLoader<'bsp,'vpk,'a> where 'bsp:'a, 'vpk:'a, { type Error=MeshError; type Index=&'a str; type Resource=vmdl::Model; fn load(&mut self,index:Self::Index)->Result<Self::Resource,Self::Error>{ let mdl_path_lower=index.to_lowercase(); //.mdl, .vvd, .dx90.vtx let path=std::path::PathBuf::from(mdl_path_lower.as_str()); let mut vvd_path=path.clone(); let mut vtx_path=path; vvd_path.set_extension("vvd"); vtx_path.set_extension("dx90.vtx"); // TODO: search more packs, possibly using an index of multiple packs let mdl=self.finder.find(mdl_path_lower.as_str())?.ok_or(MeshError::MissingMdl(mdl_path_lower))?; let vtx=self.finder.find(vtx_path.as_os_str().to_str().unwrap())?.ok_or(MeshError::MissingVtx)?; let vvd=self.finder.find(vvd_path.as_os_str().to_str().unwrap())?.ok_or(MeshError::MissingVvd)?; Ok(vmdl::Model::from_parts( vmdl::mdl::Mdl::read(mdl.as_ref())?, vmdl::vtx::Vtx::read(vtx.as_ref())?, vmdl::vvd::Vvd::read(vvd.as_ref())?, )) } } pub struct MeshLoader<'bsp,'vpk,'load,'a>{ finder:BspFinder<'bsp,'vpk>, deferred_loader:&'load mut strafesnet_deferred_loader::deferred_loader::RenderConfigDeferredLoader<Cow<'a,str>>, } impl MeshLoader<'_,'_,'_,'_>{ #[inline] pub const fn new<'bsp,'vpk,'load,'a>( finder:BspFinder<'bsp,'vpk>, deferred_loader:&'load mut strafesnet_deferred_loader::deferred_loader::RenderConfigDeferredLoader<Cow<'a,str>>, )->MeshLoader<'bsp,'vpk,'load,'a>{ MeshLoader{ finder, deferred_loader } } } impl<'bsp,'vpk,'load,'a> Loader for MeshLoader<'bsp,'vpk,'load,'a> where 'bsp:'a, 'vpk:'a, { type Error=MeshError; type Index=&'a str; type Resource=Mesh; fn load(&mut self,index:Self::Index)->Result<Self::Resource,Self::Error>{ let model=ModelLoader::new(self.finder).load(index)?; let mesh=crate::mesh::convert_mesh(model,&mut self.deferred_loader); Ok(mesh) } }