176 lines
4.3 KiB
Rust
176 lines
4.3 KiB
Rust
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)
|
|
}
|
|
}
|