aboutsummaryrefslogtreecommitdiff
path: root/examples/render-quad
diff options
context:
space:
mode:
Diffstat (limited to 'examples/render-quad')
-rw-r--r--examples/render-quad/Cargo.toml20
-rw-r--r--examples/render-quad/src/level.rs78
-rw-r--r--examples/render-quad/src/main.rs229
3 files changed, 327 insertions, 0 deletions
diff --git a/examples/render-quad/Cargo.toml b/examples/render-quad/Cargo.toml
new file mode 100644
index 0000000..d32aa6e
--- /dev/null
+++ b/examples/render-quad/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+name = "render-quad"
+version = "0.1.0"
+authors = ["Oscar <oscar.shrimpton.personal@gmail.com>"]
+edition = "2018"
+
+[dependencies]
+stockton-render = { path = "../../stockton-render", features = ["vulkan"] }
+stockton-input = { path = "../../stockton-input" }
+stockton-input-codegen = { path = "../../stockton-input-codegen" }
+stockton-types = { path = "../../stockton-types" }
+stockton-levels = { path = "../../stockton-levels" }
+stockton-contrib = { path = "../../stockton-contrib", features = ["delta_time", "flycam"] }
+winit = "^0.21"
+log = "0.4.0"
+simplelog = "^0.10"
+image = "0.23.2"
+egui = "^0.12"
+legion = { version = "^0.3" }
+anyhow = "1.0.40"
diff --git a/examples/render-quad/src/level.rs b/examples/render-quad/src/level.rs
new file mode 100644
index 0000000..d10c3b6
--- /dev/null
+++ b/examples/render-quad/src/level.rs
@@ -0,0 +1,78 @@
+use stockton_levels::parts::{
+ data::{FaceRef, Geometry, TextureRef},
+ HasFaces, HasTextures, HasVisData, IsFace, IsTexture,
+};
+
+pub struct DemoLevel {
+ pub faces: Box<[Face]>,
+ pub textures: Box<[Texture]>,
+}
+
+impl DemoLevel {
+ fn face_idx(&self, search: &Face) -> FaceRef {
+ for (idx, face) in self.faces.iter().enumerate() {
+ if face == search {
+ return idx as u32;
+ }
+ }
+ panic!("face not in level")
+ }
+}
+
+#[derive(Debug, Clone, PartialEq)]
+pub struct Face {
+ pub geometry: Geometry,
+ pub texture_idx: TextureRef,
+}
+
+impl HasFaces for DemoLevel {
+ type Face = Face;
+
+ fn get_face(&self, index: FaceRef) -> Option<&Self::Face> {
+ self.faces.get(index as usize)
+ }
+}
+
+impl IsFace<DemoLevel> for Face {
+ fn index(&self, container: &DemoLevel) -> stockton_levels::parts::data::FaceRef {
+ container.face_idx(self)
+ }
+
+ fn geometry(&self, _container: &DemoLevel) -> Geometry {
+ self.geometry.clone()
+ }
+
+ fn texture_idx(&self, _container: &DemoLevel) -> TextureRef {
+ self.texture_idx
+ }
+}
+
+pub struct Texture {
+ pub name: String,
+}
+
+impl HasTextures for DemoLevel {
+ type Texture = Texture;
+
+ fn get_texture(&self, idx: TextureRef) -> Option<&Self::Texture> {
+ self.textures.get(idx as usize)
+ }
+}
+
+impl IsTexture for Texture {
+ fn name(&self) -> &str {
+ &self.name
+ }
+}
+
+impl<'a> HasVisData<'a> for DemoLevel {
+ type Faces = std::ops::Range<FaceRef>;
+
+ fn get_visible(
+ &'a self,
+ _transform: &stockton_types::components::Transform,
+ _settings: &stockton_types::components::CameraSettings,
+ ) -> Self::Faces {
+ 0..self.faces.len() as u32
+ }
+}
diff --git a/examples/render-quad/src/main.rs b/examples/render-quad/src/main.rs
new file mode 100644
index 0000000..b16c3d0
--- /dev/null
+++ b/examples/render-quad/src/main.rs
@@ -0,0 +1,229 @@
+//! Renders ./example.bsp geometry: (), texture_idx: () geometry: (), texture_idx: ()
+
+#[macro_use]
+extern crate stockton_input_codegen;
+
+#[macro_use]
+extern crate legion;
+
+use anyhow::{Context, Result};
+use log::warn;
+use std::collections::BTreeMap;
+
+use std::sync::{Arc, RwLock};
+use stockton_levels::parts::data::{Geometry, Vertex};
+use stockton_levels::types::Rgba;
+use stockton_render::draw::LevelDrawPass;
+use winit::{event::Event, event_loop::EventLoop, window::WindowBuilder};
+
+use egui::{containers::CentralPanel, Frame};
+use stockton_contrib::delta_time::*;
+use stockton_contrib::flycam::*;
+
+use stockton_input::{Axis, InputManager, Mouse};
+
+use stockton_render::error::full_error_display;
+use stockton_render::systems::*;
+use stockton_render::{Renderer, UiState, WindowEvent};
+
+use stockton_types::components::{CameraSettings, CameraVPMatrix, Transform};
+use stockton_types::{Session, Vector2, Vector3};
+
+mod level;
+use level::*;
+
+type Dp<'a> = LevelDrawPass<'a, DemoLevel>;
+
+#[derive(InputManager, Default, Clone, Debug)]
+struct MovementInputs {
+ #[axis]
+ x: Axis,
+
+ #[axis]
+ y: Axis,
+
+ #[axis]
+ z: Axis,
+}
+
+impl FlycamInput for MovementInputs {
+ fn get_x_axis(&self) -> &Axis {
+ &self.x
+ }
+ fn get_y_axis(&self) -> &Axis {
+ &self.y
+ }
+ fn get_z_axis(&self) -> &Axis {
+ &self.z
+ }
+}
+
+#[system]
+fn hello_world(#[resource] ui: &mut UiState) {
+ CentralPanel::default()
+ .frame(Frame::none())
+ .show(ui.ctx(), |ui| {
+ ui.heading("Hello, World!");
+ });
+}
+
+fn main() {
+ if let Err(err) = try_main() {
+ eprintln!("{}", full_error_display(err));
+ }
+}
+
+fn try_main<'a>() -> Result<()> {
+ // Initialise logger
+ simplelog::TermLogger::init(
+ log::LevelFilter::Debug,
+ simplelog::ConfigBuilder::new()
+ .set_max_level(log::LevelFilter::Debug)
+ .set_thread_mode(simplelog::ThreadLogMode::Names)
+ .build(),
+ simplelog::TerminalMode::Stderr,
+ simplelog::ColorChoice::Auto,
+ )
+ .context("Error initialising logger")?;
+
+ // Make a window
+ let event_loop = EventLoop::new();
+ let window = WindowBuilder::new()
+ .build(&event_loop)
+ .context("Error creating window")?;
+
+ if window.set_cursor_grab(true).is_err() {
+ warn!("warning: cursor not grabbed");
+ }
+ window.set_cursor_visible(false);
+
+ // TODO: Parse the map file
+ let map = Arc::new(RwLock::new(DemoLevel {
+ faces: vec![Face {
+ geometry: Geometry::Vertices(
+ Vertex {
+ position: Vector3::new(-128.0, 128.0, 128.0),
+ tex: Vector2::new(0.0, 0.0),
+ color: Rgba::from_slice(&[0, 0, 0, 1]),
+ },
+ Vertex {
+ position: Vector3::new(-128.0, -128.0, 128.0),
+ tex: Vector2::new(0.0, 1.0),
+ color: Rgba::from_slice(&[0, 0, 0, 1]),
+ },
+ Vertex {
+ position: Vector3::new(128.0, 128.0, 128.0),
+ tex: Vector2::new(1.0, 0.0),
+ color: Rgba::from_slice(&[0, 0, 0, 1]),
+ },
+ ),
+ texture_idx: 0,
+ }]
+ .into_boxed_slice(),
+ textures: vec![Texture {
+ name: "example_texture".to_string(),
+ }]
+ .into_boxed_slice(),
+ }));
+
+ // Create the UI State
+ let mut ui = UiState::new();
+
+ // Create the input manager
+ let manager = {
+ use stockton_input::InputMutation::*;
+ use MovementInputsFields::*;
+
+ let mut actions = BTreeMap::new();
+
+ actions.insert(17, (Z, PositiveAxis)); // W
+ actions.insert(30, (X, NegativeAxis)); // A
+ actions.insert(31, (Z, NegativeAxis)); // S
+ actions.insert(32, (X, PositiveAxis)); // D
+ actions.insert(29, (Y, NegativeAxis)); // Ctrl
+ actions.insert(57, (Y, PositiveAxis)); // Space
+
+ MovementInputsManager::new(actions)
+ };
+
+ let ratio = window.inner_size().width as f32 / window.inner_size().height as f32;
+
+ // Load everything into the session
+ let mut session = Session::new(
+ move |resources| {
+ resources.insert(map);
+ resources.insert(manager);
+ resources.insert(Timing::default());
+ resources.insert(Mouse::default());
+ },
+ move |schedule| {
+ schedule
+ .add_system(update_deltatime_system())
+ .add_system(process_window_events_system::<
+ MovementInputsManager,
+ Dp<'static>,
+ >())
+ .flush()
+ .add_system(hello_world_system())
+ .add_system(flycam_move_system::<MovementInputsManager>())
+ .flush()
+ .add_thread_local(calc_vp_matrix_system(ratio));
+ },
+ );
+
+ // Add our player entity
+ let player = session.world.push((
+ Transform {
+ position: Vector3::new(0.0, 0.0, 0.0),
+ rotation: Vector3::new(0.0, 0.0, 0.0),
+ },
+ CameraSettings {
+ far: 1024.0,
+ fov: 90.0,
+ near: 0.1,
+ },
+ CameraVPMatrix::default(),
+ FlycamControlled::new(512.0, 400.0),
+ ));
+
+ // Create the renderer
+ let (renderer, tx): (Renderer<Dp<'static>>, _) = Renderer::new(&window, &session, player)?;
+ let new_control_flow = renderer.update_control_flow.clone();
+
+ // Populate the initial UI state
+ ui.populate_initial_state(&renderer);
+
+ session.resources.insert(renderer);
+ session.resources.insert(ui);
+
+ // Done loading - This is our main loop.
+ // It just communicates events to the session and continuously ticks
+ event_loop.run(move |event, _, flow| {
+ match event {
+ Event::MainEventsCleared => {
+ window.request_redraw();
+ }
+ Event::RedrawRequested(_) => {
+ session.do_update();
+ let mut renderer = session
+ .resources
+ .get_mut::<Renderer<Dp<'static>>>()
+ .unwrap();
+ renderer.render(&session).unwrap();
+ }
+ _ => {
+ if let Some(we) = WindowEvent::from(&event) {
+ tx.send(we).unwrap()
+ }
+ }
+ }
+
+ // Update the control flow if the session has requested it.
+ {
+ let new_control_flow = new_control_flow.read().unwrap();
+ if *new_control_flow != *flow {
+ *flow = *new_control_flow;
+ }
+ };
+ });
+}