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

more validation

This commit is contained in:
Robin Appelman 2022-02-21 22:33:24 +01:00
commit aeb8c1011d
4 changed files with 72 additions and 27 deletions

View file

@ -76,6 +76,8 @@ pub enum ValidationError {
index: i64, index: i64,
size: usize, size: usize,
}, },
#[error("bsp contains no root node")]
NoRootNode,
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]

View file

@ -3,7 +3,7 @@ use crate::data::*;
impl<'a> Handle<'a, Face> { impl<'a> Handle<'a, Face> {
/// Get the texture of the face /// Get the texture of the face
pub fn texture(&self) -> Option<Handle<TextureInfo>> { pub fn texture(&self) -> Handle<TextureInfo> {
self.bsp self.bsp
.textures_info .textures_info
.get(self.texture_info as usize) .get(self.texture_info as usize)
@ -11,6 +11,7 @@ impl<'a> Handle<'a, Face> {
bsp: self.bsp, bsp: self.bsp,
data: texture_info, data: texture_info,
}) })
.unwrap()
} }
/// Get all vertices making up the face /// Get all vertices making up the face
@ -44,8 +45,7 @@ impl<'a> Handle<'a, Face> {
/// Check if the face is flagged as visible /// Check if the face is flagged as visible
pub fn is_visible(&self) -> bool { pub fn is_visible(&self) -> bool {
self.texture() let texture = self.texture();
.map(|texture| {
!texture.flags.intersects( !texture.flags.intersects(
TextureFlags::LIGHT TextureFlags::LIGHT
| TextureFlags::SKY2D | TextureFlags::SKY2D
@ -57,8 +57,6 @@ impl<'a> Handle<'a, Face> {
| TextureFlags::NODRAW | TextureFlags::NODRAW
| TextureFlags::HITBOX, | TextureFlags::HITBOX,
) )
})
.unwrap_or_default()
} }
/// Triangulate the face /// Triangulate the face

View file

@ -56,17 +56,20 @@ impl<'a> Handle<'a, Model> {
impl<'a> Handle<'a, TextureInfo> { impl<'a> Handle<'a, TextureInfo> {
/// Get the texture data references by the texture /// Get the texture data references by the texture
pub fn texture(&self) -> Option<&TextureData> { pub fn texture(&self) -> Handle<'a, TextureData> {
self.bsp let texture = self
.bsp
.textures_data .textures_data
.get(self.data.texture_data_index as usize) .get(self.data.texture_data_index as usize)
.unwrap();
Handle::new(self.bsp, texture)
} }
} }
impl Handle<'_, Node> { impl Handle<'_, Node> {
/// Get the plane splitting this node /// Get the plane splitting this node
pub fn plane(&self) -> Option<Handle<'_, Plane>> { pub fn plane(&self) -> Handle<'_, Plane> {
self.bsp.plane(self.plane_index as _) self.bsp.plane(self.plane_index as _).unwrap()
} }
} }

View file

@ -295,8 +295,8 @@ impl Bsp {
} }
/// Get the root node of the bsp /// Get the root node of the bsp
pub fn root_node(&self) -> Option<Handle<'_, Node>> { pub fn root_node(&self) -> Handle<'_, Node> {
self.node(0) self.node(0).unwrap()
} }
/// Get all models stored in the bsp /// Get all models stored in the bsp
@ -305,11 +305,11 @@ impl Bsp {
} }
/// Find a leaf for a specific position /// Find a leaf for a specific position
pub fn leaf_at(&self, point: Vector) -> Option<Handle<'_, Leaf>> { pub fn leaf_at(&self, point: Vector) -> Handle<'_, Leaf> {
let mut current = self.root_node()?; let mut current = self.root_node();
loop { loop {
let plane = current.plane()?; let plane = current.plane();
let dot: f32 = point let dot: f32 = point
.iter() .iter()
.zip(plane.normal.iter()) .zip(plane.normal.iter())
@ -321,9 +321,9 @@ impl Bsp {
let next = if dot < plane.dist { back } else { front }; let next = if dot < plane.dist { back } else { front };
if next < 0 { if next < 0 {
return self.leaf((!next) as usize); return self.leaf((!next) as usize).unwrap();
} else { } else {
current = self.node(next as usize)?; current = self.node(next as usize).unwrap();
} }
} }
} }
@ -391,6 +391,48 @@ impl Bsp {
"displacement", "displacement",
"displacement", "displacement",
)?; )?;
self.validate_indexes(
self.faces.iter().map(|face| face.texture_info),
&self.textures_info,
"face",
"texture_info",
)?;
self.validate_indexes(
self.textures_info
.iter()
.map(|texture| texture.texture_data_index),
&self.textures_data,
"texture_info",
"texture_data",
)?;
self.validate_indexes(
self.nodes.iter().map(|node| node.plane_index),
&self.planes,
"node",
"plane",
)?;
self.validate_indexes(
self.nodes
.iter()
.flat_map(|node| node.children)
.filter_map(|index| (index >= 0).then(|| index)),
&self.nodes,
"node",
"node",
)?;
self.validate_indexes(
self.nodes
.iter()
.flat_map(|node| node.children)
.filter_map(|index| (index < 0).then(|| !index)),
&self.leaves,
"node",
"leaf",
)?;
if self.nodes.is_empty() {
return Err(ValidationError::NoRootNode.into());
}
Ok(()) Ok(())
} }