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

impl BinRead for Leaves

Read LeafV1 and convert into Leaf
This commit is contained in:
Quaternions 2025-02-17 18:29:01 -08:00 committed by Robin Appelman
commit 08414d9b51
2 changed files with 133 additions and 7 deletions

View file

@ -2,7 +2,12 @@ use std::io::{Read, Seek};
use std::mem::{align_of, size_of}; use std::mem::{align_of, size_of};
use std::ops::Deref; use std::ops::Deref;
use binrw::BinRead; use binrw::{BinRead, BinResult, Endian};
use crate::bspfile::LumpType;
use crate::BspError;
use super::LumpArgs;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Leaves { pub struct Leaves {
@ -36,6 +41,55 @@ impl Leaves {
} }
} }
impl BinRead for Leaves {
type Args<'a> = LumpArgs;
fn read_options<R: Read + Seek>(
reader: &mut R,
endian: Endian,
args: Self::Args<'_>,
) -> BinResult<Self> {
let item_size = match args.version {
1 => size_of::<LeafV1>(),
version => {
return Err(binrw::Error::Custom {
err: Box::new(BspError::LumpVersion(
crate::error::UnsupportedLumpVersion {
lump_type: "leaves",
version: version as u16,
},
)),
pos: reader.stream_position().unwrap(),
})
}
};
if args.length % item_size != 0 {
return Err(binrw::Error::Custom {
err: Box::new(BspError::InvalidLumpSize {
lump: LumpType::Leaves,
element_size: item_size,
lump_size: args.length,
}),
pos: reader.stream_position().unwrap(),
});
}
let num_entries = args.length / item_size;
let mut entries = Vec::with_capacity(num_entries);
for _ in 0..num_entries {
entries.push(Leaf::read_options(
reader,
endian,
LeafArgs {
version: args.version,
},
)?);
}
Ok(Self { leaves: entries })
}
}
struct LeafClusters<'a> { struct LeafClusters<'a> {
leaves: &'a [Leaf], leaves: &'a [Leaf],
index: usize, index: usize,
@ -135,7 +189,56 @@ impl<'a> IntoIterator for &'a mut Leaves {
} }
} }
#[derive(BinRead, Debug, Default, Clone, Copy)]
pub struct ColorRGBExp32 {
pub r: u8,
pub g: u8,
pub b: u8,
pub exponent: i8,
}
#[derive(BinRead, Debug, Default, Clone, Copy)]
pub struct CompressedLightCube {
pub color: [ColorRGBExp32; 6],
}
#[derive(Default, Debug, Clone, BinRead)] #[derive(Default, Debug, Clone, BinRead)]
pub struct LeafV1 {
pub contents: i32,
pub cluster: i16,
pub area_and_flags: i16,
// first 9 bits is area, last 7 bits is flags
pub mins: [i16; 3],
pub maxs: [i16; 3],
pub first_leaf_face: u16,
pub leaf_face_count: u16,
pub first_leaf_brush: u16,
pub leaf_brush_count: u16,
#[br(align_after = align_of::< LeafV1 > ())]
pub leaf_watter_data_id: i16,
}
static_assertions::const_assert_eq!(size_of::<LeafV1>(), 32);
impl From<LeafV1> for Leaf {
fn from(value: LeafV1) -> Self {
Self {
contents: value.contents,
cluster: value.cluster,
area_and_flags: value.area_and_flags,
mins: value.mins,
maxs: value.maxs,
first_leaf_face: value.first_leaf_face,
leaf_face_count: value.leaf_face_count,
first_leaf_brush: value.first_leaf_brush,
leaf_brush_count: value.leaf_brush_count,
leaf_watter_data_id: value.leaf_watter_data_id,
cube: Default::default(),
}
}
}
#[derive(Default, Debug, Clone)]
pub struct Leaf { pub struct Leaf {
pub contents: i32, pub contents: i32,
pub cluster: i16, pub cluster: i16,
@ -147,13 +250,39 @@ pub struct Leaf {
pub leaf_face_count: u16, pub leaf_face_count: u16,
pub first_leaf_brush: u16, pub first_leaf_brush: u16,
pub leaf_brush_count: u16, pub leaf_brush_count: u16,
#[br(align_after = align_of::< Leaf > ())]
pub leaf_watter_data_id: i16, pub leaf_watter_data_id: i16,
pub cube: CompressedLightCube,
} }
static_assertions::const_assert_eq!(size_of::<Leaf>(), 32); static_assertions::const_assert_eq!(size_of::<Leaf>(), 56);
#[test] #[test]
fn test_leaf_bytes() { fn test_leaf_bytes() {
super::test_read_bytes::<Leaf>(); super::test_read_bytes::<Leaf>();
} }
#[derive(Default, Debug, Clone)]
pub struct LeafArgs {
pub version: u32,
}
impl BinRead for Leaf {
type Args<'a> = LeafArgs;
fn read_options<R: Read + Seek>(
reader: &mut R,
endian: Endian,
args: Self::Args<'_>,
) -> BinResult<Self> {
match args.version {
1 => LeafV1::read_options(reader, endian, ()).map(Leaf::from),
version => Err(binrw::Error::Custom {
err: Box::new(crate::error::UnsupportedLumpVersion {
lump_type: "leaves",
version: version as u16,
}),
pos: reader.stream_position().unwrap(),
}),
}
}
}

View file

@ -81,10 +81,7 @@ impl Bsp {
let nodes = bsp_file let nodes = bsp_file
.lump_reader(LumpType::Nodes)? .lump_reader(LumpType::Nodes)?
.read_vec(|r| r.read())?; .read_vec(|r| r.read())?;
let leaves = bsp_file let leaves = bsp_file.lump_reader(LumpType::Leaves)?.read_args()?;
.lump_reader(LumpType::Leaves)?
.read_vec(|r| r.read())?
.into();
let leaf_faces = bsp_file let leaf_faces = bsp_file
.lump_reader(LumpType::LeafFaces)? .lump_reader(LumpType::LeafFaces)?
.read_vec(|r| r.read())?; .read_vec(|r| r.read())?;