Blender V2.61 - r43446

cycles_test.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include <stdio.h>
00020 
00021 #include "buffers.h"
00022 #include "camera.h"
00023 #include "device.h"
00024 #include "scene.h"
00025 #include "session.h"
00026 
00027 #include "util_args.h"
00028 #include "util_foreach.h"
00029 #include "util_function.h"
00030 #include "util_path.h"
00031 #include "util_progress.h"
00032 #include "util_string.h"
00033 #include "util_time.h"
00034 #include "util_view.h"
00035 
00036 #include "cycles_xml.h"
00037 
00038 CCL_NAMESPACE_BEGIN
00039 
00040 struct Options {
00041     Session *session;
00042     Scene *scene;
00043     string filepath;
00044     int width, height;
00045     SceneParams scene_params;
00046     SessionParams session_params;
00047     bool quiet;
00048 } options;
00049 
00050 static void session_print(const string& str)
00051 {
00052     /* print with carriage return to overwrite previous */
00053     printf("\r%s", str.c_str());
00054 
00055     /* add spaces to overwrite longer previous print */
00056     static int maxlen = 0;
00057     int len = str.size();
00058     maxlen = max(len, maxlen);
00059 
00060     for(int i = len; i < maxlen; i++)
00061         printf(" ");
00062 
00063     /* flush because we don't write an end of line */
00064     fflush(stdout);
00065 }
00066 
00067 static void session_print_status()
00068 {
00069     int sample;
00070     double total_time, sample_time;
00071     string status, substatus;
00072 
00073     /* get status */
00074     options.session->progress.get_sample(sample, total_time, sample_time);
00075     options.session->progress.get_status(status, substatus);
00076 
00077     if(substatus != "")
00078         status += ": " + substatus;
00079 
00080     /* print status */
00081     status = string_printf("Sample %d   %s", sample, status.c_str());
00082     session_print(status);
00083 }
00084 
00085 static BufferParams& session_buffer_params()
00086 {
00087     static BufferParams buffer_params;
00088     buffer_params.width = options.width;
00089     buffer_params.height = options.height;
00090     buffer_params.full_width = options.width;
00091     buffer_params.full_height = options.height;
00092 
00093     return buffer_params;
00094 }
00095 
00096 static void session_init()
00097 {
00098     options.session = new Session(options.session_params);
00099     options.session->reset(session_buffer_params(), options.session_params.samples);
00100     options.session->scene = options.scene;
00101     
00102     if(options.session_params.background && !options.quiet)
00103         options.session->progress.set_update_callback(function_bind(&session_print_status));
00104     else
00105         options.session->progress.set_update_callback(function_bind(&view_redraw));
00106 
00107     options.session->start();
00108 
00109     options.scene = NULL;
00110 }
00111 
00112 static void scene_init(int width, int height)
00113 {
00114     options.scene = new Scene(options.scene_params);
00115     xml_read_file(options.scene, options.filepath.c_str());
00116     
00117     if (width == 0 || height == 0) {
00118         options.width = options.scene->camera->width;
00119         options.height = options.scene->camera->height;
00120     }
00121 }
00122 
00123 static void session_exit()
00124 {
00125     if(options.session) {
00126         delete options.session;
00127         options.session = NULL;
00128     }
00129     if(options.scene) {
00130         delete options.scene;
00131         options.scene = NULL;
00132     }
00133 
00134     if(options.session_params.background && !options.quiet) {
00135         session_print("Finished Rendering.");
00136         printf("\n");
00137     }
00138 }
00139 
00140 static void display_info(Progress& progress)
00141 {
00142     static double latency = 0.0;
00143     static double last = 0;
00144     double elapsed = time_dt();
00145     string str;
00146 
00147     latency = (elapsed - last);
00148     last = elapsed;
00149 
00150     int sample;
00151     double total_time, sample_time;
00152     string status, substatus;
00153 
00154     progress.get_sample(sample, total_time, sample_time);
00155     progress.get_status(status, substatus);
00156 
00157     if(substatus != "")
00158         status += ": " + substatus;
00159 
00160     str = string_printf("latency: %.4f        sample: %d        total: %.4f        average: %.4f        %s",
00161         latency, sample, total_time, sample_time, status.c_str());
00162 
00163     view_display_info(str.c_str());
00164 }
00165 
00166 static void display()
00167 {
00168     options.session->draw(session_buffer_params());
00169 
00170     display_info(options.session->progress);
00171 }
00172 
00173 static void resize(int width, int height)
00174 {
00175     options.width= width;
00176     options.height= height;
00177 
00178     if(options.session)
00179         options.session->reset(session_buffer_params(), options.session_params.samples);
00180 }
00181 
00182 void keyboard(unsigned char key)
00183 {
00184     if(key == 'r')
00185         options.session->reset(session_buffer_params(), options.session_params.samples);
00186     else if(key == 27) // escape
00187         options.session->progress.set_cancel("Cancelled");
00188 }
00189 
00190 static int files_parse(int argc, const char *argv[])
00191 {
00192     if(argc > 0)
00193         options.filepath = argv[0];
00194 
00195     return 0;
00196 }
00197 
00198 static void options_parse(int argc, const char **argv)
00199 {
00200     options.width= 0;
00201     options.height= 0;
00202     options.filepath = "";
00203     options.session = NULL;
00204     options.quiet = false;
00205 
00206     /* device names */
00207     string device_names = "";
00208     string devicename = "cpu";
00209     bool list = false;
00210 
00211     vector<DeviceType>& types = Device::available_types();
00212 
00213     foreach(DeviceType type, types) {
00214         if(device_names != "")
00215             device_names += ", ";
00216 
00217         device_names += Device::string_from_type(type);
00218     }
00219 
00220     /* shading system */
00221     string ssname = "svm";
00222     string shadingsystems = "Shading system to use: svm";
00223 
00224 #ifdef WITH_OSL
00225     shadingsystems += ", osl"; 
00226 #endif
00227 
00228     /* parse options */
00229     ArgParse ap;
00230     bool help = false;
00231 
00232     ap.options ("Usage: cycles_test [options] file.xml",
00233         "%*", files_parse, "",
00234         "--device %s", &devicename, ("Devices to use: " + device_names).c_str(),
00235         "--shadingsys %s", &ssname, "Shading system to use: svm, osl",
00236         "--background", &options.session_params.background, "Render in background, without user interface",
00237         "--quiet", &options.quiet, "In background mode, don't print progress messages",
00238         "--samples %d", &options.session_params.samples, "Number of samples to render",
00239         "--output %s", &options.session_params.output_path, "File path to write output image",
00240         "--threads %d", &options.session_params.threads, "CPU Rendering Threads",
00241         "--width  %d", &options.width, "Window width in pixel",
00242         "--height %d", &options.height, "Window height in pixel",
00243         "--list-devices", &list, "List information about all available devices",
00244         "--help", &help, "Print help message",
00245         NULL);
00246     
00247     if(ap.parse(argc, argv) < 0) {
00248         fprintf(stderr, "%s\n", ap.error_message().c_str());
00249         ap.usage();
00250         exit(EXIT_FAILURE);
00251     }
00252     else if(list) {
00253         vector<DeviceInfo>& devices = Device::available_devices();
00254         printf("Devices:\n");
00255 
00256         foreach(DeviceInfo& info, devices) {
00257             printf("    %s%s\n",
00258                 info.description.c_str(),
00259                 (info.display_device)? " (display)": "");
00260         }
00261 
00262         exit(EXIT_SUCCESS);
00263     }
00264     else if(help || options.filepath == "") {
00265         ap.usage();
00266         exit(EXIT_SUCCESS);
00267     }
00268 
00269     if(ssname == "osl")
00270         options.scene_params.shadingsystem = SceneParams::OSL;
00271     else if(ssname == "svm")
00272         options.scene_params.shadingsystem = SceneParams::SVM;
00273 
00274     /* find matching device */
00275     DeviceType device_type = Device::type_from_string(devicename.c_str());
00276     vector<DeviceInfo>& devices = Device::available_devices();
00277     DeviceInfo device_info;
00278     bool device_available = false;
00279 
00280     foreach(DeviceInfo& device, devices) {
00281         if(device_type == device.type) {
00282             options.session_params.device = device;
00283             device_available = true;
00284             break;
00285         }
00286     }
00287 
00288     /* handle invalid configurations */
00289     if(options.session_params.device.type == DEVICE_NONE || !device_available) {
00290         fprintf(stderr, "Unknown device: %s\n", devicename.c_str());
00291         exit(EXIT_FAILURE);
00292     }
00293 #ifdef WITH_OSL
00294     else if(!(ssname == "osl" || ssname == "svm")) {
00295 #else
00296     else if(!(ssname == "svm")) {
00297 #endif
00298         fprintf(stderr, "Unknown shading system: %s\n", ssname.c_str());
00299         exit(EXIT_FAILURE);
00300     }
00301     else if(options.scene_params.shadingsystem == SceneParams::OSL && options.session_params.device.type != DEVICE_CPU) {
00302         fprintf(stderr, "OSL shading system only works with CPU device\n");
00303         exit(EXIT_FAILURE);
00304     }
00305     else if(options.session_params.samples < 0) {
00306         fprintf(stderr, "Invalid number of samples: %d\n", options.session_params.samples);
00307         exit(EXIT_FAILURE);
00308     }
00309     else if(options.filepath == "") {
00310         fprintf(stderr, "No file path specified\n");
00311         exit(EXIT_FAILURE);
00312     }
00313 
00314     /* load scene */
00315     scene_init(options.width, options.height);
00316 }
00317 
00318 CCL_NAMESPACE_END
00319 
00320 using namespace ccl;
00321 
00322 int main(int argc, const char **argv)
00323 {
00324     path_init("../build/bin/2.59/scripts/addons/cycles/");
00325 
00326     options_parse(argc, argv);
00327 
00328     if(options.session_params.background) {
00329         session_init();
00330         options.session->wait();
00331         session_exit();
00332     }
00333     else {
00334         string title = "Cycles: " + path_filename(options.filepath);
00335 
00336         /* init/exit are callback so they run while GL is initialized */
00337         view_main_loop(title.c_str(), options.width, options.height,
00338             session_init, session_exit, resize, display, keyboard);
00339     }
00340 
00341     return 0;
00342 }
00343