merge props

This commit is contained in:
Robin Appelman 2022-03-17 00:05:10 +01:00
commit 9231de3741

View file

@ -100,12 +100,13 @@ fn main() -> Result<(), Error> {
..Default::default() ..Default::default()
}; };
let mut model = Model::new_with_material(&context, &cpu_mesh, material.clone())?; let model = Model::new_with_material(&context, &cpu_mesh, material.clone())?;
// model.set_transformation(Mat4::from_angle_x(degrees(-90.0)));
let props = bsp let props = bsp
.static_props() .static_props()
.map(|prop| load_prop(&loader, prop, &context, material.clone())) .map(|prop| load_prop(&loader, prop))
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
let merged_props = merge_meshes(props);
let props_model = Model::new_with_material(&context, &merged_props, material)?;
let mut lights = Lights { let mut lights = Lights {
ambient: Some(AmbientLight { ambient: Some(AmbientLight {
@ -209,14 +210,12 @@ fn main() -> Result<(), Error> {
&camera, &camera,
&lights, &lights,
)?; )?;
for prop in &props { props_model.render_with_material(
prop.render_with_material(
&NormalMaterial::from_physical_material(&model.material), &NormalMaterial::from_physical_material(&model.material),
&camera, &camera,
&lights, &lights,
)?; )?;
} }
}
DebugType::DEPTH => { DebugType::DEPTH => {
let mut depth_material = DepthMaterial::default(); let mut depth_material = DepthMaterial::default();
depth_material.max_distance = Some(depth_max); depth_material.max_distance = Some(depth_max);
@ -260,6 +259,15 @@ fn main() -> Result<(), Error> {
Ok(()) Ok(())
} }
fn map_coords<C: Into<[f32; 3]>>(vec: C) -> [f32; 3] {
let vec = vec.into();
[
-vec[0] * UNIT_SCALE,
vec[2] * UNIT_SCALE,
vec[1] * UNIT_SCALE,
]
}
// 1 hammer unit is ~1.905cm // 1 hammer unit is ~1.905cm
const UNIT_SCALE: f32 = 1.0 / (1.905 * 100.0); const UNIT_SCALE: f32 = 1.0 / (1.905 * 100.0);
@ -273,8 +281,7 @@ fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CPUMesh {
.map(|verts| Either::Left(verts)) .map(|verts| Either::Left(verts))
.unwrap_or_else(|| Either::Right(face.triangulate().flat_map(|verts| verts))) .unwrap_or_else(|| Either::Right(face.triangulate().flat_map(|verts| verts)))
}) })
.flat_map(<[f32; 3]>::from) .flat_map(map_coords)
.map(|c| c * UNIT_SCALE)
.collect(); .collect();
let mut mesh = CPUMesh { let mut mesh = CPUMesh {
@ -287,23 +294,17 @@ fn model_to_mesh(model: Handle<vbsp::data::Model>) -> CPUMesh {
mesh mesh
} }
fn load_prop<M: Material>( fn load_prop(loader: &Loader, prop: Handle<StaticPropLump>) -> Result<CPUMesh, Error> {
loader: &Loader, let mut mesh = load_prop_mesh(loader, prop.model())?;
prop: Handle<StaticPropLump>, let translation = Mat4::from_translation(map_coords(prop.origin).into());
context: &Context,
material: M,
) -> Result<Model<M>, Error> {
let mesh = load_prop_mesh(loader, prop.model())?;
let mut model = Model::new_with_material(context, &mesh, material)?;
let translation = Mat4::from_translation(<[f32; 3]>::from(prop.origin * UNIT_SCALE).into());
let rotation = Mat4::from(Euler { let rotation = Mat4::from(Euler {
x: degrees(prop.angles[0]), x: degrees(prop.angles[0]),
y: degrees(prop.angles[1]), y: degrees(prop.angles[1]),
z: degrees(prop.angles[2]), z: degrees(prop.angles[2]),
}); });
let world = Mat4::from_angle_x(degrees(-90.0)); mesh.transform(&rotation);
model.set_transformation(translation); mesh.transform(&translation);
Ok(model) Ok(mesh)
} }
#[tracing::instrument(skip(loader))] #[tracing::instrument(skip(loader))]
@ -320,12 +321,12 @@ fn prop_to_mesh(model: &vmdl::Model) -> CPUMesh {
let positions: Vec<f32> = model let positions: Vec<f32> = model
.vertices() .vertices()
.iter() .iter()
.flat_map(|vertex| vertex.position.iter().map(|pos| pos * UNIT_SCALE)) .flat_map(|v| map_coords(v.position))
.collect(); .collect();
let normals: Vec<f32> = model let normals: Vec<f32> = model
.vertices() .vertices()
.iter() .iter()
.flat_map(|vertex| vertex.normal.iter()) .flat_map(|vertex| map_coords(vertex.normal))
.collect(); .collect();
let indices = Indices::U32( let indices = Indices::U32(
model model
@ -334,10 +335,37 @@ fn prop_to_mesh(model: &vmdl::Model) -> CPUMesh {
.collect(), .collect(),
); );
CPUMesh { let mut mesh = CPUMesh {
positions, positions,
normals: Some(normals), normals: Some(normals),
indices: Some(indices), indices: Some(indices),
..Default::default() ..Default::default()
};
mesh.compute_normals();
mesh
}
fn merge_meshes<I: IntoIterator<Item = CPUMesh>>(meshes: I) -> CPUMesh {
let mut positions = Vec::new();
let mut normals = Vec::new();
let mut indices = Vec::new();
for mesh in meshes {
mesh.validate().expect("invalid mesh");
let offset = positions.len() as u32 / 3;
positions.extend_from_slice(&mesh.positions);
normals.extend_from_slice(&mesh.normals.unwrap());
if let Indices::U32(mesh_indices) = mesh.indices.unwrap() {
indices.extend(mesh_indices.into_iter().map(|index| index + offset));
} else {
unreachable!();
}
}
CPUMesh {
positions,
normals: Some(normals),
indices: Some(Indices::U32(indices)),
..Default::default()
} }
} }