use alloc::boxed::Box; use alloc::vec::Vec; use crate::math::Vec3; use crate::bindings::*; pub type Vertex = demo3d_bsp_vertex; pub type Edge = demo3d_bsp_edge; pub type Face = demo3d_bsp_face; pub type Plane = demo3d_bsp_plane; pub type Node = demo3d_bsp_node; pub type Leaf = demo3d_bsp_leaf; pub type Portal = demo3d_bsp_portal; pub type CellPortals = demo3d_bsp_cell_portals; impl Default for Edge { fn default() -> Self { Self { vertex: [0, 0] } } } 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, } } } 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, } } } 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, } } } impl Default for Plane { fn default() -> Self { Self { dist: 0.0, normal: Vec3::ZERO, type_: 0, } } } impl Default for Vertex { fn default() -> Self { Self { position: Vec3::ZERO } } } impl Default for Portal { fn default() -> Self { Self { x0: 0.0, z0: 0.0, x1: 0.0, z1: 0.0, target_leaf: 0, } } } impl Default for CellPortals { fn default() -> Self { Self { portals: [Portal::default(); 4], num_portals: 0, } } } 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 } } } pub struct Bsp { inner: demo3d_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]>, pub heightfield: Box<[f32]>, } #[derive(Default)] pub struct BspBuilder { pub cell_portals: Vec, pub edges: Vec, pub faces: Vec, pub leafs: Vec, pub marksurfaces: Vec, pub nodes: Vec, pub planes: Vec, pub surfedges: Vec, pub vertex_lights: Vec, pub vertices: Vec, pub visdata: Vec, pub heightfield: Vec, pub heightfield_w: u16, pub heightfield_h: u16, pub heightfield_ox: f32, pub heightfield_oz: f32, pub heightfield_cell_size: f32, pub bounds_min_x: f32, pub bounds_min_z: f32, pub bounds_max_x: f32, pub bounds_max_z: f32, } impl BspBuilder { pub fn new() -> Self { Self::default() } } impl From 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 heightfield = b.heightfield.into_boxed_slice(); let inner = demo3d_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 _ }, heightfield: if heightfield.is_empty() { core::ptr::null_mut() } else { heightfield.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, num_heightfield: heightfield.len() as u32, heightfield_ox: b.heightfield_ox, heightfield_oz: b.heightfield_oz, heightfield_cell_size: b.heightfield_cell_size, heightfield_w: b.heightfield_w, heightfield_h: b.heightfield_h, visdata_size: visdata.len() as u32, bounds_min_x: b.bounds_min_x, bounds_min_z: b.bounds_min_z, bounds_max_x: b.bounds_max_x, bounds_max_z: b.bounds_max_z, }; Self { inner, cell_portals, edges, faces, leafs, marksurfaces, nodes, planes, surfedges, vertex_lights, vertices, visdata, heightfield, } } } impl Bsp { pub fn as_c_bsp(&self) -> &demo3d_bsp { &self.inner } pub fn trace(&self, from: Vec3, to: Vec3, radius: f32) -> Vec3 { unsafe { demo3d_bsp_trace(&self.inner, from, to, radius) } } } impl Default for Bsp { fn default() -> Self { BspBuilder::new().into() } }