Compare commits

...

4 Commits

Author SHA1 Message Date
926e18abf7 rustified 2024-02-13 22:12:43 -08:00
1fca3fb3f4 split in twain 2024-02-13 22:10:50 -08:00
662ccc26bc add mesh loader prototype code 2024-02-13 22:02:19 -08:00
3664d6f796 add source 2024-02-13 22:02:19 -08:00
2 changed files with 170 additions and 1 deletions

View File

@ -8,7 +8,7 @@ edition = "2021"
[features]
legacy = ["dep:lazy-regex"]
#roblox = []
#source = []
source = []
[dependencies]
lazy-regex = { version = "3.1.0", optional = true }

View File

@ -0,0 +1,169 @@
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);
}
*/
}