00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <sstream>
00025 #include <stdlib.h>
00026
00027 #include "scene.h"
00028 #include "camera.h"
00029 #include "film.h"
00030 #include "sampling.h"
00031 #include "dynload.h"
00032 #include "volume.h"
00033 #include "error.h"
00034 #include "context.h"
00035 #include "bxdf.h"
00036 #include "light.h"
00037 #include "spectrumwavelengths.h"
00038
00039 #include "randomgen.h"
00040
00041 #include <boost/thread/xtime.hpp>
00042 #include <boost/bind.hpp>
00043
00044 using namespace lux;
00045
00046
00047 u_int sampPos;
00048 boost::mutex sampPosMutex;
00049
00050
00051
00052
00053
00054 void Scene::Start() {
00055 SignalThreads(RenderThread::SIG_RUN);
00056 s_Timer.Start();
00057 }
00058
00059 void Scene::Pause() {
00060 SignalThreads(RenderThread::SIG_PAUSE);
00061 s_Timer.Stop();
00062 }
00063
00064 void Scene::Exit() {
00065 SignalThreads(RenderThread::SIG_EXIT);
00066 }
00067
00068
00069 int Scene::AddThread() {
00070 return CreateRenderThread();
00071 }
00072
00073 void Scene::RemoveThread() {
00074 RemoveRenderThread();
00075 }
00076
00077
00078 void Scene::UpdateFramebuffer() {
00079 camera->film->updateFrameBuffer();
00080 }
00081
00082 unsigned char* Scene::GetFramebuffer() {
00083 return camera->film->getFrameBuffer();
00084 }
00085
00086 int Scene::DisplayInterval() {
00087 return (int)camera->film->getldrDisplayInterval();
00088 }
00089
00090 int Scene::FilmXres() {
00091 return camera->film->xResolution;
00092 }
00093
00094 int Scene::FilmYres() {
00095 return camera->film->yResolution;
00096 }
00097
00098
00099 double Scene::Statistics(const string &statName) {
00100 if(statName=="secElapsed") {
00101
00102 if (preprocessDone)
00103 return s_Timer.Time();
00104 else
00105 return 0.0;
00106 } else if(statName=="samplesSec")
00107 return Statistics_SamplesPSec();
00108 else if(statName=="samplesTotSec")
00109 return Statistics_SamplesPTotSec();
00110 else if(statName=="samplesPx")
00111 return Statistics_SamplesPPx();
00112 else if(statName=="efficiency")
00113 return Statistics_Efficiency();
00114 else if(statName=="filmXres")
00115 return FilmXres();
00116 else if(statName=="filmYres")
00117 return FilmYres();
00118 else if(statName=="displayInterval")
00119 return DisplayInterval();
00120 else {
00121 std::string eString("luxStatistics - requested an invalid data : ");
00122 eString+=statName;
00123 luxError(LUX_BADTOKEN, LUX_ERROR, eString.c_str());
00124 return 0.;
00125 }
00126 }
00127
00128
00129 double Scene::GetNumberOfSamples() {
00130 boost::mutex::scoped_lock lock(renderThreadsMutex);
00131
00132
00133 double samples = 0.;
00134 for(unsigned int i=0;i<renderThreads.size();i++)
00135 samples +=renderThreads[i]->stat_Samples;
00136
00137
00138 samples += numberOfSamplesFromNetwork;
00139
00140 return samples;
00141 }
00142
00143 double Scene::Statistics_SamplesPPx() {
00144
00145 int xstart, xend, ystart, yend;
00146 camera->film->GetSampleExtent(&xstart, &xend, &ystart, ¥d);
00147 return GetNumberOfSamples() / (double) ((xend-xstart)*(yend-ystart));
00148 }
00149
00150 double Scene::Statistics_SamplesPSec() {
00151
00152 if (!preprocessDone)
00153 return 0.0;
00154
00155 double samples = GetNumberOfSamples();
00156 double time = s_Timer.Time();
00157 double dif_samples = samples - lastSamples;
00158 double elapsed = time - lastTime;
00159 lastSamples = samples;
00160 lastTime = time;
00161
00162
00163 if (elapsed == 0.0)
00164 return 0.0;
00165 else
00166 return dif_samples / elapsed;
00167 }
00168
00169 double Scene::Statistics_SamplesPTotSec() {
00170
00171 if (!preprocessDone)
00172 return 0.0;
00173
00174 double samples = GetNumberOfSamples();
00175 double time = s_Timer.Time();
00176
00177
00178 return samples / time;
00179 }
00180
00181 double Scene::Statistics_Efficiency() {
00182 boost::mutex::scoped_lock lock(renderThreadsMutex);
00183
00184 if(renderThreads.size() == 0)
00185 return 0.0;
00186
00187
00188 double samples = 0.;
00189 double drops = 0.;
00190 for(unsigned int i=0;i<renderThreads.size();i++) {
00191 samples +=renderThreads[i]->stat_Samples;
00192 drops +=renderThreads[i]->stat_blackSamples;
00193 }
00194
00195 if (samples == 0.0)
00196 return 0.0;
00197
00198
00199 return 100. - (drops * (100/samples));
00200 }
00201
00202 void Scene::SignalThreads(int signal) {
00203 boost::mutex::scoped_lock lock(renderThreadsMutex);
00204
00205 for(unsigned int i=0;i<renderThreads.size();i++) {
00206 renderThreads[i]->signal=signal;
00207 }
00208 CurThreadSignal = signal;
00209 }
00210
00211
00212 extern boost::thread_specific_ptr<SpectrumWavelengths> thread_wavelengths;
00213
00214
00215 void RenderThread::render(RenderThread *myThread) {
00216
00217 while(!myThread->scene->preprocessDone) {
00218 boost::xtime xt;
00219 boost::xtime_get(&xt, boost::TIME_UTC);
00220 xt.sec += 1;
00221 boost::thread::sleep(xt);
00222 }
00223
00224
00225 BSDF::arena.reset(new MemoryArena());
00226 myThread->stat_Samples = 0.;
00227
00228
00229 int seed = myThread->scene->seedBase + myThread->n;
00230 std::stringstream ss;
00231 ss << "Thread " << myThread->n << " uses seed: " << seed;
00232 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
00233 lux::random::init(seed);
00234
00235
00236 thread_wavelengths.reset(new SpectrumWavelengths());
00237 SpectrumWavelengths *thr_wl = thread_wavelengths.get();
00238
00239
00240 u_int *useSampPos = new u_int();
00241 *useSampPos = 0;
00242 u_int maxSampPos = myThread->sampler->GetTotalSamplePos();
00243
00244
00245 while (true) {
00246 if(!myThread->sampler->GetNextSample(myThread->sample, useSampPos))
00247 break;
00248
00249
00250 thr_wl->Sample(myThread->sample->wavelengths,
00251 myThread->sample->singleWavelength);
00252
00253 while(myThread->signal == RenderThread::SIG_PAUSE) {
00254 boost::xtime xt;
00255 boost::xtime_get(&xt, boost::TIME_UTC);
00256 xt.sec += 1;
00257 boost::thread::sleep(xt);
00258 }
00259 if(myThread->signal== RenderThread::SIG_EXIT)
00260 break;
00261
00262
00263 RayDifferential ray;
00264 float rayWeight = myThread->camera->GenerateRay(*(myThread->sample), &ray);
00265
00266 if (rayWeight > 0.f) {
00267
00268 ++(myThread->sample->imageX);
00269 float wt1 = myThread->camera->GenerateRay(*(myThread->sample), &ray.rx);
00270 --(myThread->sample->imageX);
00271 ++(myThread->sample->imageY);
00272 float wt2 = myThread->camera->GenerateRay(*(myThread->sample), &ray.ry);
00273 ray.hasDifferentials = wt1 > 0.f && wt2 > 0.f;
00274 --(myThread->sample->imageY);
00275
00276
00277 float alpha;
00278 SWCSpectrum Lo = myThread->surfaceIntegrator->Li(myThread->scene, ray, myThread->sample, &alpha);
00279
00280
00281
00282
00283 if (Lo.Black())
00284 myThread->stat_blackSamples++;
00285
00286
00287 myThread->sampler->AddSample(*(myThread->sample));
00288
00289
00290 BSDF::FreeAll();
00291 }
00292
00293
00294 myThread->stat_Samples++;
00295
00296 if(*useSampPos == -1 && maxSampPos != 0) {
00297 boost::mutex::scoped_lock lock(sampPosMutex);
00298 sampPos++;
00299 if( sampPos == maxSampPos )
00300 sampPos = 0;
00301 *useSampPos = sampPos;
00302 }
00303 #ifdef WIN32
00304
00305 myThread->thread->yield();
00306 #endif
00307
00308 }
00309
00310 delete useSampPos;
00311 return;
00312 }
00313
00314 int Scene::CreateRenderThread() {
00315 #if !defined(WIN32)
00316 boost::mutex::scoped_lock lock(renderThreadsMutex);
00317 #endif
00318
00319 RenderThread *rt = new RenderThread(renderThreads.size(),
00320 CurThreadSignal,
00321 surfaceIntegrator,
00322 volumeIntegrator,
00323 sampler->clone(), camera, this);
00324
00325 renderThreads.push_back(rt);
00326 rt->thread = new boost::thread(boost::bind(RenderThread::render, rt));
00327
00328 return 0;
00329 }
00330
00331 void Scene::RemoveRenderThread() {
00332 #if !defined(WIN32)
00333 boost::mutex::scoped_lock lock(renderThreadsMutex);
00334 #endif
00335
00336 renderThreads.back()->signal = RenderThread::SIG_EXIT;
00337 renderThreads.pop_back();
00338 }
00339
00340 void Scene::Render() {
00341
00342
00343
00344
00345 BSDF::arena.reset(new MemoryArena());
00346
00347
00348 int seed = seedBase - 1;
00349 std::stringstream ss;
00350 ss << "Preprocess thread uses seed: " << seed;
00351 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
00352 lux::random::init(seed);
00353
00354
00355 thread_wavelengths.reset(new SpectrumWavelengths());
00356
00357
00358 camera->film->SetScene(this);
00359 sampler->SetFilm(camera->film);
00360 surfaceIntegrator->Preprocess(this);
00361 volumeIntegrator->Preprocess(this);
00362
00363
00364 camera->AutoFocus(this);
00365
00366 sampPos = 0;
00367
00368
00369 s_Timer.Start();
00370
00371
00372 preprocessDone = true;
00373
00374
00375 CurThreadSignal = RenderThread::SIG_RUN;
00376
00377
00378
00379
00380 CreateRenderThread();
00381
00382
00383
00384 for(unsigned int i = 0; i < renderThreads.size(); i++)
00385 renderThreads[i]->thread->join();
00386
00387
00388 camera->film->WriteImage((ImageType)(IMAGE_FILEOUTPUT|IMAGE_FRAMEBUFFER));
00389 }
00390
00391 Scene::~Scene() {
00392 delete camera;
00393 delete sampler;
00394 delete surfaceIntegrator;
00395 delete volumeIntegrator;
00396 delete aggregate;
00397 delete volumeRegion;
00398 for (u_int i = 0; i < lights.size(); ++i)
00399 delete lights[i];
00400 }
00401
00402 Scene::Scene(Camera *cam, SurfaceIntegrator *si,
00403 VolumeIntegrator *vi, Sampler *s,
00404 Primitive *accel, const vector<Light *> <s,
00405 VolumeRegion *vr) {
00406 lights = lts;
00407 aggregate = accel;
00408 camera = cam;
00409 sampler = s;
00410 surfaceIntegrator = si;
00411 volumeIntegrator = vi;
00412 volumeRegion = vr;
00413 s_Timer.Reset();
00414 lastSamples = 0.;
00415 numberOfSamplesFromNetwork = 0.;
00416 lastTime = 0.;
00417 if (lts.size() == 0) {
00418 luxError(LUX_MISSINGDATA, LUX_SEVERE, "No light sources defined in scene; nothing to render. Exitting...");
00419 exit(1);
00420 }
00421
00422 bound = aggregate->WorldBound();
00423 if (volumeRegion) bound = Union(bound, volumeRegion->WorldBound());
00424
00425
00426 seedBase = rand();
00427
00428 preprocessDone = false;
00429 }
00430
00431 const BBox &Scene::WorldBound() const {
00432 return bound;
00433 }
00434
00435 SWCSpectrum Scene::Li(const RayDifferential &ray,
00436 const Sample *sample, float *alpha) const {
00437
00438
00439
00440
00441
00442
00443 return 0.;
00444 }
00445
00446 SWCSpectrum Scene::Transmittance(const Ray &ray) const {
00447 return volumeIntegrator->Transmittance(this, ray, NULL, NULL);
00448 }