diff options
35 files changed, 258 insertions, 189 deletions
diff --git a/examples/render-bsp/Cargo.toml b/examples/render-bsp/Cargo.toml index a68223f..666f035 100644 --- a/examples/render-bsp/Cargo.toml +++ b/examples/render-bsp/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Oscar <oscar.shrimpton.personal@gmail.com>"] [dependencies] stockton-render = { path = "../../stockton-render", features = ["vulkan"] } stockton-types = { path = "../../stockton-types" } -stockton-bsp = { git = "https://github.com/tcmal/rust-bsp.git" } +stockton-levels = { path = "../../stockton-levels" } winit = "^0.21" simple_logger = "1.0" image = "0.23.2" diff --git a/examples/render-bsp/src/main.rs b/examples/render-bsp/src/main.rs index 7477567..f2310e6 100644 --- a/examples/render-bsp/src/main.rs +++ b/examples/render-bsp/src/main.rs @@ -16,7 +16,7 @@ //! Renders ./example.bsp extern crate stockton_types; -extern crate stockton_bsp; +extern crate stockton_levels; extern crate stockton_render; extern crate winit; extern crate simple_logger; @@ -25,7 +25,7 @@ extern crate image; use image::load_from_memory; use std::time::SystemTime; -use stockton_bsp::BSPFile; +use stockton_levels::q3::Q3BSPFile; use stockton_types::{World, Vector3}; use stockton_render::Renderer; @@ -35,7 +35,7 @@ use winit::{ window::WindowBuilder }; -const SPEED: f32 = 25.0; +const SPEED: f32 = 100.0; #[derive(Debug)] struct KeyState { @@ -91,21 +91,22 @@ fn main() { let event_loop = EventLoop::new(); let window = WindowBuilder::new().build(&event_loop).unwrap(); let data = include_bytes!("../data/test.bsp").to_vec().into_boxed_slice(); - let bsp = BSPFile::from_buffer(data).unwrap(); + let bsp = Q3BSPFile::new(&data).unwrap(); - let world = World::new(bsp).unwrap(); + let world = World::new(bsp); let mut renderer = Renderer::new(world, &window).unwrap(); + { + renderer.context.add_texture( + load_from_memory(include_bytes!("../../render-quad/data/test1.png")) + .expect("Couldn't load test texture 1") + .into_rgba()).unwrap(); - renderer.context.add_texture( - load_from_memory(include_bytes!("../../render-quad/data/test1.png")) - .expect("Couldn't load test texture 1") - .into_rgba()).unwrap(); - - renderer.context.add_texture( - load_from_memory(include_bytes!("../../render-quad/data/test2.png")) - .expect("Couldn't load test texture 2") - .into_rgba()).unwrap(); + renderer.context.add_texture( + load_from_memory(include_bytes!("../../render-quad/data/test2.png")) + .expect("Couldn't load test texture 2") + .into_rgba()).unwrap(); + } let mut last_update = SystemTime::now(); let mut key_state = KeyState::new(); @@ -113,7 +114,6 @@ fn main() { // Keep rendering the world event_loop.run(move |event, _, flow| { *flow = ControlFlow::Poll; - match event { Event::WindowEvent { event, diff --git a/stockton-levels/src/features.rs b/stockton-levels/src/features.rs new file mode 100644 index 0000000..3f53308 --- /dev/null +++ b/stockton-levels/src/features.rs @@ -0,0 +1,21 @@ +// Copyright (C) Oscar Shrimpton 2019 + +// This program is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) +// any later version. + +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. + +// You should have received a copy of the GNU General Public License along +// with this program. If not, see <http://www.gnu.org/licenses/>. +//! Marker traits for different feature sets + +use crate::traits::*; + +pub trait MinBSPFeatures: HasBSPTree {} +impl<T> MinBSPFeatures for T + where T: HasBSPTree {}
\ No newline at end of file diff --git a/stockton-levels/src/helpers.rs b/stockton-levels/src/helpers.rs index b81fb6a..c3e6c80 100644 --- a/stockton-levels/src/helpers.rs +++ b/stockton-levels/src/helpers.rs @@ -63,9 +63,9 @@ pub fn slice_to_vec3i(slice: &[u8]) -> Vector3<i32> { ) } -/// Turn a slice of i32s into a 2D vector +/// Turn a slice of u32s into a 2D vector /// # Panics /// If slice isn't 8 bytes long. -pub fn slice_to_vec2i(slice: &[u8]) -> Vector2<i32> { - Vector2::new(slice_to_i32(&slice[0..4]), slice_to_i32(&slice[4..8])) -} +pub fn slice_to_vec2ui(slice: &[u8]) -> Vector2<u32> { + Vector2::new(slice_to_u32(&slice[0..4]), slice_to_u32(&slice[4..8])) +}
\ No newline at end of file diff --git a/stockton-levels/src/lib.rs b/stockton-levels/src/lib.rs index 37d1050..aef802e 100644 --- a/stockton-levels/src/lib.rs +++ b/stockton-levels/src/lib.rs @@ -13,6 +13,7 @@ // You should have received a copy of the GNU General Public License along // with this program. If not, see <http://www.gnu.org/licenses/>. //! Parses common features from many BSP file formats. +#![feature(generic_associated_types)] #[macro_use] extern crate bitflags; @@ -22,4 +23,6 @@ extern crate nalgebra as na; mod helpers; pub mod q3; pub mod types; -pub mod traits;
\ No newline at end of file +pub mod traits; +pub mod prelude; +pub mod features;
\ No newline at end of file diff --git a/stockton-levels/src/prelude.rs b/stockton-levels/src/prelude.rs new file mode 100644 index 0000000..8834f03 --- /dev/null +++ b/stockton-levels/src/prelude.rs @@ -0,0 +1,18 @@ +// Copyright (C) Oscar Shrimpton 2019 + +// This program is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) +// any later version. + +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. + +// You should have received a copy of the GNU General Public License along +// with this program. If not, see <http://www.gnu.org/licenses/>. +//! Common traits, etc. + +pub use crate::traits::*; +pub use crate::features::*;
\ No newline at end of file diff --git a/stockton-levels/src/q3/brushes.rs b/stockton-levels/src/q3/brushes.rs index 48462a2..f8a979d 100644 --- a/stockton-levels/src/q3/brushes.rs +++ b/stockton-levels/src/q3/brushes.rs @@ -104,14 +104,14 @@ fn get_sides( } -impl<'a> HasBrushes<'a> for Q3BSPFile { - type BrushesIter = std::slice::Iter<'a, Brush>; +impl HasBrushes for Q3BSPFile { + type BrushesIter<'a> = std::slice::Iter<'a, Brush>; - fn brushes_iter(&'a self) -> Self::BrushesIter { + fn brushes_iter<'a>(&'a self) -> Self::BrushesIter<'a> { self.brushes.iter() } - fn get_brush(&'a self, index: u32) -> &'a Brush { + fn get_brush<'a>(&'a self, index: u32) -> &'a Brush { &self.brushes[index as usize] } } diff --git a/stockton-levels/src/q3/effects.rs b/stockton-levels/src/q3/effects.rs index 2a76da9..0fddfb7 100644 --- a/stockton-levels/src/q3/effects.rs +++ b/stockton-levels/src/q3/effects.rs @@ -50,14 +50,14 @@ pub fn from_data(data: &[u8], n_brushes: u32) -> Result<Box<[Effect]>> { } -impl<'a> HasEffects<'a> for Q3BSPFile { - type EffectsIter = std::slice::Iter<'a, Effect>; +impl HasEffects for Q3BSPFile { + type EffectsIter<'a> = std::slice::Iter<'a, Effect>; - fn effects_iter(&'a self) -> Self::EffectsIter { + fn effects_iter<'a>(&'a self) -> Self::EffectsIter<'a> { self.effects.iter() } - fn get_effect(&'a self, index: u32) -> &'a Effect { + fn get_effect<'a>(&'a self, index: u32) -> &'a Effect { &self.effects[index as usize] } } diff --git a/stockton-levels/src/q3/entities.rs b/stockton-levels/src/q3/entities.rs index 1614f26..9284fe4 100644 --- a/stockton-levels/src/q3/entities.rs +++ b/stockton-levels/src/q3/entities.rs @@ -99,10 +99,10 @@ pub fn from_data(data: &[u8]) -> Result<Box<[Entity]>> { Ok(entities.into_boxed_slice()) } -impl<'a> HasEntities<'a> for Q3BSPFile { - type EntitiesIter = std::slice::Iter<'a, Entity>; +impl HasEntities for Q3BSPFile { + type EntitiesIter<'a> = std::slice::Iter<'a, Entity>; - fn entities_iter(&'a self) -> Self::EntitiesIter { + fn entities_iter<'a>(&'a self) -> Self::EntitiesIter<'a> { self.entities.iter() } } diff --git a/stockton-levels/src/q3/faces.rs b/stockton-levels/src/q3/faces.rs index 835dbe8..933f0d6 100644 --- a/stockton-levels/src/q3/faces.rs +++ b/stockton-levels/src/q3/faces.rs @@ -15,7 +15,7 @@ // You should have received a copy of the GNU General Public License // along with stockton-bsp. If not, see <http://www.gnu.org/licenses/>. -use crate::helpers::{slice_to_i32, slice_to_vec2i, slice_to_vec3}; +use crate::helpers::{slice_to_i32, slice_to_u32, slice_to_vec2ui, slice_to_vec3}; use crate::types::{Result, ParseError}; use na::Vector3; use crate::traits::faces::*; @@ -41,11 +41,11 @@ pub fn from_data( for n in 0..length { faces.push(face_from_slice( &data[n * FACE_SIZE..(n + 1) * FACE_SIZE], - n_textures as usize, - n_effects as usize, - n_vertices as usize, - n_meshverts as usize, - n_lightmaps as usize, + n_textures, + n_effects, + n_vertices, + n_meshverts, + n_lightmaps, )?); } @@ -55,24 +55,24 @@ pub fn from_data( fn face_from_slice( data: &[u8], - n_textures: usize, - n_effects: usize, - n_vertices: usize, - n_meshverts: usize, - n_lightmaps: usize, + n_textures: u32, + n_effects: u32, + n_vertices: u32, + n_meshverts: u32, + n_lightmaps: u32, ) -> Result<Face> { if data.len() != FACE_SIZE { panic!("tried to call face.from_slice with invalid slice size"); } // texture - let texture_idx = slice_to_i32(&data[0..4]) as usize; + let texture_idx = slice_to_u32(&data[0..4]); if texture_idx >= n_textures { return Err(ParseError::Invalid); } // effects - let effect_idx = slice_to_i32(&data[4..8]) as usize; + let effect_idx = slice_to_u32(&data[4..8]); let effect_idx = if effect_idx < 0xffffffff { if effect_idx >= n_effects { return Err(ParseError::Invalid); @@ -85,11 +85,11 @@ fn face_from_slice( // face type // TODO - let face_type: FaceType = unsafe { ::std::mem::transmute(slice_to_i32(&data[8..12])) }; + let face_type: FaceType = unsafe { ::std::mem::transmute(slice_to_u32(&data[8..12])) }; // vertices - let vertex_offset = slice_to_i32(&data[12..16]) as usize; - let vertex_n = slice_to_i32(&data[16..20]) as usize; + let vertex_offset = slice_to_u32(&data[12..16]); + let vertex_n = slice_to_u32(&data[16..20]); if (vertex_offset + vertex_n) > n_vertices { return Err(ParseError::Invalid); } @@ -97,8 +97,8 @@ fn face_from_slice( let vertices_idx = vertex_offset..vertex_offset + vertex_n; // meshverts - let meshverts_offset = slice_to_i32(&data[20..24]) as usize; - let meshverts_n = slice_to_i32(&data[24..28]) as usize; + let meshverts_offset = slice_to_u32(&data[20..24]); + let meshverts_n = slice_to_u32(&data[24..28]); if (meshverts_offset + meshverts_n) > n_meshverts { return Err(ParseError::Invalid); } @@ -106,20 +106,20 @@ fn face_from_slice( let meshverts_idx = meshverts_offset..meshverts_offset + meshverts_n; // lightmap - let lightmap_idx = slice_to_i32(&data[28..32]) as usize; - let lightmap_idx = if lightmap_idx < 0xffffffff { - if lightmap_idx >= n_lightmaps { + let lightmap_idx = slice_to_i32(&data[28..32]); + let lightmap_idx = if lightmap_idx > 0 { + if lightmap_idx as u32 >= n_lightmaps { return Err(ParseError::Invalid); } - Some(lightmap_idx) + Some(lightmap_idx as u32) } else { None }; // map properties - let map_start = slice_to_vec2i(&data[32..40]); - let map_size = slice_to_vec2i(&data[40..48]); + let map_start = slice_to_vec2ui(&data[32..40]); + let map_size = slice_to_vec2ui(&data[40..48]); let map_origin = slice_to_vec3(&data[48..60]); // map_vecs @@ -131,7 +131,7 @@ fn face_from_slice( // normal & size let normal = slice_to_vec3(&data[84..96]); - let size = slice_to_vec2i(&data[96..104]); + let size = slice_to_vec2ui(&data[96..104]); Ok(Face { face_type, @@ -150,14 +150,19 @@ fn face_from_slice( } -impl<'a> HasFaces<'a> for Q3BSPFile { - type FacesIter = std::slice::Iter<'a, Face>; +impl HasFaces for Q3BSPFile { + type FacesIter<'a> = std::slice::Iter<'a, Face>; - fn faces_iter(&'a self) -> Self::FacesIter { + fn faces_iter<'a>(&'a self) -> Self::FacesIter<'a> { self.faces.iter() } - fn get_face(&'a self, index: u32) -> &'a Face { + fn faces_len(&self) -> u32 { + self.faces.len() as u32 + } + + fn get_face<'a>(&'a self, index: u32) -> &'a Face { &self.faces[index as usize] } + } diff --git a/stockton-levels/src/q3/light_maps.rs b/stockton-levels/src/q3/light_maps.rs index 6743aa4..a03f164 100644 --- a/stockton-levels/src/q3/light_maps.rs +++ b/stockton-levels/src/q3/light_maps.rs @@ -46,14 +46,14 @@ pub fn from_data(data: &[u8]) -> Result<Box<[LightMap]>> { Ok(maps.into_boxed_slice()) } -impl<'a> HasLightMaps<'a> for Q3BSPFile { - type LightMapsIter = std::slice::Iter<'a, LightMap>; +impl HasLightMaps for Q3BSPFile { + type LightMapsIter<'a> = std::slice::Iter<'a, LightMap>; - fn lightmaps_iter(&'a self) -> Self::LightMapsIter { + fn lightmaps_iter<'a>(&'a self) -> Self::LightMapsIter<'a> { self.light_maps.iter() } - fn get_lightmap(&'a self, index: u32) -> &'a LightMap { + fn get_lightmap<'a>(&'a self, index: u32) -> &'a LightMap { &self.light_maps[index as usize] } }
\ No newline at end of file diff --git a/stockton-levels/src/q3/light_vols.rs b/stockton-levels/src/q3/light_vols.rs index 02c4cb4..202c375 100644 --- a/stockton-levels/src/q3/light_vols.rs +++ b/stockton-levels/src/q3/light_vols.rs @@ -43,14 +43,14 @@ pub fn from_data(data: &[u8]) -> Result<Box<[LightVol]>> { } -impl<'a> HasLightVols<'a> for Q3BSPFile { - type LightVolsIter = std::slice::Iter<'a, LightVol>; +impl HasLightVols for Q3BSPFile { + type LightVolsIter<'a> = std::slice::Iter<'a, LightVol>; - fn lightvols_iter(&'a self) -> Self::LightVolsIter { + fn lightvols_iter<'a>(&'a self) -> Self::LightVolsIter<'a> { self.light_vols.iter() } - fn get_lightvol(&'a self, index: u32) -> &'a LightVol { + fn get_lightvol<'a>(&'a self, index: u32) -> &'a LightVol { &self.light_vols[index as usize] } } diff --git a/stockton-levels/src/q3/models.rs b/stockton-levels/src/q3/models.rs index e2307d6..cd901bc 100644 --- a/stockton-levels/src/q3/models.rs +++ b/stockton-levels/src/q3/models.rs @@ -73,14 +73,14 @@ pub fn from_data( } -impl<'a> HasModels<'a> for Q3BSPFile { - type ModelsIter = std::slice::Iter<'a, Model>; +impl HasModels for Q3BSPFile { + type ModelsIter<'a> = std::slice::Iter<'a, Model>; - fn models_iter(&'a self) -> Self::ModelsIter { + fn models_iter<'a>(&'a self) -> Self::ModelsIter<'a> { self.models.iter() } - fn get_model(&'a self, index: u32) -> &'a Model { + fn get_model<'a>(&'a self, index: u32) -> &'a Model { &self.models[index as usize] } } diff --git a/stockton-levels/src/q3/planes.rs b/stockton-levels/src/q3/planes.rs index 970ddde..dd4f3aa 100644 --- a/stockton-levels/src/q3/planes.rs +++ b/stockton-levels/src/q3/planes.rs @@ -45,10 +45,14 @@ pub fn from_data(data: &[u8]) -> Result<Box<[Plane]>> { Ok(planes.into_boxed_slice()) } -impl<'a> HasPlanes<'a> for Q3BSPFile { - type PlanesIter = std::slice::Iter<'a, Plane>; +impl HasPlanes for Q3BSPFile { + type PlanesIter<'a> = std::slice::Iter<'a, Plane>; - fn planes_iter(&'a self) -> Self::PlanesIter { + fn planes_iter<'a>(&'a self) -> Self::PlanesIter<'a> { self.planes.iter() } + + fn get_plane<'a>(&'a self, idx: u32) -> &'a Plane { + &self.planes[idx as usize] + } }
\ No newline at end of file diff --git a/stockton-levels/src/q3/textures.rs b/stockton-levels/src/q3/textures.rs index 264389e..78c3135 100644 --- a/stockton-levels/src/q3/textures.rs +++ b/stockton-levels/src/q3/textures.rs @@ -50,10 +50,10 @@ pub fn from_data(lump: &[u8]) -> Result<Box<[Texture]>> { Ok(textures.into_boxed_slice()) } -impl<'a> HasTextures<'a> for Q3BSPFile { - type TexturesIter = std::slice::Iter<'a, Texture>; +impl HasTextures for Q3BSPFile { + type TexturesIter<'a> = std::slice::Iter<'a, Texture>; - fn textures_iter(&'a self) -> Self::TexturesIter { + fn textures_iter<'a>(&'a self) -> Self::TexturesIter<'a> { self.textures.iter() } } diff --git a/stockton-levels/src/q3/tree.rs b/stockton-levels/src/q3/tree.rs index 4ef5470..e157d97 100644 --- a/stockton-levels/src/q3/tree.rs +++ b/stockton-levels/src/q3/tree.rs @@ -161,8 +161,8 @@ fn compile_node( } } -impl<'a> HasBSPTree<'a> for Q3BSPFile { - fn get_bsp_root(&'a self) -> &'a BSPNode { +impl HasBSPTree for Q3BSPFile { + fn get_bsp_root<'a>(&'a self) -> &'a BSPNode { &self.tree_root } }
\ No newline at end of file diff --git a/stockton-levels/src/q3/vertices.rs b/stockton-levels/src/q3/vertices.rs index 4583aef..51a3590 100644 --- a/stockton-levels/src/q3/vertices.rs +++ b/stockton-levels/src/q3/vertices.rs @@ -18,7 +18,7 @@ use std::convert::TryInto; use super::Q3BSPFile; -use crate::helpers::{slice_to_i32, slice_to_vec3}; +use crate::helpers::{slice_to_u32, slice_to_vec3}; use crate::types::{Result, ParseError, RGBA}; use crate::traits::vertices::*; @@ -58,32 +58,32 @@ pub fn meshverts_from_data(data: &[u8]) -> Result<Box<[MeshVert]>> { let mut meshverts = Vec::with_capacity(length as usize); for n in 0..length { - meshverts.push(slice_to_i32(&data[n * 4..(n + 1) * 4])) + meshverts.push(slice_to_u32(&data[n * 4..(n + 1) * 4])) } Ok(meshverts.into_boxed_slice()) } -impl<'a> HasVertices<'a> for Q3BSPFile { - type VerticesIter = std::slice::Iter<'a, Vertex>; +impl HasVertices for Q3BSPFile { + type VerticesIter<'a> = std::slice::Iter<'a, Vertex>; - fn vertices_iter(&'a self) -> Self::VerticesIter { + fn vertices_iter<'a>(&'a self) -> Self::VerticesIter<'a> { self.vertices.iter() } - fn get_vertex(&'a self, index: u32) -> &'a Vertex { + fn get_vertex<'a>(&'a self, index: u32) -> &'a Vertex { &self.vertices[index as usize] } } -impl<'a> HasMeshVerts<'a> for Q3BSPFile { - type MeshVertsIter = std::slice::Iter<'a, MeshVert>; +impl HasMeshVerts for Q3BSPFile { + type MeshVertsIter<'a> = std::slice::Iter<'a, MeshVert>; - fn meshverts_iter(&'a self) -> Self::MeshVertsIter { + fn meshverts_iter<'a>(&'a self) -> Self::MeshVertsIter<'a> { self.meshverts.iter() } - fn get_meshvert(&self, index: u32) -> MeshVert { + fn get_meshvert<'a>(&self, index: u32) -> MeshVert { self.meshverts[index as usize] } }
\ No newline at end of file diff --git a/stockton-levels/src/traits/brushes.rs b/stockton-levels/src/traits/brushes.rs index 0b07653..6131824 100644 --- a/stockton-levels/src/traits/brushes.rs +++ b/stockton-levels/src/traits/brushes.rs @@ -17,6 +17,8 @@ //! Parses the brushes & brushsides lumps from a bsp file +use super::HasPlanes; + /// One brush record. Used for collision detection. /// "Each brush describes a convex volume as defined by its surrounding surfaces." #[derive(Debug, Clone, PartialEq)] @@ -33,9 +35,9 @@ pub struct BrushSide { pub is_opposing: bool, } -pub trait HasBrushes<'a> { - type BrushesIter: Iterator<Item = &'a Brush>; +pub trait HasBrushes: HasPlanes { + type BrushesIter<'a>: Iterator<Item = &'a Brush>; - fn brushes_iter(&'a self) -> Self::BrushesIter; - fn get_brush(&'a self, index: u32) -> &'a Brush; + fn brushes_iter<'a>(&'a self) -> Self::BrushesIter<'a>; + fn get_brush<'a>(&'a self, index: u32) -> &'a Brush; } diff --git a/stockton-levels/src/traits/effects.rs b/stockton-levels/src/traits/effects.rs index c889ea7..d969dd1 100644 --- a/stockton-levels/src/traits/effects.rs +++ b/stockton-levels/src/traits/effects.rs @@ -15,6 +15,8 @@ // You should have received a copy of the GNU General Public License // along with stockton-bsp. If not, see <http://www.gnu.org/licenses/>. +use super::HasBrushes; + /// One effect definition #[derive(Debug, Clone, PartialEq)] pub struct Effect { @@ -27,9 +29,9 @@ pub struct Effect { // todo: unknown: i32 } -pub trait HasEffects<'a> { - type EffectsIter: Iterator<Item = &'a Effect>; +pub trait HasEffects: HasBrushes { + type EffectsIter<'a>: Iterator<Item = &'a Effect>; - fn effects_iter(&'a self) -> Self::EffectsIter; - fn get_effect(&'a self, index: u32) -> &'a Effect; + fn effects_iter<'a>(&'a self) -> Self::EffectsIter<'a>; + fn get_effect<'a>(&'a self, index: u32) -> &'a Effect; } diff --git a/stockton-levels/src/traits/entities.rs b/stockton-levels/src/traits/entities.rs index 6a762e0..706f25a 100644 --- a/stockton-levels/src/traits/entities.rs +++ b/stockton-levels/src/traits/entities.rs @@ -22,8 +22,8 @@ pub struct Entity { pub attributes: HashMap<String, String>, } -pub trait HasEntities<'a> { - type EntitiesIter: Iterator<Item = &'a Entity>; +pub trait HasEntities { + type EntitiesIter<'a>: Iterator<Item = &'a Entity>; - fn entities_iter(&'a self) -> Self::EntitiesIter; + fn entities_iter<'a>(&'a self) -> Self::EntitiesIter<'a>; }
\ No newline at end of file diff --git a/stockton-levels/src/traits/faces.rs b/stockton-levels/src/traits/faces.rs index ff73c73..cb97877 100644 --- a/stockton-levels/src/traits/faces.rs +++ b/stockton-levels/src/traits/faces.rs @@ -15,9 +15,10 @@ // You should have received a copy of the GNU General Public License // along with stockton-bsp. If not, see <http://www.gnu.org/licenses/>. +use std::ops::Range; use na::{Vector2, Vector3}; -use std::ops::Range; +use super::{HasEffects, HasTextures, HasLightMaps, HasMeshVerts}; #[derive(Debug, Clone, Copy, PartialEq)] #[repr(i32)] @@ -31,24 +32,25 @@ pub enum FaceType { #[derive(Debug, Clone, PartialEq)] pub struct Face { pub face_type: FaceType, - pub texture_idx: usize, - pub effect_idx: Option<usize>, - pub lightmap_idx: Option<usize>, - pub vertices_idx: Range<usize>, - pub meshverts_idx: Range<usize>, + pub texture_idx: u32, + pub effect_idx: Option<u32>, + pub lightmap_idx: Option<u32>, + pub vertices_idx: Range<u32>, + pub meshverts_idx: Range<u32>, - pub map_start: Vector2<i32>, - pub map_size: Vector2<i32>, + pub map_start: Vector2<u32>, + pub map_size: Vector2<u32>, pub map_origin: Vector3<f32>, pub map_vecs: [Vector3<f32>; 2], pub normal: Vector3<f32>, - pub size: Vector2<i32>, + pub size: Vector2<u32>, } -pub trait HasFaces<'a> { - type FacesIter: Iterator<Item = &'a Face>; +pub trait HasFaces: HasTextures + HasEffects + HasLightMaps + HasMeshVerts { + type FacesIter<'a>: Iterator<Item = &'a Face>; - fn faces_iter(&'a self) -> Self::FacesIter; - fn get_face(&'a self, index: u32) -> &'a Face; + fn faces_iter<'a>(&'a self) -> Self::FacesIter<'a>; + fn faces_len(&self) -> u32; + fn get_face<'a>(&'a self, index: u32) -> &'a Face; } diff --git a/stockton-levels/src/traits/light_maps.rs b/stockton-levels/src/traits/light_maps.rs index 406746d..9b30d91 100644 --- a/stockton-levels/src/traits/light_maps.rs +++ b/stockton-levels/src/traits/light_maps.rs @@ -54,9 +54,9 @@ impl fmt::Debug for LightMap { } } -pub trait HasLightMaps<'a> { - type LightMapsIter: Iterator<Item = &'a LightMap>; +pub trait HasLightMaps { + type LightMapsIter<'a>: Iterator<Item = &'a LightMap>; - fn lightmaps_iter(&'a self) -> Self::LightMapsIter; - fn get_lightmap(&'a self, index: u32) -> &'a LightMap; + fn lightmaps_iter<'a>(&'a self) -> Self::LightMapsIter<'a>; + fn get_lightmap<'a>(&'a self, index: u32) -> &'a LightMap; }
\ No newline at end of file diff --git a/stockton-levels/src/traits/light_vols.rs b/stockton-levels/src/traits/light_vols.rs index 027709a..8e75401 100644 --- a/stockton-levels/src/traits/light_vols.rs +++ b/stockton-levels/src/traits/light_vols.rs @@ -15,8 +15,6 @@ // You should have received a copy of the GNU General Public License // along with stockton-bsp. If not, see <http://www.gnu.org/licenses/>. -use std::convert::TryInto; - use crate::types::RGB; #[derive(Debug, Clone, Copy)] @@ -26,9 +24,9 @@ pub struct LightVol { pub dir: [u8; 2], } -pub trait HasLightVols<'a> { - type LightVolsIter: Iterator<Item = &'a LightVol>; +pub trait HasLightVols { + type LightVolsIter<'a>: Iterator<Item = &'a LightVol>; - fn lightvols_iter(&'a self) -> Self::LightVolsIter; - fn get_lightvol(&'a self, index: u32) -> &'a LightVol; + fn lightvols_iter<'a>(&'a self) -> Self::LightVolsIter<'a>; + fn get_lightvol<'a>(&'a self, index: u32) -> &'a LightVol; } diff --git a/stockton-levels/src/traits/models.rs b/stockton-levels/src/traits/models.rs index ede7f78..7d1b896 100644 --- a/stockton-levels/src/traits/models.rs +++ b/stockton-levels/src/traits/models.rs @@ -18,6 +18,8 @@ use na::Vector3; use std::ops::Range; +use super::{HasFaces, HasBrushes}; + #[derive(Debug, Clone)] pub struct Model { pub mins: Vector3<f32>, @@ -26,9 +28,9 @@ pub struct Model { pub brushes_idx: Range<u32>, } -pub trait HasModels<'a> { - type ModelsIter: Iterator<Item = &'a Model>; +pub trait HasModels: HasFaces + HasBrushes { + type ModelsIter<'a>: Iterator<Item = &'a Model>; - fn models_iter(&'a self) -> Self::ModelsIter; - fn get_model(&'a self, index: u32) -> &'a Model; + fn models_iter<'a>(&'a self) -> Self::ModelsIter<'a>; + fn get_model<'a>(&'a self, index: u32) -> &'a Model; } diff --git a/stockton-levels/src/traits/planes.rs b/stockton-levels/src/traits/planes.rs index 6962c71..6a4e95a 100644 --- a/stockton-levels/src/traits/planes.rs +++ b/stockton-levels/src/traits/planes.rs @@ -35,8 +35,9 @@ pub struct Plane { pub dist: f32, } -pub trait HasPlanes<'a> { - type PlanesIter: Iterator<Item = &'a Plane>; +pub trait HasPlanes { + type PlanesIter<'a>: Iterator<Item = &'a Plane>; - fn planes_iter(&'a self) -> Self::PlanesIter; + fn planes_iter<'a>(&'a self) -> Self::PlanesIter<'a>; + fn get_plane<'a>(&'a self, idx: u32) -> &'a Plane; }
\ No newline at end of file diff --git a/stockton-levels/src/traits/textures.rs b/stockton-levels/src/traits/textures.rs index d1a2a83..ffd2a2f 100644 --- a/stockton-levels/src/traits/textures.rs +++ b/stockton-levels/src/traits/textures.rs @@ -142,8 +142,8 @@ bitflags!( } ); -pub trait HasTextures<'a> { - type TexturesIter: Iterator<Item = &'a Texture>; +pub trait HasTextures { + type TexturesIter<'a>: Iterator<Item = &'a Texture>; - fn textures_iter(&'a self) -> Self::TexturesIter; + fn textures_iter<'a>(&'a self) -> Self::TexturesIter<'a>; } diff --git a/stockton-levels/src/traits/tree.rs b/stockton-levels/src/traits/tree.rs index 06cfd80..bdbe705 100644 --- a/stockton-levels/src/traits/tree.rs +++ b/stockton-levels/src/traits/tree.rs @@ -18,6 +18,7 @@ //! Parses the BSP tree into a usable format use na::Vector3; +use super::{HasFaces, HasBrushes, HasVisData}; /// A node in a BSP tree. /// Either has two children *or* a leaf entry. @@ -45,6 +46,6 @@ pub struct BSPLeaf { pub brushes_idx: Box<[u32]>, } -pub trait HasBSPTree<'a> { - fn get_bsp_root(&'a self) -> &'a BSPNode; +pub trait HasBSPTree: HasFaces + HasBrushes + HasVisData { + fn get_bsp_root<'a>(&'a self) -> &'a BSPNode; }
\ No newline at end of file diff --git a/stockton-levels/src/traits/vertices.rs b/stockton-levels/src/traits/vertices.rs index cb06b3a..2afa802 100644 --- a/stockton-levels/src/traits/vertices.rs +++ b/stockton-levels/src/traits/vertices.rs @@ -18,7 +18,6 @@ use crate::helpers::{slice_to_f32}; use crate::types::RGBA; use na::Vector3; -use std::convert::TryInto; /// A vertex, used to describe a face. @@ -49,22 +48,22 @@ impl TexCoord { } /// A vertex offset, used to describe generalised triangle meshes -pub type MeshVert = i32; +pub type MeshVert = u32; -pub trait HasVertices<'a> { - type VerticesIter: Iterator<Item = &'a Vertex>; +pub trait HasVertices { + type VerticesIter<'a>: Iterator<Item = &'a Vertex>; - fn vertices_iter(&'a self) -> Self::VerticesIter; - fn get_vertex(&'a self, index: u32) -> &'a Vertex; + fn vertices_iter<'a>(&'a self) -> Self::VerticesIter<'a>; + fn get_vertex<'a>(&'a self, index: u32) -> &'a Vertex; } -pub trait HasMeshVerts<'a>: HasVertices<'a> { - type MeshVertsIter: Iterator<Item = &'a MeshVert>; +pub trait HasMeshVerts: HasVertices { + type MeshVertsIter<'a>: Iterator<Item = &'a MeshVert>; - fn meshverts_iter(&'a self) -> Self::MeshVertsIter; + fn meshverts_iter<'a>(&'a self) -> Self::MeshVertsIter<'a>; fn get_meshvert(&self, index: u32) -> MeshVert; - fn resolve_meshvert(&'a self, index: u32) -> &'a Vertex { - self.get_vertex(self.get_meshvert(index).try_into().unwrap()) + fn resolve_meshvert<'a>(&'a self, index: u32, base: u32) -> &'a Vertex { + self.get_vertex(self.get_meshvert(index) + base) } }
\ No newline at end of file diff --git a/stockton-levels/src/traits/visdata.rs b/stockton-levels/src/traits/visdata.rs index 27849d3..92ba9b8 100644 --- a/stockton-levels/src/traits/visdata.rs +++ b/stockton-levels/src/traits/visdata.rs @@ -22,7 +22,7 @@ pub trait HasVisData { type VisibleIterator: Iterator<Item = ClusterId>; /// Returns an iterator of all clusters visible from the given Cluster ID - fn all_visible_from<'a>(&'a self, from: ClusterId) -> Self::VisibleIterator; + fn all_visible_from(&self, from: ClusterId) -> Self::VisibleIterator; /// Returns true if `dest` is visible from `from`. fn cluster_visible_from(&self, from: ClusterId, dest: ClusterId) -> bool; diff --git a/stockton-render/Cargo.toml b/stockton-render/Cargo.toml index 4d2cd47..852d174 100644 --- a/stockton-render/Cargo.toml +++ b/stockton-render/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = ["Oscar <oscar.shrimpton.personal@gmail.com>"] [dependencies] -stockton-bsp = { git = "https://github.com/tcmal/rust-bsp.git" } +stockton-levels = { path = "../stockton-levels" } stockton-types = { path = "../stockton-types" } winit = "^0.21" gfx-hal = "^0.5" diff --git a/stockton-render/src/culling.rs b/stockton-render/src/culling.rs index a9b8753..2fa33b6 100644 --- a/stockton-render/src/culling.rs +++ b/stockton-render/src/culling.rs @@ -14,34 +14,45 @@ // with this program. If not, see <http://www.gnu.org/licenses/>. //! Functions for figuring out what to render +#![allow(dead_code)] -use stockton_bsp::BSPFile; +use stockton_levels::prelude::*; +use stockton_levels::traits::tree::BSPNodeValue; use stockton_types::Vector3; + /// Get the visible faces according to visdata and frustum culling // TODO: Write this. For now, just render all faces -pub fn get_visible_faces<'a>(pos: Vector3, file: &BSPFile) -> Vec<usize> { - let mut visible = Vec::with_capacity(file.faces.faces.len()); - for x in 0..file.faces.faces.len() { - visible.push(x); +pub fn get_visible_faces<T: MinBSPFeatures>(_pos: Vector3, file: &T) -> Vec<u32> { + let mut visible = Vec::with_capacity(file.faces_len() as usize); + for x in 0..file.faces_len() { + visible.push(x as u32); } return visible; } /// Get the viscluster pos lies in -fn get_cluster_id(pos: Vector3, file: &BSPFile) -> usize { - let mut node = &file.tree.root; - while node.leaf.is_none() { - let plane = file.planes.planes[node.plane_idx as usize]; - let dist = plane.normal.dot(&pos) - plane.dist; - - if dist >= 0.0 { - node = &node.children.as_ref().unwrap()[0] +fn get_cluster_id<T: MinBSPFeatures>(pos: Vector3, file: &T) -> u32 { + let mut node = file.get_bsp_root(); + loop { + if let BSPNodeValue::Children(front, back) = &node.value{ + let plane = file.get_plane(node.plane_idx); + let dist = plane.normal.dot(&pos) - plane.dist; + + if dist >= 0.0 { + node = front; + } else { + node = back; + } } else { - node = &node.children.as_ref().unwrap()[1] + break; } } - node.leaf.as_ref().unwrap().cluster_id as usize + if let BSPNodeValue::Leaf(leaf) = &node.value { + leaf.cluster_id + } else { + panic!("should have had a leaf but didn't"); + } }
\ No newline at end of file diff --git a/stockton-render/src/draw/context.rs b/stockton-render/src/draw/context.rs index 12f24ad..533cf08 100644 --- a/stockton-render/src/draw/context.rs +++ b/stockton-render/src/draw/context.rs @@ -33,10 +33,8 @@ use hal::{ window::SwapchainConfig }; use stockton_types::{Vector2, Vector3}; -use stockton_bsp::{ - BSPFile, - lumps::faces::FaceType -}; +use stockton_levels::prelude::*; +use stockton_levels::traits::faces::FaceType; use crate::{ types::*, @@ -853,19 +851,19 @@ impl<'a> RenderingContext<'a> { /// Load all active faces into the vertex buffers for drawing // TODO: This is just a POC, we need to restructure things a lot for actually texturing, etc - pub fn set_active_faces(&mut self, faces: Vec<usize>, file: &BSPFile) { + pub fn set_active_faces<M: MinBSPFeatures>(&mut self, faces: Vec<u32>, file: &M) -> () { let mut curr_vert_idx: usize = 0; let mut curr_idx_idx: usize = 0; - for face in faces.into_iter().map(|idx| &file.faces.faces[idx]) { + for face in faces.into_iter().map(|idx| file.get_face(idx)) { if face.face_type == FaceType::Polygon || face.face_type == FaceType::Mesh { - let base = face.vertices_idx.start as i32; + let base = face.vertices_idx.start; for idx in face.meshverts_idx.clone().step_by(3) { let start_idx: u16 = curr_vert_idx.try_into().unwrap(); - for mv in &file.meshverts.meshverts[idx..idx+3] { - let vert = &file.vertices.vertices[(base + mv.offset) as usize]; + for idx2 in idx..idx+3 { + let vert = &file.resolve_meshvert(idx2 as u32, base); let uv = Vector2::new(vert.tex.u[0], vert.tex.v[0]); let uvp = UVPoint (vert.position, uv, 0); diff --git a/stockton-render/src/lib.rs b/stockton-render/src/lib.rs index 3f157a1..1abc408 100644 --- a/stockton-render/src/lib.rs +++ b/stockton-render/src/lib.rs @@ -26,7 +26,7 @@ extern crate image; extern crate log; extern crate stockton_types; -extern crate stockton_bsp; +extern crate stockton_levels; extern crate arrayvec; @@ -36,22 +36,23 @@ mod types; mod culling; use stockton_types::World; +use stockton_levels::prelude::*; use error::{CreationError, FrameError}; use draw::RenderingContext; use culling::get_visible_faces; /// Renders a world to a window when you tell it to. -pub struct Renderer<'a> { - world: World, +pub struct Renderer<'a, T: MinBSPFeatures> { + world: World<T>, pub context: RenderingContext<'a> } -impl<'a> Renderer<'a> { +impl<'a, T: MinBSPFeatures> Renderer<'a, T> { /// Create a new Renderer. /// This initialises all the vulkan context, etc needed. - pub fn new(world: World, window: &winit::window::Window) -> Result<Self, CreationError> { + pub fn new(world: World<T>, window: &winit::window::Window) -> Result<Self, CreationError> { let context = RenderingContext::new(window)?; Ok(Renderer { diff --git a/stockton-types/src/lib.rs b/stockton-types/src/lib.rs index 5a409d8..bf690f1 100644 --- a/stockton-types/src/lib.rs +++ b/stockton-types/src/lib.rs @@ -14,7 +14,7 @@ // with this program. If not, see <http://www.gnu.org/licenses/>. //! Common types for all stockton crates. -extern crate stockton_bsp; +extern crate stockton_levels; extern crate nalgebra_glm as na; pub mod world; diff --git a/stockton-types/src/world.rs b/stockton-types/src/world.rs index 2c677b7..8294523 100644 --- a/stockton-types/src/world.rs +++ b/stockton-types/src/world.rs @@ -15,18 +15,19 @@ //! The thing you play on and all the associated state. -use stockton_bsp::BSPFile; +use stockton_levels::prelude::*; /// A loaded world. -pub struct World { - pub map: BSPFile +pub struct World<T: MinBSPFeatures> { + pub map: T, } -impl World { - /// Create a new world from a BSPFile. - pub fn new(bsp: BSPFile) -> Option<World> { - Some(World { - map: bsp - }) +impl<T: MinBSPFeatures> World<T> { + /// Create a new world from a level. + /// The level can be any format, as long as it has the required features of a bsp. + pub fn new(map: T) -> World<T> { + World { + map + } } }
\ No newline at end of file |