1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
/*
* Copyright (C) Oscar Shrimpton 2020
*
* 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/>.
*/
#[cfg(feature = "vulkan")]
extern crate gfx_backend_vulkan as back;
extern crate gfx_hal as hal;
extern crate nalgebra_glm as na;
#[macro_use]
extern crate legion;
mod culling;
pub mod draw;
mod error;
mod types;
pub mod window;
pub mod systems;
use culling::get_visible_faces;
use draw::RenderingContext;
use legion::world::SubWorld;
use legion::IntoQuery;
use std::sync::mpsc::{Receiver, Sender};
use std::sync::Arc;
use std::sync::RwLock;
pub use window::{WindowEvent, UIState};
use stockton_levels::prelude::*;
use stockton_types::components::{CameraSettings, Transform};
use stockton_types::Vector3;
use winit::event_loop::ControlFlow;
use winit::window::Window;
use std::sync::mpsc::channel;
/// Renders a world to a window when you tell it to.
/// Also takes ownership of the window and channels window events to be processed outside winit's event loop.
pub struct Renderer<'a> {
/// All the vulkan stuff
pub(crate) context: RenderingContext<'a>,
/// For getting events from the winit event loop
pub window_events: Receiver<WindowEvent>,
/// For updating the control flow of the winit event loop
pub update_control_flow: Arc<RwLock<ControlFlow>>,
}
impl<'a> Renderer<'a> {
/// Create a new Renderer.
pub fn new<T: MinBSPFeatures<VulkanSystem>>(
window: &Window,
file: &T,
) -> (Self, Sender<WindowEvent>) {
let (tx, rx) = channel();
let update_control_flow = Arc::new(RwLock::new(ControlFlow::Poll));
(
Renderer {
context: RenderingContext::new(window, file).unwrap(),
window_events: rx,
update_control_flow,
},
tx,
)
}
/// Render a single frame of the given map.
fn render<T: MinBSPFeatures<VulkanSystem>>(&mut self, map: &T, ui: &mut UIState, pos: Vector3) {
// Get visible faces
let faces = get_visible_faces(pos, map);
// Then draw them
if self.context.draw_vertices(map, ui, &faces).is_err() {
unsafe { self.context.handle_surface_change().unwrap() };
// If it fails twice, then error
self.context.draw_vertices(map, ui, &faces).unwrap();
}
}
fn resize(&mut self) {
unsafe { self.context.handle_surface_change().unwrap() };
}
}
/// A system that just renders the world.
#[system]
#[read_component(Transform)]
#[read_component(CameraSettings)]
pub fn do_render<T: 'static + MinBSPFeatures<VulkanSystem>>(
#[resource] renderer: &mut Renderer<'static>,
#[resource] ui: &mut UIState,
#[resource] map: &T,
world: &SubWorld,
) {
let mut query = <(&Transform, &CameraSettings)>::query();
for (transform, _) in query.iter(world) {
renderer.render(map, ui, transform.position);
}
}
|