248 lines
7.7 KiB
C++
248 lines
7.7 KiB
C++
|
|
#include <iostream>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <getopt.h>
|
|
#include <sys/time.h> /* gettimeofday() */
|
|
#include <string>
|
|
#include <map>
|
|
#include "Scene.h"
|
|
#include "distrib/distrib.h"
|
|
#include "BMP.h"
|
|
using namespace std;
|
|
|
|
void usage(const char * progname)
|
|
{
|
|
cout << "Usage: " << progname << " [options] <scene-file>" << endl;
|
|
cout << " Options:" << endl;
|
|
cout << " -o|--output-file <output-file-name>" << endl;
|
|
cout << " -w|--width <image-width>" << endl;
|
|
cout << " -h|--height <image-height>" << endl;
|
|
cout << " -m|--multisample <level>" << endl;
|
|
cout << " -f|--field-of-view <vertical-fov>" << endl;
|
|
cout << " -d|--max-depth <max-recursion-depth>" << endl;
|
|
cout << " --hosts <hosts-file>" << endl;
|
|
exit(42);
|
|
}
|
|
|
|
int main(int argc, char * argv[])
|
|
{
|
|
int opt;
|
|
int option_index;
|
|
map<string, const char *> scene_options;
|
|
vector<string> 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' },
|
|
{ "width", required_argument, NULL, 'w' },
|
|
{ "height", required_argument, NULL, 'h' },
|
|
{ "multisample", required_argument, NULL, 'm' },
|
|
{ "field-of-view", required_argument, NULL, 'f' },
|
|
{ "max-depth", required_argument, NULL, 'd' },
|
|
{ "help", no_argument, NULL, 256 },
|
|
{ "host", required_argument, NULL, 257 },
|
|
{ "port", required_argument, NULL, 258 },
|
|
{ "hosts", required_argument, NULL, 259 },
|
|
{ NULL, 0, NULL, 0 }
|
|
};
|
|
|
|
while ((opt = getopt_long(argc, argv, "o:w:h:m:f:d:",
|
|
long_options, &option_index)) != -1)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case 'o':
|
|
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;
|
|
client_options.push_back("--max-depth");
|
|
client_options.push_back(optarg);
|
|
break;
|
|
case 256:
|
|
usage(argv[0]);
|
|
break;
|
|
case 257:
|
|
server_name = optarg;
|
|
server = false;
|
|
distributed = true;
|
|
break;
|
|
case 258:
|
|
server_port = atoi(optarg);
|
|
distributed = true;
|
|
break;
|
|
case 259:
|
|
hosts_file = optarg;
|
|
distributed = true;
|
|
break;
|
|
default:
|
|
usage(argv[0]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (optind >= argc)
|
|
{
|
|
usage(argv[0]);
|
|
}
|
|
|
|
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 */
|
|
|
|
#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;
|
|
cout << "Elapsed time: " << total_seconds << " seconds";
|
|
|
|
double seconds = total_seconds;
|
|
int days = (int) (seconds / (60.0 * 60.0 * 24.0));
|
|
seconds -= days * 60.0 * 60.0 * 24.0;
|
|
int hours = (int) (seconds / (60.0 * 60.0));
|
|
seconds -= hours * 60.0 * 60.0;
|
|
int minutes = (int) (seconds / 60.0);
|
|
seconds -= minutes * 60.0;
|
|
if (days || hours || minutes)
|
|
{
|
|
cout << " (";
|
|
if (days)
|
|
cout << days << (days == 1 ? " day, " : " days, ");
|
|
if (days || hours)
|
|
cout << hours << (hours == 1 ? " hour, " : " hours, ");
|
|
cout << minutes << (minutes == 1 ? " minute, " : " minutes, ");
|
|
cout << seconds << (seconds == 1 ? " second)" : " seconds)");
|
|
}
|
|
cout << endl;
|
|
}
|
|
|
|
return 0;
|
|
}
|