2026-01-25 09:26:30 -06:00
|
|
|
extern crate alloc;
|
|
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
use alloc::boxed::Box;
|
2026-01-25 09:26:30 -06:00
|
|
|
use alloc::vec::Vec;
|
|
|
|
|
|
2026-02-05 02:42:58 -06:00
|
|
|
use crate::math::Vec3;
|
2026-01-31 09:31:17 -06:00
|
|
|
use crate::pxl8::*;
|
2026-01-25 09:26:30 -06:00
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
pub type Vertex = pxl8_bsp_vertex;
|
|
|
|
|
pub type Edge = pxl8_bsp_edge;
|
|
|
|
|
pub type Face = pxl8_bsp_face;
|
|
|
|
|
pub type Plane = pxl8_bsp_plane;
|
|
|
|
|
pub type Node = pxl8_bsp_node;
|
|
|
|
|
pub type Leaf = pxl8_bsp_leaf;
|
|
|
|
|
pub type Portal = pxl8_bsp_portal;
|
|
|
|
|
pub type CellPortals = pxl8_bsp_cell_portals;
|
|
|
|
|
|
|
|
|
|
impl Default for Edge {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self { vertex: [0, 0] }
|
|
|
|
|
}
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
impl Default for Face {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
first_edge: 0,
|
|
|
|
|
lightmap_offset: 0,
|
|
|
|
|
num_edges: 0,
|
|
|
|
|
plane_id: 0,
|
|
|
|
|
side: 0,
|
|
|
|
|
styles: [0; 4],
|
|
|
|
|
material_id: 0,
|
2026-02-05 02:42:58 -06:00
|
|
|
aabb_min: Vec3::ZERO,
|
|
|
|
|
aabb_max: Vec3::ZERO,
|
2026-01-31 09:31:17 -06:00
|
|
|
}
|
|
|
|
|
}
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
impl Default for Leaf {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
ambient_level: [0; 4],
|
|
|
|
|
contents: 0,
|
|
|
|
|
first_marksurface: 0,
|
|
|
|
|
maxs: [0; 3],
|
|
|
|
|
mins: [0; 3],
|
|
|
|
|
num_marksurfaces: 0,
|
|
|
|
|
visofs: -1,
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
impl Default for Node {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
children: [0, 0],
|
|
|
|
|
first_face: 0,
|
|
|
|
|
maxs: [0; 3],
|
|
|
|
|
mins: [0; 3],
|
|
|
|
|
num_faces: 0,
|
|
|
|
|
plane_id: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
impl Default for Plane {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
dist: 0.0,
|
2026-02-05 02:42:58 -06:00
|
|
|
normal: Vec3::ZERO,
|
2026-01-31 09:31:17 -06:00
|
|
|
type_: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
impl Default for Vertex {
|
|
|
|
|
fn default() -> Self {
|
2026-02-05 02:42:58 -06:00
|
|
|
Self { position: Vec3::ZERO }
|
2026-01-31 09:31:17 -06:00
|
|
|
}
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
impl Default for Portal {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
x0: 0.0,
|
|
|
|
|
z0: 0.0,
|
|
|
|
|
x1: 0.0,
|
|
|
|
|
z1: 0.0,
|
|
|
|
|
target_leaf: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
impl Default for CellPortals {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
portals: [Portal::default(); 4],
|
|
|
|
|
num_portals: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
|
2026-02-02 17:48:25 -06:00
|
|
|
impl Clone for Face {
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
first_edge: self.first_edge,
|
|
|
|
|
lightmap_offset: self.lightmap_offset,
|
|
|
|
|
num_edges: self.num_edges,
|
|
|
|
|
plane_id: self.plane_id,
|
|
|
|
|
side: self.side,
|
|
|
|
|
styles: self.styles,
|
|
|
|
|
material_id: self.material_id,
|
|
|
|
|
aabb_min: self.aabb_min,
|
|
|
|
|
aabb_max: self.aabb_max,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Clone for Plane {
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
dist: self.dist,
|
|
|
|
|
normal: self.normal,
|
|
|
|
|
type_: self.type_,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Clone for Vertex {
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
Self { position: self.position }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-25 09:26:30 -06:00
|
|
|
pub struct Bsp {
|
2026-01-31 09:31:17 -06:00
|
|
|
inner: pxl8_bsp,
|
|
|
|
|
pub cell_portals: Box<[CellPortals]>,
|
|
|
|
|
pub edges: Box<[Edge]>,
|
|
|
|
|
pub faces: Box<[Face]>,
|
|
|
|
|
pub leafs: Box<[Leaf]>,
|
|
|
|
|
pub marksurfaces: Box<[u16]>,
|
|
|
|
|
pub nodes: Box<[Node]>,
|
|
|
|
|
pub planes: Box<[Plane]>,
|
|
|
|
|
pub surfedges: Box<[i32]>,
|
|
|
|
|
pub vertex_lights: Box<[u32]>,
|
|
|
|
|
pub vertices: Box<[Vertex]>,
|
|
|
|
|
pub visdata: Box<[u8]>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
|
pub struct BspBuilder {
|
|
|
|
|
pub cell_portals: Vec<CellPortals>,
|
|
|
|
|
pub edges: Vec<Edge>,
|
|
|
|
|
pub faces: Vec<Face>,
|
|
|
|
|
pub leafs: Vec<Leaf>,
|
2026-01-25 09:26:30 -06:00
|
|
|
pub marksurfaces: Vec<u16>,
|
2026-01-31 09:31:17 -06:00
|
|
|
pub nodes: Vec<Node>,
|
|
|
|
|
pub planes: Vec<Plane>,
|
|
|
|
|
pub surfedges: Vec<i32>,
|
2026-01-25 09:26:30 -06:00
|
|
|
pub vertex_lights: Vec<u32>,
|
2026-01-31 09:31:17 -06:00
|
|
|
pub vertices: Vec<Vertex>,
|
|
|
|
|
pub visdata: Vec<u8>,
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
impl BspBuilder {
|
2026-01-25 09:26:30 -06:00
|
|
|
pub fn new() -> Self {
|
2026-01-31 09:31:17 -06:00
|
|
|
Self::default()
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
2026-01-31 09:31:17 -06:00
|
|
|
}
|
2026-01-25 09:26:30 -06:00
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
impl From<BspBuilder> for Bsp {
|
|
|
|
|
fn from(b: BspBuilder) -> Self {
|
|
|
|
|
let cell_portals = b.cell_portals.into_boxed_slice();
|
|
|
|
|
let edges = b.edges.into_boxed_slice();
|
|
|
|
|
let faces = b.faces.into_boxed_slice();
|
|
|
|
|
let leafs = b.leafs.into_boxed_slice();
|
|
|
|
|
let marksurfaces = b.marksurfaces.into_boxed_slice();
|
|
|
|
|
let nodes = b.nodes.into_boxed_slice();
|
|
|
|
|
let planes = b.planes.into_boxed_slice();
|
|
|
|
|
let surfedges = b.surfedges.into_boxed_slice();
|
|
|
|
|
let vertex_lights = b.vertex_lights.into_boxed_slice();
|
|
|
|
|
let vertices = b.vertices.into_boxed_slice();
|
|
|
|
|
let visdata = b.visdata.into_boxed_slice();
|
|
|
|
|
|
|
|
|
|
let inner = pxl8_bsp {
|
|
|
|
|
cell_portals: if cell_portals.is_empty() { core::ptr::null_mut() } else { cell_portals.as_ptr() as *mut _ },
|
|
|
|
|
edges: if edges.is_empty() { core::ptr::null_mut() } else { edges.as_ptr() as *mut _ },
|
|
|
|
|
faces: if faces.is_empty() { core::ptr::null_mut() } else { faces.as_ptr() as *mut _ },
|
|
|
|
|
leafs: if leafs.is_empty() { core::ptr::null_mut() } else { leafs.as_ptr() as *mut _ },
|
|
|
|
|
lightdata: core::ptr::null_mut(),
|
|
|
|
|
lightmaps: core::ptr::null_mut(),
|
|
|
|
|
marksurfaces: if marksurfaces.is_empty() { core::ptr::null_mut() } else { marksurfaces.as_ptr() as *mut _ },
|
|
|
|
|
models: core::ptr::null_mut(),
|
|
|
|
|
nodes: if nodes.is_empty() { core::ptr::null_mut() } else { nodes.as_ptr() as *mut _ },
|
|
|
|
|
planes: if planes.is_empty() { core::ptr::null_mut() } else { planes.as_ptr() as *mut _ },
|
|
|
|
|
surfedges: if surfedges.is_empty() { core::ptr::null_mut() } else { surfedges.as_ptr() as *mut _ },
|
|
|
|
|
vertex_lights: if vertex_lights.is_empty() { core::ptr::null_mut() } else { vertex_lights.as_ptr() as *mut _ },
|
|
|
|
|
vertices: if vertices.is_empty() { core::ptr::null_mut() } else { vertices.as_ptr() as *mut _ },
|
|
|
|
|
visdata: if visdata.is_empty() { core::ptr::null_mut() } else { visdata.as_ptr() as *mut _ },
|
|
|
|
|
lightdata_size: 0,
|
|
|
|
|
num_cell_portals: cell_portals.len() as u32,
|
|
|
|
|
num_edges: edges.len() as u32,
|
|
|
|
|
num_faces: faces.len() as u32,
|
|
|
|
|
num_leafs: leafs.len() as u32,
|
|
|
|
|
num_lightmaps: 0,
|
|
|
|
|
num_marksurfaces: marksurfaces.len() as u32,
|
|
|
|
|
num_models: 0,
|
|
|
|
|
num_nodes: nodes.len() as u32,
|
|
|
|
|
num_planes: planes.len() as u32,
|
|
|
|
|
num_surfedges: surfedges.len() as u32,
|
|
|
|
|
num_vertex_lights: vertex_lights.len() as u32,
|
|
|
|
|
num_vertices: vertices.len() as u32,
|
|
|
|
|
visdata_size: visdata.len() as u32,
|
|
|
|
|
};
|
2026-01-25 09:26:30 -06:00
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
Self {
|
|
|
|
|
inner,
|
|
|
|
|
cell_portals,
|
|
|
|
|
edges,
|
|
|
|
|
faces,
|
|
|
|
|
leafs,
|
|
|
|
|
marksurfaces,
|
|
|
|
|
nodes,
|
|
|
|
|
planes,
|
|
|
|
|
surfedges,
|
|
|
|
|
vertex_lights,
|
|
|
|
|
vertices,
|
|
|
|
|
visdata,
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
}
|
2026-01-31 09:31:17 -06:00
|
|
|
}
|
2026-01-25 09:26:30 -06:00
|
|
|
|
2026-01-31 09:31:17 -06:00
|
|
|
impl Bsp {
|
|
|
|
|
pub fn as_c_bsp(&self) -> &pxl8_bsp {
|
|
|
|
|
&self.inner
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn trace(&self, from: Vec3, to: Vec3, radius: f32) -> Vec3 {
|
2026-01-31 09:31:17 -06:00
|
|
|
unsafe { pxl8_bsp_trace(&self.inner, from, to, radius) }
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for Bsp {
|
|
|
|
|
fn default() -> Self {
|
2026-01-31 09:31:17 -06:00
|
|
|
BspBuilder::new().into()
|
2026-01-25 09:26:30 -06:00
|
|
|
}
|
|
|
|
|
}
|