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:
parent
96b42c80bf
commit
ff124c7f2c
1 changed files with 47 additions and 12 deletions
59
src/lib.rs
59
src/lib.rs
|
|
@ -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 _)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue