dedup materials

This commit is contained in:
Robin Appelman 2023-12-10 19:32:36 +01:00
commit 6b70a04675
3 changed files with 81 additions and 85 deletions

1
Cargo.lock generated
View file

@ -3014,7 +3014,6 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "vmdl" name = "vmdl"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/icewind1991/vmdl#70a6adebdd8f6b7d60625c2539aa3e68403526fb"
dependencies = [ dependencies = [
"arrayvec 0.7.4", "arrayvec 0.7.4",
"bitflags 1.3.2", "bitflags 1.3.2",

View file

@ -15,7 +15,8 @@ delaunator = "1.0.1"
itertools = "0.10.5" itertools = "0.10.5"
steamlocate = "1.1.0" steamlocate = "1.1.0"
vpk = { version = "0.1.4", git = "https://github.com/icewind1991/vpk-rs", branch = "perf" } vpk = { version = "0.1.4", git = "https://github.com/icewind1991/vpk-rs", branch = "perf" }
vmdl = { version = "*", git = "https://github.com/icewind1991/vmdl" } #vmdl = { version = "*", git = "https://github.com/icewind1991/vmdl" }
vmdl = { version = "*", path = "../vmdl" }
tracing = "0.1.37" tracing = "0.1.37"
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
tracing-tree = "0.2.2" tracing-tree = "0.2.2"

View file

@ -2,21 +2,19 @@ use crate::{Error, Loader};
use cgmath::{vec4, Matrix, SquareMatrix}; use cgmath::{vec4, Matrix, SquareMatrix};
use std::collections::HashMap; use std::collections::HashMap;
use three_d::{ use three_d::{
Color, CpuMaterial, CpuMesh, CpuModel, CpuTexture, Indices, Mat4, Positions, TextureData, Vec2, Color, CpuMaterial, CpuMesh, CpuModel, CpuTexture, Mat4, Positions, TextureData, Vec2, Vec3,
Vec3,
}; };
use tracing::error; use tracing::error;
use vbsp::{Bsp, Face, Handle, StaticPropLump}; use vbsp::{Bsp, Face, Handle, StaticPropLump};
use vmdl::mdl::Mdl; use vmdl::mdl::{Mdl, TextureInfo};
use vmdl::vtx::Vtx; use vmdl::vtx::Vtx;
use vmdl::vvd::Vvd; use vmdl::vvd::Vvd;
use vtf::vtf::VTF; use vtf::vtf::VTF;
pub fn load_map(data: &[u8], loader: &mut Loader) -> Result<Vec<CpuModel>, Error> { pub fn load_map(data: &[u8], loader: &mut Loader) -> Result<Vec<CpuModel>, Error> {
let (cpu_model, bsp) = load_world(data, loader)?; let (world, bsp) = load_world(data, loader)?;
let mut props = load_props(loader, bsp.static_props())?; let props = load_props(loader, bsp.static_props())?;
props.insert(0, cpu_model); Ok(vec![world, props])
Ok(props)
} }
fn apply_transform<C: Into<Vec3>>(coord: C, transform: Mat4) -> Vec3 { fn apply_transform<C: Into<Vec3>>(coord: C, transform: Mat4) -> Vec3 {
@ -128,21 +126,35 @@ fn model_to_model(model: Handle<vbsp::data::Model>, loader: &Loader) -> CpuModel
fn load_props<'a, I: Iterator<Item = Handle<'a, StaticPropLump>>>( fn load_props<'a, I: Iterator<Item = Handle<'a, StaticPropLump>>>(
loader: &Loader, loader: &Loader,
props: I, props: I,
) -> Result<Vec<CpuModel>, Error> { ) -> Result<CpuModel, Error> {
let props = props.map(|prop| { let props: Vec<ModelData> = props
.map(|prop| {
let model = load_prop(loader, prop.model())?; let model = load_prop(loader, prop.model())?;
let transform = let transform =
Mat4::from_translation(map_coords(prop.origin)) * Mat4::from(prop.rotation()); Mat4::from_translation(map_coords(prop.origin)) * Mat4::from(prop.rotation());
Ok(ModelData { Ok::<_, Error>(ModelData {
model, model,
transform, transform,
skin: prop.skin, skin: prop.skin,
}) })
}); })
.collect::<Result<_, _>>()?;
props let geometries = props.iter().flat_map(prop_to_meshes).collect();
.map(|res| res.map(|prop| prop_to_model(prop, loader)))
.collect::<Result<_, Error>>() let textures: HashMap<_, _> = props
.iter()
.flat_map(|prop| prop.model.textures())
.map(|tex| (tex.name.as_str(), tex))
.collect();
let materials: Vec<_> = textures
.into_values()
.map(|tex| prop_texture_to_material(tex, loader))
.collect();
Ok(CpuModel {
geometries,
materials,
})
} }
#[tracing::instrument(skip(loader))] #[tracing::instrument(skip(loader))]
@ -160,10 +172,10 @@ struct ModelData {
skin: i32, skin: i32,
} }
fn prop_to_model(prop: ModelData, loader: &Loader) -> CpuModel { fn prop_to_meshes(prop: &ModelData) -> impl Iterator<Item = CpuMesh> + '_ {
let transform = prop.transform; let transform = prop.transform;
let normal_transform = transform.invert().unwrap().transpose() * -1.0; let normal_transform = transform.invert().unwrap().transpose() * -1.0;
let model = prop.model; let model = &prop.model;
let skin = match model.skin_tables().nth(prop.skin as usize) { let skin = match model.skin_tables().nth(prop.skin as usize) {
Some(skin) => skin, Some(skin) => skin,
@ -173,9 +185,7 @@ fn prop_to_model(prop: ModelData, loader: &Loader) -> CpuModel {
} }
}; };
let geometries = model model.meshes().map(move |mesh| {
.meshes()
.map(|mesh| {
let texture = skin let texture = skin
.texture(mesh.material_index()) .texture(mesh.material_index())
.expect("texture out of bounds"); .expect("texture out of bounds");
@ -192,10 +202,7 @@ fn prop_to_model(prop: ModelData, loader: &Loader) -> CpuModel {
.collect(); .collect();
let uvs: Vec<Vec2> = mesh let uvs: Vec<Vec2> = mesh
.vertices() .vertices()
.map(|vertex| Vec2 { .map(|vertex| vertex.texture_coordinates.into())
x: vertex.texture_coordinates[0],
y: vertex.texture_coordinates[1],
})
.collect(); .collect();
CpuMesh { CpuMesh {
@ -206,21 +213,17 @@ fn prop_to_model(prop: ModelData, loader: &Loader) -> CpuModel {
..Default::default() ..Default::default()
} }
}) })
.collect(); }
let materials = model fn prop_texture_to_material(texture: &TextureInfo, loader: &Loader) -> CpuMaterial {
.textures() match load_texture(&texture.name, &texture.search_paths, loader) {
.iter()
.map(|texture| {
let dirs = model.texture_directories();
match load_texture(&texture.name, dirs, loader) {
Ok(texture) => CpuMaterial { Ok(texture) => CpuMaterial {
albedo: Color::default(), albedo: Color::default(),
name: texture.name.clone(), name: texture.name.clone(),
albedo_texture: Some(texture), albedo_texture: Some(texture),
..Default::default() ..Default::default()
}, },
Err(e) => CpuMaterial { Err(_) => CpuMaterial {
albedo: Color { albedo: Color {
r: 255, r: 255,
g: 0, g: 0,
@ -231,13 +234,6 @@ fn prop_to_model(prop: ModelData, loader: &Loader) -> CpuModel {
..Default::default() ..Default::default()
}, },
} }
})
.collect();
CpuModel {
materials,
geometries,
}
} }
fn load_texture(name: &str, dirs: &[String], loader: &Loader) -> Result<CpuTexture, Error> { fn load_texture(name: &str, dirs: &[String], loader: &Loader) -> Result<CpuTexture, Error> {