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, pub edges: Vec, pub surfedges: Vec, pub planes: Vec, pub faces: Vec, pub nodes: Vec, pub leafs: Vec, pub marksurfaces: Vec, pub cell_portals: Vec, pub visdata: Vec, pub vertex_lights: Vec, } 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() } }