use std::io::Read; use std::path::PathBuf; use std::collections::HashMap; use crate::texture::{Texture,Textures}; use strafesnet_common::model::{MeshId,TextureId}; pub struct TextureLoader{ texture_paths:HashMap<PathBuf,TextureId>, } impl TextureLoader{ pub fn acquire_texture_id(&mut self,name:&str)->TextureId{ let texture_id=TextureId::new(self.texture_paths.len() as u32); *self.texture_paths.entry(name.into()).or_insert(texture_id) } } pub struct MeshLoader{ mesh_paths:HashMap<PathBuf,MeshId>, } impl MeshLoader{ pub fn acquire_mesh_id(&mut self,name:&str)->MeshId{ let texture_id=MeshId::new(self.mesh_paths.len() as u32); *self.mesh_paths.entry(name.into()).or_insert(texture_id) } } pub struct Loader{ texture_loader:TextureLoader, mesh_loader:MeshLoader, } impl Loader{ pub fn new()->Self{ Self{ texture_loader:TextureLoader{texture_paths:HashMap::new()}, mesh_loader:MeshLoader{mesh_paths:HashMap::new()}, } } pub fn get_inner_mut(&mut self)->(&mut TextureLoader,&mut MeshLoader){ (&mut self.texture_loader,&mut self.mesh_loader) } } impl Loader{ pub fn load_textures(&self)->Result<Textures,std::io::Error>{ Ok(Textures::new(Vec::new())) } /* pub fn load_meshes(&mut self)->Result<Meshes,std::io::Error>{ //call self.acquire_texture_id for each texture in the mesh //generate unique meshes let mut model_map=std::collections::HashMap::with_capacity(model_dedupe.len()); let mut prop_models=Vec::new(); for model_name in model_dedupe{ let model_name_lower=model_name.to_lowercase(); //.mdl, .vvd, .dx90.vtx let mut path=std::path::PathBuf::from(model_name_lower.as_str()); let file_name=std::path::PathBuf::from(path.file_stem().unwrap()); path.pop(); path.push(file_name); let mut vvd_path=path.clone(); let mut vtx_path=path.clone(); vvd_path.set_extension("vvd"); vtx_path.set_extension("dx90.vtx"); match (bsp.pack.get(model_name_lower.as_str()),bsp.pack.get(vvd_path.as_os_str().to_str().unwrap()),bsp.pack.get(vtx_path.as_os_str().to_str().unwrap())){ (Ok(Some(mdl_file)),Ok(Some(vvd_file)),Ok(Some(vtx_file)))=>{ match (vmdl::mdl::Mdl::read(mdl_file.as_ref()),vmdl::vvd::Vvd::read(vvd_file.as_ref()),vmdl::vtx::Vtx::read(vtx_file.as_ref())){ (Ok(mdl),Ok(vvd),Ok(vtx))=>{ let model=vmdl::Model::from_parts(mdl,vtx,vvd); let texture_paths=model.texture_directories(); if texture_paths.len()!=1{ println!("WARNING: multiple texture paths"); } let skin=model.skin_tables().nth(0).unwrap(); let mut spam_pos=Vec::with_capacity(model.vertices().len()); let mut spam_normal=Vec::with_capacity(model.vertices().len()); let mut spam_tex=Vec::with_capacity(model.vertices().len()); let mut spam_vertices=Vec::with_capacity(model.vertices().len()); for (i,vertex) in model.vertices().iter().enumerate(){ spam_pos.push(valve_transform(<[f32;3]>::from(vertex.position))); spam_normal.push(valve_transform(<[f32;3]>::from(vertex.normal))); spam_tex.push(glam::Vec2::from_array(vertex.texture_coordinates)); spam_vertices.push(model::IndexedVertex{ pos:model::PositionId::new(i as u32), tex:model::TextureCoordinateId::new(i as u32), normal:model::NormalId::new(i as u32), color:model::ColorId::new(0), }); } let model_id=prop_models.len(); model_map.insert(model_name,model_id); prop_models.push(model::Mesh{ unique_pos:spam_pos, unique_normal:spam_normal, unique_tex:spam_tex, unique_color:vec![glam::Vec4::ONE], unique_vertices:spam_vertices, groups:model.meshes().map(|mesh|{ let texture=if let (Some(texture_path),Some(texture_name))=(texture_paths.get(0),skin.texture(mesh.material_index())){ let mut path=std::path::PathBuf::from(texture_path.as_str()); path.push(texture_name); let texture_location=path.as_os_str().to_str().unwrap(); let texture_id=if let Some(&texture_id)=texture_id_from_name.get(texture_location){ texture_id }else{ println!("texture! {}",texture_location); let texture_id=name_from_texture_id.len() as u32; texture_id_from_name.insert(texture_location.to_string(),texture_id); name_from_texture_id.push(texture_location.to_string()); texture_id }; Some(texture_id) }else{ None }; model::IndexedGroup{ texture, polys:{ //looking at the code, it would seem that the strips are pre-deindexed into triangle lists when calling this function mesh.vertex_strip_indices().map(|strip|{ strip.collect::<Vec<usize>>().chunks(3).map(|tri|{ model::IndexedPolygon{vertices:vec![tri[0] as u32,tri[1] as u32,tri[2] as u32]} }).collect::<Vec<model::IndexedPolygon>>() }).flatten().collect() }, } }).collect(), instances:Vec::new(), }); }, _=>println!("model_name={} error",model_name), } }, _=>println!("no model name={}",model_name), } } //generate model instances for prop in bsp.static_props(){ let placement=prop.as_prop_placement(); if let Some(&model_index)=model_map.get(placement.model){ prop_models[model_index].instances.push(model::ModelInstance{ transform:integer::Planar64Affine3::new( integer::Planar64Mat3::try_from( glam::Mat3A::from_diagonal(glam::Vec3::splat(placement.scale)) //TODO: figure this out *glam::Mat3A::from_quat(glam::Quat::from_xyzw( placement.rotation.v.x,//b placement.rotation.v.y,//c placement.rotation.v.z,//d placement.rotation.s,//a )) ).unwrap(), valve_transform(<[f32;3]>::from(placement.origin)), ), attributes:model::CollisionAttributes::Decoration, ..Default::default() }); }else{ //println!("model not found {}",placement.model); } } //actually add the prop models prop_models.append(&mut models); } */ }