Got the bare beginnings of scene file parsing and rendering working.

It still doesn't parse or render any actual objects in the scene,
so all renders are just black.  But the basic structures are in
place.  Yay!
This commit is contained in:
Nathan Vegdahl 2016-05-21 15:14:10 -07:00
parent 4988a6d1e6
commit f5dd8f7a14
5 changed files with 221 additions and 110 deletions

View File

@ -178,6 +178,10 @@ impl BVH {
pub fn traverse<T, F>(&self, rays: &mut [Ray], objects: &[T], mut obj_ray_test: F)
where F: FnMut(&T, &mut [Ray])
{
if self.nodes.len() == 0 {
return;
}
let mut i_stack = [0; 65];
let mut ray_i_stack = [rays.len(); 65];
let mut stack_ptr = 1;

View File

@ -36,7 +36,7 @@ use scene::Scene;
use assembly::{AssemblyBuilder, Object};
use renderer::Renderer;
use surface::triangle_mesh::TriangleMesh;
use parse::DataTree;
use parse::{parse_scene, DataTree};
// ----------------------------------------------------------------
@ -81,76 +81,86 @@ fn main() {
return;
}
// =======================
// Print tree from psy file if passed as an argument.
// TODO: remove this, because it's for debugging
if let Some(fp) = args.flag_input {
let mut f = io::BufReader::new(File::open(fp).unwrap());
// Parse data tree of scene file
let mut s = String::new();
let dt = if let Some(fp) = args.flag_input {
let mut f = io::BufReader::new(File::open(fp).unwrap());
let _ = f.read_to_string(&mut s);
let dt = DataTree::from_str(&s);
println!("{:#?}", dt);
return;
}
// =======================
DataTree::from_str(&s).unwrap()
} else {
panic!()
};
// Generate a scene of triangles
// let mesh = TriangleMesh::from_triangles(2, {
// let mut triangles = Vec::new();
// let xres = 32;
// let yres = 32;
// let xinc = 512.0 / (xres as f32);
// let yinc = 512.0 / (yres as f32);
// for x in 0..xres {
// for y in 0..yres {
// let i = y * xres + x;
// let cx = halton::sample(0, i) * 512.0;
// let cy = halton::sample(1, i) * 512.0;
// let cz = halton::sample(2, i) * 512.0;
// let cx = x as f32 * xinc;
// let cy = y as f32 * yinc;
// let cz = 1.0;
// triangles.push((Point::new(cx, cy, cz + 1.0),
// Point::new(cx + xinc, cy, cz + 1.1),
// Point::new(cx, cy + yinc, cz + 1.2)));
// triangles.push((Point::new(cx + 25.0, cy, cz + 1.0),
// Point::new(cx + 25.0 + xinc, cy, cz + 1.1),
// Point::new(cx + 25.0, cy + yinc, cz + 1.2)));
// }
// }
// triangles
// });
//
// let cam = Camera::new(vec![Matrix4x4::from_location(Point::new(256.0, 256.0, -1024.0))],
// vec![0.785],
// vec![20.0],
// vec![1026.0]);
//
// let mut assembly_b = AssemblyBuilder::new();
// assembly_b.add_object("yar", Object::Surface(Box::new(mesh)));
// assembly_b.add_object_instance("yar",
// Some(&[Matrix4x4::from_location(Point::new(25.0, 0.0, 0.0))]));
// let assembly = assembly_b.build();
//
// let scene = Scene {
// name: None,
// background_color: (0.0, 0.0, 0.0),
// camera: cam,
// root: assembly,
// };
//
// let r = Renderer {
// output_file: args.arg_imgpath.clone(),
// resolution: (512, 512),
// spp: samples_per_pixel as usize,
// scene: scene,
// };
//
println!("Scene built.");
let samples_per_pixel = args.flag_spp.unwrap_or_else(|| 16);
println!("Sample count: {}", samples_per_pixel);
println!("Ray size: {} bytes", mem::size_of::<Ray>());
// Generate a scene of triangles
let mesh = TriangleMesh::from_triangles(2, {
let mut triangles = Vec::new();
let xres = 32;
let yres = 32;
let xinc = 512.0 / (xres as f32);
let yinc = 512.0 / (yres as f32);
for x in 0..xres {
for y in 0..yres {
let i = y * xres + x;
let cx = halton::sample(0, i) * 512.0;
let cy = halton::sample(1, i) * 512.0;
let cz = halton::sample(2, i) * 512.0;
// let cx = x as f32 * xinc;
// let cy = y as f32 * yinc;
// let cz = 1.0;
triangles.push((Point::new(cx, cy, cz + 1.0),
Point::new(cx + xinc, cy, cz + 1.1),
Point::new(cx, cy + yinc, cz + 1.2)));
triangles.push((Point::new(cx + 25.0, cy, cz + 1.0),
Point::new(cx + 25.0 + xinc, cy, cz + 1.1),
Point::new(cx + 25.0, cy + yinc, cz + 1.2)));
}
}
triangles
});
println!("Scene built.");
let cam = Camera::new(vec![Matrix4x4::from_location(Point::new(256.0, 256.0, -1024.0))],
vec![0.785],
vec![20.0],
vec![1026.0]);
let mut assembly_b = AssemblyBuilder::new();
assembly_b.add_object("yar", Object::Surface(Box::new(mesh)));
assembly_b.add_object_instance("yar",
Some(&[Matrix4x4::from_location(Point::new(25.0, 0.0, 0.0))]));
let assembly = assembly_b.build();
let scene = Scene {
name: None,
background_color: (0.0, 0.0, 0.0),
camera: cam,
root: assembly,
};
let r = Renderer {
output_file: args.arg_imgpath.clone(),
resolution: (512, 512),
spp: samples_per_pixel as usize,
scene: scene,
};
// Iterate through scenes and render them
if let DataTree::Internal{ref children, ..} = dt {
for child in children {
if child.type_name() == "Scene" {
println!("Parsing scene...");
let r = parse_scene(child).unwrap();
println!("Rendering scene...");
r.render();
}
}
}
}

View File

@ -4,3 +4,4 @@ mod psy_assembly;
pub mod basics;
pub use self::data_tree::DataTree;
pub use self::psy::parse_scene;

View File

@ -14,27 +14,36 @@ use camera::Camera;
use renderer::Renderer;
use scene::Scene;
#[derive(Copy, Clone, Debug)]
pub enum PsyParseError {
UnknownError,
SectionWrongCount(&'static str, usize),
}
/// Takes in a DataTree representing a Scene node and returns
/// a renderer.
pub fn parse_frame(tree: &DataTree) -> Result<Renderer, ()> {
pub fn parse_scene(tree: &DataTree) -> Result<Renderer, PsyParseError> {
// Verify we have the right number of each section
if tree.count_children_with_type_name("Output") != 1 {
return Err(());
let count = tree.count_children_with_type_name("Output");
return Err(PsyParseError::SectionWrongCount("Output", count));
}
if tree.count_children_with_type_name("RenderSettings") != 1 {
return Err(());
let count = tree.count_children_with_type_name("RenderSettings");
return Err(PsyParseError::SectionWrongCount("RenderSettings", count));
}
if tree.count_children_with_type_name("Camera") != 1 {
return Err(());
let count = tree.count_children_with_type_name("Camera");
return Err(PsyParseError::SectionWrongCount("Camera", count));
}
if tree.count_children_with_type_name("World") != 1 {
return Err(());
let count = tree.count_children_with_type_name("World");
return Err(PsyParseError::SectionWrongCount("World", count));
}
if tree.count_children_with_type_name("Assembly") != 1 {
return Err(());
let count = tree.count_children_with_type_name("Assembly");
return Err(PsyParseError::SectionWrongCount("Root Assembly", count));
}
// Parse output info
@ -73,23 +82,22 @@ pub fn parse_frame(tree: &DataTree) -> Result<Renderer, ()> {
root: assembly,
};
// // Put renderer together
// let renderer = Renderer {
// output_file: output_info.0.clone(),
// resolution: (render_settings.0.0 as usize, render_settings.0.1 as usize),
// spp: render_settings.1,
// scene: scene,
// }
//
// return Ok(renderer);
// Put renderer together
let renderer = Renderer {
output_file: output_info.clone(),
resolution: ((render_settings.0).0 as usize,
(render_settings.0).1 as usize),
spp: render_settings.1 as usize,
scene: scene,
};
return Err(());
return Ok(renderer);
}
fn parse_output_info(tree: &DataTree) -> Result<(String), ()> {
fn parse_output_info(tree: &DataTree) -> Result<String, PsyParseError> {
if let &DataTree::Internal{ref children, ..} = tree {
let mut found_path = false;
let mut path = String::new();
@ -109,17 +117,17 @@ fn parse_output_info(tree: &DataTree) -> Result<(String), ()> {
if found_path {
return Ok((path));
} else {
return Err(());
return Err(PsyParseError::UnknownError);
}
} else {
return Err(());
return Err(PsyParseError::UnknownError);
};
}
fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), ()> {
fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyParseError> {
if let &DataTree::Internal{ref children, ..} = tree {
let mut found_res = false;
let mut found_spp = false;
@ -137,7 +145,7 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), ()>
res = (w, h);
} else {
// Found Resolution, but its contents is not in the right format
return Err(());
return Err(PsyParseError::UnknownError);
}
}
@ -148,7 +156,7 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), ()>
spp = n;
} else {
// Found SamplesPerPixel, but its contents is not in the right format
return Err(());
return Err(PsyParseError::UnknownError);
}
}
@ -158,7 +166,7 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), ()>
seed = n;
} else {
// Found Seed, but its contents is not in the right format
return Err(());
return Err(PsyParseError::UnknownError);
}
}
@ -169,17 +177,17 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), ()>
if found_res && found_spp {
return Ok((res, spp, seed));
} else {
return Err(());
return Err(PsyParseError::UnknownError);
}
} else {
return Err(());
return Err(PsyParseError::UnknownError);
};
}
fn parse_camera(tree: &DataTree) -> Result<Camera, ()> {
fn parse_camera(tree: &DataTree) -> Result<Camera, PsyParseError> {
if let &DataTree::Internal{ref children, ..} = tree {
let mut mats = Vec::new();
let mut fovs = Vec::new();
@ -195,7 +203,7 @@ fn parse_camera(tree: &DataTree) -> Result<Camera, ()> {
fovs.push(fov * (3.1415926536 / 180.0));
} else {
// Found Fov, but its contents is not in the right format
return Err(());
return Err(PsyParseError::UnknownError);
}
}
@ -205,7 +213,7 @@ fn parse_camera(tree: &DataTree) -> Result<Camera, ()> {
focus_distances.push(fd);
} else {
// Found FocalDistance, but its contents is not in the right format
return Err(());
return Err(PsyParseError::UnknownError);
}
}
@ -215,7 +223,7 @@ fn parse_camera(tree: &DataTree) -> Result<Camera, ()> {
aperture_radii.push(ar);
} else {
// Found ApertureRadius, but its contents is not in the right format
return Err(());
return Err(PsyParseError::UnknownError);
}
}
@ -225,7 +233,7 @@ fn parse_camera(tree: &DataTree) -> Result<Camera, ()> {
mats.push(mat);
} else {
// Found Transform, but its contents is not in the right format
return Err(());
return Err(PsyParseError::UnknownError);
}
}
@ -235,14 +243,14 @@ fn parse_camera(tree: &DataTree) -> Result<Camera, ()> {
return Ok(Camera::new(mats, fovs, aperture_radii, focus_distances));
} else {
return Err(());
return Err(PsyParseError::UnknownError);
}
}
fn parse_world(tree: &DataTree) -> Result<(f32, f32, f32), ()> {
fn parse_world(tree: &DataTree) -> Result<(f32, f32, f32), PsyParseError> {
if tree.is_internal() {
let mut found_background_color = false;
let mut background_color = (0.0, 0.0, 0.0);
@ -250,19 +258,19 @@ fn parse_world(tree: &DataTree) -> Result<(f32, f32, f32), ()> {
// Parse background shader
let bgs = {
if tree.count_children_with_type_name("BackgroundShader") != 1 {
return Err(());
return Err(PsyParseError::UnknownError);
}
tree.get_first_child_with_type_name("BackgroundShader").unwrap()
};
let bgs_type = {
if bgs.count_children_with_type_name("Type") != 1 {
return Err(());
return Err(PsyParseError::UnknownError);
}
if let &DataTree::Leaf{contents, ..} = tree.get_first_child_with_type_name("Type")
if let &DataTree::Leaf{contents, ..} = bgs.get_first_child_with_type_name("Type")
.unwrap() {
contents.trim()
} else {
return Err(());
return Err(PsyParseError::UnknownError);
}
};
match bgs_type {
@ -276,26 +284,26 @@ fn parse_world(tree: &DataTree) -> Result<(f32, f32, f32), ()> {
found_background_color = true;
background_color = color;
} else {
return Err(());
return Err(PsyParseError::UnknownError);
}
} else {
return Err(());
return Err(PsyParseError::UnknownError);
}
}
_ => return Err(()),
_ => return Err(PsyParseError::UnknownError),
}
return Ok(background_color);
} else {
return Err(());
return Err(PsyParseError::UnknownError);
}
}
fn parse_matrix(contents: &str) -> Result<Matrix4x4, ()> {
fn parse_matrix(contents: &str) -> Result<Matrix4x4, PsyParseError> {
if let IResult::Done(_, ns) = closure!(terminated!(tuple!(ws_f32,
ws_f32,
ws_f32,
@ -330,6 +338,6 @@ fn parse_matrix(contents: &str) -> Result<Matrix4x4, ()> {
ns.14,
ns.15));
} else {
return Err(());
return Err(PsyParseError::UnknownError);
}
}

View File

@ -7,12 +7,100 @@ use nom::IResult;
use super::DataTree;
use super::basics::{ws_u32, ws_f32};
use super::psy::PsyParseError;
use math::Matrix4x4;
use camera::Camera;
use renderer::Renderer;
use assembly::Assembly;
use assembly::{Assembly, AssemblyBuilder};
pub fn parse_assembly(tree: &DataTree) -> Result<Assembly, ()> {
unimplemented!()
pub fn parse_assembly(tree: &DataTree) -> Result<Assembly, PsyParseError> {
let mut builder = AssemblyBuilder::new();
if let &DataTree::Internal{ref children, ..} = tree {
for child in children {
match child.type_name() {
// Sub-Assembly
"Assembly" => {
if let &DataTree::Internal {ident: Some(ident), ..} = child {
builder.add_assembly(ident, try!(parse_assembly(&child)));
} else {
// TODO: error condition of some kind, because no ident
}
}
_ => {
// TODO: some kind of error, because not a known type name
}
// // Bilinear Patch
// "BilinearPatch" => {
// assembly->add_object(child.name, parse_bilinear_patch(child));
// }
//
// // Bicubic Patch
// else if (child.type == "BicubicPatch") {
// assembly->add_object(child.name, parse_bicubic_patch(child));
// }
//
// // Subdivision surface
// else if (child.type == "SubdivisionSurface") {
// assembly->add_object(child.name, parse_subdivision_surface(child));
// }
//
// // Sphere
// else if (child.type == "Sphere") {
// assembly->add_object(child.name, parse_sphere(child));
// }
//
// // Surface shader
// else if (child.type == "SurfaceShader") {
// assembly->add_surface_shader(child.name, parse_surface_shader(child));
// }
//
// // Sphere Light
// else if (child.type == "SphereLight") {
// assembly->add_object(child.name, parse_sphere_light(child));
// }
//
// // Rectangle Light
// else if (child.type == "RectangleLight") {
// assembly->add_object(child.name, parse_rectangle_light(child));
// }
//
// // Instance
// else if (child.type == "Instance") {
// // Parse
// std::string name = "";
// std::vector<Transform> xforms;
// const SurfaceShader *shader = nullptr;
// for (const auto& child2: child.children) {
// if (child2.type == "Transform") {
// xforms.emplace_back(parse_matrix(child2.leaf_contents));
// } else if (child2.type == "Data") {
// name = child2.leaf_contents;
// } else if (child2.type == "SurfaceShaderBind") {
// shader = assembly->get_surface_shader(child2.leaf_contents);
// if (shader == nullptr) {
// std::cout << "ERROR: attempted to bind surface shader that doesn't exist." << std::endl;
// }
// }
// }
//
// // Add instance
// if (assembly->object_map.count(name) != 0) {
// assembly->create_object_instance(name, xforms, shader);
// } else if (assembly->assembly_map.count(name) != 0) {
// assembly->create_assembly_instance(name, xforms, shader);
// } else {
// std::cout << "ERROR: attempted to add instace for data that doesn't exist." << std::endl;
// }
// }
}
}
} else {
return Err(PsyParseError::UnknownError);
}
return Ok(builder.build());
}