2011-04-27 11:58:34 +00:00
|
|
|
/*
|
2013-08-18 14:16:15 +00:00
|
|
|
* Copyright 2011-2013 Blender Foundation
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License
|
2011-04-27 11:58:34 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "buffers.h"
|
|
|
|
#include "camera.h"
|
|
|
|
#include "device.h"
|
|
|
|
#include "scene.h"
|
|
|
|
#include "session.h"
|
|
|
|
|
|
|
|
#include "util_args.h"
|
|
|
|
#include "util_foreach.h"
|
|
|
|
#include "util_function.h"
|
|
|
|
#include "util_path.h"
|
|
|
|
#include "util_progress.h"
|
|
|
|
#include "util_string.h"
|
|
|
|
#include "util_time.h"
|
2013-08-30 17:34:27 +00:00
|
|
|
|
|
|
|
#ifdef WITH_CYCLES_STANDALONE_GUI
|
2011-04-27 11:58:34 +00:00
|
|
|
#include "util_view.h"
|
2013-08-30 17:34:27 +00:00
|
|
|
#endif
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
#include "cycles_xml.h"
|
|
|
|
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
|
|
|
|
struct Options {
|
|
|
|
Session *session;
|
|
|
|
Scene *scene;
|
|
|
|
string filepath;
|
|
|
|
int width, height;
|
|
|
|
SceneParams scene_params;
|
|
|
|
SessionParams session_params;
|
|
|
|
bool quiet;
|
|
|
|
} options;
|
|
|
|
|
|
|
|
static void session_print(const string& str)
|
|
|
|
{
|
|
|
|
/* print with carriage return to overwrite previous */
|
|
|
|
printf("\r%s", str.c_str());
|
|
|
|
|
|
|
|
/* add spaces to overwrite longer previous print */
|
|
|
|
static int maxlen = 0;
|
|
|
|
int len = str.size();
|
|
|
|
maxlen = max(len, maxlen);
|
|
|
|
|
|
|
|
for(int i = len; i < maxlen; i++)
|
|
|
|
printf(" ");
|
|
|
|
|
|
|
|
/* flush because we don't write an end of line */
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void session_print_status()
|
|
|
|
{
|
2012-09-04 13:29:07 +00:00
|
|
|
int sample, tile;
|
2011-09-16 13:14:02 +00:00
|
|
|
double total_time, sample_time;
|
2011-04-27 11:58:34 +00:00
|
|
|
string status, substatus;
|
|
|
|
|
|
|
|
/* get status */
|
2012-09-04 13:29:07 +00:00
|
|
|
sample = options.session->progress.get_sample();
|
|
|
|
options.session->progress.get_tile(tile, total_time, sample_time);
|
2011-04-27 11:58:34 +00:00
|
|
|
options.session->progress.get_status(status, substatus);
|
|
|
|
|
|
|
|
if(substatus != "")
|
|
|
|
status += ": " + substatus;
|
|
|
|
|
|
|
|
/* print status */
|
2011-09-16 13:14:02 +00:00
|
|
|
status = string_printf("Sample %d %s", sample, status.c_str());
|
2011-04-27 11:58:34 +00:00
|
|
|
session_print(status);
|
|
|
|
}
|
|
|
|
|
2011-12-21 20:51:43 +00:00
|
|
|
static BufferParams& session_buffer_params()
|
2011-12-20 12:25:37 +00:00
|
|
|
{
|
2011-12-21 20:51:43 +00:00
|
|
|
static BufferParams buffer_params;
|
2011-12-20 12:25:37 +00:00
|
|
|
buffer_params.width = options.width;
|
|
|
|
buffer_params.height = options.height;
|
|
|
|
buffer_params.full_width = options.width;
|
|
|
|
buffer_params.full_height = options.height;
|
|
|
|
|
|
|
|
return buffer_params;
|
|
|
|
}
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
static void session_init()
|
|
|
|
{
|
|
|
|
options.session = new Session(options.session_params);
|
2011-12-20 12:25:37 +00:00
|
|
|
options.session->reset(session_buffer_params(), options.session_params.samples);
|
2011-04-27 11:58:34 +00:00
|
|
|
options.session->scene = options.scene;
|
|
|
|
|
|
|
|
if(options.session_params.background && !options.quiet)
|
|
|
|
options.session->progress.set_update_callback(function_bind(&session_print_status));
|
2013-08-30 17:34:27 +00:00
|
|
|
#ifdef WITH_CYCLES_STANDALONE_GUI
|
2011-04-27 11:58:34 +00:00
|
|
|
else
|
|
|
|
options.session->progress.set_update_callback(function_bind(&view_redraw));
|
2013-08-30 17:34:27 +00:00
|
|
|
#endif
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
options.session->start();
|
|
|
|
|
|
|
|
options.scene = NULL;
|
|
|
|
}
|
|
|
|
|
2011-12-25 13:34:18 +00:00
|
|
|
static void scene_init(int width, int height)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2012-09-04 13:29:07 +00:00
|
|
|
options.scene = new Scene(options.scene_params, options.session_params.device);
|
2011-04-27 11:58:34 +00:00
|
|
|
xml_read_file(options.scene, options.filepath.c_str());
|
2011-12-25 13:34:18 +00:00
|
|
|
|
|
|
|
if (width == 0 || height == 0) {
|
|
|
|
options.width = options.scene->camera->width;
|
|
|
|
options.height = options.scene->camera->height;
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void session_exit()
|
|
|
|
{
|
|
|
|
if(options.session) {
|
|
|
|
delete options.session;
|
|
|
|
options.session = NULL;
|
|
|
|
}
|
|
|
|
if(options.scene) {
|
|
|
|
delete options.scene;
|
|
|
|
options.scene = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(options.session_params.background && !options.quiet) {
|
|
|
|
session_print("Finished Rendering.");
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-30 17:34:27 +00:00
|
|
|
#ifdef WITH_CYCLES_STANDALONE_GUI
|
2011-04-27 11:58:34 +00:00
|
|
|
static void display_info(Progress& progress)
|
|
|
|
{
|
|
|
|
static double latency = 0.0;
|
|
|
|
static double last = 0;
|
|
|
|
double elapsed = time_dt();
|
|
|
|
string str;
|
|
|
|
|
|
|
|
latency = (elapsed - last);
|
|
|
|
last = elapsed;
|
|
|
|
|
2012-09-04 13:29:07 +00:00
|
|
|
int sample, tile;
|
2011-09-16 13:14:02 +00:00
|
|
|
double total_time, sample_time;
|
2011-04-27 11:58:34 +00:00
|
|
|
string status, substatus;
|
|
|
|
|
2012-09-04 13:29:07 +00:00
|
|
|
sample = progress.get_sample();
|
|
|
|
progress.get_tile(tile, total_time, sample_time);
|
2011-04-27 11:58:34 +00:00
|
|
|
progress.get_status(status, substatus);
|
|
|
|
|
|
|
|
if(substatus != "")
|
|
|
|
status += ": " + substatus;
|
|
|
|
|
2011-09-16 13:14:02 +00:00
|
|
|
str = string_printf("latency: %.4f sample: %d total: %.4f average: %.4f %s",
|
|
|
|
latency, sample, total_time, sample_time, status.c_str());
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
view_display_info(str.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
static void display()
|
|
|
|
{
|
2011-12-20 12:25:37 +00:00
|
|
|
options.session->draw(session_buffer_params());
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
display_info(options.session->progress);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void resize(int width, int height)
|
|
|
|
{
|
2012-06-09 18:56:12 +00:00
|
|
|
options.width = width;
|
|
|
|
options.height = height;
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
if(options.session)
|
2011-12-20 12:25:37 +00:00
|
|
|
options.session->reset(session_buffer_params(), options.session_params.samples);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2013-07-21 16:40:34 +00:00
|
|
|
static void keyboard(unsigned char key)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
if(key == 'r')
|
2011-12-20 12:25:37 +00:00
|
|
|
options.session->reset(session_buffer_params(), options.session_params.samples);
|
2011-04-27 11:58:34 +00:00
|
|
|
else if(key == 27) // escape
|
|
|
|
options.session->progress.set_cancel("Cancelled");
|
|
|
|
}
|
2013-08-30 17:34:27 +00:00
|
|
|
#endif
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
static int files_parse(int argc, const char *argv[])
|
|
|
|
{
|
|
|
|
if(argc > 0)
|
|
|
|
options.filepath = argv[0];
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void options_parse(int argc, const char **argv)
|
|
|
|
{
|
2012-06-09 18:56:12 +00:00
|
|
|
options.width = 0;
|
|
|
|
options.height = 0;
|
2011-04-28 13:47:27 +00:00
|
|
|
options.filepath = "";
|
2011-04-27 11:58:34 +00:00
|
|
|
options.session = NULL;
|
|
|
|
options.quiet = false;
|
|
|
|
|
2012-01-04 18:06:32 +00:00
|
|
|
/* device names */
|
|
|
|
string device_names = "";
|
2011-04-27 11:58:34 +00:00
|
|
|
string devicename = "cpu";
|
2012-01-04 18:06:32 +00:00
|
|
|
bool list = false;
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2012-01-04 18:06:32 +00:00
|
|
|
vector<DeviceType>& types = Device::available_types();
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
foreach(DeviceType type, types) {
|
2012-01-04 18:06:32 +00:00
|
|
|
if(device_names != "")
|
|
|
|
device_names += ", ";
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2012-01-04 18:06:32 +00:00
|
|
|
device_names += Device::string_from_type(type);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* shading system */
|
|
|
|
string ssname = "svm";
|
|
|
|
string shadingsystems = "Shading system to use: svm";
|
|
|
|
|
|
|
|
#ifdef WITH_OSL
|
|
|
|
shadingsystems += ", osl";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* parse options */
|
|
|
|
ArgParse ap;
|
|
|
|
bool help = false;
|
|
|
|
|
2013-08-27 02:37:48 +00:00
|
|
|
ap.options ("Usage: cycles [options] file.xml",
|
2011-04-27 11:58:34 +00:00
|
|
|
"%*", files_parse, "",
|
2012-01-04 18:06:32 +00:00
|
|
|
"--device %s", &devicename, ("Devices to use: " + device_names).c_str(),
|
2011-04-27 11:58:34 +00:00
|
|
|
"--shadingsys %s", &ssname, "Shading system to use: svm, osl",
|
|
|
|
"--background", &options.session_params.background, "Render in background, without user interface",
|
|
|
|
"--quiet", &options.quiet, "In background mode, don't print progress messages",
|
2011-09-16 13:14:02 +00:00
|
|
|
"--samples %d", &options.session_params.samples, "Number of samples to render",
|
2011-04-27 11:58:34 +00:00
|
|
|
"--output %s", &options.session_params.output_path, "File path to write output image",
|
2011-08-24 10:44:04 +00:00
|
|
|
"--threads %d", &options.session_params.threads, "CPU Rendering Threads",
|
2011-12-25 13:34:18 +00:00
|
|
|
"--width %d", &options.width, "Window width in pixel",
|
|
|
|
"--height %d", &options.height, "Window height in pixel",
|
2012-01-04 18:06:32 +00:00
|
|
|
"--list-devices", &list, "List information about all available devices",
|
2011-04-27 11:58:34 +00:00
|
|
|
"--help", &help, "Print help message",
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if(ap.parse(argc, argv) < 0) {
|
2012-08-09 23:00:57 +00:00
|
|
|
fprintf(stderr, "%s\n", ap.geterror().c_str());
|
2011-04-27 11:58:34 +00:00
|
|
|
ap.usage();
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2012-01-04 18:06:32 +00:00
|
|
|
else if(list) {
|
|
|
|
vector<DeviceInfo>& devices = Device::available_devices();
|
|
|
|
printf("Devices:\n");
|
|
|
|
|
|
|
|
foreach(DeviceInfo& info, devices) {
|
|
|
|
printf(" %s%s\n",
|
|
|
|
info.description.c_str(),
|
|
|
|
(info.display_device)? " (display)": "");
|
|
|
|
}
|
|
|
|
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
else if(help || options.filepath == "") {
|
|
|
|
ap.usage();
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ssname == "osl")
|
|
|
|
options.scene_params.shadingsystem = SceneParams::OSL;
|
|
|
|
else if(ssname == "svm")
|
|
|
|
options.scene_params.shadingsystem = SceneParams::SVM;
|
2012-09-14 13:11:48 +00:00
|
|
|
|
2013-08-30 17:34:27 +00:00
|
|
|
#ifdef WITH_CYCLES_STANDALONE_GUI
|
|
|
|
/* Progressive rendering for GUI */
|
|
|
|
if(!options.session_params.background)
|
|
|
|
options.session_params.progressive = true;
|
|
|
|
#else
|
|
|
|
/* When building without GUI, set background */
|
|
|
|
options.session_params.background = true;
|
|
|
|
#endif
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2012-01-04 18:06:32 +00:00
|
|
|
/* find matching device */
|
|
|
|
DeviceType device_type = Device::type_from_string(devicename.c_str());
|
|
|
|
vector<DeviceInfo>& devices = Device::available_devices();
|
|
|
|
DeviceInfo device_info;
|
|
|
|
bool device_available = false;
|
|
|
|
|
|
|
|
foreach(DeviceInfo& device, devices) {
|
|
|
|
if(device_type == device.type) {
|
|
|
|
options.session_params.device = device;
|
|
|
|
device_available = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2012-01-04 18:06:32 +00:00
|
|
|
/* handle invalid configurations */
|
|
|
|
if(options.session_params.device.type == DEVICE_NONE || !device_available) {
|
2011-04-27 11:58:34 +00:00
|
|
|
fprintf(stderr, "Unknown device: %s\n", devicename.c_str());
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
#ifdef WITH_OSL
|
|
|
|
else if(!(ssname == "osl" || ssname == "svm")) {
|
|
|
|
#else
|
|
|
|
else if(!(ssname == "svm")) {
|
|
|
|
#endif
|
|
|
|
fprintf(stderr, "Unknown shading system: %s\n", ssname.c_str());
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2012-01-04 18:06:32 +00:00
|
|
|
else if(options.scene_params.shadingsystem == SceneParams::OSL && options.session_params.device.type != DEVICE_CPU) {
|
2011-04-27 11:58:34 +00:00
|
|
|
fprintf(stderr, "OSL shading system only works with CPU device\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2011-09-16 13:14:02 +00:00
|
|
|
else if(options.session_params.samples < 0) {
|
|
|
|
fprintf(stderr, "Invalid number of samples: %d\n", options.session_params.samples);
|
2011-04-27 11:58:34 +00:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
else if(options.filepath == "") {
|
|
|
|
fprintf(stderr, "No file path specified\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* load scene */
|
2011-12-25 13:34:18 +00:00
|
|
|
scene_init(options.width, options.height);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CCL_NAMESPACE_END
|
|
|
|
|
|
|
|
using namespace ccl;
|
|
|
|
|
|
|
|
int main(int argc, const char **argv)
|
|
|
|
{
|
2012-11-09 21:44:31 +00:00
|
|
|
path_init();
|
2011-04-27 11:58:34 +00:00
|
|
|
options_parse(argc, argv);
|
2013-08-30 17:34:27 +00:00
|
|
|
|
|
|
|
#ifdef WITH_CYCLES_STANDALONE_GUI
|
2011-04-27 11:58:34 +00:00
|
|
|
if(options.session_params.background) {
|
2013-08-30 17:34:27 +00:00
|
|
|
#endif
|
2011-04-27 11:58:34 +00:00
|
|
|
session_init();
|
|
|
|
options.session->wait();
|
|
|
|
session_exit();
|
2013-08-30 17:34:27 +00:00
|
|
|
#ifdef WITH_CYCLES_STANDALONE_GUI
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
string title = "Cycles: " + path_filename(options.filepath);
|
|
|
|
|
|
|
|
/* init/exit are callback so they run while GL is initialized */
|
|
|
|
view_main_loop(title.c_str(), options.width, options.height,
|
|
|
|
session_init, session_exit, resize, display, keyboard);
|
|
|
|
}
|
2013-08-30 17:34:27 +00:00
|
|
|
#endif
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|