From 71f75da220dfae544fcad7f3730e86b99c3e73c9 Mon Sep 17 00:00:00 2001
From: Quaternions <krakow20@gmail.com>
Date: Tue, 13 Feb 2024 20:32:21 -0800
Subject: [PATCH] add mesh loader prototype code

---
 src/source.rs | 126 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 123 insertions(+), 3 deletions(-)

diff --git a/src/source.rs b/src/source.rs
index 819183c..0a01f6f 100644
--- a/src/source.rs
+++ b/src/source.rs
@@ -32,7 +32,127 @@ impl Loader{
 	fn load_textures(&self)->Result<Textures,std::io::Error>{
 		Ok(Textures::new(Vec::new()))
 	}
-	// fn load_meshes(&self)->Result<Meshes,std::io::Error>{
-	// 	Ok(Meshes::new(Vec::new()))
-	// }
+	/*
+	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);
+	}
+	*/
 }
\ No newline at end of file