mirror of
https://codeberg.org/icewind/vbsp.git
synced 2026-06-03 18:54:05 +02:00
valve bsp wip
This commit is contained in:
parent
dbba7565d8
commit
08a1c53535
6 changed files with 568 additions and 712 deletions
|
|
@ -14,6 +14,10 @@ bitflags = "1.0"
|
||||||
bv = "0.11"
|
bv = "0.11"
|
||||||
byteorder = "0.5"
|
byteorder = "0.5"
|
||||||
itertools = "0.8"
|
itertools = "0.8"
|
||||||
|
thiserror = "1.0"
|
||||||
|
lzma-rs = "0.1.3"
|
||||||
|
binread = "1.0"
|
||||||
|
parse-display = "0.1.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
bench = []
|
bench = []
|
||||||
|
|
|
||||||
13
base.bench
Normal file
13
base.bench
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
running 1 test
|
||||||
|
test tests::random_file ... ignored
|
||||||
|
|
||||||
|
test result: ok. 0 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out
|
||||||
|
|
||||||
|
|
||||||
|
running 2 tests
|
||||||
|
test benches::from_bytes ... bench: 3,231,796 ns/iter (+/- 72,247)
|
||||||
|
test benches::leaf_at ... bench: 92 ns/iter (+/- 3)
|
||||||
|
|
||||||
|
test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out
|
||||||
|
|
||||||
BIN
koth_bagel_rc2a.bsp
Normal file
BIN
koth_bagel_rc2a.bsp
Normal file
Binary file not shown.
149
src/bspfile.rs
Normal file
149
src/bspfile.rs
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
use crate::*;
|
||||||
|
use binread::io::Cursor;
|
||||||
|
use binread::BinReaderExt;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
pub struct BspFile<'a> {
|
||||||
|
data: &'a [u8],
|
||||||
|
directories: Directories,
|
||||||
|
header: Header,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BspFile<'a> {
|
||||||
|
pub fn new(data: &'a [u8]) -> BspResult<Self> {
|
||||||
|
const EXPECTED_HEADER: Header = Header {
|
||||||
|
v: b'V',
|
||||||
|
b: b'B',
|
||||||
|
s: b'S',
|
||||||
|
p: b'P',
|
||||||
|
};
|
||||||
|
// TODO: Use this to decide on the version to parse it as
|
||||||
|
const EXPECTED_VERSION: u32 = 0x14;
|
||||||
|
|
||||||
|
let mut cursor = Cursor::new(data);
|
||||||
|
let header: Header = cursor.read_le()?;
|
||||||
|
let version: u32 = cursor.read_le()?;
|
||||||
|
|
||||||
|
if header != EXPECTED_HEADER || version != EXPECTED_VERSION {
|
||||||
|
return Err(BspError::UnexpectedHeader(header));
|
||||||
|
}
|
||||||
|
|
||||||
|
let directories = cursor.read_le()?;
|
||||||
|
|
||||||
|
let map_version: u32 = cursor.read_le()?;
|
||||||
|
dbg!(map_version);
|
||||||
|
|
||||||
|
Ok(BspFile {
|
||||||
|
data,
|
||||||
|
directories,
|
||||||
|
header,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn directories(&self) -> &Directories {
|
||||||
|
&self.directories
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn header(&self) -> &Header {
|
||||||
|
&self.header
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lump_reader(&self, lump: LumpType) -> BspResult<LumpReader<Cursor<Cow<[u8]>>>> {
|
||||||
|
let data = self.get_lump(lump)?;
|
||||||
|
Ok(LumpReader::new(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_lump(&self, lump: LumpType) -> BspResult<Cow<[u8]>> {
|
||||||
|
let lump = &self.directories[lump];
|
||||||
|
let raw_data = self
|
||||||
|
.data
|
||||||
|
.get(lump.offset as usize..lump.offset as usize + lump.length as usize)
|
||||||
|
.ok_or_else(|| BspError::LumpOutOfBounds(lump.clone()))?;
|
||||||
|
|
||||||
|
Ok(match lump.ident {
|
||||||
|
0 => Cow::Borrowed(raw_data),
|
||||||
|
_ => {
|
||||||
|
let mut data: Vec<u8> = Vec::with_capacity(lump.ident as usize);
|
||||||
|
let mut cursor = Cursor::new(raw_data);
|
||||||
|
lzma_rs::lzma_decompress(&mut cursor, &mut data)
|
||||||
|
.map_err(BspError::LumpDecompressError)?;
|
||||||
|
if data.len() != lump.ident as usize {
|
||||||
|
return Err(BspError::UnexpectedUncompressedLumpSize {
|
||||||
|
got: data.len() as u32,
|
||||||
|
expected: lump.ident,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Cow::Owned(data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub enum LumpType {
|
||||||
|
Entities,
|
||||||
|
Planes,
|
||||||
|
TextureData,
|
||||||
|
Vertices,
|
||||||
|
Visibility,
|
||||||
|
Nodes,
|
||||||
|
TextureInfo,
|
||||||
|
Faces,
|
||||||
|
Lighting,
|
||||||
|
Occlusion,
|
||||||
|
Leaves,
|
||||||
|
FaceIds,
|
||||||
|
Edges,
|
||||||
|
SurfaceEdges,
|
||||||
|
Models,
|
||||||
|
WorldLights,
|
||||||
|
LeafFaces,
|
||||||
|
LeafBrushes,
|
||||||
|
Brushes,
|
||||||
|
BrushSides,
|
||||||
|
Areas,
|
||||||
|
AreaPortals,
|
||||||
|
Unused0,
|
||||||
|
Unused1,
|
||||||
|
Unused2,
|
||||||
|
Unused3,
|
||||||
|
DisplayInfo,
|
||||||
|
OriginalFaces,
|
||||||
|
PhysDisplay,
|
||||||
|
PhysCollide,
|
||||||
|
VertNormals,
|
||||||
|
VertNormalIndices,
|
||||||
|
DisplayLightMapAlphas,
|
||||||
|
DisplayVertices,
|
||||||
|
DisplayLightMapSamplePositions,
|
||||||
|
GameLump,
|
||||||
|
LeafWaterData,
|
||||||
|
Primitives,
|
||||||
|
PrimVertices,
|
||||||
|
PrimIndices,
|
||||||
|
PakFile,
|
||||||
|
ClipPortalVertices,
|
||||||
|
CubeMaps,
|
||||||
|
TextureDataStringData,
|
||||||
|
TextureDataStringTable,
|
||||||
|
Overlays,
|
||||||
|
LeafMinimumDistanceToWater,
|
||||||
|
FaceMacroTextureInfo,
|
||||||
|
DisplayTris,
|
||||||
|
PhysicsCollideSurface,
|
||||||
|
WaterOverlays,
|
||||||
|
LeafAmbientIndexHdr,
|
||||||
|
LeafAmbientIndex,
|
||||||
|
LightingHdr,
|
||||||
|
WorldLightsHdr,
|
||||||
|
LeafAmbientLightingHdr,
|
||||||
|
LeafAmbientLighting,
|
||||||
|
XZipPakFile,
|
||||||
|
FacesHdr,
|
||||||
|
MapFlags,
|
||||||
|
OverlayFades,
|
||||||
|
OverlaySystemLevels,
|
||||||
|
PhysLevel,
|
||||||
|
DisplayMultiBlend,
|
||||||
|
}
|
||||||
927
src/lib.rs
927
src/lib.rs
File diff suppressed because it is too large
Load diff
83
src/reader.rs
Normal file
83
src/reader.rs
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
use crate::*;
|
||||||
|
use binread::BinReaderExt;
|
||||||
|
use bv::BitVec;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::mem::size_of;
|
||||||
|
|
||||||
|
pub struct LumpReader<R> {
|
||||||
|
inner: R,
|
||||||
|
length: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> LumpReader<Cursor<Cow<'a, [u8]>>> {
|
||||||
|
pub fn new(data: Cow<'a, [u8]>) -> Self {
|
||||||
|
let length = data.len();
|
||||||
|
let reader = Cursor::new(data);
|
||||||
|
LumpReader {
|
||||||
|
inner: reader,
|
||||||
|
length,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: BinReaderExt + Read> LumpReader<R> {
|
||||||
|
pub fn read_entities(&mut self) -> BspResult<Entities> {
|
||||||
|
let mut entities = String::with_capacity(self.length);
|
||||||
|
self.inner.read_to_string(&mut entities)?;
|
||||||
|
Ok(Entities { entities })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_vec<F, T>(&mut self, mut f: F) -> BspResult<Vec<T>>
|
||||||
|
where
|
||||||
|
F: FnMut(&mut LumpReader<R>) -> BspResult<T>,
|
||||||
|
{
|
||||||
|
let num_entries = self.length / size_of::<T>();
|
||||||
|
let mut entries = Vec::with_capacity(num_entries);
|
||||||
|
|
||||||
|
for _ in 0..num_entries {
|
||||||
|
entries.push(f(self)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read<T: BinRead>(&mut self) -> BspResult<T> {
|
||||||
|
Ok(self.inner.read_le()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_visdata(&mut self) -> BspResult<VisData> {
|
||||||
|
if (self.length as usize) < std::mem::size_of::<u32>() * 2 {
|
||||||
|
return Ok(VisData::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
let n_vecs = self.inner.read_le()?;
|
||||||
|
let sz_vecs = self.inner.read_le()?;
|
||||||
|
let vecs_size = n_vecs as u64 * sz_vecs as u64;
|
||||||
|
let mut vecs = Vec::with_capacity(
|
||||||
|
vecs_size
|
||||||
|
.try_into()
|
||||||
|
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?,
|
||||||
|
);
|
||||||
|
self.inner
|
||||||
|
.by_ref()
|
||||||
|
.take(vecs_size as u64)
|
||||||
|
.read_to_end(&mut vecs)?;
|
||||||
|
|
||||||
|
if (vecs.len() as u64) < vecs_size {
|
||||||
|
return Err(BspError::UnexpectedEOF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vecs.len() as u64) > vecs_size {
|
||||||
|
return Err(BspError::UnexpectedExtraData);
|
||||||
|
}
|
||||||
|
|
||||||
|
let vecs = BitVec::from_bits(vecs);
|
||||||
|
|
||||||
|
let vis_data = VisData {
|
||||||
|
n_vecs,
|
||||||
|
sz_vecs,
|
||||||
|
vecs,
|
||||||
|
};
|
||||||
|
Ok(vis_data)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue