summaryrefslogtreecommitdiff
path: root/racer-tracer/src/main.rs
diff options
context:
space:
mode:
authorSakarias Johansson <sakarias.johansson@goodbyekansas.com>2023-04-09 19:11:39 +0200
committerSakarias Johansson <sakariasjohansson@hotmail.com>2023-04-14 16:39:04 +0200
commit0ae6ca062f5936ae6f595f45ca0a78ed049452bc (patch)
tree712111e3aa823de7dc85eadca8fd5f78124afa6b /racer-tracer/src/main.rs
parent5f8faa17457426c4ca8c54bf67b5aa96eb7a52ea (diff)
downloadracer-tracer-0ae6ca062f5936ae6f595f45ca0a78ed049452bc.tar.gz
racer-tracer-0ae6ca062f5936ae6f595f45ca0a78ed049452bc.tar.xz
racer-tracer-0ae6ca062f5936ae6f595f45ca0a78ed049452bc.zip
✨ Add scene controller
Wanted to be able to for example move around freely in the scene but also have something that would for example follow key frames and render a gif. Abstracted it with a scene controller. You can hook up keybinds and other thigns for it as well. Right now there is only the interactive scene controller which keep the behaviours previous to this change. Now I could possibly switch it out with something that uses key frames to render several images to create for example a gif. List of other Misc changes: - Add configuration setting for scene controller (`scene_controller`) - Add configuration setting for renderer - Add configuration setting for preview renderer (`preview_renderer`) - Add clone to Config. - Add from implementation for Renderer to be created from the config object. - Add cancel event to image action. An action could be blocking when the application wants to exit. Actions can now listen to the cancel event to exit early and not block. - Fixed bug where WaitForSignal action would block after application tries to exit. - Add method to KeyInputs to be able to take a list of callbacks instead of manually registering every callback one at the time.
Diffstat (limited to 'racer-tracer/src/main.rs')
-rw-r--r--racer-tracer/src/main.rs177
1 files changed, 49 insertions, 128 deletions
diff --git a/racer-tracer/src/main.rs b/racer-tracer/src/main.rs
index f950000..c31f09b 100644
--- a/racer-tracer/src/main.rs
+++ b/racer-tracer/src/main.rs
@@ -10,6 +10,7 @@ mod material;
mod ray;
mod renderer;
mod scene;
+mod scene_controller;
mod terminal;
mod util;
mod vec3;
@@ -25,9 +26,7 @@ use std::{
convert::TryFrom,
fs::OpenOptions,
path::Path,
- sync::RwLock,
time::{Duration, Instant},
- vec::Vec,
};
use minifb::{Key, Window, WindowOptions};
@@ -37,7 +36,7 @@ use synchronoise::SignalEvent;
use terminal::Terminal;
use crate::{
- renderer::{RenderData, Renderer},
+ scene_controller::{interactive::InteractiveScene, SceneController, SceneData},
vec3::Vec3,
};
@@ -45,22 +44,16 @@ use crate::{
camera::Camera,
config::{Args, Config},
error::TracerError,
- image_action::ImageAction,
key_inputs::KeyInputs,
- renderer::{cpu::CpuRenderer, cpu_scaled::CpuRendererScaled},
scene::Scene,
};
fn run(config: Config, log: Logger, term: Terminal) -> Result<(), TracerError> {
info!(log, "Starting racer-tracer {}", env!("CARGO_PKG_VERSION"));
- let renderer: &dyn Renderer = &CpuRenderer {} as &dyn Renderer;
- let renderer_preview: &dyn Renderer = &CpuRendererScaled {} as &dyn Renderer;
let image = image::Image::new(config.screen.width, config.screen.height);
- let screen_buffer: RwLock<Vec<u32>> = RwLock::new(vec![0; image.width * image.height]);
let look_from = Vec3::new(13.0, 2.0, 3.0);
let look_at = Vec3::new(0.0, 0.0, 0.0);
- let camera_speed = 2.0;
- let camera = RwLock::new(Camera::new(
+ let camera = Camera::new(
look_from,
look_at,
Vec3::new(0.0, 1.0, 0.0),
@@ -68,120 +61,42 @@ fn run(config: Config, log: Logger, term: Terminal) -> Result<(), TracerError> {
&image,
0.1,
10.0,
- ));
-
+ );
let scene = Scene::try_new(&config.loader)?;
-
let mut window_res: Result<(), TracerError> = Ok(());
let mut render_res: Result<(), TracerError> = Ok(());
-
- let render_image = SignalEvent::manual(false);
let exit = SignalEvent::manual(false);
- let image_action: Box<dyn ImageAction> = (&config.image_action).into();
-
- // Setting up controls
- let mut key_inputs = KeyInputs::new(log.new(o!("scope" => "key-intputs")));
- let render_image_fn = |_| {
- render_image.signal();
- Ok(())
- };
- key_inputs.release(Key::R, &render_image_fn);
-
- let go_forward = |dt: f64| {
- camera
- .write()
- .map_err(|e| TracerError::KeyError(e.to_string()))
- .map(|mut cam| {
- cam.go_forward(-dt * camera_speed);
- })
- };
- key_inputs.down(Key::W, &go_forward);
-
- let go_back = |dt: f64| {
- camera
- .write()
- .map_err(|e| TracerError::KeyError(e.to_string()))
- .map(|mut cam| {
- cam.go_forward(dt * camera_speed);
- })
+ let scene_controller = {
+ match &config.scene_controller {
+ config::ConfigSceneController::Interactive => {
+ let camera_speed = 0.000002;
+ InteractiveScene::new(
+ SceneData {
+ log: log.new(o!("scope" => "scene-controller")),
+ term,
+ config: config.clone(),
+ scene,
+ camera,
+ image: image.clone(),
+ },
+ camera_speed,
+ )
+ }
+ }
};
- key_inputs.down(Key::S, &go_back);
- let go_left = |dt: f64| {
- camera
- .write()
- .map_err(|e| TracerError::KeyError(e.to_string()))
- .map(|mut cam| {
- cam.go_right(-dt * camera_speed);
- })
- };
- key_inputs.down(Key::A, &go_left);
-
- let go_right = |dt: f64| {
- camera
- .write()
- .map_err(|e| TracerError::KeyError(e.to_string()))
- .map(|mut cam| {
- cam.go_right(dt * camera_speed);
- })
- };
- key_inputs.down(Key::D, &go_right);
+ let mut inputs = KeyInputs::new(log.new(o!("scope" => "key-inputs")));
+ inputs.register_inputs(scene_controller.get_inputs());
rayon::scope(|s| {
+ // Render
s.spawn(|_| {
while render_res.is_ok() {
render_res = (!exit.wait_timeout(Duration::from_secs(0)))
.then_some(|| ())
.ok_or(TracerError::ExitEvent)
- .and_then(|_| {
- render_image
- .wait_timeout(Duration::from_secs(0))
- .then_some(|| ())
- .map_or_else(
- || {
- render_image.reset();
- // Render preview
- renderer_preview.render(RenderData {
- buffer: &screen_buffer,
- camera: &camera,
- image: &image,
- scene: &scene,
- config: &config,
- cancel_event: None,
- })
- },
- |_| {
- render_image.reset();
- let render_time = Instant::now();
- renderer
- .render(RenderData {
- buffer: &screen_buffer,
- camera: &camera,
- image: &image,
- scene: &scene,
- config: &config,
- cancel_event: Some(&render_image),
- })
- .and_then(|_| {
- info!(
- log,
- "It took {} seconds to render the image.",
- Instant::now()
- .duration_since(render_time)
- .as_secs()
- );
- image_action.action(
- &screen_buffer,
- &render_image,
- &config,
- log.new(o!("scope" => "image-action")),
- &term,
- )
- })
- },
- )
- });
+ .and_then(|_| scene_controller.render());
}
if render_res.is_err() {
@@ -189,6 +104,7 @@ fn run(config: Config, log: Logger, term: Terminal) -> Result<(), TracerError> {
}
});
+ // Update
s.spawn(|_| {
window_res = Window::new(
"racer-tracer",
@@ -201,27 +117,32 @@ fn run(config: Config, log: Logger, term: Terminal) -> Result<(), TracerError> {
window.limit_update_rate(Some(std::time::Duration::from_micros(16600)));
window
})
- .and_then(|mut window| {
+ .map(|mut window| {
let mut t = Instant::now();
- while window.is_open() && !window.is_key_down(Key::Escape) && !exit.status() {
- let dt = t.elapsed().as_micros() as f64 / 1000000.0;
+ while window_res.is_ok()
+ && window.is_open()
+ && !window.is_key_down(Key::Escape)
+ && !exit.status()
+ {
+ let dt = t.elapsed().as_micros() as f64;
t = Instant::now();
- key_inputs.update(&window, dt);
- // Sleep a bit to not hog the lock on the buffer all the time.
- std::thread::sleep(std::time::Duration::from_millis(1));
-
- screen_buffer
- .read()
- .map_err(|e| TracerError::FailedToUpdateWindow(e.to_string()))
- .and_then(|buf| {
- window
- .update_with_buffer(&buf, image.width, image.height)
- .map_err(|e| TracerError::FailedToUpdateWindow(e.to_string()))
- })?
+ inputs.update(&window, dt);
+
+ window_res =
+ scene_controller
+ .get_buffer()
+ .and_then(|maybe_buf| match maybe_buf {
+ Some(buf) => window
+ .update_with_buffer(&buf, image.width, image.height)
+ .map_err(|e| TracerError::FailedToUpdateWindow(e.to_string())),
+ None => {
+ window.update();
+ Ok(())
+ }
+ });
}
exit.signal();
- render_image.signal();
- Ok(())
+ scene_controller.stop()
});
});
});
@@ -265,7 +186,7 @@ fn main() {
Err(TracerError::ExitEvent) => {}
Ok(_) => {}
Err(e) => {
- error!(log, "{}", e);
+ error!(log, "Error: {}", e);
let exit_code = i32::from(e);
error!(log, "Exiting with: {}", exit_code);
std::process::exit(exit_code)