Moved ray tracing responsibilities to the Tracer.

This is still pretty WIP, but it at least gets the functionality
back to where it was before.
This commit is contained in:
Nathan Vegdahl 2016-03-13 13:01:10 -07:00
parent e96798ab6b
commit f6891173eb
5 changed files with 70 additions and 26 deletions

View File

@ -9,19 +9,19 @@ use ray::Ray;
#[derive(Debug)]
pub struct Assembly {
// Instance list
instances: Vec<Instance>,
xforms: Vec<Matrix4x4>,
pub instances: Vec<Instance>,
pub xforms: Vec<Matrix4x4>,
// Object list
objects: Vec<Object>,
pub objects: Vec<Object>,
object_map: HashMap<String, usize>, // map Name -> Index
// Assembly list
assemblies: Vec<Assembly>,
pub assemblies: Vec<Assembly>,
assembly_map: HashMap<String, usize>, // map Name -> Index
// Object accel
object_accel: BVH,
pub object_accel: BVH,
}
impl Assembly {
@ -37,17 +37,6 @@ impl Assembly {
}
}
// TODO: this is just temporary. Remove this and move tracing functionality
// into the tracer.
pub fn intersect_rays(&self, rays: &mut [Ray], isects: &mut [SurfaceIntersection]) {
for obj in self.objects.iter() {
match obj {
&Object::Surface(ref surface) => {
surface.intersect_rays(rays, isects);
}
}
}
}
pub fn add_object(&mut self, name: &str, obj: Object) {
@ -64,7 +53,7 @@ pub enum Object {
#[derive(Debug, Copy, Clone)]
enum Instance {
pub enum Instance {
Object {
data_index: usize,
transform_indices: (usize, usize),

View File

@ -2,6 +2,7 @@
use std::path::Path;
use tracer::Tracer;
use camera::Camera;
use halton;
use math::fast_logit;
@ -21,7 +22,7 @@ pub struct Renderer {
impl Renderer {
pub fn render(&self) {
let mut rays = Vec::new();
let mut isects = Vec::new();
let mut tracer = Tracer::from_assembly(&self.scene.root);
let mut img = Image::new(self.resolution.0, self.resolution.1);
// Render image of ray-traced triangle
@ -34,7 +35,6 @@ impl Renderer {
// Generate rays
rays.clear();
isects.clear();
for si in 0..self.spp {
let mut ray = {
let filter_x = fast_logit(halton::sample(3, offset + si as u32), 1.5);
@ -47,11 +47,10 @@ impl Renderer {
};
ray.id = si as u32;
rays.push(ray);
isects.push(surface::SurfaceIntersection::Miss);
}
// Test rays against scene
self.scene.root.intersect_rays(&mut rays, &mut isects);
let isects = tracer.trace(&rays);
// Calculate color based on ray hits
let mut r = 0.0;

View File

@ -8,7 +8,7 @@ use ray::Ray;
use math::{Point, Normal, Matrix4x4};
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum SurfaceIntersection {
Miss,
Occlude,

View File

@ -1,10 +1,63 @@
use std::iter;
use std::slice;
use math::Matrix4x4;
use assembly::{Assembly, Object};
use ray::Ray;
use surface::SurfaceIntersection;
pub struct Tracer<'a> {
root: &'a Assembly,
rays: Vec<Ray>, // Should only be used from trace(), not any other methods
xform_stack: Vec<Matrix4x4>,
world_rays: &'a [Ray],
intersections: &'a mut [SurfaceIntersection],
rays: Vec<Ray>,
isects: Vec<SurfaceIntersection>,
}
impl<'a> Tracer<'a> {
pub fn from_assembly(assembly: &'a Assembly) -> Tracer<'a> {
Tracer {
root: assembly,
xform_stack: Vec::new(),
rays: Vec::new(),
isects: Vec::new(),
}
}
pub fn trace<'b>(&'b mut self, wrays: &[Ray]) -> &'b [SurfaceIntersection] {
// Ready the rays
self.rays.clear();
self.rays.reserve(wrays.len());
self.rays.extend(wrays.iter());
// Ready the isects
self.isects.clear();
self.isects.reserve(wrays.len());
self.isects.extend(iter::repeat(SurfaceIntersection::Miss).take(wrays.len()));
// Start tracing
let ray_refs = unsafe {
// IMPORTANT NOTE:
// We're creating an unsafe non-lifetime-bound slice of self.rays
// here so that we can pass it to trace_assembly() without
// conflicting with self.
// Because of this, it is absolutely CRITICAL that self.rays
// NOT be used in any other methods. The rays should only be
// accessed in other methods via the mutable slice passed directly
// to them in their function parameters.
slice::from_raw_parts_mut(self.rays.as_mut_ptr(), self.rays.len())
};
self.trace_assembly(self.root, wrays, ray_refs);
return &self.isects;
}
fn trace_assembly<'b>(&'b mut self, assembly: &Assembly, wrays: &[Ray], rays: &mut [Ray]) {
for obj in assembly.objects.iter() {
match obj {
&Object::Surface(ref surface) => {
surface.intersect_rays(rays, &mut self.isects);
}
}
}
}
}

View File

@ -1 +1,4 @@
- Implement a basic camera.
- Implement a Tracer to handle ray tracing responsibilities, with hierarchical
instancing, etc.
- Basic scene parsing with triangle meshes.
- Unit tests for scene parsing.