use loader crate

This commit is contained in:
Robin Appelman 2023-12-20 17:38:11 +01:00
commit d8cb4acc49
8 changed files with 247 additions and 163 deletions

225
Cargo.lock generated
View file

@ -39,6 +39,18 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]]
name = "aes"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
"opaque-debug",
]
[[package]]
name = "ahash"
version = "0.8.6"
@ -196,6 +208,12 @@ dependencies = [
"backtrace",
]
[[package]]
name = "base64ct"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "beef"
version = "0.5.2"
@ -338,6 +356,27 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bzip2"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
dependencies = [
"bzip2-sys",
"libc",
]
[[package]]
name = "bzip2-sys"
version = "0.1.11+1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]]
name = "calloop"
version = "0.10.6"
@ -393,6 +432,15 @@ dependencies = [
"num-traits 0.2.17",
]
[[package]]
name = "cipher"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
dependencies = [
"generic-array",
]
[[package]]
name = "clap"
version = "4.4.11"
@ -445,6 +493,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "constant_time_eq"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]]
name = "core-foundation"
version = "0.9.4"
@ -577,12 +631,12 @@ dependencies = [
]
[[package]]
name = "delaunator"
version = "1.0.2"
name = "deranged"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab46e386c7a38300a0d93b0f3e484bc2ee0aded66c47b14762ec9ab383934fa"
checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc"
dependencies = [
"robust",
"powerfmt",
]
[[package]]
@ -593,6 +647,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
@ -952,6 +1007,15 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]]
name = "image"
version = "0.23.14"
@ -1634,6 +1698,12 @@ version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "orbclient"
version = "0.3.47"
@ -1713,12 +1783,35 @@ dependencies = [
"syn 2.0.41",
]
[[package]]
name = "password-hash"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700"
dependencies = [
"base64ct",
"rand_core",
"subtle",
]
[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "pbkdf2"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
dependencies = [
"digest",
"hmac",
"password-hash",
"sha2",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
@ -1807,6 +1900,12 @@ dependencies = [
"miniz_oxide 0.7.1",
]
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "proc-macro-crate"
version = "1.3.1"
@ -1869,6 +1968,12 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "raw-window-handle"
version = "0.5.2"
@ -1974,12 +2079,6 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "robust"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5864e7ef1a6b7bcf1d6ca3f655e65e724ed3b52546a0d0a663c991522f552ea"
[[package]]
name = "rustc-demangle"
version = "0.1.23"
@ -2095,6 +2194,17 @@ dependencies = [
"syn 2.0.41",
]
[[package]]
name = "sha1"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha2"
version = "0.10.8"
@ -2245,6 +2355,12 @@ dependencies = [
"syn 2.0.41",
]
[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "supports-color"
version = "2.1.0"
@ -2348,6 +2464,20 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "tf-asset-loader"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d19874714b7454f34d6142f9a2e2521b6e48ff4b3929cbac7acc72f161baf7bf"
dependencies = [
"steamlocate",
"thiserror",
"tracing",
"vbsp",
"vpk",
"zip-lzma",
]
[[package]]
name = "tf-demo-parser"
version = "0.4.0"
@ -2402,6 +2532,8 @@ dependencies = [
[[package]]
name = "three-d"
version = "0.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2db9010227411ab0aa5948e770304e807e5c9b6d5d0719c3de248bae7be7096"
dependencies = [
"cgmath",
"egui",
@ -2443,6 +2575,35 @@ dependencies = [
"weezl",
]
[[package]]
name = "time"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e"
dependencies = [
"deranged",
"itoa",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f"
dependencies = [
"time-core",
]
[[package]]
name = "tiny-skia"
version = "0.8.4"
@ -2672,13 +2833,12 @@ version = "0.1.0"
dependencies = [
"cgmath",
"clap",
"delaunator",
"image",
"itertools 0.10.5",
"itertools 0.12.0",
"miette",
"splines",
"steamid-ng",
"steamlocate",
"tf-asset-loader",
"tf-demo-parser",
"thiserror",
"three-d",
@ -2689,7 +2849,6 @@ dependencies = [
"vbsp",
"vmdl",
"vmt-parser",
"vpk",
"vtf",
]
@ -3273,8 +3432,46 @@ version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b480cb31fccfb2786565c0e0712865fd6f1ea0ea850c50316f643c3948196e63"
dependencies = [
"aes",
"byteorder 1.5.0",
"bzip2",
"constant_time_eq",
"crc32fast",
"crossbeam-utils",
"flate2",
"hmac",
"lzma",
"pbkdf2",
"sha1",
"time",
"zstd",
]
[[package]]
name = "zstd"
version = "0.10.2+zstd.1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f4a6bd64f22b5e3e94b4e238669ff9f10815c27a5180108b849d24174a83847"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "4.1.6+zstd.1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94b61c51bb270702d6167b8ce67340d2754b088d0c091b06e593aa772c3ee9bb"
dependencies = [
"libc",
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "1.6.3+zstd.1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc49afa5c8d634e75761feda8c592051e7eeb4683ba827211eb0d731d3402ea8"
dependencies = [
"cc",
"libc",
]

View file

@ -6,17 +6,13 @@ authors = ["Robin Appelman <robin@icewind.nl>"]
license = "MIT"
[dependencies]
#three-d = { version = "0.16.3", features = ["egui-gui"] }
three-d = { version = "0.16.3", features = ["egui-gui"], path = "../rust/three-d" }
three-d = { version = "0.16.3", features = ["egui-gui"] }
three-d-asset = { version = "0.6" }
vbsp = { version = "0.3.0", git = "https://github.com/icewind1991/vbsp" }
#vbsp = { version = "0.3.0", path = "../bsp" }
miette = { version = "5.5.0", features = ["fancy"] }
thiserror = "1.0.37"
delaunator = "1.0.1"
itertools = "0.10.5"
steamlocate = "=2.0.0-alpha.0"
vpk = "0.2.0"
itertools = "0.12.0"
vmdl = { version = "*", git = "https://github.com/icewind1991/vmdl" }
#vmdl = { version = "*", path = "../vmdl" }
tracing = "0.1.37"
@ -30,6 +26,12 @@ splines = { version = "4.1.1", features = ["cgmath"] }
vtf = "0.1.6"
vmt-parser = { version = "0.1", git = "https://github.com/icewind1991/vmt-parser" }
image = "0.23.14"
tf-asset-loader = { version = "0.1", features = ["bsp"] }
# make tf-asset-loader use the same vbsp version
[patch.crates-io]
#vbsp = { version = "0.3.0", path = "../bsp" }
vbsp = { version = "0.3.0", git = "https://github.com/icewind1991/vbsp" }
[profile.dev.package."*"]
opt-level = 2

View file

@ -1,9 +1,10 @@
use crate::material::{convert_material, load_material_fallback};
use crate::prop::load_props;
use crate::{Error, Loader};
use crate::Error;
use cgmath::Matrix4;
use itertools::Itertools;
use std::collections::{HashMap, HashSet};
use tf_asset_loader::Loader;
use three_d::{CpuModel, Positions, Vec3};
use three_d_asset::{Geometry, Primitive, TriMesh};
use vbsp::{Bsp, Handle};
@ -98,7 +99,7 @@ fn model_to_model(model: Handle<vbsp::data::Model>, loader: &Loader) -> CpuModel
fn load_world(data: &[u8], loader: &mut Loader) -> Result<(CpuModel, Bsp), Error> {
let bsp = Bsp::read(data)?;
loader.set_pack(bsp.pack.clone());
loader.add_source(bsp.pack.clone());
let world_model = bsp
.models()

View file

@ -1,126 +0,0 @@
use crate::Error;
use std::fmt::{Debug, Formatter};
use std::fs;
use std::path::PathBuf;
use steamlocate::SteamDir;
use tracing::debug;
use vbsp::Packfile;
use vpk::VPK;
pub struct Loader {
pack: Option<Packfile>,
tf_dir: PathBuf,
download: PathBuf,
vpks: Vec<VPK>,
}
impl Debug for Loader {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Loader")
.field("tf_dir", &self.tf_dir)
.finish_non_exhaustive()
}
}
impl Loader {
pub fn new() -> Result<Self, Error> {
let tf2_dir = SteamDir::locate()
.ok_or("Can't find steam directory")?
.app(&440)
.ok_or("Can't find tf2 directory")?
.path
.clone();
let tf_dir = tf2_dir.join("tf");
let hl_dir = tf2_dir.join("hl2");
let download = tf_dir.join("download");
let vpks = tf_dir
.read_dir()?
.chain(hl_dir.read_dir()?)
.filter_map(|item| item.ok())
.filter_map(|item| Some(item.path().to_str()?.to_string()))
.filter(|path| path.ends_with("dir.vpk"))
.map(|path| vpk::from_path(&path))
.filter_map(|res| res.ok())
.collect();
Ok(Loader {
tf_dir,
download,
vpks,
pack: None,
})
}
pub fn set_pack(&mut self, pack: Packfile) {
self.pack = Some(pack);
}
#[tracing::instrument]
pub fn exists(&self, name: &str) -> bool {
debug!("loading {}", name);
if name.ends_with("bsp") {
let path = self.tf_dir.join(name);
if path.exists() {
return true;
}
let path = self.download.join(name);
if path.exists() {
return true;
}
}
for vpk in self.vpks.iter() {
if vpk.tree.contains_key(name) {
return true;
}
}
if let Some(pack) = &self.pack {
if pack.get(name).ok().flatten().is_some() {
return true;
}
}
false
}
#[tracing::instrument]
pub fn load(&self, name: &str) -> Result<Vec<u8>, Error> {
debug!("loading {}", name);
if name.ends_with("bsp") {
let path = self.tf_dir.join(name);
if path.exists() {
debug!("found in tf2 dir");
return Ok(fs::read(path)?);
}
let path = self.download.join(name);
if path.exists() {
debug!("found in download dir");
return Ok(fs::read(path)?);
}
}
if let Some(pack) = &self.pack {
if let Some(data) = pack.get(name)? {
debug!("got {} bytes from packfile", data.len());
return Ok(data);
}
}
for vpk in self.vpks.iter() {
if let Some(entry) = vpk.tree.get(name) {
let data = entry.get()?.into_owned();
debug!("got {} bytes from vpk", data.len());
return Ok(data);
}
}
Err(Error::ResourceNotFound(name.to_string()))
}
pub fn find_in_paths(&self, name: &str, paths: &[String]) -> Option<String> {
for path in paths {
let full_path = format!("{}{}", path, name);
if self.exists(&full_path) {
return Some(full_path);
}
}
None
}
}

View file

@ -1,7 +1,6 @@
mod bsp;
mod control;
mod demo;
mod loader;
mod material;
mod prop;
mod renderer;
@ -11,6 +10,7 @@ mod wrapping;
use clap::Parser;
use std::fs;
use std::string::FromUtf8Error;
use tf_asset_loader::{Loader, LoaderError};
use crate::bsp::load_map;
use crate::control::{Control, DemoCamera};
@ -18,7 +18,6 @@ use crate::demo::DemoInfo;
use crate::renderer::Renderer;
use crate::ui::DebugUI;
use control::FirstPerson;
use loader::Loader;
use thiserror::Error;
use three_d::*;
use tracing_subscriber::{prelude::*, EnvFilter};
@ -44,8 +43,6 @@ pub enum Error {
#[error(transparent)]
IO(#[from] std::io::Error),
#[error(transparent)]
Vpk(#[from] vpk::Error),
#[error(transparent)]
Vtf(#[from] vtf::Error),
#[error(transparent)]
Vdf(#[from] VdfError),
@ -61,6 +58,8 @@ pub enum Error {
Render(#[from] RendererError),
#[error(transparent)]
String(#[from] FromUtf8Error),
#[error(transparent)]
Loader(#[from] LoaderError),
#[error("resource {0} not found in vpks or pack")]
ResourceNotFound(String),
}
@ -98,7 +97,9 @@ fn main() -> Result<(), Error> {
if args.path.ends_with(".dem") {
let demo = DemoInfo::new(args.path, &args.player.unwrap_or_default())?;
let mut loader = Loader::new()?;
let map = loader.load(&format!("maps/{}.bsp", demo.map))?;
let map = loader
.load(&format!("maps/{}.bsp", demo.map))?
.ok_or(Error::ResourceNotFound(demo.map.clone()))?;
let models = load_map(&map, &mut loader)?;
play(window, DemoCamera::new(demo), models)

View file

@ -1,6 +1,6 @@
use crate::loader::Loader;
use crate::Error;
use image::{DynamicImage, GenericImageView};
use tf_asset_loader::Loader;
use three_d::{CpuMaterial, CpuTexture};
use three_d_asset::Srgba;
use tracing::{error, instrument};
@ -58,7 +58,9 @@ pub fn load_material(
let path = loader
.find_in_paths(&path, &dirs)
.ok_or(Error::ResourceNotFound(path))?;
let raw = loader.load(&path)?;
let raw = loader
.load(&path)?
.ok_or_else(|| Error::ResourceNotFound(path.clone()))?;
let vdf = String::from_utf8(raw)?;
let material = from_str(&vdf).map_err(|e| {
@ -67,7 +69,9 @@ pub fn load_material(
Error::Other(format!("Failed to load material {}", path))
})?;
let material = material.resolve(|path| {
let data = loader.load(path)?;
let data = loader
.load(path)?
.ok_or(Error::ResourceNotFound(path.into()))?;
let vdf = String::from_utf8(data)?;
Ok::<_, Error>(vdf)
})?;
@ -120,7 +124,7 @@ fn load_texture(name: &str, loader: &Loader) -> Result<DynamicImage, Error> {
"materials/{}.vtf",
name.trim_end_matches(".vtf").trim_start_matches('/')
);
let mut raw = loader.load(&path)?;
let mut raw = loader.load(&path)?.ok_or(Error::ResourceNotFound(path))?;
let vtf = VTF::read(&mut raw)?;
let image = vtf.highres_image.decode(0)?;
Ok(image)

View file

@ -1,6 +1,7 @@
use crate::bsp::map_coords;
use crate::material::{convert_material, load_material_fallback};
use crate::{Error, Loader};
use crate::Error;
use tf_asset_loader::Loader;
use three_d::{CpuMaterial, CpuModel, Mat4, Positions, Vec2, Vec3, Vec4};
use three_d_asset::{Geometry, Primitive, TriMesh};
use tracing::{error, warn};
@ -11,9 +12,14 @@ use vmdl::vvd::Vvd;
#[tracing::instrument(skip(loader))]
pub fn load_prop(loader: &Loader, name: &str) -> Result<vmdl::Model, Error> {
let mdl = Mdl::read(&loader.load(name)?)?;
let vtx = Vtx::read(&loader.load(&name.replace(".mdl", ".dx90.vtx"))?)?;
let vvd = Vvd::read(&loader.load(&name.replace(".mdl", ".vvd"))?)?;
let load = |name: &str| -> Result<Vec<u8>, Error> {
loader
.load(name)?
.ok_or(Error::ResourceNotFound(name.into()))
};
let mdl = Mdl::read(&load(name)?)?;
let vtx = Vtx::read(&load(&name.replace(".mdl", ".dx90.vtx"))?)?;
let vvd = Vvd::read(&load(&name.replace(".mdl", ".vvd"))?)?;
Ok(vmdl::Model::from_parts(mdl, vtx, vvd))
}

View file

@ -1,12 +1,11 @@
use crate::control::{Control, DebugToggle};
use crate::ui::DebugType;
use crate::DebugUI;
use std::sync::Arc;
use three_d::*;
pub struct Renderer<C: Control> {
gui: DebugUI,
pub models: Vec<Model<Arc<PhysicalMaterial>>>,
pub models: Vec<Model<PhysicalMaterial>>,
ambient_lights: Vec<AmbientLight>,
directional_lights: Vec<DirectionalLight>,
pub context: Context,