diff --git a/main/Scene.cc b/main/Scene.cc index 0d0dc11..e50dda7 100644 --- a/main/Scene.cc +++ b/main/Scene.cc @@ -22,14 +22,10 @@ Scene::Scene(const map & options, m_width = 800; m_height = 600; m_multisample_level = 1; - m_output_file_name = "fart.bmp"; m_vfov = 60.0; - m_verbose = true; - m_data = NULL; m_ambient_light = Color(0.2, 0.2, 0.2); m_max_depth = 10; m_transforms.push(Transform()); - m_server = true; load(filename); @@ -41,79 +37,23 @@ Scene::Scene(const map & options, if (it->first == "width") { m_width = atoi(it->second); - m_client_options.push_back("--width"); - m_client_options.push_back(it->second); } else if (it->first == "height") { m_height = atoi(it->second); - m_client_options.push_back("--height"); - m_client_options.push_back(it->second); } else if (it->first == "multisample") { m_multisample_level = atoi(it->second); - m_client_options.push_back("--multisample"); - m_client_options.push_back(it->second); } else if (it->first == "field-of-view") { m_vfov = atof(it->second); - m_client_options.push_back("--field-of-view"); - m_client_options.push_back(it->second); - } - else if (it->first == "output-file") - { - m_output_file_name = it->second; - /* no client option necessary */ } else if (it->first == "max-depth") { m_max_depth = atoi(it->second); - m_client_options.push_back("--max-depth"); - m_client_options.push_back(it->second); } - else if (it->first == "verbose") - { - m_verbose = true; - /* no client option necessary */ - } - else if (it->first == "host") - { - m_server_name = it->second; - m_server = false; - /* no client option necessary */ - } - else if (it->first == "port") - { - m_server_port = atoi(it->second); - /* no client option necessary */ - } - else if (it->first == "hosts") - { - m_hosts_file = it->second; - /* no client option necessary */ - } - } - m_client_options.push_back(filename); - - /* start the distribution infrastructure */ - if (m_server) - { - if (m_hosts_file != "") - m_distrib.readHostFile(m_hosts_file.c_str()); - m_distrib.startServer(); - m_distrib.startClients(m_client_options); - - m_data = new unsigned char[m_width * m_height * 3]; /* 24bpp */ - int num_tasks = (m_width * m_height + (UNIT_TASK_SIZE - 1)) - / UNIT_TASK_SIZE; - m_distrib.set_num_tasks(num_tasks); - m_distrib.set_data(m_data, 3 * m_width * m_height); - } - else - { - m_distrib.startClient(m_server_name.c_str(), m_server_port); } /* view plane distance is calculated based on the field of view */ @@ -125,92 +65,6 @@ Scene::Scene(const map & options, Scene::~Scene() { - if (m_data != NULL) - delete m_data; -} - -void Scene::render() -{ - if (m_server) - { - /* server version */ - if (m_verbose) - { - cout << " *** Beginning scene render ***" << endl; - cout << "Parameters:" << endl; - cout << "----------------------------------------" << endl; - cout << " Width: " << m_width << endl; - cout << " Height: " << m_height << endl; - cout << " Multisample Level: " << m_multisample_level << endl; - cout << " Vertical Field of View: " << m_vfov << endl; - cout << "----------------------------------------" << endl; - } - - if (m_distrib.getNumClients() < 1) - { - for (int i = 0; i < m_height; i++) - { - for (int j = 0; j < m_width; j++) - { - renderPixel(j, i, &m_data[3 * (m_width * i + j)]); - } - } - } - else - { - /* work on tasks in this thread until there are no more */ - taskLoop(); - /* TODO: change wait condition */ - for (;;) - { - if (m_distrib.getNumTasksInProgress() == 0) - break; - usleep(100000); - } - } - - if (m_verbose) - { - cout << " *** Ending scene render ***" << endl; - cout << "Writing output file '" << m_output_file_name - << '\'' << endl; - } - BMP outputImage(m_output_file_name.c_str(), m_width, m_height, m_data); - } - else - { - /* client version */ - taskLoop(); - } -} - -void Scene::taskLoop() -{ - unsigned char data[3 * UNIT_TASK_SIZE]; - for (;;) - { - int task_id = m_distrib.getTask(); - if (task_id < 0) - break; - int pixel = task_id * UNIT_TASK_SIZE; - int i = pixel / m_width; - int j = pixel % m_width; - for (int t = 0; t < UNIT_TASK_SIZE; t++) - { - renderPixel(j, i, &data[3 * t]); - j++; - if (j >= m_width) - { - j = 0; - i++; - if (i >= m_height) - break; - } - } - int ret = m_distrib.send_data(task_id, data, 3 * UNIT_TASK_SIZE); - if (ret != 0) - break; - } } void Scene::renderPixel(int x, int y, unsigned char * pixel) diff --git a/main/Scene.h b/main/Scene.h index dd1de38..5b87ae1 100644 --- a/main/Scene.h +++ b/main/Scene.h @@ -13,8 +13,6 @@ #include "util/Color.h" #include "util/Material.h" -#include "distrib/distrib.h" - #include "shapes/shapes.h" #include "parser/parser.h" @@ -30,16 +28,19 @@ class Scene Scene(const std::map & options, const char * filename); ~Scene(); - void render(); void setWidth(int width) { m_width = width; } void setHeight(int height) { m_height = height; } void setMultisampleLevel(int level) { m_multisample_level = level; } void setVFOV(double vfov) { m_vfov = vfov; } void setAmbientLight(const Color & al) { m_ambient_light = al; } + void renderPixel(int x, int y, unsigned char * pixel); + int getWidth() { return m_width; } + int getHeight() { return m_height; } + int getMultisampleLevel() { return m_multisample_level; } + double getVFOV() { return m_vfov; } protected: /* private methods */ - void renderPixel(int x, int y, unsigned char * pixel); Color traceRay(const Ray & ray); Color traceRayRecurse(const Ray & ray, int depth, double factor); Shape::Intersection getRayClosestHit(const Ray & ray); @@ -49,7 +50,6 @@ class Scene const Vector & surfaceNormal); Color calculateLightContribution(const Ray & toLight, refptr light); - void taskLoop(); /* In Scene-load.cc */ void load(const char * filename); @@ -74,8 +74,6 @@ class Scene int m_width; int m_height; int m_multisample_level; - std::string m_output_file_name; - bool m_verbose; double m_vfov; Color m_ambient_light; int m_max_depth; @@ -89,17 +87,6 @@ class Scene double m_sample_span; double m_half_sample_span; std::map< std::string, refptr > m_materials; - - /* distribution infrastructure */ - bool m_server; - std::string m_server_name; - std::string m_hosts_file; - int m_server_port; - distrib m_distrib; - std::vector m_client_options; - - /* framebuffer */ - unsigned char * m_data; }; #endif diff --git a/main/fart.cc b/main/fart.cc index 6f2c288..49c5c74 100644 --- a/main/fart.cc +++ b/main/fart.cc @@ -8,6 +8,8 @@ #include #include #include "Scene.h" +#include "distrib/distrib.h" +#include "BMP.h" using namespace std; void usage(const char * progname) @@ -21,7 +23,6 @@ void usage(const char * progname) cout << " -f|--field-of-view " << endl; cout << " -d|--max-depth " << endl; cout << " --hosts " << endl; - cout << " -v|--verbose" << endl; exit(42); } @@ -30,7 +31,14 @@ int main(int argc, char * argv[]) int opt; int option_index; map scene_options; + vector client_options; bool server = true; + bool distributed = false; + const char * hosts_file = NULL; + const char * server_name = NULL; + int server_port = 0; + unsigned char * data = NULL; + const char * output_file_name = NULL; static const struct option long_options[] = { { "output-file", required_argument, NULL, 'o' }, @@ -39,7 +47,6 @@ int main(int argc, char * argv[]) { "multisample", required_argument, NULL, 'm' }, { "field-of-view", required_argument, NULL, 'f' }, { "max-depth", required_argument, NULL, 'd' }, - { "verbose", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 256 }, { "host", required_argument, NULL, 257 }, { "port", required_argument, NULL, 258 }, @@ -47,44 +54,54 @@ int main(int argc, char * argv[]) { NULL, 0, NULL, 0 } }; - while ((opt = getopt_long(argc, argv, "o:w:h:m:f:d:v", + while ((opt = getopt_long(argc, argv, "o:w:h:m:f:d:", long_options, &option_index)) != -1) { switch (opt) { case 'o': - scene_options["output-file"] = optarg; + output_file_name = optarg; break; case 'w': scene_options["width"] = optarg; + client_options.push_back("--width"); + client_options.push_back(optarg); break; case 'h': scene_options["height"] = optarg; + client_options.push_back("--height"); + client_options.push_back(optarg); break; case 'm': scene_options["multisample"] = optarg; + client_options.push_back("--multisample"); + client_options.push_back(optarg); break; case 'f': scene_options["field-of-view"] = optarg; + client_options.push_back("--field-of-view"); + client_options.push_back(optarg); break; case 'd': scene_options["max-depth"] = optarg; - break; - case 'v': - scene_options["verbose"] = optarg; + client_options.push_back("--max-depth"); + client_options.push_back(optarg); break; case 256: usage(argv[0]); break; case 257: - scene_options["host"] = optarg; + server_name = optarg; server = false; + distributed = true; break; case 258: - scene_options["port"] = optarg; + server_port = atoi(optarg); + distributed = true; break; case 259: - scene_options["hosts"] = optarg; + hosts_file = optarg; + distributed = true; break; default: usage(argv[0]); @@ -97,17 +114,110 @@ int main(int argc, char * argv[]) usage(argv[0]); } - Scene scene(scene_options, argv[optind]); + const char * filename = argv[optind]; + client_options.push_back(filename); + Scene scene(scene_options, filename); + + const int width = scene.getWidth(); + const int height = scene.getHeight(); + + if (server) + { + /* allocate data for the image */ + data = new unsigned char[3 * width * height]; + + cout << " *** Beginning scene render ***" << endl; + cout << "Parameters:" << endl; + cout << "----------------------------------------" << endl; + cout << " Width: " << width << endl; + cout << " Height: " << height << endl; + cout << " Multisample Level: " << scene.getMultisampleLevel() << endl; + cout << " Vertical Field of View: " << scene.getVFOV() << endl; + cout << "----------------------------------------" << endl; + } struct timeval before, after; gettimeofday(&before, NULL); /* start timing */ - scene.render(); +#if 0 +void Scene::taskLoop() +{ + unsigned char data[3 * UNIT_TASK_SIZE]; + for (;;) + { + int task_id = m_distrib.getTask(); + if (task_id < 0) + break; + int pixel = task_id * UNIT_TASK_SIZE; + int i = pixel / m_width; + int j = pixel % m_width; + for (int t = 0; t < UNIT_TASK_SIZE; t++) + { + renderPixel(j, i, &data[3 * t]); + j++; + if (j >= m_width) + { + j = 0; + i++; + if (i >= m_height) + break; + } + } + int ret = m_distrib.send_data(task_id, data, 3 * UNIT_TASK_SIZE); + if (ret != 0) + break; + } +} +#endif + + if (distributed) + { + /* start the distribution infrastructure */ + distrib the_distrib; + if (server) + { + if (strcmp(hosts_file, "")) + the_distrib.readHostFile(hosts_file); + + int num_tasks = (width * height + (UNIT_TASK_SIZE - 1)) + / UNIT_TASK_SIZE; + the_distrib.set_num_tasks(num_tasks); + the_distrib.set_data(data, 3 * width * height); + + the_distrib.startServer(); + the_distrib.startClients(client_options); + /* TODO: wait until all tasks are complete */ + } + else + { + the_distrib.startClient(server_name, server_port); + } + } + else + { + /* "sequential" version */ + unsigned char * pixel = &data[0]; + for (int i = 0; i < height; i++) + { + for (int j = 0; j < width; j++) + { + scene.renderPixel(j, i, pixel); + pixel += 3; + } + } + } gettimeofday(&after, NULL); /* stop timing */ if (server) { + cout << " *** Ending scene render ***" << endl; + cout << "Writing output file '" << output_file_name << '\'' << endl; + + /* write the image */ + BMP outputImage(output_file_name, width, height, data); + + /* print how much time has elapsed */ double time_before = before.tv_sec + before.tv_usec / 1000000.0; double time_after = after.tv_sec + after.tv_usec / 1000000.0; double total_seconds = time_after - time_before;