tab down this function
This commit is contained in:
parent
05f466727c
commit
ea55d4bcfb
394
src/bsp.rs
394
src/bsp.rs
@ -13,217 +13,217 @@ where
|
|||||||
AcquireTextureId:FnMut(&str)->model::TextureId,
|
AcquireTextureId:FnMut(&str)->model::TextureId,
|
||||||
AcquireMeshId:FnMut(&str)->model::MeshId,
|
AcquireMeshId:FnMut(&str)->model::MeshId,
|
||||||
{
|
{
|
||||||
let mut spawn_point=integer::Planar64Vec3::ZERO;
|
let mut spawn_point=integer::Planar64Vec3::ZERO;
|
||||||
|
|
||||||
let vertices: Vec<_> = bsp
|
let vertices: Vec<_> = bsp
|
||||||
.vertices
|
.vertices
|
||||||
.iter()
|
.iter()
|
||||||
.map(|vertex|<[f32;3]>::from(vertex.position))
|
.map(|vertex|<[f32;3]>::from(vertex.position))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut name_from_texture_id=Vec::new();
|
let mut name_from_texture_id=Vec::new();
|
||||||
let mut texture_id_from_name=std::collections::HashMap::new();
|
let mut texture_id_from_name=std::collections::HashMap::new();
|
||||||
|
|
||||||
let mut models=bsp.models().map(|world_model|{
|
let mut models=bsp.models().map(|world_model|{
|
||||||
//non-deduplicated
|
//non-deduplicated
|
||||||
let mut spam_pos=Vec::new();
|
let mut spam_pos=Vec::new();
|
||||||
let mut spam_tex=Vec::new();
|
let mut spam_tex=Vec::new();
|
||||||
let mut spam_normal=Vec::new();
|
let mut spam_normal=Vec::new();
|
||||||
let mut spam_vertices=Vec::new();
|
let mut spam_vertices=Vec::new();
|
||||||
let groups=world_model.faces()
|
let groups=world_model.faces()
|
||||||
.filter(|face|face.is_visible())//TODO: look at this
|
.filter(|face|face.is_visible())//TODO: look at this
|
||||||
.map(|face|{
|
.map(|face|{
|
||||||
let face_texture=face.texture();
|
let face_texture=face.texture();
|
||||||
let face_texture_data=face_texture.texture_data();
|
let face_texture_data=face_texture.texture_data();
|
||||||
let (texture_u,texture_v)=(glam::Vec3A::from_slice(&face_texture.texture_transforms_u[0..3]),glam::Vec3A::from_slice(&face_texture.texture_transforms_v[0..3]));
|
let (texture_u,texture_v)=(glam::Vec3A::from_slice(&face_texture.texture_transforms_u[0..3]),glam::Vec3A::from_slice(&face_texture.texture_transforms_v[0..3]));
|
||||||
let texture_offset=glam::vec2(face_texture.texture_transforms_u[3],face_texture.texture_transforms_v[3]);
|
let texture_offset=glam::vec2(face_texture.texture_transforms_u[3],face_texture.texture_transforms_v[3]);
|
||||||
let texture_size=glam::vec2(face_texture_data.width as f32,face_texture_data.height as f32);
|
let texture_size=glam::vec2(face_texture_data.width as f32,face_texture_data.height as f32);
|
||||||
|
|
||||||
//texture
|
//texture
|
||||||
let texture_id=if let Some(&texture_id)=texture_id_from_name.get(face_texture_data.name()){
|
let texture_id=if let Some(&texture_id)=texture_id_from_name.get(face_texture_data.name()){
|
||||||
texture_id
|
texture_id
|
||||||
}else{
|
}else{
|
||||||
let texture_id=name_from_texture_id.len() as u32;
|
let texture_id=name_from_texture_id.len() as u32;
|
||||||
texture_id_from_name.insert(face_texture_data.name().to_string(),texture_id);
|
texture_id_from_name.insert(face_texture_data.name().to_string(),texture_id);
|
||||||
name_from_texture_id.push(face_texture_data.name().to_string());
|
name_from_texture_id.push(face_texture_data.name().to_string());
|
||||||
texture_id
|
texture_id
|
||||||
};
|
};
|
||||||
|
|
||||||
//normal
|
//normal
|
||||||
let normal=face.normal();
|
let normal=face.normal();
|
||||||
let normal_idx=spam_normal.len() as u32;
|
let normal_idx=spam_normal.len() as u32;
|
||||||
spam_normal.push(valve_transform(<[f32;3]>::from(normal)));
|
spam_normal.push(valve_transform(<[f32;3]>::from(normal)));
|
||||||
let mut indices:Vec<u32>=face.vertex_positions().map(|vertex_position|{
|
let mut indices:Vec<u32>=face.vertex_positions().map(|vertex_position|{
|
||||||
let vertex_xyz=<[f32;3]>::from(vertex_position);
|
let vertex_xyz=<[f32;3]>::from(vertex_position);
|
||||||
let pos=glam::Vec3A::from_array(vertex_xyz);
|
let pos=glam::Vec3A::from_array(vertex_xyz);
|
||||||
let pos_idx=spam_pos.len();
|
let pos_idx=spam_pos.len();
|
||||||
spam_pos.push(valve_transform(vertex_xyz));
|
spam_pos.push(valve_transform(vertex_xyz));
|
||||||
|
|
||||||
//calculate texture coordinates
|
//calculate texture coordinates
|
||||||
let tex=(glam::vec2(pos.dot(texture_u),pos.dot(texture_v))+texture_offset)/texture_size;
|
let tex=(glam::vec2(pos.dot(texture_u),pos.dot(texture_v))+texture_offset)/texture_size;
|
||||||
let tex_idx=spam_tex.len() as u32;
|
let tex_idx=spam_tex.len() as u32;
|
||||||
spam_tex.push(tex);
|
spam_tex.push(tex);
|
||||||
|
|
||||||
let i=spam_vertices.len() as u32;
|
let i=spam_vertices.len() as u32;
|
||||||
spam_vertices.push(model::IndexedVertex{
|
spam_vertices.push(model::IndexedVertex{
|
||||||
pos: pos_idx as u32,
|
pos: pos_idx as u32,
|
||||||
tex: tex_idx as u32,
|
tex: tex_idx as u32,
|
||||||
normal: normal_idx,
|
normal: normal_idx,
|
||||||
color: 0,
|
color: 0,
|
||||||
});
|
});
|
||||||
i
|
i
|
||||||
}).collect();
|
|
||||||
indices.reverse();
|
|
||||||
texture:Some(texture_id),
|
|
||||||
model::IndexedGroup::PolygonList(vec![model::IndexedPolygon{indices}])
|
|
||||||
}).collect();
|
|
||||||
model::Mesh{
|
|
||||||
unique_pos:spam_pos,
|
|
||||||
unique_tex:spam_tex,
|
|
||||||
unique_normal:spam_normal,
|
|
||||||
unique_color:vec![glam::Vec4::ONE],
|
|
||||||
unique_vertices:spam_vertices,
|
|
||||||
groups,
|
|
||||||
instances:vec![model::Model{
|
|
||||||
attributes:gameplay_attributes::CollisionAttributes::Decoration,
|
|
||||||
transform:integer::Planar64Affine3::new(
|
|
||||||
integer::Planar64Mat3::default(),
|
|
||||||
valve_transform(<[f32;3]>::from(world_model.origin))
|
|
||||||
),
|
|
||||||
..Default::default()
|
|
||||||
}],
|
|
||||||
}
|
|
||||||
}).collect();
|
}).collect();
|
||||||
|
indices.reverse();
|
||||||
|
texture:Some(texture_id),
|
||||||
|
model::IndexedGroup::PolygonList(vec![model::IndexedPolygon{indices}])
|
||||||
|
}).collect();
|
||||||
|
model::Mesh{
|
||||||
|
unique_pos:spam_pos,
|
||||||
|
unique_tex:spam_tex,
|
||||||
|
unique_normal:spam_normal,
|
||||||
|
unique_color:vec![glam::Vec4::ONE],
|
||||||
|
unique_vertices:spam_vertices,
|
||||||
|
groups,
|
||||||
|
instances:vec![model::Model{
|
||||||
|
attributes:gameplay_attributes::CollisionAttributes::Decoration,
|
||||||
|
transform:integer::Planar64Affine3::new(
|
||||||
|
integer::Planar64Mat3::default(),
|
||||||
|
valve_transform(<[f32;3]>::from(world_model.origin))
|
||||||
|
),
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
//dedupe prop models
|
//dedupe prop models
|
||||||
let mut model_dedupe=std::collections::HashSet::new();
|
let mut model_dedupe=std::collections::HashSet::new();
|
||||||
for prop in bsp.static_props(){
|
for prop in bsp.static_props(){
|
||||||
model_dedupe.insert(prop.model());
|
model_dedupe.insert(prop.model());
|
||||||
}
|
}
|
||||||
|
|
||||||
//generate unique meshes
|
//generate unique meshes
|
||||||
let mut model_map=std::collections::HashMap::with_capacity(model_dedupe.len());
|
let mut model_map=std::collections::HashMap::with_capacity(model_dedupe.len());
|
||||||
let mut prop_models=Vec::new();
|
let mut prop_models=Vec::new();
|
||||||
for model_name in model_dedupe{
|
for model_name in model_dedupe{
|
||||||
let model_name_lower=model_name.to_lowercase();
|
let model_name_lower=model_name.to_lowercase();
|
||||||
//.mdl, .vvd, .dx90.vtx
|
//.mdl, .vvd, .dx90.vtx
|
||||||
let mut path=std::path::PathBuf::from(model_name_lower.as_str());
|
let mut path=std::path::PathBuf::from(model_name_lower.as_str());
|
||||||
let file_name=std::path::PathBuf::from(path.file_stem().unwrap());
|
let file_name=std::path::PathBuf::from(path.file_stem().unwrap());
|
||||||
path.pop();
|
path.pop();
|
||||||
path.push(file_name);
|
path.push(file_name);
|
||||||
let mut vvd_path=path.clone();
|
let mut vvd_path=path.clone();
|
||||||
let mut vtx_path=path.clone();
|
let mut vtx_path=path.clone();
|
||||||
vvd_path.set_extension("vvd");
|
vvd_path.set_extension("vvd");
|
||||||
vtx_path.set_extension("dx90.vtx");
|
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())){
|
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)))=>{
|
(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())){
|
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))=>{
|
(Ok(mdl),Ok(vvd),Ok(vtx))=>{
|
||||||
let model=vmdl::Model::from_parts(mdl,vtx,vvd);
|
let model=vmdl::Model::from_parts(mdl,vtx,vvd);
|
||||||
let texture_paths=model.texture_directories();
|
let texture_paths=model.texture_directories();
|
||||||
if texture_paths.len()!=1{
|
if texture_paths.len()!=1{
|
||||||
println!("WARNING: multiple texture paths");
|
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:i as u32,
|
|
||||||
tex:i as u32,
|
|
||||||
normal:i as u32,
|
|
||||||
color: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),
|
|
||||||
}
|
}
|
||||||
|
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:i as u32,
|
||||||
|
tex:i as u32,
|
||||||
|
normal:i as u32,
|
||||||
|
color: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!("no model name={}",model_name),
|
_=>println!("model_name={} error",model_name),
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
_=>println!("no model name={}",model_name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//generate model instances
|
//generate model instances
|
||||||
for prop in bsp.static_props(){
|
for prop in bsp.static_props(){
|
||||||
let placement=prop.as_prop_placement();
|
let placement=prop.as_prop_placement();
|
||||||
if let Some(&model_index)=model_map.get(placement.model){
|
if let Some(&model_index)=model_map.get(placement.model){
|
||||||
prop_models[model_index].instances.push(model::ModelInstance{
|
prop_models[model_index].instances.push(model::ModelInstance{
|
||||||
transform:integer::Planar64Affine3::new(
|
transform:integer::Planar64Affine3::new(
|
||||||
integer::Planar64Mat3::try_from(
|
integer::Planar64Mat3::try_from(
|
||||||
glam::Mat3A::from_diagonal(glam::Vec3::splat(placement.scale))
|
glam::Mat3A::from_diagonal(glam::Vec3::splat(placement.scale))
|
||||||
//TODO: figure this out
|
//TODO: figure this out
|
||||||
*glam::Mat3A::from_quat(glam::Quat::from_xyzw(
|
*glam::Mat3A::from_quat(glam::Quat::from_xyzw(
|
||||||
placement.rotation.v.x,//b
|
placement.rotation.v.x,//b
|
||||||
placement.rotation.v.y,//c
|
placement.rotation.v.y,//c
|
||||||
placement.rotation.v.z,//d
|
placement.rotation.v.z,//d
|
||||||
placement.rotation.s,//a
|
placement.rotation.s,//a
|
||||||
))
|
))
|
||||||
).unwrap(),
|
).unwrap(),
|
||||||
valve_transform(<[f32;3]>::from(placement.origin)),
|
valve_transform(<[f32;3]>::from(placement.origin)),
|
||||||
),
|
),
|
||||||
attributes:model::CollisionAttributes::Decoration,
|
attributes:model::CollisionAttributes::Decoration,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
//println!("model not found {}",placement.model);
|
//println!("model not found {}",placement.model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//actually add the prop models
|
//actually add the prop models
|
||||||
prop_models.append(&mut models);
|
prop_models.append(&mut models);
|
||||||
|
|
||||||
Ok(model::MeshInstances{
|
Ok(model::MeshInstances{
|
||||||
textures:name_from_texture_id,
|
textures:name_from_texture_id,
|
||||||
models:prop_models,
|
models:prop_models,
|
||||||
spawn_point,
|
spawn_point,
|
||||||
modes:Vec::new(),
|
modes:Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user