From 907d15f64345a92550a839eee2559f291826fbf7 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Sun, 3 Jan 2016 00:09:23 -0800 Subject: [PATCH] Started creating an interface for surfaces. Testing it out by making a bogus TriangleMesh surface type. --- src/main.rs | 15 +++------- src/parse/psy.rs | 14 ++++++---- src/renderer.rs | 49 ++++++++++++++++---------------- src/surface/mod.rs | 23 +++++++++++++++ src/surface/triangle_mesh.rs | 54 ++++++++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+), 42 deletions(-) create mode 100644 src/surface/mod.rs create mode 100644 src/surface/triangle_mesh.rs diff --git a/src/main.rs b/src/main.rs index 0809536..c49179d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ mod parse; mod renderer; mod image; mod triangle; +mod surface; mod bvh; mod halton; @@ -21,9 +22,9 @@ use docopt::Docopt; use math::{Point, Matrix4x4}; use ray::Ray; -use bbox::BBox; use camera::Camera; use renderer::Renderer; +use surface::triangle_mesh::TriangleMesh; // ---------------------------------------------------------------- @@ -73,7 +74,7 @@ fn main() { println!("Ray size: {} bytes", mem::size_of::()); // Generate a scene of triangles - let mut triangles = { + let mesh = TriangleMesh::from_triangles({ let mut triangles = Vec::new(); let xres = 32; let yres = 32; @@ -97,14 +98,6 @@ fn main() { } } triangles - }; - let accel = bvh::BVH::from_objects(&mut triangles[..], 3, |tri| { - let minimum = tri.0.min(tri.1.min(tri.2)); - let maximum = tri.0.max(tri.1.max(tri.2)); - BBox { - min: minimum, - max: maximum, - } }); println!("Scene built."); @@ -118,7 +111,7 @@ fn main() { resolution: (512, 512), spp: samples_per_pixel as usize, camera: cam, - scene: (triangles, accel), + scene: mesh, }; r.render(); diff --git a/src/parse/psy.rs b/src/parse/psy.rs index b1f7224..a1f7d9a 100644 --- a/src/parse/psy.rs +++ b/src/parse/psy.rs @@ -1,7 +1,9 @@ -// use renderer::Renderer; -// -// use super::DataTree; +#![allow(dead_code)] -// pub fn parse_frame<'a>(tree: &DataTree) -> Renderer<'a> { -// unimplemented!() -// } +use renderer::Renderer; + +use super::DataTree; + +pub fn parse_frame(tree: &DataTree) -> Renderer { + unimplemented!() +} diff --git a/src/renderer.rs b/src/renderer.rs index 045e458..fffb6ed 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -1,18 +1,20 @@ +#![allow(dead_code)] + use std::path::Path; use camera::Camera; use halton; -use math::{Point, fast_logit}; +use math::fast_logit; use image::Image; -use bvh::BVH; -use triangle; +use surface; +use surface::Surface; pub struct Renderer { pub output_file: String, pub resolution: (usize, usize), pub spp: usize, pub camera: Camera, - pub scene: (Vec<(Point, Point, Point)>, BVH), + pub scene: surface::triangle_mesh::TriangleMesh, } impl Renderer { @@ -44,39 +46,36 @@ impl Renderer { }; ray.id = si as u32; rays.push(ray); - isects.push((false, 0.0, 0.0)); + isects.push(surface::SurfaceIntersection::Miss); } // Test rays against scene - self.scene.1.traverse(&mut rays, &self.scene.0, |tri, rs| { - for r in rs { - if let Some((t, tri_u, tri_v)) = triangle::intersect_ray(r, *tri) { - if t < r.max_t { - isects[r.id as usize] = (true, tri_u, tri_v); - r.max_t = t; - } - } - } - }); + self.scene.intersect_rays(&mut rays, &mut isects); // Calculate color based on ray hits let mut r = 0.0; let mut g = 0.0; let mut b = 0.0; - for &(hit, u, v) in isects.iter() { - if hit { - r += u; - g += v; - b += (1.0 - u - v).max(0.0); + for isect in isects.iter() { + if let &surface::SurfaceIntersection::Hit{ + t: _, + pos: _, + nor: _, + space: _, + uv, + } = isect { + r += uv.0; + g += uv.1; + b += (1.0 - uv.0 - uv.1).max(0.0); } else { r += 0.02; g += 0.02; b += 0.02; } } - r = 255.0 * sRGB_gamma(r / self.spp as f32); - g = 255.0 * sRGB_gamma(g / self.spp as f32); - b = 255.0 * sRGB_gamma(b / self.spp as f32); + r = 255.0 * srgb_gamma(r / self.spp as f32); + g = 255.0 * srgb_gamma(g / self.spp as f32); + b = 255.0 * srgb_gamma(b / self.spp as f32); // Set pixel color img.set(x, y, (r as u8, g as u8, b as u8)); @@ -102,7 +101,7 @@ fn hash_u32(n: u32, seed: u32) -> u32 { } -fn sRGB_gamma(n: f32) -> f32 { +fn srgb_gamma(n: f32) -> f32 { if n < 0.0031308 { n * 12.92 } else { @@ -110,7 +109,7 @@ fn sRGB_gamma(n: f32) -> f32 { } } -fn sRGB_inv_gamma(n: f32) -> f32 { +fn srgb_inv_gamma(n: f32) -> f32 { if n < 0.04045 { n / 12.92 } else { diff --git a/src/surface/mod.rs b/src/surface/mod.rs new file mode 100644 index 0000000..78c04e4 --- /dev/null +++ b/src/surface/mod.rs @@ -0,0 +1,23 @@ +#![allow(dead_code)] + +pub mod triangle_mesh; + +use ray::Ray; +use math::{Point, Normal, Matrix4x4}; + + +pub enum SurfaceIntersection { + Miss, + Occlude, + Hit { + t: f32, + pos: Point, + nor: Normal, + space: Matrix4x4, + uv: (f32, f32), + }, +} + +pub trait Surface { + fn intersect_rays(&self, rays: &mut [Ray], isects: &mut [SurfaceIntersection]); +} diff --git a/src/surface/triangle_mesh.rs b/src/surface/triangle_mesh.rs new file mode 100644 index 0000000..a809527 --- /dev/null +++ b/src/surface/triangle_mesh.rs @@ -0,0 +1,54 @@ +#![allow(dead_code)] + +use math::{Point, Normal, Matrix4x4}; +use ray::Ray; +use triangle; +use bbox::BBox; +use bvh::BVH; + +use super::{Surface, SurfaceIntersection}; + +pub struct TriangleMesh { + geo: Vec<(Point, Point, Point)>, + accel: BVH, +} + +impl TriangleMesh { + pub fn from_triangles(mut triangles: Vec<(Point, Point, Point)>) -> TriangleMesh { + let accel = BVH::from_objects(&mut triangles[..], 3, |tri| { + let minimum = tri.0.min(tri.1.min(tri.2)); + let maximum = tri.0.max(tri.1.max(tri.2)); + BBox { + min: minimum, + max: maximum, + } + }); + + TriangleMesh { + geo: triangles, + accel: accel, + } + } +} + + +impl Surface for TriangleMesh { + fn intersect_rays(&self, rays: &mut [Ray], isects: &mut [SurfaceIntersection]) { + self.accel.traverse(&mut rays[..], &self.geo, |tri, rs| { + for r in rs { + if let Some((t, tri_u, tri_v)) = triangle::intersect_ray(r, *tri) { + if t < r.max_t { + isects[r.id as usize] = SurfaceIntersection::Hit { + t: t, + pos: r.orig + (r.dir * t), + nor: Normal::new(0.0, 0.0, 0.0), // TODO + space: Matrix4x4::new(), // TODO + uv: (tri_u, tri_v), + }; + r.max_t = t; + } + } + } + }); + } +}