Skip to content

Commit

Permalink
make it easier to debug ray tracing
Browse files Browse the repository at this point in the history
Jakub Hlusička committed Aug 31, 2016
1 parent 1122fd0 commit a349365
Showing 6 changed files with 91 additions and 26 deletions.
11 changes: 11 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@ fn main() {

fn run<F: CustomFloat>() {
const ARG_SCENE: &'static str = "SCENE";
const ARG_DEBUG: &'static str = "DEBUG";

let matches = App::new("euclider")
.version(crate_version!())
@@ -66,9 +67,14 @@ fn run<F: CustomFloat>() {
.help("Loads a `.json` scene file")
.takes_value(true)
.required(true))
.arg(Arg::with_name(ARG_DEBUG)
.short("d")
.long("debug")
.help("Displays debug info"))
.get_matches();

let scene = matches.value_of(ARG_SCENE).unwrap();
let debug = matches.is_present(ARG_DEBUG);
let mut reader = BufReader::new(File::open(scene)
.expect("Unable to find the scene file."));
let mut json = String::new();
@@ -80,7 +86,12 @@ fn run<F: CustomFloat>() {
let simulation = Simulation::builder()
.environment(*environment)
.threads(num_cpus::get() as u32)
.debug(debug)
.build();

if debug {
println!("Running in debug mode.");
}

simulation.start();
}
32 changes: 28 additions & 4 deletions src/simulation.rs
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ use universe::Environment;
use util::CustomFloat;

pub struct Simulation<F: CustomFloat> {
debug: bool,
threads: u32,
environment: Box<Environment<F>>,
facade: Option<GlutinFacade>,
@@ -34,6 +35,7 @@ pub struct Simulation<F: CustomFloat> {
pub struct SimulationBuilder<F: CustomFloat> {
environment: Option<Box<Environment<F>>>,
threads: Option<u32>,
debug: bool,
float_precision: PhantomData<F>,
}

@@ -101,7 +103,7 @@ impl<F: CustomFloat> Simulation<F> {
}

self.last_updated_instant = Some(now);
let result = self.context.update(self.facade.as_mut().unwrap());
let result = self.context.update(self.facade.as_mut().unwrap(), self.debug);

self.environment.update(&delta, &self.context);

@@ -112,6 +114,7 @@ impl<F: CustomFloat> Simulation<F> {
SimulationBuilder {
environment: None,
threads: None,
debug: false,
float_precision: PhantomData,
}
}
@@ -128,8 +131,14 @@ impl<F: CustomFloat> SimulationBuilder<F> {
self
}

pub fn debug(mut self, debug: bool) -> Self {
self.debug = debug;
self
}

pub fn build(self) -> Simulation<F> {
Simulation {
debug: self.debug,
threads: self.threads.expect("Specify the number of threads before building the simulation."),
environment: self.environment.expect("Specify the environment before bulding the simulation."),
facade: None,
@@ -148,6 +157,7 @@ pub struct SimulationContext {
pub mouse: Point2<i32>,
pub delta_mouse: Vector2<i32>,
pub resolution: u32,
pub debugging: bool,
}

impl SimulationContext {
@@ -158,6 +168,7 @@ impl SimulationContext {
mouse: na::origin(),
delta_mouse: na::zero(),
resolution: 8,
debugging: false,
}
}

@@ -178,21 +189,34 @@ impl SimulationContext {
}

#[allow(unused_variables)]
pub fn update(&mut self, facade: &mut GlutinFacade) -> Result<(), Event> {
pub fn update(&mut self, facade: &mut GlutinFacade, debug: bool) -> Result<(), Event> {
self.reset_delta_mouse();
for event in facade.poll_events() {
match event {
Event::KeyboardInput(state, character, Some(virtual_code)) => {
match state {
ElementState::Pressed => {
self.pressed_keys.insert(virtual_code);

if debug && virtual_code == VirtualKeyCode::LAlt {
self.debugging = true;
}
}
ElementState::Released => {
self.pressed_keys.remove(&virtual_code);

if virtual_code == VirtualKeyCode::Escape {
return Err(event);
match virtual_code {
VirtualKeyCode::Escape => {
return Err(event);
},
VirtualKeyCode::LAlt => {
if debug {
self.debugging = false;
}
},
_ => ()
}

}
};
}
6 changes: 4 additions & 2 deletions src/universe/d3/entity/camera.rs
Original file line number Diff line number Diff line change
@@ -194,7 +194,8 @@ impl<F: CustomFloat> Camera<F, Point3<F>, Vector3<F>> for PitchYawCamera3<F> {
= universe.trace_path_unknown(delta_time,
&distance,
&self.data.location,
&direction) {
&direction,
context.debugging) {
let rotation_scale = direction.angle_between(&new_direction);

if !ApproxEq::approx_eq_ulps(&rotation_scale,
@@ -391,7 +392,8 @@ impl<F: CustomFloat> Camera<F, Point3<F>, Vector3<F>> for FreeCamera3<F> {
= universe.trace_path_unknown(delta_time,
&distance,
&self.data.location,
&direction) {
&direction,
context.debugging) {
let rotation_scale = direction.angle_between(&new_direction);

if !ApproxEq::approx_eq_ulps(&rotation_scale,
3 changes: 2 additions & 1 deletion src/universe/d4/entity/camera.rs
Original file line number Diff line number Diff line change
@@ -199,7 +199,8 @@ impl<F: CustomFloat> Camera<F, Point4<F>, Vector4<F>> for FreeCamera4<F> {
= universe.trace_path_unknown(delta_time,
&distance,
&self.location,
&direction) {
&direction,
context.debugging) {
let rotation_scale = direction.angle_between(&new_direction);

if !ApproxEq::approx_eq_ulps(&rotation_scale,
1 change: 1 addition & 0 deletions src/universe/entity/shape.rs
Original file line number Diff line number Diff line change
@@ -108,6 +108,7 @@ pub struct TracingContext<'a,
P: 'a + CustomPoint<F, V>,
V: 'a + CustomVector<F, P>>
{
pub debugging: bool,
pub time: Duration,
pub origin_traceable: &'a Traceable<F, P, V>,
pub origin_location: P,
64 changes: 45 additions & 19 deletions src/universe/mod.rs
Original file line number Diff line number Diff line change
@@ -86,6 +86,7 @@ pub trait Universe<F: CustomFloat>
belongs_to: &'a Traceable<F, Self::P, Self::V>,
location: &Self::P,
direction: &Self::V,
debug: bool,
filter: &Fn(&Traceable<F, Self::P, Self::V>) -> bool)
-> Option<TraceResult<'a, F, Self::P, Self::V>> {
let material = belongs_to.material();
@@ -124,6 +125,7 @@ pub trait Universe<F: CustomFloat>
if closest_distance.is_none() ||
closest_distance.unwrap() > intersection.distance {
let context = TracingContext {
debugging: debug,
time: *time,
origin_traceable: belongs_to,
origin_location: *location,
@@ -149,10 +151,11 @@ pub trait Universe<F: CustomFloat>
max_depth: &u32,
belongs_to: &Traceable<F, Self::P, Self::V>,
location: &Self::P,
direction: &Self::V)
direction: &Self::V,
debug: bool)
-> Rgba<F> {
if *max_depth > 0 {
let result = self.trace_closest(time, belongs_to, location, direction, &|other| {
let result = self.trace_closest(time, belongs_to, location, direction, debug, &|other| {
other.surface().is_some()
});

@@ -163,7 +166,7 @@ pub trait Universe<F: CustomFloat>
general: general_context,
depth_remaining: max_depth,
trace: &|time, traceable, location, direction| {
self.trace(time, &(*max_depth - 1), traceable, location, direction)
self.trace(time, &(*max_depth - 1), traceable, location, direction, debug)
},
material_at: &|point| {
self.material_at(point)
@@ -185,9 +188,10 @@ pub trait Universe<F: CustomFloat>
distance: &F,
belongs_to: &Traceable<F, Self::P, Self::V>,
location: &Self::P,
direction: &Self::V)
direction: &Self::V,
debug: bool)
-> (Self::P, Self::V) {
let result = self.trace_closest(time, belongs_to, location, direction, &|other| {
let result = self.trace_closest(time, belongs_to, location, direction, debug, &|other| {
other.surface().is_some()
});

@@ -198,7 +202,7 @@ pub trait Universe<F: CustomFloat>
general: general_context,
distance: distance,
trace: &|time, distance, traceable, location, direction| {
self.trace_path(time, distance, traceable, location, direction)
self.trace_path(time, distance, traceable, location, direction, debug)
},
material_at: &|point| {
self.material_at(point)
@@ -250,15 +254,17 @@ pub trait Universe<F: CustomFloat>
time: &Duration,
max_depth: &u32,
location: &Self::P,
direction: &Self::V)
direction: &Self::V,
debug: bool)
-> Option<Rgb<F>> {
self.material_at(location).map(|belongs_to| {
let mut transitioned_direction = *direction;
belongs_to.material().enter(location, &mut transitioned_direction);
let background =
Rgba::from(Rgb::new(Cast::from(1.0), Cast::from(1.0), Cast::from(1.0)))
.into_premultiplied();
let foreground = self.trace(time, max_depth, belongs_to, location, &transitioned_direction)
let foreground = self.trace(time, max_depth, belongs_to, location,
&transitioned_direction, debug)
.into_premultiplied();
Rgb::from_premultiplied(foreground.over(background))
})
@@ -268,13 +274,14 @@ pub trait Universe<F: CustomFloat>
time: &Duration,
distance: &F,
location: &Self::P,
direction: &Self::V)
direction: &Self::V,
debug: bool)
-> Option<(Self::P, Self::V)> {
self.material_at(location).map(|belongs_to| {
let mut transitioned_direction = *direction;

belongs_to.material().enter(location, &mut transitioned_direction);
self.trace_path(time, distance, belongs_to, location, &transitioned_direction)
self.trace_path(time, distance, belongs_to, location, &transitioned_direction, debug)
})
}
}
@@ -287,7 +294,8 @@ pub trait Environment<F: CustomFloat>: Sync {
screen_x: i32,
screen_y: i32,
screen_width: i32,
screen_height: i32)
screen_height: i32,
debug: bool)
-> Rgb<F>;
fn render(&self,
dimensions: (u32, u32),
@@ -302,18 +310,35 @@ pub trait Environment<F: CustomFloat>: Sync {
let max_depth = self.max_depth();
let mut data: Vec<u8> = vec!(0; (buffer_width * buffer_height) as usize * COLOR_DIM);
let mut pool = Pool::new(threads);
let buffer_width_half = buffer_width / 2;
let buffer_height_half = buffer_height / 2;

pool.scoped(|scope| {
for (index, chunk) in &mut data.chunks_mut(COLOR_DIM).enumerate() {
scope.execute(move || {
let x = index as u32 % buffer_width;
let y = index as u32 / buffer_width;
let color = self.trace_screen_point(time,
&max_depth,
x as i32,
y as i32,
buffer_width as i32,
buffer_height as i32);
let debug_pixel = context.debugging
&& x == buffer_width_half
&& y == buffer_height_half;
let debug_pixel_surrounding = context.debugging
&& (x == buffer_width_half
&& (y == buffer_height_half - 1
|| y == buffer_height_half + 1)
|| y == buffer_height_half
&& (x == buffer_width_half - 1
|| x == buffer_width_half + 1));
let color = if debug_pixel_surrounding {
Rgb::new_u8(255, 0, 0)
} else {
self.trace_screen_point(time,
&max_depth,
x as i32,
y as i32,
buffer_width as i32,
buffer_height as i32,
debug_pixel)
};
let color = image::Rgb { data: color.to_pixel() };

for (i, result) in chunk.iter_mut().enumerate() {
@@ -349,14 +374,15 @@ impl<F: CustomFloat, P: CustomPoint<F, V>, V: CustomVector<F, P>, U: Universe<F,
screen_x: i32,
screen_y: i32,
screen_width: i32,
screen_height: i32)
screen_height: i32,
debug: bool)
-> Rgb<F> {
let camera = self.camera().try_read()
.expect("Could not get the origin location and direction, the camera is mutably borrowed.");
let point = camera.get_ray_point(screen_x, screen_y, screen_width, screen_height);
let vector = camera.get_ray_vector(screen_x, screen_y, screen_width, screen_height);

match self.trace_unknown(time, max_depth, &point, &vector) {
match self.trace_unknown(time, max_depth, &point, &vector, debug) {
Some(color) => color,
None => {
let checkerboard_size = 8;

0 comments on commit a349365

Please sign in to comment.