Skip to main content

stockton_bsp/
lib.rs

1// Copyright (C) 2019 Oscar Shrimpton
2//
3// This file is part of stockton-bsp.
4//
5// stockton-bsp is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// stockton-bsp is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with stockton-bsp.  If not, see <http://www.gnu.org/licenses/>.
17
18#[macro_use]
19extern crate bitflags;
20extern crate bit_vec;
21extern crate nalgebra as na;
22
23#[macro_use]
24mod macros;
25pub mod directory;
26pub mod lumps;
27pub mod types;
28
29use lumps::*;
30use directory::Header;
31use types::{Error, Result};
32
33/// Represents a parsed BSP file.
34#[derive(Debug, Clone)]
35pub struct BSPFile {
36    pub directory: Header,
37    pub entities: EntitiesLump,
38    pub textures: TexturesLump,
39    pub planes: PlanesLump,
40    pub light_vols: LightVolsLump,
41    pub brushes: BrushesLump,
42    pub vertices: VerticesLump,
43    pub meshverts: MeshVertsLump,
44    pub light_maps: LightMapsLump,
45    pub effects: EffectsLump,
46    pub faces: FaceLump,
47    pub tree: BSPTree,
48    pub visdata: VisDataLump,
49    pub models: ModelsLump,
50
51    /// Only present for Quake live maps (IBSP47)
52    pub advertisements: Option<AdvertisementsLump>
53}
54
55impl BSPFile {
56    /// Try to parse the given buffer as a BSP file
57    pub fn from_buffer(buf: Box<[u8]>) -> Result<BSPFile> {
58        let header = Header::from(&buf)?;
59
60        match header.version {
61            // Quake 3 or Quake LIVE (IBSP47)
62            0x2e | 0x2f => {
63                let entities = EntitiesLump::from_lump(header.get_lump(&buf, 0))?;
64                let textures = TexturesLump::from_lump(header.get_lump(&buf, 1))?;
65                let planes = PlanesLump::from_lump(header.get_lump(&buf, 2))?;
66                let vertices = VerticesLump::from_lump(header.get_lump(&buf, 10))?;
67                let meshverts = MeshVertsLump::from_lump(header.get_lump(&buf, 11))?;
68                let light_maps = LightMapsLump::from_lump(header.get_lump(&buf, 14))?;
69                let light_vols = LightVolsLump::from_lump(header.get_lump(&buf, 15))?;
70                let visdata = VisDataLump::from_lump(header.get_lump(&buf, 16))?;
71                let brushes = BrushesLump::from_lump(
72                    header.get_lump(&buf, 8),
73                    header.get_lump(&buf, 9),
74                    &textures,
75                    &planes
76                )?;
77                let effects = EffectsLump::from_lump(header.get_lump(&buf, 12), &brushes)?;
78                let faces = FaceLump::from_lump(
79                    header.get_lump(&buf, 13),
80                    &textures,
81                    &effects,
82                    &vertices,
83                    &meshverts,
84                    &light_maps,
85                )?;
86                let tree = BSPTree::from_lumps(
87                    header.get_lump(&buf, 3),
88                    header.get_lump(&buf, 4),
89                    header.get_lump(&buf, 5),
90                    header.get_lump(&buf, 6),
91                    &faces,
92                    &brushes,
93                )?;
94
95                let models = ModelsLump::from_lump(header.get_lump(&buf, 7), &faces, &brushes)?;
96
97                // Quake Live has an advertisements lump
98                let advertisements = if header.version == 0x2f {
99                    Some(AdvertisementsLump::from_lump(header.get_lump(&buf, 17))?)
100                } else {
101                    None
102                };
103
104                Ok(BSPFile {
105                    directory: header,
106                    entities,
107                    textures,
108                    planes,
109                    light_vols,
110                    light_maps,
111                    vertices,
112                    meshverts,
113                    visdata,
114                    advertisements,
115                    brushes,
116                    effects,
117                    faces,
118                    tree,
119                    models
120                })
121            }
122            _ => Err(Error::Unsupported {
123                version: header.version,
124            }),
125        }
126    }
127}