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

Derive more traits, fix zero-length visdata

This commit is contained in:
Jef 2019-04-17 11:35:53 +02:00
commit ff124c7f2c

View file

@ -215,9 +215,9 @@ impl<'a> Entity<'a> {
} }
bitflags! { bitflags! {
pub struct SurfFlags: u32 { pub struct SurfaceFlags: u32 {
const NODAMAGE = 0b0000_0000_0000_0000_0001; // Never give falling damage const NODAMAGE = 0b0000_0000_0000_0000_0001; // Never give falling damage
const SLICK = 0b0000_0000_0000_0000_0010; // Effects game physics const SLICK = 0b0000_0000_0000_0000_0010; // Affects game physics
const SKY = 0b0000_0000_0000_0000_0100; // Lighting from environment map const SKY = 0b0000_0000_0000_0000_0100; // Lighting from environment map
const LADDER = 0b0000_0000_0000_0000_1000; // Climbable ladder const LADDER = 0b0000_0000_0000_0000_1000; // Climbable ladder
const NOIMPACT = 0b0000_0000_0000_0001_0000; // Don't make missile explosions const NOIMPACT = 0b0000_0000_0000_0001_0000; // Don't make missile explosions
@ -237,6 +237,12 @@ bitflags! {
} }
} }
impl SurfaceFlags {
pub fn should_draw(&self) -> bool {
!self.intersects(Self::HINT | Self::SKIP | Self::NODRAW | Self::LIGHTFILTER)
}
}
bitflags! { bitflags! {
pub struct ContentFlags: u32 { pub struct ContentFlags: u32 {
// An eye is never valid in a solid // An eye is never valid in a solid
@ -283,7 +289,7 @@ bitflags! {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Texture { pub struct Texture {
pub name: ArrayString<[u8; 64]>, pub name: ArrayString<[u8; 64]>,
pub flags: SurfFlags, pub flags: SurfaceFlags,
pub contents: ContentFlags, pub contents: ContentFlags,
} }
@ -440,7 +446,7 @@ elsize! {
} }
} }
#[derive(Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct VisData { pub struct VisData {
pub n_vecs: u32, // Number of vectors. pub n_vecs: u32, // Number of vectors.
pub sz_vecs: u32, // Size of each vector, in bytes. pub sz_vecs: u32, // Size of each vector, in bytes.
@ -550,7 +556,7 @@ impl<R: Read> BspReader<R> {
fn read_texture(&mut self) -> io::Result<Texture> { fn read_texture(&mut self) -> io::Result<Texture> {
let name = self.read_name()?; let name = self.read_name()?;
let flags = let flags =
SurfFlags::from_bits(self.inner.read_u32::<LittleEndian>()?).ok_or_else(|| { SurfaceFlags::from_bits(self.inner.read_u32::<LittleEndian>()?).ok_or_else(|| {
Error::new( Error::new(
ErrorKind::InvalidData, ErrorKind::InvalidData,
format!("Invalid surface flag in texture: {}", name), format!("Invalid surface flag in texture: {}", name),
@ -872,24 +878,32 @@ impl<R: Read> BspReader<R> {
}) })
} }
fn read_visdata(&mut self) -> io::Result<VisData> { fn read_visdata(&mut self, entry: &DirEntry) -> io::Result<VisData> {
if (entry.length as usize) < std::mem::size_of::<u32>() * 2 {
return Ok(VisData::default());
}
let n_vecs = self.inner.read_u32::<LittleEndian>()?; let n_vecs = self.inner.read_u32::<LittleEndian>()?;
let sz_vecs = self.inner.read_u32::<LittleEndian>()?; let sz_vecs = self.inner.read_u32::<LittleEndian>()?;
let vecs_size = n_vecs as usize * sz_vecs as usize; let vecs_size = n_vecs as u64 * sz_vecs as u64;
let mut vecs = Vec::with_capacity(vecs_size); let mut vecs = Vec::with_capacity(
vecs_size
.try_into()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?,
);
self.inner self.inner
.by_ref() .by_ref()
.take(vecs_size as u64) .take(vecs_size as u64)
.read_to_end(&mut vecs)?; .read_to_end(&mut vecs)?;
if vecs.len() < vecs_size { if (vecs.len() as u64) < vecs_size {
return Err(Error::new( return Err(Error::new(
ErrorKind::InvalidData, ErrorKind::InvalidData,
format!("Unexpected EOF while reading VisData"), format!("Unexpected EOF while reading VisData"),
)); ));
} }
if vecs.len() > vecs_size { if (vecs.len() as u64) > vecs_size {
return Err(Error::new( return Err(Error::new(
ErrorKind::InvalidData, ErrorKind::InvalidData,
format!("Extra data at end of file"), format!("Extra data at end of file"),
@ -1049,7 +1063,11 @@ impl Bsp {
if header != EXPECTED_HEADER || version != EXPECTED_VERSION { if header != EXPECTED_HEADER || version != EXPECTED_VERSION {
return Err(Error::new( return Err(Error::new(
ErrorKind::InvalidData, ErrorKind::InvalidData,
format!("Invalid header or version"), format!(
"Invalid header or version (expected {:?}, got {:?})",
(EXPECTED_HEADER, EXPECTED_VERSION),
(header, version)
),
)); ));
} }
@ -1072,10 +1090,11 @@ impl Bsp {
let faces = reader.read_entry(&dir_entries.faces, |r| r.read_face())?; let faces = reader.read_entry(&dir_entries.faces, |r| r.read_face())?;
let lightmaps = reader.read_entry(&dir_entries.lightmaps, |r| r.read_lightmap())?; let lightmaps = reader.read_entry(&dir_entries.lightmaps, |r| r.read_lightmap())?;
let lightvols = reader.read_entry(&dir_entries.lightvols, |r| r.read_lightvol())?; let lightvols = reader.read_entry(&dir_entries.lightvols, |r| r.read_lightvol())?;
reader reader
.inner .inner
.seek(SeekFrom::Start(dir_entries.visdata.offset as u64))?; .seek(SeekFrom::Start(dir_entries.visdata.offset as u64))?;
let vis_data = reader.read_visdata()?; let vis_data = reader.read_visdata(&dir_entries.visdata)?;
Ok({ Ok({
Bsp { Bsp {
@ -1137,6 +1156,10 @@ impl Bsp {
self.node(0) self.node(0)
} }
pub fn models(&self) -> impl Iterator<Item = Handle<'_, Model>> {
self.models.iter().map(move |m| Handle::new(self, m))
}
pub fn leaf_at(&self, point: [f32; 3]) -> Option<Handle<'_, Leaf>> { pub fn leaf_at(&self, point: [f32; 3]) -> Option<Handle<'_, Leaf>> {
let mut current = self.root_node()?; let mut current = self.root_node()?;
@ -1167,6 +1190,18 @@ impl<'a, T> Handle<'a, T> {
} }
} }
impl<'a> Handle<'a, Model> {
pub fn faces(&self) -> impl Iterator<Item = Handle<'a, Face>> {
let start = self.face as usize;
let end = start + self.num_faces as usize;
let bsp = self.bsp;
bsp.faces[start..end]
.iter()
.map(move |face| Handle::new(bsp, face))
}
}
impl<'a> Handle<'a, Face> { impl<'a> Handle<'a, Face> {
pub fn texture(&self) -> Option<&Texture> { pub fn texture(&self) -> Option<&Texture> {
self.bsp.texture(self.texture as _) self.bsp.texture(self.texture as _)