Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

main.cpp

Go to the documentation of this file.
00001 /*
00002     toxic - A Global Illumination Renderer
00003     Copyright (C) 2003-2004 Francois Beaune
00004     Contact: http://toxicengine.sourceforge.net/
00005 
00006     This file is part of toxic.
00007 
00008     toxic is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     toxic is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with toxic; if not, write to the Free Software
00020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 // Guess the home path in Windows version in Release mode.
00024 #ifdef _WIN32
00025 #ifndef _DEBUG
00026 #define GUESS_HOME_PATH
00027 #endif  // !_DEBUG
00028 #endif  // _WIN32
00029 
00030 #include "clparser.h"
00031 #include "common/math/mt19937rng.h"
00032 #include "common/math/real.h"   // sheep::sq<>()
00033 #ifdef GUESS_HOME_PATH
00034 #include "common/misc/apppath.h"
00035 #endif  // GUESS_HOME_PATH
00036 #include "common/misc/consoleprogressmonitor.h"
00037 #include "common/misc/minmax.h"
00038 #include "common/misc/stringutils.h"
00039 #include "renderer/causticsphotontracer.h"
00040 #include "renderer/context.h"
00041 #include "renderer/framebuffer.h"
00042 #include "renderer/globalphotontracer.h"
00043 #include "renderer/globals.h"
00044 #include "renderer/icamera.h"
00045 #ifdef _DEBUG
00046 #include "renderer/photon.h"
00047 #endif  // _DEBUG
00048 #include "renderer/photonmap.h"
00049 #include "renderer/renderer.h"
00050 #include "renderer/scene.h"
00051 #include "renderer/settings.h"
00052 #include "renderer/statistics.h"
00053 #include "renderer/utilities.h"
00054 #include "driversettings.h"
00055 #include "driversettingswrapper.h"
00056 #include "error.h"
00057 #include "helpers.h"
00058 #include "scenebuilder.h"
00059 #include "scenesettingswrapper.h"
00060 #include "version.h"
00061 
00062 #ifdef ENABLE_MULTITHREADING
00063 #pragma warning(disable : 4275)
00064 #pragma warning(disable : 4251)
00065 
00066 #include <boost/thread/mutex.hpp>
00067 #include <boost/thread/thread.hpp>
00068 #endif  // ENABLE_MULTITHREADING
00069 
00070 #include <IL/il.h>
00071 #include <IL/ilu.h>
00072 
00073 #include <cassert>
00074 #include <cstdio>
00075 #include <cstdlib>  // std::exit(), EXIT_FAILURE, EXIT_SUCCESS
00076 #include <iostream>
00077 #include <sstream>
00078 #include <string>
00079 
00080 using namespace sheep;
00081 using namespace std;
00082 using namespace toxic;
00083 
00084 namespace { 
00085     void print_disclaimer() {
00086         cout << "toxic - A Global Illumination Renderer" << endl;
00087         cout << "Copyright (C) 2003-2004 Francois Beaune" << endl << endl;
00088         cout << "Visit http://toxicengine.sourceforge.net/ for more information." << endl;
00089         cout << endl;
00090     }
00091 
00092     string get_home_path() {
00093 #ifdef GUESS_HOME_PATH
00094         string path = StringUtils::GetPath(GetApplicationPath());
00095 
00096         // toxic binary must be located in the bin\ directory.
00097         const string bin_path = "bin\\";
00098 
00099         // Issue an error message if this is not the case.
00100         if(StringUtils::CompareNoCase(path.substr(path.size() - bin_path.size()), "bin\\")) {
00101             cerr << Error << "toxic is not installed correctly. Please reinstall it." << endl;
00102             exit(EXIT_FAILURE);
00103         }
00104 
00105         // Compute the home path by removing the bin\ suffix
00106         path = path.substr(0, path.size() - bin_path.size());
00107 
00108         return path;
00109 #else
00110         const char *home_env = getenv("TOXICHOME");
00111 
00112         if(!home_env) {
00113             cerr << Warning << "'TOXICHOME' environment variable not set." << endl;
00114             return "./";
00115         }
00116 
00117         return StringUtils::NormalizePath(home_env);
00118 #endif  // GUESS_HOME_PATH
00119     }
00120 
00121     void load_settings(DriverSettingsWrapper *driver_settings,
00122                        SceneSettingsWrapper *scene_settings,
00123                        const string &home_path)
00124     {
00125         assert(driver_settings);
00126         assert(scene_settings);
00127 
00128         string driver_settings_file =
00129             driver_settings->m_settings_files.m_driver_settings_file;
00130 
00131         if(driver_settings_file.size() == 0) {
00132             driver_settings_file = home_path + "settings/toxicsettings.xml";
00133         }
00134 
00135         // Load driver settings.
00136         driver_settings->Load(driver_settings_file, home_path);
00137 
00138         // Load scene settings.
00139         scene_settings->Load(
00140             driver_settings->m_settings_files.m_scene_settings_file,
00141             home_path
00142         );
00143     }
00144 
00145     void print_statistics(const Statistics &statistics) {
00146         Indenter indenter;
00147 
00148         cout << indenter() << "Rendering Statistics:" << endl;
00149         indenter.Indent();
00150 
00151         // Pixels.
00152 
00153         cout << indenter() << "Pixels" << endl;
00154         indenter.Indent();
00155 
00156         cout << indenter() << "Rendered Pixels: "
00157             << ConvertNumberToString(statistics.m_total_pixels)
00158             << endl;
00159 
00160         indenter.Unindent();
00161 
00162         // Photons.
00163 
00164         cout << indenter() << "Photons" << endl;
00165         indenter.Indent();
00166 
00167         cout << indenter() << "Photons in Global Photon Map: "
00168             << ConvertNumberToString(statistics.m_gpm_photons)
00169             << endl;
00170         cout << indenter() << "Photons in Caustics Photon Map: "
00171             << ConvertNumberToString(statistics.m_cpm_photons)
00172             << endl;
00173 
00174         indenter.Unindent();
00175 
00176         // Rays.
00177 
00178         cout << indenter() << "Rays" << endl;
00179         indenter.Indent();
00180 
00181         const int64 total_rays_cast = statistics.ComputeTotalRays();
00182 
00183         cout << indenter() << "Total Rays Cast: "
00184             << ConvertNumberToString(total_rays_cast)
00185             << endl;
00186         indenter.Indent();
00187         cout << indenter() << "Primary Rays: "
00188             << ConvertNumberToString(statistics.m_primary_rays)
00189             << " ("
00190             << Percentage(statistics.m_primary_rays, total_rays_cast)
00191             << ')' << endl;
00192         cout << indenter() << "Secondary Rays: "
00193             << ConvertNumberToString(statistics.m_secondary_rays)
00194             << " ("
00195             << Percentage(statistics.m_secondary_rays, total_rays_cast)
00196             << ')' << endl;
00197         cout << indenter() << "Shadow Rays: "
00198             << ConvertNumberToString(statistics.m_shadow_rays)
00199             << " ("
00200             << Percentage(statistics.m_shadow_rays, total_rays_cast)
00201             << ')' << endl;
00202         cout << indenter() << "Primary Final Gathering Rays: "
00203             << ConvertNumberToString(statistics.m_primary_final_gathering_rays)
00204             << " ("
00205             << Percentage(statistics.m_primary_final_gathering_rays, total_rays_cast)
00206             << ')' << endl;
00207         cout << indenter() << "Secondary Final Gathering Rays: "
00208             << ConvertNumberToString(statistics.m_secondary_final_gathering_rays)
00209             << " ("
00210             << Percentage(statistics.m_secondary_final_gathering_rays, total_rays_cast)
00211             << ')' << endl;
00212         indenter.Unindent();
00213 
00214         cout << indenter() << "Average Rays per Pixel: "
00215             << Ratio(total_rays_cast, statistics.m_total_pixels)
00216             << endl;
00217         indenter.Indent();
00218         cout << indenter() << "Primary Rays: "
00219             << Ratio(statistics.m_primary_rays, statistics.m_total_pixels)
00220             << endl;
00221         cout << indenter() << "Secondary Rays: "
00222             << Ratio(statistics.m_secondary_rays, statistics.m_total_pixels)
00223             << endl;
00224         cout << indenter() << "Shadow Rays: "
00225             << Ratio(statistics.m_shadow_rays, statistics.m_total_pixels)
00226             << endl;
00227         cout << indenter() << "Primary Final Gathering Rays: "
00228             << Ratio(statistics.m_primary_final_gathering_rays, statistics.m_total_pixels)
00229             << endl;
00230         cout << indenter() << "Secondary Final Gathering Rays: "
00231             << Ratio(statistics.m_secondary_final_gathering_rays, statistics.m_total_pixels)
00232             << endl;
00233         indenter.Unindent();
00234 
00235         indenter.Unindent();
00236 
00237         // Intersections.
00238 
00239         cout << indenter() << "Intersections" << endl;
00240         indenter.Indent();
00241 
00242         cout << indenter() << "Intersections Tested: "
00243             << ConvertNumberToString(statistics.m_tested_intersections)
00244             << endl;
00245         cout << indenter() << "Intersections Found: "
00246             << ConvertNumberToString(statistics.m_intersections_found)
00247             << endl;
00248         cout << indenter() << "Found/Tested Intersections Ratio: "
00249             << Percentage(statistics.m_intersections_found, statistics.m_tested_intersections)
00250             << endl;
00251 
00252         indenter.Unindent();
00253     }
00254 }
00255 
00256 #ifdef ENABLE_MULTITHREADING
00257 
00258 boost::mutex io_mutex;
00259 
00260 void foo() {
00261     for(int i = 0; i < 100; ++i) {
00262         boost::mutex::scoped_lock lock(io_mutex);
00263         cerr << '*';
00264     }
00265 }
00266 
00267 class RenderingThread {
00268 public:
00269     RenderingThread(Renderer *renderer, const Context &context) :
00270         m_renderer(renderer),
00271         m_context(context)
00272     {
00273         assert(renderer);
00274         assert(progmon);
00275     }
00276 
00277     void operator()() const {
00278         while(!m_renderer->IsRenderComplete()) {
00279             m_renderer->RenderNextPixel(m_context);
00280         }
00281     }
00282 
00283 private:
00284     Renderer *m_renderer;
00285     const Context &m_context;
00286 };
00287 
00288 class ProgressMonitoringThread {
00289 public:
00290     void operator()() const {
00291         while(true) {
00292         }
00293     }
00294 
00295 private:
00296 
00297     bool is_render_complete() const {
00298         for(int i = 0; i < nthreads; ++i) {
00299             if(IsRenderComplete
00300         }
00301     }
00302 };
00303 
00304 #endif  // ENABLE_MULTITHREADING
00305 
00306 int main(int argc, char *argv[]) {
00307     //!\todo Create a DevILManager() following the example of XercesManager().
00308     ilInit();
00309     iluInit();
00310 
00311     print_disclaimer();
00312 
00313     // Print version informations.
00314     cout << "Running toxic version " << VERSION << ", build " << BUILD_NUMBER << endl << endl;
00315 
00316 #ifdef _DEBUG
00317     cout << "DEBUG: Size of the Photon structure: "
00318         << sizeof(Photon)
00319         << " bytes"
00320         << endl << endl;
00321 #endif  // _DEBUG
00322 
00323     const string home_path = get_home_path();
00324 
00325 #ifdef _DEBUG
00326     cout << "DEBUG: Home path: " << home_path << endl << endl;
00327 #endif  // _DEBUG
00328 
00329     DriverSettingsWrapper driver_settings;
00330     SceneSettingsWrapper scene_settings;
00331 
00332     // Parse the command line.
00333     CLParser(&driver_settings).Parse(argc, argv);
00334 
00335     // Load settings.
00336     load_settings(&driver_settings, &scene_settings, home_path);
00337 
00338     // Check settings consistency.
00339     driver_settings.CheckConsistency();
00340     scene_settings.CheckConsistency();
00341 
00342     // Print settings.
00343     driver_settings.Print(cout);
00344     cout << endl;
00345     scene_settings.Print(cout);
00346     cout << endl;
00347 
00348     ConsoleProgressMonitor progmon;
00349     stringstream ss;
00350 
00351     // Count the number of task to complete.
00352     int task_count = 0;
00353     ++task_count;       // initialize framebuffer
00354     ++task_count;       // initialize scene
00355     if(scene_settings.m_rendering.m_components.m_indirect_lighting.m_enabled)
00356         ++task_count;   // build/load global photon map
00357     if(scene_settings.m_rendering.m_components.m_caustics.m_enabled)
00358         ++task_count;   // build/load caustics photon map
00359     if(driver_settings.m_primary_output.m_enabled)
00360         ++task_count;   // generate primary output
00361 
00362     int current_task = 0;
00363 
00364     // Create the Context object.
00365     MT19937RNG rng;
00366     Statistics statistics;
00367     Context context(&rng, &scene_settings, &statistics);
00368 
00369     // Create the Renderer object.
00370     Renderer renderer;
00371 
00372     cout << ++current_task << '/' << task_count << ". Initializing framebuffer" << endl;
00373 
00374     // Allocate memory for the framebuffer.
00375     cout << "     * Memory allocation" << flush;
00376     Framebuffer *framebuffer = new Framebuffer(
00377         driver_settings.m_primary_output.m_width,
00378         driver_settings.m_primary_output.m_height,
00379         Framebuffer::RGB_FLOAT_32
00380     );
00381     cout << " [" << ConvertSizeToString(framebuffer->GetSizeInMemory(), true)
00382         << " allocated]." << endl;
00383 
00384     // Initialize (clear) the framebuffer.
00385     cout << "     * Memory initialization" << flush;
00386     framebuffer->Clear();
00387     cout << '.' << endl;
00388 
00389     // Assign the framebuffer to the renderer.
00390     renderer.SetFramebuffer(framebuffer);
00391 
00392     // Restrict the render area on demand.
00393     if(scene_settings.m_output.m_render_area.m_enabled) {
00394         renderer.SetRenderArea(
00395             scene_settings.m_output.m_render_area.m_x0,
00396             scene_settings.m_output.m_render_area.m_y0,
00397             scene_settings.m_output.m_render_area.m_x1,
00398             scene_settings.m_output.m_render_area.m_y1
00399         );
00400     }
00401 
00402     // Load the input file.
00403 
00404     cout << ++current_task << '/' << task_count << ". Initializing scene" << endl;
00405 
00406     SceneBuilder *scene_builder;
00407     const Scene *scene;
00408     const ICamera *camera;
00409 
00410     bool successful = false;
00411 
00412     try {
00413         scene_builder = new SceneBuilder(
00414             context,
00415             framebuffer,
00416             driver_settings.m_input_files.m_scene_file,
00417             home_path,
00418             &progmon
00419         );
00420 
00421         scene = scene_builder->GetScene().release();
00422         camera = scene_builder->GetCamera().release();
00423 
00424         successful = true;
00425     }
00426     catch(const SceneBuilder::ParseErrorException &e) {
00427         cerr << Error << e.m_message << endl;
00428     }
00429     catch(const SceneBuilder::LoadErrorException &e) {
00430         cerr << Error << e.m_message << endl;
00431     }
00432     catch(...) {
00433         cerr << Error << "Unknown exception." << endl;
00434     }
00435 
00436     if(!successful) {
00437         cerr << Error << "Could not load the scene file '"
00438             << driver_settings.m_input_files.m_scene_file
00439             << "'." << endl;
00440         return EXIT_FAILURE;
00441     }
00442 
00443     renderer.SetScene(scene);
00444     renderer.SetCamera(camera);
00445 
00446     cout << "     * Scene composition" << endl;
00447     cout << "         Objects: " << scene->GetRootObject()->GetObjectCount() << endl;
00448     cout << "         Light sources: " << scene->GetLightCount() << endl;
00449 
00450     PhotonMap *global_pm = 0;
00451 
00452     if(scene_settings.m_rendering.m_components.m_indirect_lighting.m_enabled) {
00453         if(driver_settings.m_global_photon_map.m_op == DriverSettings::LOAD_PM) {
00454             // Load the global photon map from disk.
00455 
00456             ss.str("");
00457             ss << ++current_task << '/' << task_count << ". Reading GPM from file "
00458                 << driver_settings.m_global_photon_map.m_file;
00459             progmon.Reset(ss.str());
00460 
00461             global_pm = PhotonMap::CreateFromFile(
00462                 driver_settings.m_global_photon_map.m_file,
00463                 &progmon
00464             );
00465 
00466             if(!global_pm) {
00467                 cerr << Error << "Failed to read from file '"
00468                     << driver_settings.m_global_photon_map.m_file << "'." << endl;
00469                 return EXIT_FAILURE;
00470             }
00471 
00472             statistics.m_gpm_photons = global_pm->GetPhotonCount();
00473             // 'statistics.m_photon_rays' is not updated.
00474         } else {
00475             // Build the global photon map from scratch.
00476 
00477             cout << ++current_task << '/' << task_count << ". Building global photon map (GPM)" << endl;
00478 
00479             // Allocate memory for the global photon map.
00480             global_pm = new PhotonMap();
00481 
00482             // Build the global photon map by tracing photons through the scene.
00483             progmon.Reset("     * Photon tracing");
00484             GlobalPhotonTracer().BuildPhotonMap(
00485                 context,
00486                 global_pm,
00487                 scene,
00488                 scene_settings.m_rendering.m_components.m_indirect_lighting.m_photon_tracing.m_photons,
00489                 &progmon
00490             );
00491 
00492             // Balance the global photon map.
00493             cout << "     * Photon map balancing" << flush;
00494             global_pm->Balance();
00495             cout << '.' << endl;
00496 
00497             // Precompute radiances if necessary.
00498             if(scene_settings.m_rendering.m_components.m_indirect_lighting.m_radiance_precomp.m_enabled) {
00499 #ifdef ENABLE_RADIANCES_PRECOMPUTATION
00500                 progmon.Reset("     * Radiances precomputation");
00501                 global_pm->PrecomputeRadiances(
00502                     scene_settings.m_rendering.m_components.m_indirect_lighting.m_radiance_precomp.m_spacing,
00503                     scene_settings.m_rendering.m_components.m_indirect_lighting.m_radiance_est.m_max_distance,
00504                     scene_settings.m_rendering.m_components.m_indirect_lighting.m_radiance_est.m_max_photons,
00505                     &progmon
00506                 );
00507 #else
00508                 cout << "     * Radiances precomputation not available. Using standard radiance estimate." << endl;
00509 #endif  // ENABLE_RADIANCES_PRECOMPUTATION
00510             }
00511         }
00512 
00513         // Display some early statistics.
00514         cout << "     * Early statistics" << endl;
00515         cout << "         Allocated memory: "
00516             << ConvertSizeToString(global_pm->GetSizeInMemory(), true)
00517             << endl;
00518         if(driver_settings.m_global_photon_map.m_op != DriverSettings::LOAD_PM) {
00519             cout << "         Emitted photons: "
00520                 << ConvertNumberToString(scene_settings.m_rendering.m_components.m_indirect_lighting.m_photon_tracing.m_photons)
00521                 << endl;
00522         }
00523         cout << "         Stored photons: "
00524             << ConvertNumberToString(statistics.m_gpm_photons);
00525         if(driver_settings.m_global_photon_map.m_op != DriverSettings::LOAD_PM) {
00526             cout << " ("
00527                 << Percentage(statistics.m_gpm_photons, scene_settings.m_rendering.m_components.m_indirect_lighting.m_photon_tracing.m_photons)
00528                 << ')';
00529         }
00530         cout << endl;
00531 
00532         if(driver_settings.m_global_photon_map.m_op == DriverSettings::BUILD_AND_SAVE_PM) {
00533             // Save the global photon map to disk.
00534 
00535             ss.str("");
00536             ss << "     * Writing GPM to file "
00537                 << driver_settings.m_global_photon_map.m_file;
00538             progmon.Reset(ss.str());
00539 
00540             if(!global_pm->WriteToFile(
00541                 driver_settings.m_global_photon_map.m_file,
00542                 &progmon))
00543             {
00544                 cerr << Error << "Failed to write to file '"
00545                     << driver_settings.m_global_photon_map.m_file << "'." << endl;
00546                 //return EXIT_FAILURE;
00547             }
00548         }
00549 
00550         // Assign the global photon map to the renderer.
00551         renderer.SetGlobalPhotonMap(global_pm);
00552     }
00553 
00554     PhotonMap *caustics_pm = 0;
00555 
00556     if(scene_settings.m_rendering.m_components.m_caustics.m_enabled) {
00557         if(driver_settings.m_caustics_photon_map.m_op == DriverSettings::LOAD_PM) {
00558             // Load the caustics photon map from disk.
00559 
00560             ss.str("");
00561             ss << ++current_task << '/' << task_count << ". Reading CPM from file "
00562                 << driver_settings.m_caustics_photon_map.m_file;
00563             progmon.Reset(ss.str());
00564 
00565             caustics_pm = PhotonMap::CreateFromFile(
00566                 driver_settings.m_caustics_photon_map.m_file,
00567                 &progmon
00568             );
00569 
00570             if(!caustics_pm) {
00571                 cerr << Error << "Failed to read from file '"
00572                     << driver_settings.m_caustics_photon_map.m_file << "'." << endl;
00573                 return EXIT_FAILURE;
00574             }
00575 
00576             statistics.m_cpm_photons = caustics_pm->GetPhotonCount();
00577             // 'statistics.m_photon_rays' is not updated.
00578         } else {
00579             // Build the caustics photon map from scratch.
00580 
00581             cout << ++current_task << '/' << task_count << ". Building caustics photon map (CPM)" << endl;
00582 
00583             // Allocate memory for the caustics photon map.
00584             caustics_pm = new PhotonMap();
00585 
00586             // Build the caustics photon map by tracing photons through the scene.
00587             progmon.Reset("     * Photon tracing");
00588             CausticsPhotonTracer().BuildPhotonMap(
00589                 context,
00590                 caustics_pm,
00591                 scene,
00592                 scene_settings.m_rendering.m_components.m_caustics.m_photon_tracing.m_photons,
00593                 &progmon
00594             );
00595 
00596             cout << "     * Allocated memory: "
00597                 << ConvertSizeToString(caustics_pm->GetSizeInMemory(), true)
00598                 << "." << endl;
00599 
00600             // Balance the caustics photon map.
00601             cout << "     * Photon map balancing" << flush;
00602             caustics_pm->Balance();
00603             cout << '.' << endl;
00604         }
00605 
00606         // Display some early statistics.
00607         cout << "     * Early statistics" << endl;
00608         cout << "         Allocated memory: "
00609             << ConvertSizeToString(caustics_pm->GetSizeInMemory(), true)
00610             << endl;
00611         if(driver_settings.m_caustics_photon_map.m_op != DriverSettings::LOAD_PM) {
00612             cout << "         Emitted photons: "
00613                 << ConvertNumberToString(scene_settings.m_rendering.m_components.m_caustics.m_photon_tracing.m_photons)
00614                 << endl;
00615         }
00616         cout << "         Stored photons: "
00617             << ConvertNumberToString(statistics.m_cpm_photons);
00618         if(driver_settings.m_caustics_photon_map.m_op != DriverSettings::LOAD_PM) {
00619             cout << " ("
00620                 << Percentage(statistics.m_cpm_photons, scene_settings.m_rendering.m_components.m_caustics.m_photon_tracing.m_photons)
00621                 << ')';
00622         }
00623         cout << endl;
00624 
00625         if(driver_settings.m_caustics_photon_map.m_op == DriverSettings::BUILD_AND_SAVE_PM) {
00626             // Save the caustics photon map to disk.
00627 
00628             ss.str("");
00629             ss << "     * Writing CPM to file "
00630                 << driver_settings.m_caustics_photon_map.m_file;
00631             progmon.Reset(ss.str());
00632 
00633             if(!caustics_pm->WriteToFile(
00634                 driver_settings.m_caustics_photon_map.m_file,
00635                 &progmon))
00636             {
00637                 cerr << Error << "Failed to write to file '"
00638                     << driver_settings.m_caustics_photon_map.m_file << "'." << endl;
00639                 //return EXIT_FAILURE;
00640             }
00641         }
00642 
00643         // Assign the caustics photon map to the scene.
00644         renderer.SetCausticsPhotonMap(caustics_pm);
00645     }
00646 
00647     if(driver_settings.m_primary_output.m_enabled) {
00648         cout << ++current_task << '/' << task_count << ". Generating primary output" << endl;
00649 
00650         ss.str("");
00651         ss << "     * Rendering";
00652         progmon.Reset(ss.str());
00653         progmon.StartJob(0.0, 1.0);
00654 
00655         // Initialize the renderer.
00656         renderer.Restart(context);
00657 
00658 #ifdef ENABLE_MULTITHREADING
00659         boost::thread_group threads;
00660 
00661         // Create a thread that will display total rendering progress.
00662         threads.create_thread(ProgressMonitoringThread());
00663 #endif  // ENABLE_MULTITHREADING
00664 
00665         // Render loop.
00666         while(!renderer.IsRenderComplete()) {
00667             renderer.RenderNextPixel(context);
00668 
00669 #ifdef ENABLE_MULTITHREADING
00670             boost::mutex::scoped_lock lock(io_mutex);
00671 #endif  // ENABLE_MULTITHREADING
00672 
00673             progmon.SetJobProgress(renderer.GetProgress());
00674         }
00675 
00676 #ifdef ENABLE_MULTITHREADING
00677         threads.join_all();
00678 #endif  // ENABLE_MULTITHREADING
00679 
00680         progmon.Done();
00681 
00682 //framebuffer->Normalize();
00683 
00684 //      renderer.Annotate(context);
00685 
00686         // Gamma correct the image if gamma correction is enabled.
00687         if(scene_settings.m_output.m_gamma_correction.m_enabled) {
00688             cout << "     * Applying gamma correction" << flush;
00689             framebuffer->CorrectGamma(
00690                 scene_settings.m_output.m_gamma_correction.m_target_gamma
00691             );
00692             cout << '.' << endl;
00693         }
00694 
00695         // Write rendered image to disk.
00696         cout << "     * Writing rendered image to file "
00697             << driver_settings.m_primary_output.m_file << flush;
00698         if(!framebuffer->WriteToDisk(driver_settings.m_primary_output.m_file)) {
00699             cerr << Error << "Failed to write to file '"
00700                 << driver_settings.m_primary_output.m_file << "'." << endl;
00701             //!\todo Try to save to another file (like backup.png).
00702             return EXIT_FAILURE;
00703         }
00704         cout << '.' << endl;
00705     }
00706 
00707     cout << endl;
00708 
00709     // Print statistics.
00710     print_statistics(statistics);
00711 
00712     delete caustics_pm;
00713     delete global_pm;
00714     delete camera;
00715     delete scene;
00716     delete scene_builder;
00717     delete framebuffer;
00718 
00719     return EXIT_SUCCESS;
00720 }

Generated on Tue May 11 01:31:50 2004 for toxic by doxygen 1.3.6