Started creating an interface for surfaces.

Testing it out by making a bogus TriangleMesh surface type.
This commit is contained in:
Nathan Vegdahl 2016-01-03 00:09:23 -08:00
parent d7f6142749
commit 907d15f643
5 changed files with 113 additions and 42 deletions

View File

@ -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::<Ray>());
// 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();

View File

@ -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!()
}

View File

@ -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 {

23
src/surface/mod.rs Normal file
View File

@ -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]);
}

View File

@ -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;
}
}
}
});
}
}