173 lines
4.1 KiB
Rust
173 lines
4.1 KiB
Rust
extern crate alloc;
|
|
|
|
use alloc::vec::Vec;
|
|
|
|
use crate::math::Vec3;
|
|
|
|
#[derive(Clone, Copy, Default)]
|
|
pub struct BspVertex {
|
|
pub position: Vec3,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Default)]
|
|
pub struct BspEdge {
|
|
pub vertex: [u16; 2],
|
|
}
|
|
|
|
#[derive(Clone, Copy, Default)]
|
|
pub struct BspFace {
|
|
pub first_edge: u32,
|
|
pub lightmap_offset: u32,
|
|
pub num_edges: u16,
|
|
pub plane_id: u16,
|
|
pub side: u16,
|
|
pub styles: [u8; 4],
|
|
pub material_id: u16,
|
|
pub aabb_min: Vec3,
|
|
pub aabb_max: Vec3,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Default)]
|
|
pub struct BspPlane {
|
|
pub normal: Vec3,
|
|
pub dist: f32,
|
|
pub plane_type: i32,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Default)]
|
|
pub struct BspNode {
|
|
pub children: [i32; 2],
|
|
pub first_face: u16,
|
|
pub maxs: [i16; 3],
|
|
pub mins: [i16; 3],
|
|
pub num_faces: u16,
|
|
pub plane_id: u32,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Default)]
|
|
pub struct BspLeaf {
|
|
pub ambient_level: [u8; 4],
|
|
pub contents: i32,
|
|
pub first_marksurface: u16,
|
|
pub maxs: [i16; 3],
|
|
pub mins: [i16; 3],
|
|
pub num_marksurfaces: u16,
|
|
pub visofs: i32,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Default)]
|
|
pub struct BspPortal {
|
|
pub x0: f32,
|
|
pub z0: f32,
|
|
pub x1: f32,
|
|
pub z1: f32,
|
|
pub target_leaf: u32,
|
|
}
|
|
|
|
#[derive(Clone, Default)]
|
|
pub struct BspCellPortals {
|
|
pub portals: [BspPortal; 4],
|
|
pub num_portals: u8,
|
|
}
|
|
|
|
pub struct Bsp {
|
|
pub vertices: Vec<BspVertex>,
|
|
pub edges: Vec<BspEdge>,
|
|
pub surfedges: Vec<i32>,
|
|
pub planes: Vec<BspPlane>,
|
|
pub faces: Vec<BspFace>,
|
|
pub nodes: Vec<BspNode>,
|
|
pub leafs: Vec<BspLeaf>,
|
|
pub marksurfaces: Vec<u16>,
|
|
pub cell_portals: Vec<BspCellPortals>,
|
|
pub visdata: Vec<u8>,
|
|
pub vertex_lights: Vec<u32>,
|
|
}
|
|
|
|
impl Bsp {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
vertices: Vec::new(),
|
|
edges: Vec::new(),
|
|
surfedges: Vec::new(),
|
|
planes: Vec::new(),
|
|
faces: Vec::new(),
|
|
nodes: Vec::new(),
|
|
leafs: Vec::new(),
|
|
marksurfaces: Vec::new(),
|
|
cell_portals: Vec::new(),
|
|
visdata: Vec::new(),
|
|
vertex_lights: Vec::new(),
|
|
}
|
|
}
|
|
|
|
pub fn find_leaf(&self, pos: Vec3) -> i32 {
|
|
if self.nodes.is_empty() {
|
|
return -1;
|
|
}
|
|
|
|
let mut node_id: i32 = 0;
|
|
|
|
while node_id >= 0 {
|
|
let node = &self.nodes[node_id as usize];
|
|
let plane = &self.planes[node.plane_id as usize];
|
|
|
|
let dist = pos.dot(plane.normal) - plane.dist;
|
|
node_id = node.children[if dist < 0.0 { 1 } else { 0 }];
|
|
}
|
|
|
|
-(node_id + 1)
|
|
}
|
|
|
|
pub fn point_solid(&self, pos: Vec3) -> bool {
|
|
let leaf = self.find_leaf(pos);
|
|
if leaf < 0 || leaf as usize >= self.leafs.len() {
|
|
return true;
|
|
}
|
|
self.leafs[leaf as usize].contents == -1
|
|
}
|
|
|
|
fn point_clear(&self, x: f32, y: f32, z: f32, radius: f32) -> bool {
|
|
if self.point_solid(Vec3::new(x, y, z)) { return false; }
|
|
if self.point_solid(Vec3::new(x + radius, y, z)) { return false; }
|
|
if self.point_solid(Vec3::new(x - radius, y, z)) { return false; }
|
|
if self.point_solid(Vec3::new(x, y, z + radius)) { return false; }
|
|
if self.point_solid(Vec3::new(x, y, z - radius)) { return false; }
|
|
true
|
|
}
|
|
|
|
pub fn trace(&self, from: Vec3, to: Vec3, radius: f32) -> Vec3 {
|
|
if self.nodes.is_empty() {
|
|
return to;
|
|
}
|
|
|
|
if self.point_clear(to.x, to.y, to.z, radius) {
|
|
return to;
|
|
}
|
|
|
|
let x_ok = self.point_clear(to.x, from.y, from.z, radius);
|
|
let z_ok = self.point_clear(from.x, from.y, to.z, radius);
|
|
|
|
if x_ok && z_ok {
|
|
let dx = to.x - from.x;
|
|
let dz = to.z - from.z;
|
|
if dx * dx > dz * dz {
|
|
Vec3::new(to.x, from.y, from.z)
|
|
} else {
|
|
Vec3::new(from.x, from.y, to.z)
|
|
}
|
|
} else if x_ok {
|
|
Vec3::new(to.x, from.y, from.z)
|
|
} else if z_ok {
|
|
Vec3::new(from.x, from.y, to.z)
|
|
} else {
|
|
from
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for Bsp {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|