From d0ffec8f603036013b5458e155206f12e7fd5a46 Mon Sep 17 00:00:00 2001 From: Miguel Angel Astor Romero Date: Wed, 18 Jan 2017 21:46:24 -0400 Subject: [PATCH] Scene reader reads figures now. --- TODO.org | 251 ++++++++++++++++++++++++++++++++++++ disk.hpp | 6 +- figure.hpp | 4 +- main.cpp | 294 +++--------------------------------------- path_tracer.cpp | 42 +++--- path_tracer.hpp | 2 +- plane.hpp | 6 +- scene.cpp | 309 ++++++++++++++++++++++++++++++++++++++------- scene.hpp | 13 ++ scenes/scene3.json | 8 +- sphere.hpp | 6 +- tracer.hpp | 6 +- whitted_tracer.cpp | 34 +++-- whitted_tracer.hpp | 2 +- 14 files changed, 596 insertions(+), 387 deletions(-) diff --git a/TODO.org b/TODO.org index 1034b39..6cd1974 100644 --- a/TODO.org +++ b/TODO.org @@ -27,3 +27,254 @@ - [ ] Texture mapping - [ ] Photon mapping +* Junk + +#+BEGIN_SRC c++ + void scene_1(vector
& vf, vector & vl, Environment * & e, Camera * c) { + Sphere * s; + Plane * p; + Disk * d; + DirectionalLight * l; + + e = new Environment(NULL, false, vec3(0.7f, 0.4f, 0.05f)); + + s = new Sphere(1.0f, 1.0f, -2.0f, 0.5f); + s->m_mat->m_diffuse = vec3(1.0f, 0.0f, 0.0f); + vf.push_back(static_cast
(s)); + + s = new Sphere(-1.0f, 1.0f, -2.0f, 0.5f); + s->m_mat->m_diffuse = vec3(0.0f, 1.0f, 0.0f); + vf.push_back(static_cast
(s)); + + s = new Sphere(1.0f, -1.0f, -2.0f, 0.5f); + s->m_mat->m_diffuse = vec3(0.0f, 0.0f, 1.0f); + vf.push_back(static_cast
(s)); + + s = new Sphere(-1.0f, -1.0f, -2.0f, 0.5f); + s->m_mat->m_diffuse = vec3(1.0f, 0.0f, 1.0f); + vf.push_back(static_cast
(s)); + + s = new Sphere(0.0f, 0.0f, -2.0f, 1.0f); + s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 0.0f); + vf.push_back(static_cast
(s)); + + p = new Plane(vec3(0.0f, -1.5f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); + p->m_mat->m_diffuse = vec3(1.0f, 0.5f, 0.4f); + vf.push_back(static_cast
(p)); + + s = new Sphere(-1.5f, 0.0f, -2.0f, 0.5f); + s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 1.0f); + s->m_mat->m_rho = 0.3f; + vf.push_back(static_cast
(s)); + + s = new Sphere(1.5f, 0.0f, -2.0f, 0.5f); + s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 1.0f); + s->m_mat->m_rho = 0.08f; + s->m_mat->m_refract = true; + s->m_mat->m_ref_index = 1.1f; + vf.push_back(static_cast
(s)); + + s = new Sphere(0.0f, 1.5f, -2.0f, 0.5f); + s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 1.0f); + s->m_mat->m_rho = 0.5f; + vf.push_back(static_cast
(s)); + + s = new Sphere(0.0f, 0.0f, -1.0f, 0.25f); + s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 1.0f); + s->m_mat->m_rho = 0.1f; + vf.push_back(static_cast
(s)); + + d = new Disk(vec3(-0.0f, -0.0f, -0.5f), vec3(0.0f, 0.0f, 0.1f), 0.25f); + d->m_mat->m_diffuse = vec3(1.0f, 0.0f, 0.0f); + d->m_mat->m_rho = 0.3f; + d->m_mat->m_refract = true; + d->m_mat->m_ref_index = 1.33f; + vf.push_back(static_cast
(d)); + + l = new DirectionalLight(); + l->m_position = normalize(vec3(1.0f, 1.0f, 1.0f)); + l->m_diffuse = vec3(0.0f, 1.0f, 1.0f); + vl.push_back(static_cast(l)); + + l = new DirectionalLight(); + l->m_position = normalize(vec3(-1.0f, 1.0f, 1.0f)); + l->m_diffuse = vec3(1.0f, 1.0f, 0.0f); + vl.push_back(static_cast(l)); + + l = new DirectionalLight(); + l->m_position = normalize(vec3(0.0f, 1.0f, -1.0f)); + l->m_diffuse = vec3(1.0f, 0.0f, 1.0f); + vl.push_back(static_cast(l)); + } + + void scene_2(vector
& vf, vector & vl, Environment * & e, Camera * c) { + Sphere * s; + Plane * p; + Disk * d; + PointLight * l; + + s = new Sphere(0.2f, 0.0f, -0.75f, 0.25f); + s->m_mat->m_diffuse = vec3(1.0f); + s->m_mat->m_rho = 0.2f; + vf.push_back(static_cast
(s)); + + p = new Plane(vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); + p->m_mat->m_diffuse = vec3(0.0f, 1.0f, 0.0f); + p->m_mat->m_specular = vec3(0.0f); + vf.push_back(static_cast
(p)); + + p = new Plane(vec3(-2.0f, 0.0f, 0.0f), vec3(1.0f, 0.0f, 0.0f)); + p->m_mat->m_diffuse = vec3(1.0f, 0.0f, 0.0f); + p->m_mat->m_specular = vec3(0.0f); + vf.push_back(static_cast
(p)); + + p = new Plane(vec3(2.0f, 0.0f, 0.0f), vec3(-1.0f, 0.0f, 0.0f)); + p->m_mat->m_diffuse = vec3(0.0f, 0.0f, 1.0f); + p->m_mat->m_specular = vec3(0.0f); + vf.push_back(static_cast
(p)); + + p = new Plane(vec3(0.0f, 1.0f, 0.0f), vec3(0.0f, -1.0f, 0.0f)); + p->m_mat->m_diffuse = vec3(0.0f, 1.0f, 1.0f); + p->m_mat->m_specular = vec3(0.0f); + vf.push_back(static_cast
(p)); + + p = new Plane(vec3(0.0f, 0.0f, -2.0f), vec3(0.0f, 0.0f, 1.0f)); + p->m_mat->m_diffuse = vec3(1.0f, 0.0f, 1.0f); + p->m_mat->m_specular = vec3(0.0f); + vf.push_back(static_cast
(p)); + + p = new Plane(vec3(0.0f, 0.0f, 1.1f), vec3(0.0f, 0.0f, -1.0f)); + p->m_mat->m_diffuse = vec3(1.0f, 1.0f, 0.0f); + p->m_mat->m_specular = vec3(0.0f); + vf.push_back(static_cast
(p)); + + s = new Sphere(-0.5f, -0.5f, -1.5f, 0.5f); + s->m_mat->m_diffuse = vec3(0.0f); + s->m_mat->m_rho = 1.0f; + vf.push_back(static_cast
(s)); + + s = new Sphere(-0.5f, -0.5f, 0.6f, 0.5f); + s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 0.0f); + s->m_mat->m_refract = true; + s->m_mat->m_ref_index = 1.33f; + vf.push_back(static_cast
(s)); + + d = new Disk(vec3(-0.25f, 1.0f, -1.0f), vec3(1.0f, 0.0f, 0.0f), 0.25f); + d->m_mat->m_diffuse = vec3(1.0f); + vf.push_back(static_cast
(d)); + + d = new Disk(vec3(0.25f, 1.0f, -1.0f), vec3(-1.0f, 0.0f, 0.0f), 0.25f); + d->m_mat->m_diffuse = vec3(1.0f); + vf.push_back(static_cast
(d)); + + d = new Disk(vec3(0.0f, 1.0f, -1.25f), vec3(0.0f, 0.0f, 1.0f), 0.25f); + d->m_mat->m_diffuse = vec3(1.0f); + vf.push_back(static_cast
(d)); + + d = new Disk(vec3(0.0f, 1.0f, -0.75f), vec3(0.0f, 0.0f, -1.0f), 0.25f); + d->m_mat->m_diffuse = vec3(1.0f); + vf.push_back(static_cast
(d)); + + l = new PointLight(); + l->m_position = vec3(0.0f, 0.9f, -1.0f); + l->m_diffuse = vec3(1.0f); + vl.push_back(static_cast(l)); + } + + void scene_3(vector
& vf, vector & vl, Environment * & e, Camera * c) { + Sphere * s; + Disk * d; + // SpotLight * l; + // DirectionalLight * l2; + vec3 eye = vec3(0.0f, 1.5f, 1.0f); + vec3 center = vec3(0.0f, 0.0f, -2.0f); + vec3 left = vec3(-1.0f, 0.0f, 0.0f); + + e = new Environment("textures/pisa.hdr"); + + c->m_eye = eye; + c->m_look = center; + c->m_up = cross(normalize(center - eye), left); + c->translate(vec3(1.0f, 0.0f, 0.0f)); + //c->roll(15.0f); + + // s = new Sphere(0.0f, -0.15f, -2.0f, 1.0f); + // s->m_mat->m_diffuse = vec3(1.0f, 0.5f, 0.0f); + // s->m_mat->m_specular = vec3(0.3f); + // s->m_mat->m_shininess = 5.0f; + // s->m_mat->m_rho = 0.4f; + // s->m_mat->m_refract = true; + // s->m_mat->m_ref_index = 1.33f; + // vf.push_back(static_cast
(s)); + + // s = new Sphere(0.0f, -0.15f, -2.0f, 0.5f); + // s->m_mat->m_diffuse = vec3(0.0f); + // s->m_mat->m_specular = vec3(0.0f); + // s->m_mat->m_rho = 0.0f; + // s->m_mat->m_refract = true; + // s->m_mat->m_ref_index = 2.6f; + // vf.push_back(static_cast
(s)); + + s = new Sphere(2.0f, 0.0f, -2.0f, 1.5f, new HeidrichSeidelAnisotropicBRDF(vec3(0.0f, 1.0f, 0.0f))); + s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 0.0f); + s->m_mat->m_shininess = 128.0f; + vf.push_back(static_cast
(s)); + + s = new Sphere(-1.0f, 0.0f, -3.25f, 1.5f); + s->m_mat->m_diffuse = vec3(1.0f, 0.0f, 1.0f); + s->m_mat->m_rho = 0.4f; + vf.push_back(static_cast
(s)); + + s = new Sphere(1.0f, 0.0f, -3.25f, 1.5f); + s->m_mat->m_diffuse = vec3(1.0f); + s->m_mat->m_rho = 0.4f; + vf.push_back(static_cast
(s)); + + d = new Disk(vec3(1.0f, -1.5f, -3.25f), vec3(0.0f, 1.0f, 0.0f), 3.0f); + d->m_mat->m_diffuse = vec3(0.0f, 0.5f, 0.5f); + d->m_mat->m_specular = vec3(0.0f); + vf.push_back(static_cast
(d)); + + // l = new SpotLight(); + // l->m_position = normalize(vec3(-2.0f, 1.5f, -1.0f)); + // l->m_diffuse = vec3(1.0f, 1.0f, 0.0f); + // l->m_spot_dir = normalize(vec3(0.5f, 0.0f, -2.5f) - vec3(-2.0f, 1.5f, -1.0f)); + // l->m_spot_cutoff = 89.0f; + // l->m_spot_exponent = 10.0f; + // vl.push_back(static_cast(l)); + + // l2 = new DirectionalLight(); + // l2->m_position = normalize(vec3(-1.0f, 0.7f, 1.0f)); + // l2->m_diffuse = vec3(1.0f, 1.0f, 1.0f); + // vl.push_back(static_cast(l2)); + + // l2 = new DirectionalLight(); + // l2->m_position = normalize(vec3(-0.5f, 0.7f, 1.0f)); + // l2->m_diffuse = vec3(0.0f, 0.0f, 1.0f); + // l2->m_specular = vec3(0.0f, 0.0f, 1.0f); + // vl.push_back(static_cast(l2)); + + // l = new DirectionalLight(); + // l->m_position = normalize(vec3(1.0f, 0.0f, 1.0f)); + // l->m_diffuse = vec3(0.5f); + // vl.push_back(static_cast(l)); + } + + void scene_4(vector
& vf, vector & vl, Environment * & e, Camera * c) { + Sphere * s; + Plane * p; + + e = new Environment("textures/pisa.hdr"); + + s = new Sphere(0.0f, 0.0f, -2.0f, 1.0f); + s->m_mat->m_diffuse = vec3(1.0f); + s->m_mat->m_rho = 0.3f; + vf.push_back(static_cast
(s)); + + p = new Plane(vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); + p->m_mat->m_diffuse = vec3(1.0f); + p->m_mat->m_specular = vec3(0.0f); + vf.push_back(static_cast
(p)); + } + +#+END_SRC diff --git a/disk.hpp b/disk.hpp index 4471e25..766d76d 100644 --- a/disk.hpp +++ b/disk.hpp @@ -13,11 +13,11 @@ class Disk : public Plane { public: float m_radius; - Disk(BRDF * _brdf = NULL): Plane(_brdf), m_radius(1.0f) { } + Disk(Material * mat = NULL): Plane(mat), m_radius(1.0f) { } - Disk(float x, float y, float z, float nx, float ny, float nz, float _r, BRDF * _brdf = NULL): Plane(x, y, z, nx, ny, nz, _brdf), m_radius(_r) { } + Disk(float x, float y, float z, float nx, float ny, float nz, float _r, Material * mat = NULL): Plane(x, y, z, nx, ny, nz, mat), m_radius(_r) { } - Disk(vec3 _p, vec3 _n, float _r, BRDF * _brdf = NULL): Plane(_p, _n, _brdf), m_radius(_r) { } + Disk(vec3 _p, vec3 _n, float _r, Material * mat = NULL): Plane(_p, _n, mat), m_radius(_r) { } virtual ~Disk() { } diff --git a/figure.hpp b/figure.hpp index b047978..2289e01 100644 --- a/figure.hpp +++ b/figure.hpp @@ -13,8 +13,8 @@ class Figure { public: Material * m_mat; - Figure(BRDF * brdf = NULL) { - m_mat = new Material(brdf); + Figure(Material * mat = NULL) { + m_mat = mat == NULL ? new Material() : mat; } virtual ~Figure() { diff --git a/main.cpp b/main.cpp index 9240500..d427451 100644 --- a/main.cpp +++ b/main.cpp @@ -43,10 +43,10 @@ using namespace glm; //////////////////////////////////////////// // Function prototypes. //////////////////////////////////////////// -static void scene_1(vector
& vf, vector & vl, Environment * & e, Camera * c); -static void scene_2(vector
& vf, vector & vl, Environment * & e, Camera * c); -static void scene_3(vector
& vf, vector & vl, Environment * & e, Camera * c); -static void scene_4(vector
& vf, vector & vl, Environment * & e, Camera * c); +// static void scene_1(vector
& vf, vector & vl, Environment * & e, Camera * c); +// static void scene_2(vector
& vf, vector & vl, Environment * & e, Camera * c); +// static void scene_3(vector
& vf, vector & vl, Environment * & e, Camera * c); +// static void scene_4(vector
& vf, vector & vl, Environment * & e, Camera * c); static void print_usage(char ** const argv); static void parse_args(int argc, char ** const argv); @@ -79,8 +79,6 @@ static float g_exposure = 0.0f; int main(int argc, char ** argv) { Ray r; vec2 sample; - vector
figures; - vector lights; Tracer * tracer; size_t total; size_t current = 0; @@ -90,8 +88,6 @@ int main(int argc, char ** argv) { BYTE * bits; FIRGBF *pixel; int pitch; - Camera * cam; - Environment * env = NULL; Scene * scn; parse_args(argc, argv); @@ -99,40 +95,39 @@ int main(int argc, char ** argv) { // Initialize everything. FreeImage_Initialise(); - cam = new Camera(); - image = new vec3*[g_h]; for (int i = 0; i < g_h; i++) { image[i] = new vec3[g_w]; } try { - scn = new Scene("scenes/scene3.json"); - delete scn; + scn = new Scene(g_input_file); } catch (SceneError & e) { cout << e.what() << endl; + return EXIT_FAILURE; } - - scene_3(figures, lights, env, cam); - // Create the tracer object. cout << "Rendering the input file: " << ANSI_BOLD_YELLOW << g_input_file << ANSI_RESET_STYLE << endl; cout << "The scene contains: " << endl; - cout << " " << ANSI_BOLD_YELLOW << figures.size() << ANSI_RESET_STYLE << (figures.size() != 1 ? " figures." : " figure.") << endl; - cout << " " << ANSI_BOLD_YELLOW << lights.size() << ANSI_RESET_STYLE << " light " << (lights.size() != 1 ? "sources." : "source.") << endl; + cout << " " << ANSI_BOLD_YELLOW << scn->m_figures.size() << ANSI_RESET_STYLE << (scn->m_figures.size() != 1 ? " figures." : " figure.") << endl; + cout << " " << ANSI_BOLD_YELLOW << scn->m_lights.size() << ANSI_RESET_STYLE << " light " << (scn->m_lights.size() != 1 ? "sources." : "source.") << endl; cout << "Output image resolution is " << ANSI_BOLD_YELLOW << g_w << "x" << g_h << ANSI_RESET_STYLE << " pixels." << endl; cout << "Using " << ANSI_BOLD_YELLOW << g_samples << ANSI_RESET_STYLE << " samples per pixel." << endl; cout << "Maximum ray tree depth is " << ANSI_BOLD_YELLOW << g_max_depth << ANSI_RESET_STYLE << "." << endl; + // Create the tracer object. if (g_tracer == WHITTED) { cout << "Using " << ANSI_BOLD_YELLOW << "Whitted" << ANSI_RESET_STYLE << " ray tracing." << endl; tracer = static_cast(new WhittedTracer(g_max_depth)); + } else if(g_tracer == MONTE_CARLO) { cout << "Using " << ANSI_BOLD_YELLOW << "Monte Carlo" << ANSI_RESET_STYLE << " path tracing." << endl; tracer = static_cast(new PathTracer(g_max_depth)); + } else if(g_tracer == JENSEN) { cerr << "Photon mapping coming soon." << endl; return EXIT_FAILURE; + } else { cerr << "Must specify a ray tracer with \"-t\"." << endl; print_usage(argv); @@ -148,8 +143,8 @@ int main(int argc, char ** argv) { for (int k = 0; k < g_samples; k++) { sample = sample_pixel(i, j, g_w, g_h, g_a_ratio, g_fov); r = Ray(normalize(vec3(sample, -0.5f) - vec3(0.0f)), vec3(0.0f)); - cam->view_to_world(r); - image[i][j] += tracer->trace_ray(r, figures, lights, env, 0); + scn->m_cam->view_to_world(r); + image[i][j] += tracer->trace_ray(r, scn, 0); #pragma omp atomic current++; } @@ -187,20 +182,8 @@ int main(int argc, char ** argv) { if (g_out_file_name != NULL) free(g_out_file_name); - delete cam; + delete scn; delete tracer; - if (env != NULL) - delete env; - - for (size_t i = 0; i < figures.size(); i++) { - delete figures[i]; - } - figures.clear(); - - for (size_t i = 0; i < lights.size(); i++) { - delete lights[i]; - } - lights.clear(); for (int i = 0; i < g_h; i++) delete[] image[i]; @@ -359,250 +342,3 @@ void parse_args(int argc, char ** const argv) { exit(EXIT_FAILURE); } } - -void scene_1(vector
& vf, vector & vl, Environment * & e, Camera * c) { - Sphere * s; - Plane * p; - Disk * d; - DirectionalLight * l; - - e = new Environment(NULL, false, vec3(0.7f, 0.4f, 0.05f)); - - s = new Sphere(1.0f, 1.0f, -2.0f, 0.5f); - s->m_mat->m_diffuse = vec3(1.0f, 0.0f, 0.0f); - vf.push_back(static_cast
(s)); - - s = new Sphere(-1.0f, 1.0f, -2.0f, 0.5f); - s->m_mat->m_diffuse = vec3(0.0f, 1.0f, 0.0f); - vf.push_back(static_cast
(s)); - - s = new Sphere(1.0f, -1.0f, -2.0f, 0.5f); - s->m_mat->m_diffuse = vec3(0.0f, 0.0f, 1.0f); - vf.push_back(static_cast
(s)); - - s = new Sphere(-1.0f, -1.0f, -2.0f, 0.5f); - s->m_mat->m_diffuse = vec3(1.0f, 0.0f, 1.0f); - vf.push_back(static_cast
(s)); - - s = new Sphere(0.0f, 0.0f, -2.0f, 1.0f); - s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 0.0f); - vf.push_back(static_cast
(s)); - - p = new Plane(vec3(0.0f, -1.5f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); - p->m_mat->m_diffuse = vec3(1.0f, 0.5f, 0.4f); - vf.push_back(static_cast
(p)); - - s = new Sphere(-1.5f, 0.0f, -2.0f, 0.5f); - s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 1.0f); - s->m_mat->m_rho = 0.3f; - vf.push_back(static_cast
(s)); - - s = new Sphere(1.5f, 0.0f, -2.0f, 0.5f); - s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 1.0f); - s->m_mat->m_rho = 0.08f; - s->m_mat->m_refract = true; - s->m_mat->m_ref_index = 1.1f; - vf.push_back(static_cast
(s)); - - s = new Sphere(0.0f, 1.5f, -2.0f, 0.5f); - s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 1.0f); - s->m_mat->m_rho = 0.5f; - vf.push_back(static_cast
(s)); - - s = new Sphere(0.0f, 0.0f, -1.0f, 0.25f); - s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 1.0f); - s->m_mat->m_rho = 0.1f; - vf.push_back(static_cast
(s)); - - d = new Disk(vec3(-0.0f, -0.0f, -0.5f), vec3(0.0f, 0.0f, 0.1f), 0.25f); - d->m_mat->m_diffuse = vec3(1.0f, 0.0f, 0.0f); - d->m_mat->m_rho = 0.3f; - d->m_mat->m_refract = true; - d->m_mat->m_ref_index = 1.33f; - vf.push_back(static_cast
(d)); - - l = new DirectionalLight(); - l->m_position = normalize(vec3(1.0f, 1.0f, 1.0f)); - l->m_diffuse = vec3(0.0f, 1.0f, 1.0f); - vl.push_back(static_cast(l)); - - l = new DirectionalLight(); - l->m_position = normalize(vec3(-1.0f, 1.0f, 1.0f)); - l->m_diffuse = vec3(1.0f, 1.0f, 0.0f); - vl.push_back(static_cast(l)); - - l = new DirectionalLight(); - l->m_position = normalize(vec3(0.0f, 1.0f, -1.0f)); - l->m_diffuse = vec3(1.0f, 0.0f, 1.0f); - vl.push_back(static_cast(l)); -} - -void scene_2(vector
& vf, vector & vl, Environment * & e, Camera * c) { - Sphere * s; - Plane * p; - Disk * d; - PointLight * l; - - s = new Sphere(0.2f, 0.0f, -0.75f, 0.25f); - s->m_mat->m_diffuse = vec3(1.0f); - s->m_mat->m_rho = 0.2f; - vf.push_back(static_cast
(s)); - - p = new Plane(vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); - p->m_mat->m_diffuse = vec3(0.0f, 1.0f, 0.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); - - p = new Plane(vec3(-2.0f, 0.0f, 0.0f), vec3(1.0f, 0.0f, 0.0f)); - p->m_mat->m_diffuse = vec3(1.0f, 0.0f, 0.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); - - p = new Plane(vec3(2.0f, 0.0f, 0.0f), vec3(-1.0f, 0.0f, 0.0f)); - p->m_mat->m_diffuse = vec3(0.0f, 0.0f, 1.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); - - p = new Plane(vec3(0.0f, 1.0f, 0.0f), vec3(0.0f, -1.0f, 0.0f)); - p->m_mat->m_diffuse = vec3(0.0f, 1.0f, 1.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); - - p = new Plane(vec3(0.0f, 0.0f, -2.0f), vec3(0.0f, 0.0f, 1.0f)); - p->m_mat->m_diffuse = vec3(1.0f, 0.0f, 1.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); - - p = new Plane(vec3(0.0f, 0.0f, 1.1f), vec3(0.0f, 0.0f, -1.0f)); - p->m_mat->m_diffuse = vec3(1.0f, 1.0f, 0.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); - - s = new Sphere(-0.5f, -0.5f, -1.5f, 0.5f); - s->m_mat->m_diffuse = vec3(0.0f); - s->m_mat->m_rho = 1.0f; - vf.push_back(static_cast
(s)); - - s = new Sphere(-0.5f, -0.5f, 0.6f, 0.5f); - s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 0.0f); - s->m_mat->m_refract = true; - s->m_mat->m_ref_index = 1.33f; - vf.push_back(static_cast
(s)); - - d = new Disk(vec3(-0.25f, 1.0f, -1.0f), vec3(1.0f, 0.0f, 0.0f), 0.25f); - d->m_mat->m_diffuse = vec3(1.0f); - vf.push_back(static_cast
(d)); - - d = new Disk(vec3(0.25f, 1.0f, -1.0f), vec3(-1.0f, 0.0f, 0.0f), 0.25f); - d->m_mat->m_diffuse = vec3(1.0f); - vf.push_back(static_cast
(d)); - - d = new Disk(vec3(0.0f, 1.0f, -1.25f), vec3(0.0f, 0.0f, 1.0f), 0.25f); - d->m_mat->m_diffuse = vec3(1.0f); - vf.push_back(static_cast
(d)); - - d = new Disk(vec3(0.0f, 1.0f, -0.75f), vec3(0.0f, 0.0f, -1.0f), 0.25f); - d->m_mat->m_diffuse = vec3(1.0f); - vf.push_back(static_cast
(d)); - - l = new PointLight(); - l->m_position = vec3(0.0f, 0.9f, -1.0f); - l->m_diffuse = vec3(1.0f); - vl.push_back(static_cast(l)); -} - -void scene_3(vector
& vf, vector & vl, Environment * & e, Camera * c) { - Sphere * s; - Disk * d; - // SpotLight * l; - // DirectionalLight * l2; - vec3 eye = vec3(0.0f, 1.5f, 1.0f); - vec3 center = vec3(0.0f, 0.0f, -2.0f); - vec3 left = vec3(-1.0f, 0.0f, 0.0f); - - e = new Environment("textures/pisa.hdr"); - - c->m_eye = eye; - c->m_look = center; - c->m_up = cross(normalize(center - eye), left); - c->translate(vec3(1.0f, 0.0f, 0.0f)); - //c->roll(15.0f); - - // s = new Sphere(0.0f, -0.15f, -2.0f, 1.0f); - // s->m_mat->m_diffuse = vec3(1.0f, 0.5f, 0.0f); - // s->m_mat->m_specular = vec3(0.3f); - // s->m_mat->m_shininess = 5.0f; - // s->m_mat->m_rho = 0.4f; - // s->m_mat->m_refract = true; - // s->m_mat->m_ref_index = 1.33f; - // vf.push_back(static_cast
(s)); - - // s = new Sphere(0.0f, -0.15f, -2.0f, 0.5f); - // s->m_mat->m_diffuse = vec3(0.0f); - // s->m_mat->m_specular = vec3(0.0f); - // s->m_mat->m_rho = 0.0f; - // s->m_mat->m_refract = true; - // s->m_mat->m_ref_index = 2.6f; - // vf.push_back(static_cast
(s)); - - s = new Sphere(2.0f, 0.0f, -2.0f, 1.5f, new HeidrichSeidelAnisotropicBRDF(vec3(0.0f, 1.0f, 0.0f))); - s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 0.0f); - s->m_mat->m_shininess = 128.0f; - vf.push_back(static_cast
(s)); - - s = new Sphere(-1.0f, 0.0f, -3.25f, 1.5f); - s->m_mat->m_diffuse = vec3(1.0f, 0.0f, 1.0f); - s->m_mat->m_rho = 0.4f; - vf.push_back(static_cast
(s)); - - s = new Sphere(1.0f, 0.0f, -3.25f, 1.5f); - s->m_mat->m_diffuse = vec3(1.0f); - s->m_mat->m_rho = 0.4f; - vf.push_back(static_cast
(s)); - - d = new Disk(vec3(1.0f, -1.5f, -3.25f), vec3(0.0f, 1.0f, 0.0f), 3.0f); - d->m_mat->m_diffuse = vec3(0.0f, 0.5f, 0.5f); - d->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(d)); - - // l = new SpotLight(); - // l->m_position = normalize(vec3(-2.0f, 1.5f, -1.0f)); - // l->m_diffuse = vec3(1.0f, 1.0f, 0.0f); - // l->m_spot_dir = normalize(vec3(0.5f, 0.0f, -2.5f) - vec3(-2.0f, 1.5f, -1.0f)); - // l->m_spot_cutoff = 89.0f; - // l->m_spot_exponent = 10.0f; - // vl.push_back(static_cast(l)); - - // l2 = new DirectionalLight(); - // l2->m_position = normalize(vec3(-1.0f, 0.7f, 1.0f)); - // l2->m_diffuse = vec3(1.0f, 1.0f, 1.0f); - // vl.push_back(static_cast(l2)); - - // l2 = new DirectionalLight(); - // l2->m_position = normalize(vec3(-0.5f, 0.7f, 1.0f)); - // l2->m_diffuse = vec3(0.0f, 0.0f, 1.0f); - // l2->m_specular = vec3(0.0f, 0.0f, 1.0f); - // vl.push_back(static_cast(l2)); - - // l = new DirectionalLight(); - // l->m_position = normalize(vec3(1.0f, 0.0f, 1.0f)); - // l->m_diffuse = vec3(0.5f); - // vl.push_back(static_cast(l)); -} - -void scene_4(vector
& vf, vector & vl, Environment * & e, Camera * c) { - Sphere * s; - Plane * p; - - e = new Environment("textures/pisa.hdr"); - - s = new Sphere(0.0f, 0.0f, -2.0f, 1.0f); - s->m_mat->m_diffuse = vec3(1.0f); - s->m_mat->m_rho = 0.3f; - vf.push_back(static_cast
(s)); - - p = new Plane(vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); - p->m_mat->m_diffuse = vec3(1.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); -} diff --git a/path_tracer.cpp b/path_tracer.cpp index a16c0dd..ad232ca 100644 --- a/path_tracer.cpp +++ b/path_tracer.cpp @@ -10,7 +10,7 @@ using namespace glm; PathTracer::~PathTracer() { } -vec3 PathTracer::trace_ray(Ray & r, vector
& v_figures, vector & v_lights, Environment * e, unsigned int rec_level) const { +vec3 PathTracer::trace_ray(Ray & r, Scene * s, unsigned int rec_level) const { float t, _t; Figure * _f; vec3 n, color, i_pos, ref, sample, dir_diff_color, dir_spec_color, ind_color, amb_color; @@ -22,10 +22,10 @@ vec3 PathTracer::trace_ray(Ray & r, vector
& v_figures, vectorintersect(r, _t) && _t < t) { + for (size_t f = 0; f < s->m_figures.size(); f++) { + if (s->m_figures[f]->intersect(r, _t) && _t < t) { t = _t; - _f = v_figures[f]; + _f = s->m_figures[f]; } } @@ -38,22 +38,22 @@ vec3 PathTracer::trace_ray(Ray & r, vector
& v_figures, vectorm_mat->m_refract) { // Calculate the direct lighting. - for (size_t l = 0; l < v_lights.size(); l++) { + for (size_t l = 0; l < s->m_lights.size(); l++) { // For every light source vis = true; // Cast a shadow ray to determine visibility. - sr = Ray(v_lights[l]->direction(i_pos), i_pos + n * BIAS); - for (size_t f = 0; f < v_figures.size(); f++) { - if (v_figures[f]->intersect(sr, _t) && _t < v_lights[l]->distance(i_pos)) { + sr = Ray(s->m_lights[l]->direction(i_pos), i_pos + n * BIAS); + for (size_t f = 0; f < s->m_figures.size(); f++) { + if (s->m_figures[f]->intersect(sr, _t) && _t < s->m_lights[l]->distance(i_pos)) { vis = false; break; } } // Evaluate the shading model accounting for visibility. - dir_diff_color += vis ? v_lights[l]->diffuse(n, r, i_pos, *_f->m_mat) : vec3(0.0f); - dir_spec_color += vis ? v_lights[l]->specular(n, r, i_pos, *_f->m_mat) : vec3(0.0f); + dir_diff_color += vis ? s->m_lights[l]->diffuse(n, r, i_pos, *_f->m_mat) : vec3(0.0f); + dir_spec_color += vis ? s->m_lights[l]->specular(n, r, i_pos, *_f->m_mat) : vec3(0.0f); } // Calculate indirect lighting contribution. @@ -63,7 +63,7 @@ vec3 PathTracer::trace_ray(Ray & r, vector
& v_figures, vector & v_figures, vectorintersect(rr, _t)) { + for (size_t f = 0; f < s->m_figures.size(); f++) { + if (s->m_figures[f]->intersect(rr, _t)) { vis = false; break; } } - amb_color = vis ? e->get_color(rr) * max(dot(n, rr.m_direction), 0.0f) / PDF : vec3(0.0f); + amb_color = vis ? s->m_env->get_color(rr) * max(dot(n, rr.m_direction), 0.0f) / PDF : vec3(0.0f); // Add lighting. color += ((dir_diff_color + ind_color + amb_color) * (_f->m_mat->m_diffuse / pi())) + (_f->m_mat->m_specular * dir_spec_color); @@ -91,7 +91,7 @@ vec3 PathTracer::trace_ray(Ray & r, vector
& v_figures, vectorm_mat->m_rho > 0.0f && rec_level < m_max_depth) { rr = Ray(normalize(reflect(r.m_direction, n)), i_pos + n * BIAS); - color += _f->m_mat->m_rho * trace_ray(rr, v_figures, v_lights, e, rec_level + 1); + color += _f->m_mat->m_rho * trace_ray(rr, s, rec_level + 1); } else if (_f->m_mat->m_rho > 0.0f && rec_level >= m_max_depth) return vec3(0.0f); @@ -102,14 +102,14 @@ vec3 PathTracer::trace_ray(Ray & r, vector
& v_figures, vector 0.0f && rec_level < m_max_depth) { rr = Ray(normalize(reflect(r.m_direction, n)), i_pos + n * BIAS); - color += kr * trace_ray(rr, v_figures, v_lights, e, rec_level + 1); + color += kr * trace_ray(rr, s, rec_level + 1); } else if (rec_level >= m_max_depth) return vec3(0.0f); // Determine the transmission color. if (_f->m_mat->m_refract && kr < 1.0f && rec_level < m_max_depth) { rr = Ray(normalize(refract(r.m_direction, n, r.m_ref_index / _f->m_mat->m_ref_index)), i_pos - n * BIAS, _f->m_mat->m_ref_index); - color += (1.0f - kr) * trace_ray(rr, v_figures, v_lights, e, rec_level + 1); + color += (1.0f - kr) * trace_ray(rr, s, rec_level + 1); } else if (rec_level >= m_max_depth) return vec3(0.0f); @@ -118,10 +118,6 @@ vec3 PathTracer::trace_ray(Ray & r, vector
& v_figures, vectorm_mat->m_emission + color; - } else { - if (e != NULL) - return e->get_color(r); - else - return vec3(0.0f); - } + } else + return s->m_env->get_color(r); } diff --git a/path_tracer.hpp b/path_tracer.hpp index f4853f6..1e1da0c 100644 --- a/path_tracer.hpp +++ b/path_tracer.hpp @@ -12,7 +12,7 @@ public: virtual ~PathTracer(); - virtual vec3 trace_ray(Ray & r, vector
& v_figures, vector & v_lights, Environment * e, unsigned int rec_level) const; + virtual vec3 trace_ray(Ray & r, Scene * s, unsigned int rec_level) const; }; #endif diff --git a/plane.hpp b/plane.hpp index 00e3ffa..41f1c50 100644 --- a/plane.hpp +++ b/plane.hpp @@ -14,11 +14,11 @@ public: vec3 m_point; vec3 m_normal; - Plane(BRDF * _brdf = NULL): Figure(_brdf), m_point(vec3(0.0f)), m_normal(vec3(0.0f, 0.0f, 1.0f)) { } + Plane(Material * mat = NULL): Figure(mat), m_point(vec3(0.0f)), m_normal(vec3(0.0f, 0.0f, 1.0f)) { } - Plane(float x, float y, float z, float nx, float ny, float nz, BRDF * _brdf = NULL): Figure(_brdf), m_point(vec3(x, y, z)), m_normal(normalize(vec3(nx, ny, nz))) { } + Plane(float x, float y, float z, float nx, float ny, float nz, Material * mat = NULL): Figure(mat), m_point(vec3(x, y, z)), m_normal(normalize(vec3(nx, ny, nz))) { } - Plane(vec3 _p, vec3 _n, BRDF * _brdf = NULL): Figure(_brdf), m_point(_p), m_normal(normalize(_n)) { } + Plane(vec3 _p, vec3 _n, Material * mat = NULL): Figure(mat), m_point(_p), m_normal(normalize(_n)) { } virtual ~Plane() { } diff --git a/scene.cpp b/scene.cpp index ff8f673..ebc6ae1 100644 --- a/scene.cpp +++ b/scene.cpp @@ -3,12 +3,21 @@ #include #include #include +#include #include #include -#include #include "scene.hpp" +#include "brdf.hpp" +#include "phong_brdf.hpp" +#include "hsa_brdf.hpp" +#include "sphere.hpp" +#include "plane.hpp" +#include "disk.hpp" +#include "directional_light.hpp" +#include "point_light.hpp" +#include "spot_light.hpp" using std::cerr; using std::endl; @@ -21,7 +30,6 @@ using glm::vec3; using glm::normalize; using glm::cross; using json_spirit::read; -using json_spirit::Value; using json_spirit::Error_position; using json_spirit::Object; using json_spirit::Array; @@ -46,6 +54,9 @@ static const string CAM_EYE_KEY = "eye"; static const string CAM_CNT_KEY = "look"; static const string CAM_LFT_KEY = "left"; static const string CAM_UPV_KEY = "up"; +static const string CAM_RLL_KEY = "roll"; +static const string CAM_PTC_KEY = "pitch"; +static const string CAM_YAW_KEY = "yaw"; static const string FIG_POS_KEY = "position"; static const string FIG_MAT_KEY = "material"; @@ -63,9 +74,12 @@ static const string MLT_RFI_KEY = "ref_index"; static const string MLT_BRF_KEY = "transmissive"; static const string MLT_BRD_KEY = "brdf"; -static void read_vector(Value & val, vec3 & vec) throw(SceneError); -static void read_environment(Value & v, Environment * & e) throw(SceneError); -static void read_camera(Value & v, Camera * & c) throw(SceneError); +static const string BRD_PHN_KEY = "phong"; +static const string BRD_HSA_KEY = "heidrich-seidel"; + +static const string GEO_TRN_KEY = "translation"; +static const string GEO_SCL_KEY = "scaling"; +static const string GEO_ROT_KEY = "rotation"; Scene::Scene(const char * file_name, int h, int w, float fov) throw(SceneError) { ostringstream oss; @@ -90,20 +104,23 @@ Scene::Scene(const char * file_name, int h, int w, float fov) throw(SceneError) top_level = val.get_value(); try { - for(Object::iterator it = top_level.begin(); it != top_level.end(); it++) { + for (Object::iterator it = top_level.begin(); it != top_level.end(); it++) { if ((*it).name_ == ENV_KEY) - read_environment((*it).value_, m_env); + read_environment((*it).value_); else if ((*it).name_ == CAM_KEY) - read_camera((*it).value_, m_cam); + read_camera((*it).value_); - else if ((*it).name_ == SPH_KEY) { + else if ((*it).name_ == SPH_KEY) + m_figures.push_back(read_sphere((*it).value_)); - } else if ((*it).name_ == PLN_KEY) { + else if ((*it).name_ == PLN_KEY) + m_figures.push_back(read_plane((*it).value_)); - } else if ((*it).name_ == DSK_KEY) { + else if ((*it).name_ == DSK_KEY) + m_figures.push_back(read_disk((*it).value_)); - } else if ((*it).name_ == DLT_KEY) { + else if ((*it).name_ == DLT_KEY) { } else if ((*it).name_ == PLT_KEY) { @@ -141,7 +158,7 @@ Scene::~Scene() { m_lights.clear(); } -inline void read_vector(Value & val, vec3 & vec) throw(SceneError) { +void Scene::read_vector(Value & val, vec3 & vec) throw(SceneError) { Array a = val.get_value(); if (a.size() < 3) @@ -150,73 +167,273 @@ inline void read_vector(Value & val, vec3 & vec) throw(SceneError) { vec = vec3(a[0].get_value(), a[1].get_value(), a[2].get_value()); } -void read_environment(Value & v, Environment * & e) throw(SceneError) { +void Scene::read_environment(Value & v) throw(SceneError) { string t_name = ""; bool l_probe = false, has_tex = false, has_color = false; - vec3 color; + vec3 color = vec3(1.0f); Object env_obj = v.get_value(); - for(Object::iterator it = env_obj.begin(); it != env_obj.end(); it++) { - if ((*it).name_ == ENV_TEX_KEY) + for (Object::iterator it = env_obj.begin(); it != env_obj.end(); it++) { + if ((*it).name_ == ENV_TEX_KEY) { t_name = (*it).value_.get_value(); + has_tex = true; - else if ((*it).name_ == ENV_LPB_KEY) + } else if ((*it).name_ == ENV_LPB_KEY) l_probe = (*it).value_.get_value(); - else if ((*it).name_ == ENV_COL_KEY) + else if ((*it).name_ == ENV_COL_KEY) { try { read_vector((*it).value_, color); } catch (SceneError & e) { throw e; } + has_color = true; + } else - cerr << "Unrecognized key \"" << (*it).name_ << "\" in input file." << endl; + cerr << "Unrecognized key \"" << (*it).name_ << "\" in environment." << endl; } if (!has_tex && !has_color) throw SceneError("Environment must specify either a texture or color."); - - e = new Environment(has_tex ? t_name.c_str() : NULL , l_probe, color); + + m_env = new Environment(has_tex ? t_name.c_str() : NULL , l_probe, color); } -void read_camera(Value & v, Camera * & c) throw(SceneError) { +void Scene::read_camera(Value & v) throw(SceneError) { bool has_up = false, has_left = false, has_eye = false, has_look = false; - vec3 eye, look, left, up; + vec3 eye, look, left, up, translation; + float pitch = 0.0f, yaw = 0.0f, roll = 0.0f; Object cam_obj = v.get_value(); - for(Object::iterator it = cam_obj.begin(); it != cam_obj.end(); it++) { - if ((*it).name_ == CAM_EYE_KEY) { - read_vector((*it).value_, eye); - has_eye = true; + try { + for (Object::iterator it = cam_obj.begin(); it != cam_obj.end(); it++) { + if ((*it).name_ == CAM_EYE_KEY) { + read_vector((*it).value_, eye); + has_eye = true; - } else if ((*it).name_ == CAM_CNT_KEY) { - read_vector((*it).value_, look); - has_look = true; + } else if ((*it).name_ == CAM_CNT_KEY) { + read_vector((*it).value_, look); + has_look = true; - } else if ((*it).name_ == CAM_LFT_KEY) { - read_vector((*it).value_, left); - has_left = true; + } else if ((*it).name_ == CAM_LFT_KEY) { + read_vector((*it).value_, left); + has_left = true; - } else if ((*it).name_ == CAM_UPV_KEY) { - read_vector((*it).value_, up); - has_up = true; + } else if ((*it).name_ == CAM_UPV_KEY) { + read_vector((*it).value_, up); + has_up = true; - } else - cerr << "Unrecognized key \"" << (*it).name_ << "\" in input file." << endl; + } else if ((*it).name_ == GEO_TRN_KEY) + read_vector((*it).value_, translation); + + else if ((*it).name_ == CAM_RLL_KEY) + roll = static_cast((*it).value_.get_value()); + + else if ((*it).name_ == CAM_PTC_KEY) + pitch = static_cast((*it).value_.get_value()); + + else if ((*it).name_ == CAM_YAW_KEY) + yaw = static_cast((*it).value_.get_value()); + + else + cerr << "Unrecognized key \"" << (*it).name_ << "\" in camera." << endl; + } + } catch (SceneError & e) { + throw e; } - if (!has_eye) - throw SceneError("Must specify an eye position for the camera."); - - if (!has_look) - throw SceneError("Must specify a look position for the camera."); + if (!has_eye || !has_look) + throw SceneError("Must specify an eye and look positions for the camera."); if (has_up) - c = new Camera(eye, look, up); + m_cam = new Camera(eye, look, up); else if(!has_up && has_left) { up = cross(normalize(look - eye), left); - c = new Camera(eye, look, up); + m_cam = new Camera(eye, look, up); } else throw SceneError("Must specify either an up or left vector for the camera."); + + m_cam->pitch(pitch); + m_cam->yaw(yaw); + m_cam->roll(roll); + m_cam->translate(translation); +} + +Material * Scene::read_material(Value & v) throw(SceneError) { + vec3 emission = vec3(0.0f), diffuse = vec3(1.0f), specular = vec3(1.0f); + bool transmissive = false; + float rho = 0.0f, ref_index = 1.0f, shininess = 89.0f; + Material * mat = NULL; + Object mat_obj = v.get_value(); + + try { + for (Object::iterator it = mat_obj.begin(); it != mat_obj.end(); it++) { + if ((*it).name_ == MLT_EMS_KEY) { + read_vector((*it).value_, emission); + + } else if ((*it).name_ == MLT_DIF_KEY) { + read_vector((*it).value_, diffuse); + + } else if ((*it).name_ == MLT_SPC_KEY) { + read_vector((*it).value_, specular); + + } else if ((*it).name_ == MLT_RHO_KEY) { + rho = static_cast((*it).value_.get_value()); + + } else if ((*it).name_ == MLT_SHN_KEY) { + shininess = static_cast((*it).value_.get_value()); + + } else if ((*it).name_ == MLT_RFI_KEY) { + ref_index = static_cast((*it).value_.get_value()); + + } else if ((*it).name_ == MLT_BRF_KEY) { + transmissive = (*it).value_.get_value(); + + } else if ((*it).name_ == MLT_BRD_KEY) { + if ((*it).value_.get_value() == BRD_PHN_KEY) + mat = new Material(new PhongBRDF()); + else if ((*it).value_.get_value() == BRD_HSA_KEY) + mat = new Material(new HeidrichSeidelAnisotropicBRDF(vec3(0.0f, 1.0f, 0.0f))); + + } else + cerr << "Unrecognized key \"" << (*it).name_ << "\" in material." << endl; + } + } catch(SceneError & e) { + throw e; + } + + if (mat == NULL) + mat = new Material(); + mat->m_emission = emission; + mat->m_diffuse = diffuse; + mat->m_specular = specular; + mat->m_rho = rho; + mat->m_ref_index = ref_index; + mat->m_shininess = shininess; + mat->m_refract = transmissive; + + return mat; +} + +Figure * Scene::read_sphere(Value &v) throw(SceneError) { + bool has_position = false, has_radius = false; + vec3 position; + float radius = 1.0f; + Material * mat = NULL; + Object sph_obj = v.get_value(); + + try { + for (Object::iterator it = sph_obj.begin(); it != sph_obj.end(); it++) { + if ((*it).name_ == FIG_POS_KEY) { + read_vector((*it).value_, position); + has_position = true; + + } else if ((*it).name_ == FIG_MAT_KEY) { + try { + mat = read_material((*it).value_); + } catch (SceneError & e) { + throw e; + } + + } else if ((*it).name_ == FIG_RAD_KEY) { + radius = static_cast((*it).value_.get_value()); + + if (radius <= 0.0f) + throw SceneError("Sphere radius must be greater than 0."); + + has_radius = true; + + } else + cerr << "Unrecognized key \"" << (*it).name_ << "\" in sphere." << endl; + } + } catch (SceneError & e) { + throw e; + } + + if (!has_position || !has_radius) + throw SceneError("Sphere must specify a position and radius."); + + return static_cast
(new Sphere(position, radius, mat)); +} + +Figure * Scene::read_plane(Value &v) throw(SceneError) { + bool has_position = false, has_normal = false; + vec3 position, normal = vec3(0.0f, 1.0f, 0.0f); + Material * mat = NULL; + Object pln_obj = v.get_value(); + + try { + for (Object::iterator it = pln_obj.begin(); it != pln_obj.end(); it++) { + if ((*it).name_ == FIG_POS_KEY || (*it).name_ == PLN_PNT_KEY) { + read_vector((*it).value_, position); + has_position = true; + + } else if ((*it).name_ == FIG_MAT_KEY) { + try { + mat = read_material((*it).value_); + } catch (SceneError & e) { + throw e; + } + + } else if ((*it).name_ == FIG_NOR_KEY) { + read_vector((*it).value_, normal); + has_normal = true; + + } else + cerr << "Unrecognized key \"" << (*it).name_ << "\" in plane." << endl; + } + } catch (SceneError & e) { + throw e; + } + + if (!has_position || !has_normal) + throw SceneError("Plane must specify a point and normal vector."); + + return static_cast
(new Plane(position, normal, mat)); +} + +Figure * Scene::read_disk(Value &v) throw(SceneError) { + bool has_position = false, has_normal = false, has_radius = false; + vec3 position, normal = vec3(0.0f, 1.0f, 0.0f); + float radius = 1.0f; + Material * mat = NULL; + Object dsk_obj = v.get_value(); + + try { + for (Object::iterator it = dsk_obj.begin(); it != dsk_obj.end(); it++) { + if ((*it).name_ == FIG_POS_KEY || (*it).name_ == PLN_PNT_KEY) { + read_vector((*it).value_, position); + has_position = true; + + } else if ((*it).name_ == FIG_MAT_KEY) { + try { + mat = read_material((*it).value_); + } catch (SceneError & e) { + throw e; + } + + } else if ((*it).name_ == FIG_NOR_KEY) { + read_vector((*it).value_, normal); + has_normal = true; + + } else if ((*it).name_ == FIG_RAD_KEY) { + radius = static_cast((*it).value_.get_value()); + + if (radius <= 0.0f) + throw SceneError("Disk radius must be greater than 0."); + + has_radius = true; + + } else + cerr << "Unrecognized key \"" << (*it).name_ << "\" in disk." << endl; + } + } catch (SceneError & e) { + throw e; + } + + if (!has_position || !has_normal || !has_radius) + throw SceneError("Disk must specify a point, a normal vector and a radius."); + + return static_cast
(new Disk(position, normal, radius, mat)); } diff --git a/scene.hpp b/scene.hpp index c68ba59..b43eb6c 100644 --- a/scene.hpp +++ b/scene.hpp @@ -6,14 +6,18 @@ #include #include +#include + #include "camera.hpp" #include "figure.hpp" #include "light.hpp" +#include "material.hpp" #include "environment.hpp" using std::string; using std::vector; using std::runtime_error; +using json_spirit::Value; class SceneError: public runtime_error { public: @@ -29,6 +33,15 @@ public: Scene(const char * file_name, int h = 480, int w = 640, float fov = 90.0f) throw(SceneError); ~Scene(); + +private: + void read_vector(Value & val, vec3 & vec) throw(SceneError); + void read_environment(Value & v) throw(SceneError); + void read_camera(Value & v) throw(SceneError); + Material * read_material(Value & v) throw(SceneError); + Figure * read_sphere(Value &v) throw(SceneError); + Figure * read_plane(Value &v) throw(SceneError); + Figure * read_disk(Value &v) throw(SceneError); }; #endif diff --git a/scenes/scene3.json b/scenes/scene3.json index db6bbbc..541def5 100644 --- a/scenes/scene3.json +++ b/scenes/scene3.json @@ -7,15 +7,17 @@ "camera": { "eye": [0.0, 1.5, 1.0], "look": [0.0, 0.0, -2.0], - "left": [-1.0, 0.0, 0.0] + "left": [-1.0, 0.0, 0.0], + "translation": [1.0, 0.0, 0.0] }, "sphere": { "position": [2.0, 0.0, -2.0], "radius": 1.5, "material": { - "diffuse": [1.0f, 0.0f, 1.0f], - "shininess": 128.0 + "diffuse": [1.0, 1.0, 0.0], + "shininess": 128.0, + "brdf": "heidrich-seidel" } }, diff --git a/sphere.hpp b/sphere.hpp index 555187e..42172f4 100644 --- a/sphere.hpp +++ b/sphere.hpp @@ -13,11 +13,11 @@ public: vec3 m_center; float m_radius; - Sphere(BRDF * _brdf = NULL): Figure(_brdf), m_center(vec3(0.0f)), m_radius(0.5f) { } + Sphere(Material * mat = NULL): Figure(mat), m_center(vec3(0.0f)), m_radius(0.5f) { } - Sphere(float x, float y, float z, float r, BRDF * _brdf = NULL): Figure(_brdf), m_center(vec3(x, y, z)), m_radius(r) { } + Sphere(float x, float y, float z, float r, Material * mat = NULL): Figure(mat), m_center(vec3(x, y, z)), m_radius(r) { } - Sphere(vec3 _c, float r, BRDF * _brdf = NULL): Figure(_brdf), m_center(_c), m_radius(r) { } + Sphere(vec3 _c, float r, Material * mat = NULL): Figure(mat), m_center(_c), m_radius(r) { } virtual ~Sphere() { } diff --git a/tracer.hpp b/tracer.hpp index bf6107b..513eb00 100644 --- a/tracer.hpp +++ b/tracer.hpp @@ -6,10 +6,8 @@ #include -#include "figure.hpp" -#include "light.hpp" -#include "environment.hpp" #include "ray.hpp" +#include "scene.hpp" using std::vector; using glm::vec2; @@ -29,7 +27,7 @@ public: virtual ~Tracer() { } - virtual vec3 trace_ray(Ray & r, vector
& v_figures, vector & v_lights, Environment * e, unsigned int rec_level) const = 0; + virtual vec3 trace_ray(Ray & r, Scene * s, unsigned int rec_level) const = 0; protected: float fresnel(const vec3 & i, const vec3 & n, const float ir1, const float ir2) const; diff --git a/whitted_tracer.cpp b/whitted_tracer.cpp index d3fae17..63eeb7e 100644 --- a/whitted_tracer.cpp +++ b/whitted_tracer.cpp @@ -9,7 +9,7 @@ using namespace glm; WhittedTracer::~WhittedTracer() { } -vec3 WhittedTracer::trace_ray(Ray & r, vector
& v_figures, vector & v_lights, Environment * e, unsigned int rec_level) const { +vec3 WhittedTracer::trace_ray(Ray & r, Scene * s, unsigned int rec_level) const { float t, _t; Figure * _f; vec3 n, color, i_pos, ref, dir_diff_color, dir_spec_color; @@ -21,10 +21,10 @@ vec3 WhittedTracer::trace_ray(Ray & r, vector
& v_figures, vectorintersect(r, _t) && _t < t) { + for (size_t f = 0; f < s->m_figures.size(); f++) { + if (s->m_figures[f]->intersect(r, _t) && _t < t) { t = _t; - _f = v_figures[f]; + _f = s->m_figures[f]; } } @@ -37,22 +37,22 @@ vec3 WhittedTracer::trace_ray(Ray & r, vector
& v_figures, vectorm_mat->m_refract) { // Calculate the direct lighting. - for (size_t l = 0; l < v_lights.size(); l++) { + for (size_t l = 0; l < s->m_lights.size(); l++) { // For every light source vis = true; // Cast a shadow ray to determine visibility. - sr = Ray(v_lights[l]->direction(i_pos), i_pos + n * BIAS); - for (size_t f = 0; f < v_figures.size(); f++) { - if (v_figures[f]->intersect(sr, _t) && _t < v_lights[l]->distance(i_pos)) { + sr = Ray(s->m_lights[l]->direction(i_pos), i_pos + n * BIAS); + for (size_t f = 0; f < s->m_figures.size(); f++) { + if (s->m_figures[f]->intersect(sr, _t) && _t < s->m_lights[l]->distance(i_pos)) { vis = false; break; } } // Evaluate the shading model accounting for visibility. - dir_diff_color += vis ? v_lights[l]->diffuse(n, r, i_pos, *_f->m_mat) : vec3(0.0f); - dir_spec_color += vis ? v_lights[l]->specular(n, r, i_pos, *_f->m_mat) : vec3(0.0f); + dir_diff_color += vis ? s->m_lights[l]->diffuse(n, r, i_pos, *_f->m_mat) : vec3(0.0f); + dir_spec_color += vis ? s->m_lights[l]->specular(n, r, i_pos, *_f->m_mat) : vec3(0.0f); } color += (dir_diff_color * (_f->m_mat->m_diffuse / pi())) + (_f->m_mat->m_specular * dir_spec_color); @@ -60,7 +60,7 @@ vec3 WhittedTracer::trace_ray(Ray & r, vector
& v_figures, vectorm_mat->m_rho > 0.0f && rec_level < m_max_depth) { rr = Ray(normalize(reflect(r.m_direction, n)), i_pos + n * BIAS); - color += _f->m_mat->m_rho * trace_ray(rr, v_figures, v_lights, e, rec_level + 1); + color += _f->m_mat->m_rho * trace_ray(rr, s, rec_level + 1); } else if (_f->m_mat->m_rho > 0.0f && rec_level >= m_max_depth) return vec3(0.0f); @@ -71,14 +71,14 @@ vec3 WhittedTracer::trace_ray(Ray & r, vector
& v_figures, vector 0.0f && rec_level < m_max_depth) { rr = Ray(normalize(reflect(r.m_direction, n)), i_pos + n * BIAS); - color += kr * trace_ray(rr, v_figures, v_lights, e, rec_level + 1); + color += kr * trace_ray(rr, s, rec_level + 1); } else if (rec_level >= m_max_depth) return vec3(0.0f); // Determine the transmission color. if (_f->m_mat->m_refract && kr < 1.0f && rec_level < m_max_depth) { rr = Ray(normalize(refract(r.m_direction, n, r.m_ref_index / _f->m_mat->m_ref_index)), i_pos - n * BIAS, _f->m_mat->m_ref_index); - color += (1.0f - kr) * trace_ray(rr, v_figures, v_lights, e, rec_level + 1); + color += (1.0f - kr) * trace_ray(rr, s, rec_level + 1); } else if (rec_level >= m_max_depth) return vec3(0.0f); @@ -87,10 +87,6 @@ vec3 WhittedTracer::trace_ray(Ray & r, vector
& v_figures, vectorm_mat->m_emission + color; - } else { - if (e != NULL) - return e->get_color(r); - else - return vec3(0.0f); - } + } else + return s->m_env->get_color(r); } diff --git a/whitted_tracer.hpp b/whitted_tracer.hpp index 00692c1..8e3f802 100644 --- a/whitted_tracer.hpp +++ b/whitted_tracer.hpp @@ -12,7 +12,7 @@ public: virtual ~WhittedTracer(); - virtual vec3 trace_ray(Ray & r, vector
& v_figures, vector & v_lights, Environment * e, unsigned int rec_level) const; + virtual vec3 trace_ray(Ray & r, Scene * s, unsigned int rec_level) const; }; #endif