1
0
Fork 0
mirror of https://codeberg.org/icewind/vbsp.git synced 2026-06-03 18:54:05 +02:00

texture info handling

This commit is contained in:
Robin Appelman 2022-12-07 22:03:32 +01:00
commit e132a34a00
6 changed files with 69 additions and 7 deletions

View file

@ -1,3 +1,4 @@
#[allow(unused_imports)]
use std::ops::Deref; use std::ops::Deref;
fn main() -> Result<(), vbsp::BspError> { fn main() -> Result<(), vbsp::BspError> {
@ -12,9 +13,13 @@ fn main() -> Result<(), vbsp::BspError> {
// } // }
// } // }
for prop in bsp.static_props() { // for prop in bsp.static_props() {
dbg!(prop.deref()); // dbg!(prop.deref());
dbg!(prop.model()); // dbg!(prop.model());
// }
for tex in bsp.textures() {
println!("{}", tex.name());
} }
Ok(()) Ok(())

View file

@ -43,10 +43,10 @@ impl<'a> BspFile<'a> {
pub fn lump_reader(&self, lump: LumpType) -> BspResult<LumpReader<Cursor<Cow<[u8]>>>> { pub fn lump_reader(&self, lump: LumpType) -> BspResult<LumpReader<Cursor<Cow<[u8]>>>> {
let data = self.get_lump(lump)?; let data = self.get_lump(lump)?;
Ok(LumpReader::new(data)) Ok(LumpReader::new(data, lump))
} }
fn get_lump(&self, lump: LumpType) -> BspResult<Cow<[u8]>> { pub fn get_lump(&self, lump: LumpType) -> BspResult<Cow<[u8]>> {
let lump = &self.directories[lump]; let lump = &self.directories[lump];
let raw_data = self let raw_data = self
.data .data

View file

@ -2,6 +2,7 @@ use crate::data::*;
use std::num::{ParseFloatError, ParseIntError}; use std::num::{ParseFloatError, ParseIntError};
use thiserror::Error; use thiserror::Error;
use zip::result::ZipError; use zip::result::ZipError;
use crate::bspfile::LumpType;
#[non_exhaustive] #[non_exhaustive]
#[derive(Debug, Error)] #[derive(Debug, Error)]
@ -16,6 +17,7 @@ pub enum BspError {
MalformedCompressedGameLump, MalformedCompressedGameLump,
#[error("Invalid lump size, lump size {lump_size} is not a multiple of the element size {element_size}")] #[error("Invalid lump size, lump size {lump_size} is not a multiple of the element size {element_size}")]
InvalidLumpSize { InvalidLumpSize {
lump: LumpType,
element_size: usize, element_size: usize,
lump_size: usize, lump_size: usize,
}, },

View file

@ -119,3 +119,24 @@ impl<'a> Handle<'a, Leaf> {
.filter_map(move |leaf_face| bsp.face(leaf_face.face as usize)) .filter_map(move |leaf_face| bsp.face(leaf_face.face as usize))
} }
} }
impl<'a> Handle<'a, TextureInfo> {
pub fn texture_data(&self) -> Handle<'a, TextureData> {
Handle::new(self.bsp, &self.bsp.textures_data[self.data.texture_data_index as usize])
}
pub fn name(&self) -> &'a str {
self.texture_data().name()
}
}
impl<'a> Handle<'a, TextureData> {
pub fn name(&self) -> &'a str {
let start = self.bsp.texture_string_tables[self.name_string_table_id as usize] as usize;
let part = &self.bsp.texture_string_data[start..];
if let Some((s, _)) = part.split_once("\0") {
s
} else {
part
}
}
}

View file

@ -159,6 +159,8 @@ pub struct Bsp {
pub entities: Entities, pub entities: Entities,
pub textures_data: Vec<TextureData>, pub textures_data: Vec<TextureData>,
pub textures_info: Vec<TextureInfo>, pub textures_info: Vec<TextureInfo>,
pub texture_string_tables: Vec<i32>,
pub texture_string_data: String,
pub planes: Vec<Plane>, pub planes: Vec<Plane>,
pub nodes: Vec<Node>, pub nodes: Vec<Node>,
pub leaves: Leaves, pub leaves: Leaves,
@ -191,6 +193,12 @@ impl Bsp {
let textures_info = bsp_file let textures_info = bsp_file
.lump_reader(LumpType::TextureInfo)? .lump_reader(LumpType::TextureInfo)?
.read_vec(|r| r.read())?; .read_vec(|r| r.read())?;
let texture_string_tables = bsp_file
.lump_reader(LumpType::TextureDataStringTable)?
.read_vec(|r| r.read())?;
let texture_string_data = String::from_utf8(bsp_file
.get_lump(LumpType::TextureDataStringData)?
.into_owned()).map_err(|e| BspError::String(StringError::NonUTF8(e.utf8_error())))?;
let planes = bsp_file let planes = bsp_file
.lump_reader(LumpType::Planes)? .lump_reader(LumpType::Planes)?
.read_vec(|r| r.read())?; .read_vec(|r| r.read())?;
@ -253,6 +261,8 @@ impl Bsp {
entities, entities,
textures_data, textures_data,
textures_info, textures_info,
texture_string_tables,
texture_string_data,
planes, planes,
nodes, nodes,
leaves, leaves,
@ -315,6 +325,11 @@ impl Bsp {
self.models.iter().map(move |m| Handle::new(self, m)) self.models.iter().map(move |m| Handle::new(self, m))
} }
/// Get all models stored in the bsp
pub fn textures(&self) -> impl Iterator<Item = Handle<'_, TextureInfo>> {
self.textures_info.iter().map(move |m| Handle::new(self, m))
}
/// Find a leaf for a specific position /// Find a leaf for a specific position
pub fn leaf_at(&self, point: Vector) -> Handle<'_, Leaf> { pub fn leaf_at(&self, point: Vector) -> Handle<'_, Leaf> {
let mut current = self.root_node(); let mut current = self.root_node();
@ -424,6 +439,22 @@ impl Bsp {
"texture_info", "texture_info",
"texture_data", "texture_data",
)?; )?;
self.validate_indexes(
self.textures_data
.iter()
.map(|texture| texture.name_string_table_id),
&self.texture_string_tables,
"textures_data",
"texture_string_tables",
)?;
self.validate_indexes(
self.texture_string_tables
.iter()
.map(|texture| *texture),
&self.texture_string_data.as_bytes(),
"texture_string_tables",
"texture_string_data",
)?;
self.validate_indexes( self.validate_indexes(
self.nodes.iter().map(|node| node.plane_index), self.nodes.iter().map(|node| node.plane_index),
&self.planes, &self.planes,

View file

@ -1,6 +1,5 @@
use crate::*; use crate::*;
use binrw::BinReaderExt; use binrw::BinReaderExt;
// use std::any::type_name;
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt::Debug; use std::fmt::Debug;
use std::mem::size_of; use std::mem::size_of;
@ -8,15 +7,17 @@ use std::mem::size_of;
pub struct LumpReader<R> { pub struct LumpReader<R> {
inner: R, inner: R,
length: usize, length: usize,
lump: LumpType,
} }
impl<'a> LumpReader<Cursor<Cow<'a, [u8]>>> { impl<'a> LumpReader<Cursor<Cow<'a, [u8]>>> {
pub fn new(data: Cow<'a, [u8]>) -> Self { pub fn new(data: Cow<'a, [u8]>, lump: LumpType) -> Self {
let length = data.len(); let length = data.len();
let reader = Cursor::new(data); let reader = Cursor::new(data);
LumpReader { LumpReader {
inner: reader, inner: reader,
length, length,
lump,
} }
} }
@ -32,12 +33,14 @@ impl<R: BinReaderExt + Read> LumpReader<R> {
Ok(Entities { entities }) Ok(Entities { entities })
} }
/// Read a list of items with a fixed size
pub fn read_vec<F, T>(&mut self, mut f: F) -> BspResult<Vec<T>> pub fn read_vec<F, T>(&mut self, mut f: F) -> BspResult<Vec<T>>
where where
F: FnMut(&mut LumpReader<R>) -> BspResult<T>, F: FnMut(&mut LumpReader<R>) -> BspResult<T>,
{ {
if self.length % size_of::<T>() != 0 { if self.length % size_of::<T>() != 0 {
return Err(BspError::InvalidLumpSize { return Err(BspError::InvalidLumpSize {
lump: self.lump,
element_size: size_of::<T>(), element_size: size_of::<T>(),
lump_size: self.length, lump_size: self.length,
}); });