better lighting
This commit is contained in:
parent
805a2713a3
commit
6ed4e17065
75 changed files with 6417 additions and 3667 deletions
315
pxl8d/src/bsp.rs
315
pxl8d/src/bsp.rs
|
|
@ -1,173 +1,216 @@
|
|||
extern crate alloc;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::math::Vec3;
|
||||
use crate::math::{Vec3, VEC3_ZERO};
|
||||
use crate::pxl8::*;
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct BspVertex {
|
||||
pub position: Vec3,
|
||||
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] }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct BspEdge {
|
||||
pub vertex: [u16; 2],
|
||||
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,
|
||||
aabb_min: VEC3_ZERO,
|
||||
aabb_max: VEC3_ZERO,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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,
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct BspPlane {
|
||||
pub normal: Vec3,
|
||||
pub dist: f32,
|
||||
pub plane_type: i32,
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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,
|
||||
impl Default for Plane {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
dist: 0.0,
|
||||
normal: VEC3_ZERO,
|
||||
type_: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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,
|
||||
impl Default for Vertex {
|
||||
fn default() -> Self {
|
||||
Self { position: VEC3_ZERO }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct BspPortal {
|
||||
pub x0: f32,
|
||||
pub z0: f32,
|
||||
pub x1: f32,
|
||||
pub z1: f32,
|
||||
pub target_leaf: u32,
|
||||
impl Default for Portal {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
x0: 0.0,
|
||||
z0: 0.0,
|
||||
x1: 0.0,
|
||||
z1: 0.0,
|
||||
target_leaf: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct BspCellPortals {
|
||||
pub portals: [BspPortal; 4],
|
||||
pub num_portals: u8,
|
||||
impl Default for CellPortals {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
portals: [Portal::default(); 4],
|
||||
num_portals: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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>,
|
||||
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>,
|
||||
pub marksurfaces: Vec<u16>,
|
||||
pub cell_portals: Vec<BspCellPortals>,
|
||||
pub visdata: Vec<u8>,
|
||||
pub nodes: Vec<Node>,
|
||||
pub planes: Vec<Plane>,
|
||||
pub surfedges: Vec<i32>,
|
||||
pub vertex_lights: Vec<u32>,
|
||||
pub vertices: Vec<Vertex>,
|
||||
pub visdata: Vec<u8>,
|
||||
}
|
||||
|
||||
impl BspBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
Self {
|
||||
inner,
|
||||
cell_portals,
|
||||
edges,
|
||||
faces,
|
||||
leafs,
|
||||
marksurfaces,
|
||||
nodes,
|
||||
planes,
|
||||
surfedges,
|
||||
vertex_lights,
|
||||
vertices,
|
||||
visdata,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 as_c_bsp(&self) -> &pxl8_bsp {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
unsafe { pxl8_bsp_trace(&self.inner, from, to, radius) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Bsp {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
BspBuilder::new().into()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue