mirror of
https://codeberg.org/icewind/vbsp.git
synced 2026-06-03 18:54:05 +02:00
Merge pull request #14 from krakow10/version19
Add LeafV0 + Leaves Version Decoding
This commit is contained in:
commit
ebc4e8b3ed
5 changed files with 359 additions and 171 deletions
|
|
@ -34,12 +34,16 @@ 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 entry = self.get_lump_entry(lump);
|
||||||
Ok(LumpReader::new(data, lump))
|
let data = self.get_lump(entry)?;
|
||||||
|
Ok(LumpReader::new(data, lump, entry.version))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_lump(&self, lump: LumpType) -> BspResult<Cow<[u8]>> {
|
pub fn get_lump_entry(&self, lump: LumpType) -> &LumpEntry {
|
||||||
let lump = &self.directories[lump];
|
&self.directories[lump]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_lump(&self, lump: &LumpEntry) -> BspResult<Cow<[u8]>> {
|
||||||
let raw_data = self
|
let raw_data = self
|
||||||
.data
|
.data
|
||||||
.get(lump.offset as usize..lump.offset as usize + lump.length as usize)
|
.get(lump.offset as usize..lump.offset as usize + lump.length as usize)
|
||||||
|
|
|
||||||
327
src/data/leaves.rs
Normal file
327
src/data/leaves.rs
Normal file
|
|
@ -0,0 +1,327 @@
|
||||||
|
use std::io::{Read, Seek};
|
||||||
|
use std::mem::{align_of, size_of};
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use binrw::{BinRead, BinResult, Endian};
|
||||||
|
|
||||||
|
use crate::bspfile::LumpType;
|
||||||
|
use crate::BspError;
|
||||||
|
|
||||||
|
use super::LumpArgs;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Leaves {
|
||||||
|
leaves: Vec<Leaf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Leaves {
|
||||||
|
pub fn new(mut leaves: Vec<Leaf>) -> Self {
|
||||||
|
leaves.sort_unstable_by_key(|leaf| leaf.cluster);
|
||||||
|
|
||||||
|
Leaves { leaves }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> impl Iterator<Item = &Leaf> {
|
||||||
|
self.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Leaf> {
|
||||||
|
self.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_inner(self) -> Vec<Leaf> {
|
||||||
|
self.leaves
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clusters(&self) -> impl Iterator<Item = impl Iterator<Item = &Leaf>> {
|
||||||
|
LeafClusters {
|
||||||
|
leaves: &self.leaves,
|
||||||
|
index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
0 => size_of::<LeafV0>(),
|
||||||
|
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> {
|
||||||
|
leaves: &'a [Leaf],
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for LeafClusters<'a> {
|
||||||
|
type Item = <&'a [Leaf] as IntoIterator>::IntoIter;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let cluster = self.leaves.get(self.index)?.cluster;
|
||||||
|
let remaining_leaves = self.leaves.get(self.index..)?;
|
||||||
|
let cluster_size = remaining_leaves
|
||||||
|
.iter()
|
||||||
|
.take_while(|leaf| leaf.cluster == cluster)
|
||||||
|
.count();
|
||||||
|
self.index += cluster_size;
|
||||||
|
Some(remaining_leaves[0..cluster_size].iter())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_leaf_clusters() {
|
||||||
|
let leaves: Leaves = vec![
|
||||||
|
Leaf {
|
||||||
|
contents: 0,
|
||||||
|
cluster: 0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Leaf {
|
||||||
|
contents: 1,
|
||||||
|
cluster: 0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Leaf {
|
||||||
|
contents: 2,
|
||||||
|
cluster: 1,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Leaf {
|
||||||
|
contents: 3,
|
||||||
|
cluster: 2,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Leaf {
|
||||||
|
contents: 4,
|
||||||
|
cluster: 2,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
]
|
||||||
|
.into();
|
||||||
|
|
||||||
|
let clustered: Vec<Vec<i32>> = leaves
|
||||||
|
.clusters()
|
||||||
|
.map(|cluster| cluster.map(|leaf| leaf.contents).collect())
|
||||||
|
.collect();
|
||||||
|
assert_eq!(vec![vec![0, 1], vec![2], vec![3, 4]], clustered);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<Leaf>> for Leaves {
|
||||||
|
fn from(other: Vec<Leaf>) -> Self {
|
||||||
|
Self::new(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Leaves {
|
||||||
|
type Target = [Leaf];
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.leaves
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for Leaves {
|
||||||
|
type Item = Leaf;
|
||||||
|
type IntoIter = <Vec<Leaf> as IntoIterator>::IntoIter;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.leaves.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a Leaves {
|
||||||
|
type Item = &'a Leaf;
|
||||||
|
type IntoIter = <&'a [Leaf] as IntoIterator>::IntoIter;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.leaves[..].iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a mut Leaves {
|
||||||
|
type Item = &'a mut Leaf;
|
||||||
|
type IntoIter = <&'a mut [Leaf] as IntoIterator>::IntoIter;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.leaves.iter_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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)]
|
||||||
|
pub struct LeafV0 {
|
||||||
|
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,
|
||||||
|
pub leaf_watter_data_id: i16,
|
||||||
|
#[br(align_after = align_of::< LeafV0 > ())]
|
||||||
|
pub cube: CompressedLightCube,
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assertions::const_assert_eq!(size_of::<LeafV0>(), 56);
|
||||||
|
|
||||||
|
impl From<LeafV0> for Leaf {
|
||||||
|
fn from(value: LeafV0) -> 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: value.cube,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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 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,
|
||||||
|
pub leaf_watter_data_id: i16,
|
||||||
|
pub cube: CompressedLightCube,
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assertions::const_assert_eq!(size_of::<Leaf>(), 56);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_leaf_bytes() {
|
||||||
|
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 {
|
||||||
|
0 => LeafV0::read_options(reader, endian, ()).map(Leaf::from),
|
||||||
|
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(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
mod displacement;
|
mod displacement;
|
||||||
mod entity;
|
mod entity;
|
||||||
mod game;
|
mod game;
|
||||||
|
mod leaves;
|
||||||
mod prop;
|
mod prop;
|
||||||
mod vector;
|
mod vector;
|
||||||
|
|
||||||
pub use self::displacement::*;
|
pub use self::displacement::*;
|
||||||
pub use self::entity::*;
|
pub use self::entity::*;
|
||||||
pub use self::game::*;
|
pub use self::game::*;
|
||||||
|
pub use self::leaves::*;
|
||||||
pub use self::prop::PropPlacement;
|
pub use self::prop::PropPlacement;
|
||||||
pub use self::vector::*;
|
pub use self::vector::*;
|
||||||
use crate::bspfile::LumpType;
|
use crate::bspfile::LumpType;
|
||||||
|
|
@ -26,7 +28,7 @@ use std::cmp::min;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use std::io::{Cursor, Read, Seek};
|
use std::io::{Cursor, Read, Seek};
|
||||||
use std::mem::{align_of, size_of};
|
use std::mem::size_of;
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
@ -83,6 +85,12 @@ pub struct Header {
|
||||||
pub version: BspVersion,
|
pub version: BspVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
|
pub struct LumpArgs {
|
||||||
|
pub length: usize,
|
||||||
|
pub version: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, BinRead)]
|
#[derive(Clone, Copy, Debug, Default, BinRead)]
|
||||||
#[br(little)]
|
#[br(little)]
|
||||||
pub struct LumpEntry {
|
pub struct LumpEntry {
|
||||||
|
|
@ -225,29 +233,6 @@ pub struct Node {
|
||||||
|
|
||||||
static_assertions::const_assert_eq!(size_of::<Node>(), 32);
|
static_assertions::const_assert_eq!(size_of::<Node>(), 32);
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, BinRead)]
|
|
||||||
pub struct Leaf {
|
|
||||||
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::< Leaf > ())]
|
|
||||||
pub leaf_watter_data_id: i16,
|
|
||||||
}
|
|
||||||
|
|
||||||
static_assertions::const_assert_eq!(size_of::<Leaf>(), 32);
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_leaf_bytes() {
|
|
||||||
test_read_bytes::<Leaf>();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, BinRead)]
|
#[derive(Debug, Clone, BinRead)]
|
||||||
pub struct LeafBrush {
|
pub struct LeafBrush {
|
||||||
pub brush: u16,
|
pub brush: u16,
|
||||||
|
|
|
||||||
140
src/lib.rs
140
src/lib.rs
|
|
@ -17,141 +17,10 @@ pub use error::{BspError, StringError};
|
||||||
use lzma_rs::decompress::{Options, UnpackedSize};
|
use lzma_rs::decompress::{Options, UnpackedSize};
|
||||||
use reader::LumpReader;
|
use reader::LumpReader;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::{io::Read, ops::Deref};
|
use std::io::Read;
|
||||||
|
|
||||||
pub type BspResult<T> = Result<T, BspError>;
|
pub type BspResult<T> = Result<T, BspError>;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Leaves {
|
|
||||||
leaves: Vec<Leaf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Leaves {
|
|
||||||
pub fn new(mut leaves: Vec<Leaf>) -> Self {
|
|
||||||
leaves.sort_unstable_by_key(|leaf| leaf.cluster);
|
|
||||||
|
|
||||||
Leaves { leaves }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = &Leaf> {
|
|
||||||
self.into_iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Leaf> {
|
|
||||||
self.into_iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_inner(self) -> Vec<Leaf> {
|
|
||||||
self.leaves
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clusters(&self) -> impl Iterator<Item = impl Iterator<Item = &Leaf>> {
|
|
||||||
LeafClusters {
|
|
||||||
leaves: &self.leaves,
|
|
||||||
index: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LeafClusters<'a> {
|
|
||||||
leaves: &'a [Leaf],
|
|
||||||
index: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for LeafClusters<'a> {
|
|
||||||
type Item = <&'a [Leaf] as IntoIterator>::IntoIter;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
let cluster = self.leaves.get(self.index)?.cluster;
|
|
||||||
let remaining_leaves = self.leaves.get(self.index..)?;
|
|
||||||
let cluster_size = remaining_leaves
|
|
||||||
.iter()
|
|
||||||
.take_while(|leaf| leaf.cluster == cluster)
|
|
||||||
.count();
|
|
||||||
self.index += cluster_size;
|
|
||||||
Some(remaining_leaves[0..cluster_size].iter())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_leaf_clusters() {
|
|
||||||
let leaves: Leaves = vec![
|
|
||||||
Leaf {
|
|
||||||
contents: 0,
|
|
||||||
cluster: 0,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Leaf {
|
|
||||||
contents: 1,
|
|
||||||
cluster: 0,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Leaf {
|
|
||||||
contents: 2,
|
|
||||||
cluster: 1,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Leaf {
|
|
||||||
contents: 3,
|
|
||||||
cluster: 2,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Leaf {
|
|
||||||
contents: 4,
|
|
||||||
cluster: 2,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
]
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let clustered: Vec<Vec<i32>> = leaves
|
|
||||||
.clusters()
|
|
||||||
.map(|cluster| cluster.map(|leaf| leaf.contents).collect())
|
|
||||||
.collect();
|
|
||||||
assert_eq!(vec![vec![0, 1], vec![2], vec![3, 4]], clustered);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Vec<Leaf>> for Leaves {
|
|
||||||
fn from(other: Vec<Leaf>) -> Self {
|
|
||||||
Self::new(other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for Leaves {
|
|
||||||
type Target = [Leaf];
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.leaves
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoIterator for Leaves {
|
|
||||||
type Item = Leaf;
|
|
||||||
type IntoIter = <Vec<Leaf> as IntoIterator>::IntoIter;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
self.leaves.into_iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> IntoIterator for &'a Leaves {
|
|
||||||
type Item = &'a Leaf;
|
|
||||||
type IntoIter = <&'a [Leaf] as IntoIterator>::IntoIter;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
self.leaves[..].iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> IntoIterator for &'a mut Leaves {
|
|
||||||
type Item = &'a mut Leaf;
|
|
||||||
type IntoIter = <&'a mut [Leaf] as IntoIterator>::IntoIter;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
self.leaves.iter_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Store all the allocated objects inline to improve cache usage
|
// TODO: Store all the allocated objects inline to improve cache usage
|
||||||
/// A parsed bsp file
|
/// A parsed bsp file
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -202,7 +71,7 @@ impl Bsp {
|
||||||
.read_vec(|r| r.read())?;
|
.read_vec(|r| r.read())?;
|
||||||
let texture_string_data = String::from_utf8(
|
let texture_string_data = String::from_utf8(
|
||||||
bsp_file
|
bsp_file
|
||||||
.get_lump(LumpType::TextureDataStringData)?
|
.get_lump(bsp_file.get_lump_entry(LumpType::TextureDataStringData))?
|
||||||
.into_owned(),
|
.into_owned(),
|
||||||
)
|
)
|
||||||
.map_err(|e| BspError::String(StringError::NonUTF8(e.utf8_error())))?;
|
.map_err(|e| BspError::String(StringError::NonUTF8(e.utf8_error())))?;
|
||||||
|
|
@ -212,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())?;
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,18 @@ pub struct LumpReader<R> {
|
||||||
inner: R,
|
inner: R,
|
||||||
length: usize,
|
length: usize,
|
||||||
lump: LumpType,
|
lump: LumpType,
|
||||||
|
version: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LumpReader<Cursor<Cow<'a, [u8]>>> {
|
impl<'a> LumpReader<Cursor<Cow<'a, [u8]>>> {
|
||||||
pub fn new(data: Cow<'a, [u8]>, lump: LumpType) -> Self {
|
pub fn new(data: Cow<'a, [u8]>, lump: LumpType, version: u32) -> 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,
|
lump,
|
||||||
|
version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,11 +60,7 @@ impl<R: BinReaderExt + Read> LumpReader<R> {
|
||||||
Ok(entries)
|
Ok(entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<T: BinRead + Debug>(&mut self) -> BspResult<T>
|
pub fn read<'a, T: BinRead<Args<'a> = ()> + Debug>(&mut self) -> BspResult<T> {
|
||||||
where
|
|
||||||
T::Args<'static>: Default,
|
|
||||||
<T as BinRead>::Args<'static>: Clone,
|
|
||||||
{
|
|
||||||
// let start = self.inner.stream_position().unwrap() as usize;
|
// let start = self.inner.stream_position().unwrap() as usize;
|
||||||
let result = self.inner.read_le()?;
|
let result = self.inner.read_le()?;
|
||||||
// let end = self.inner.stream_position().unwrap() as usize;
|
// let end = self.inner.stream_position().unwrap() as usize;
|
||||||
|
|
@ -76,6 +74,14 @@ impl<R: BinReaderExt + Read> LumpReader<R> {
|
||||||
// );
|
// );
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
pub fn read_args<'a, T: BinRead<Args<'a> = LumpArgs> + Debug>(&mut self) -> BspResult<T> {
|
||||||
|
let args = LumpArgs {
|
||||||
|
length: self.length,
|
||||||
|
version: self.version,
|
||||||
|
};
|
||||||
|
let result = T::read_options(&mut self.inner, binrw::Endian::Little, args)?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read_visdata(&mut self) -> BspResult<VisData> {
|
pub fn read_visdata(&mut self) -> BspResult<VisData> {
|
||||||
if self.length < size_of::<u32>() * 2 {
|
if self.length < size_of::<u32>() * 2 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue