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 "volume.h"
00032 #include "error.h"
00033 #include "context.h"
00034 #include "bxdf.h"
00035 #include "light.h"
00036 #include "spectrumwavelengths.h"
00037 #include "transport.h"
00038
00039 #include "randomgen.h"
00040
00041 #include "fastmutex.h"
00042
00043 #include <boost/thread/xtime.hpp>
00044 #include <boost/bind.hpp>
00045
00046 using namespace lux;
00047
00048
00049 static u_int sampPos;
00050 static fast_mutex sampPosMutex;
00051
00052
00053 void Scene::Start() {
00054 SignalThreads(RUN);
00055 }
00056
00057 void Scene::Pause() {
00058 SignalThreads(PAUSE);
00059 }
00060
00061 void Scene::Exit() {
00062 SignalThreads(EXIT);
00063 }
00064
00065
00066 int Scene::AddThread() {
00067 return CreateRenderThread();
00068 }
00069
00070 void Scene::RemoveThread() {
00071 RemoveRenderThread();
00072 }
00073
00074 int Scene::getThreadsStatus(RenderingThreadInfo *info, int maxInfoCount) {
00075 #if !defined(WIN32)
00076 boost::mutex::scoped_lock lock(renderThreadsMutex);
00077 #endif
00078
00079 for (int i = 0; i < min<int>(renderThreads.size(), maxInfoCount); i++) {
00080 info[i].threadIndex = renderThreads[i]->n;
00081 info[i].status = renderThreads[i]->signal;
00082 }
00083
00084 return renderThreads.size();
00085 }
00086
00087 void Scene::SaveFLM( const string& filename ) {
00088 camera->film->WriteFilm(filename);
00089 }
00090
00091
00092 void Scene::UpdateFramebuffer() {
00093 camera->film->updateFrameBuffer();
00094
00095
00096
00097 if (contribPool)
00098 contribPool->CheckFilmWriteOuputInterval();
00099 }
00100
00101 unsigned char* Scene::GetFramebuffer() {
00102 return camera->film->getFrameBuffer();
00103 }
00104
00105
00106 void Scene::getHistogramImage(unsigned char *outPixels, int width, int height, int options){
00107 camera->film->getHistogramImage(outPixels, width, height, options);
00108 }
00109
00110
00111
00112 void Scene::SetParameterValue(luxComponent comp, luxComponentParameters param, double value, int index) {
00113 if(comp == LUX_FILM)
00114 camera->film->SetParameterValue(param, value, index);
00115 }
00116 double Scene::GetParameterValue(luxComponent comp, luxComponentParameters param, int index) {
00117 if(comp == LUX_FILM)
00118 return camera->film->GetParameterValue(param, index);
00119 else
00120 return 0.;
00121 }
00122 double Scene::GetDefaultParameterValue(luxComponent comp, luxComponentParameters param, int index) {
00123 if(comp == LUX_FILM)
00124 return camera->film->GetDefaultParameterValue(param, index);
00125 else
00126 return 0.;
00127 }
00128 void Scene::SetStringParameterValue(luxComponent comp, luxComponentParameters param, const string& value, int index) {
00129 }
00130 string Scene::GetStringParameterValue(luxComponent comp, luxComponentParameters param, int index) {
00131 if(comp == LUX_FILM)
00132 return camera->film->GetStringParameterValue(param, index);
00133 else
00134 return "";
00135 }
00136 string Scene::GetDefaultStringParameterValue(luxComponent comp, luxComponentParameters param, int index) {
00137 return "";
00138 }
00139
00140 int Scene::DisplayInterval() {
00141 return (int)camera->film->getldrDisplayInterval();
00142 }
00143
00144 int Scene::FilmXres() {
00145 return camera->film->GetXPixelCount();
00146 }
00147
00148 int Scene::FilmYres() {
00149 return camera->film->GetYPixelCount();
00150 }
00151
00152
00153 double Scene::Statistics(const string &statName) {
00154 if(statName=="secElapsed") {
00155
00156 if (preprocessDone)
00157 return s_Timer.Time();
00158 else
00159 return 0.0;
00160 } else if(statName=="samplesSec")
00161 return Statistics_SamplesPSec();
00162 else if(statName=="samplesTotSec")
00163 return Statistics_SamplesPTotSec();
00164 else if(statName=="samplesPx")
00165 return Statistics_SamplesPPx();
00166 else if(statName=="efficiency")
00167 return Statistics_Efficiency();
00168 else if(statName=="filmXres")
00169 return FilmXres();
00170 else if(statName=="filmYres")
00171 return FilmYres();
00172 else if(statName=="displayInterval")
00173 return DisplayInterval();
00174 else if(statName == "filmEV")
00175 return camera->film->EV;
00176 else {
00177 std::string eString("luxStatistics - requested an invalid data : ");
00178 eString+=statName;
00179 luxError(LUX_BADTOKEN, LUX_ERROR, eString.c_str());
00180 return 0.;
00181 }
00182 }
00183
00184
00185 double Scene::GetNumberOfSamples()
00186 {
00187 if (s_Timer.Time() - lastTime > .5f) {
00188 boost::mutex::scoped_lock lockThreads(renderThreadsMutex);
00189 for (u_int i = 0; i < renderThreads.size(); ++i) {
00190 fast_mutex::scoped_lock lockStats(renderThreads[i]->statLock);
00191 stat_Samples += renderThreads[i]->samples;
00192 stat_blackSamples += renderThreads[i]->blackSamples;
00193 renderThreads[i]->samples = 0.;
00194 renderThreads[i]->blackSamples = 0.;
00195 }
00196 }
00197
00198 return stat_Samples + numberOfSamplesFromNetwork;
00199 }
00200
00201 double Scene::Statistics_SamplesPPx()
00202 {
00203
00204 int xstart, xend, ystart, yend;
00205 camera->film->GetSampleExtent(&xstart, &xend, &ystart, ¥d);
00206 return GetNumberOfSamples() / ((xend - xstart) * (yend - ystart));
00207 }
00208
00209 double Scene::Statistics_SamplesPSec()
00210 {
00211
00212 if (!preprocessDone)
00213 return 0.0;
00214
00215 double samples = GetNumberOfSamples();
00216 double time = s_Timer.Time();
00217 double dif_samples = samples - lastSamples;
00218 double elapsed = time - lastTime;
00219 lastSamples = samples;
00220 lastTime = time;
00221
00222
00223 if (elapsed == 0.0)
00224 return 0.0;
00225 else
00226 return dif_samples / elapsed;
00227 }
00228
00229 double Scene::Statistics_SamplesPTotSec()
00230 {
00231
00232 if (!preprocessDone)
00233 return 0.0;
00234
00235 double samples = GetNumberOfSamples();
00236 double time = s_Timer.Time();
00237
00238
00239 return samples / time;
00240 }
00241
00242 double Scene::Statistics_Efficiency()
00243 {
00244 if (stat_Samples == 0.0)
00245 return 0.0;
00246
00247 return (100.f * stat_blackSamples) / stat_Samples;
00248 }
00249
00250 void Scene::SignalThreads(ThreadSignals signal) {
00251 #if !defined(WIN32)
00252 boost::mutex::scoped_lock lock(renderThreadsMutex);
00253 #endif
00254
00255 for(unsigned int i=0;i<renderThreads.size();i++) {
00256 if(renderThreads[i])
00257 renderThreads[i]->signal=signal;
00258 }
00259 CurThreadSignal = signal;
00260 }
00261
00262
00263 void RenderThread::render(RenderThread *myThread) {
00264 if (myThread->scene->IsFilmOnly())
00265 return;
00266
00267
00268 while(!myThread->scene->preprocessDone) {
00269 boost::xtime xt;
00270 boost::xtime_get(&xt, boost::TIME_UTC);
00271 ++xt.sec;
00272 boost::thread::sleep(xt);
00273 }
00274
00275
00276 int seed = myThread->scene->seedBase + myThread->n;
00277 std::stringstream ss;
00278 ss << "Thread " << myThread->n << " uses seed: " << seed;
00279 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
00280
00281
00282 myThread->tspack = new TsPack();
00283
00284 myThread->tspack->swl = new SpectrumWavelengths();
00285 myThread->tspack->rng = new RandomGenerator();
00286 myThread->tspack->rng->init(seed);
00287 myThread->tspack->arena = new MemoryArena();
00288 myThread->tspack->camera = myThread->scene->camera->Clone();
00289
00290 myThread->sampler->SetTsPack(myThread->tspack);
00291
00292 myThread->tspack->time = 0.f;
00293
00294
00295 u_int *useSampPos = new u_int();
00296 *useSampPos = 0;
00297 u_int maxSampPos = myThread->sampler->GetTotalSamplePos();
00298
00299
00300 while (true) {
00301 if(!myThread->sampler->GetNextSample(myThread->sample, useSampPos)) {
00302
00303
00304 if (myThread->scene->suspendThreadsWhenDone) {
00305 myThread->signal = PAUSE;
00306
00307
00308 while(myThread->signal == PAUSE) {
00309 boost::xtime xt;
00310 boost::xtime_get(&xt, boost::TIME_UTC);
00311 xt.sec += 1;
00312 boost::thread::sleep(xt);
00313 }
00314
00315 if(myThread->signal == EXIT)
00316 break;
00317 else
00318 continue;
00319 } else
00320 break;
00321 }
00322
00323
00324 myThread->tspack->time = myThread->tspack->camera->GetTime(myThread->sample->time);
00325
00326 myThread->tspack->camera->SampleMotion(myThread->tspack->time);
00327
00328
00329 myThread->tspack->swl->Sample(myThread->sample->wavelengths,
00330 myThread->sample->singleWavelength);
00331
00332 while(myThread->signal == PAUSE) {
00333 boost::xtime xt;
00334 boost::xtime_get(&xt, boost::TIME_UTC);
00335 xt.sec += 1;
00336 boost::thread::sleep(xt);
00337 }
00338 if(myThread->signal== EXIT)
00339 break;
00340
00341
00342
00343 do {
00344 fast_mutex::scoped_lock lockStats(myThread->statLock);
00345 myThread->blackSamples += myThread->surfaceIntegrator->Li(myThread->tspack,
00346 myThread->scene, myThread->sample);
00347 } while(0);
00348
00349
00350
00351 myThread->sampler->AddSample(*(myThread->sample));
00352
00353
00354 BSDF::FreeAll(myThread->tspack);
00355
00356
00357 do {
00358 fast_mutex::scoped_lock lockThreads(myThread->statLock);
00359 ++(myThread->samples);
00360 } while(0);
00361
00362
00363 if(*useSampPos == ~0U && maxSampPos != 0) {
00364 fast_mutex::scoped_lock lock(sampPosMutex);
00365 sampPos++;
00366 if( sampPos == maxSampPos )
00367 sampPos = 0;
00368 *useSampPos = sampPos;
00369 }
00370
00371 #ifdef WIN32
00372
00373 myThread->thread->yield();
00374 #endif
00375 }
00376
00377 myThread->sampler->Cleanup();
00378
00379 delete useSampPos;
00380
00381 delete myThread->tspack->swl;
00382 delete myThread->tspack->rng;
00383 delete myThread->tspack->arena;
00384
00385 delete myThread->tspack;
00386 return;
00387 }
00388
00389 int Scene::CreateRenderThread()
00390 {
00391 if (IsFilmOnly())
00392 return 0;
00393
00394 #if !defined(WIN32)
00395 boost::mutex::scoped_lock lock(renderThreadsMutex);
00396 #endif
00397
00398
00399
00400 if (CurThreadSignal != EXIT) {
00401 RenderThread *rt = new RenderThread(renderThreads.size(),
00402 CurThreadSignal, surfaceIntegrator, volumeIntegrator,
00403 sampler, camera, this);
00404
00405 renderThreads.push_back(rt);
00406 rt->thread = new boost::thread(boost::bind(RenderThread::render, rt));
00407 }
00408
00409 return renderThreads.size();
00410 }
00411
00412 void Scene::RemoveRenderThread()
00413 {
00414 #if !defined(WIN32)
00415 boost::mutex::scoped_lock lock(renderThreadsMutex);
00416 #endif
00417
00418 if (renderThreads.size() == 0)
00419 return;
00420 renderThreads.back()->signal = EXIT;
00421 renderThreads.back()->thread->join();
00422 delete renderThreads.back();
00423 renderThreads.pop_back();
00424 }
00425
00426 void Scene::Render() {
00427 if (IsFilmOnly())
00428 return;
00429
00430
00431
00432
00433 int seed = seedBase - 1;
00434 std::stringstream ss;
00435 ss << "Preprocess thread uses seed: " << seed;
00436 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
00437
00438
00439 contribPool = new ContributionPool();
00440 contribPool->SetFilm(camera->film);
00441
00442
00443 tspack = new TsPack();
00444 tspack->swl = new SpectrumWavelengths();
00445 tspack->rng = new RandomGenerator();
00446 tspack->rng->init(seed);
00447 tspack->arena = new MemoryArena();
00448
00449 sampler->SetTsPack(tspack);
00450
00451
00452 camera->film->SetScene(this);
00453 sampler->SetFilm(camera->film);
00454 sampler->SetContributionPool(contribPool);
00455 surfaceIntegrator->Preprocess(tspack, this);
00456 volumeIntegrator->Preprocess(tspack, this);
00457 camera->film->CreateBuffers();
00458
00459
00460 camera->AutoFocus(this);
00461
00462 sampPos = 0;
00463
00464
00465 s_Timer.Start();
00466
00467
00468 preprocessDone = true;
00469 Context::luxSceneReady();
00470
00471
00472 CurThreadSignal = RUN;
00473
00474
00475 CreateRenderThread();
00476
00477
00478
00479
00480
00481
00482 renderThreads[0]->thread->join();
00483
00484
00485 {
00486 #if !defined(WIN32)
00487 boost::mutex::scoped_lock lock(renderThreadsMutex);
00488 #endif
00489
00490
00491 for(unsigned int i = 0; i < renderThreads.size(); i++) {
00492 renderThreads[i]->thread->join();
00493 delete renderThreads[i];
00494 }
00495 renderThreads.clear();
00496
00497
00498
00499 CurThreadSignal = EXIT;
00500 }
00501
00502
00503 contribPool->Flush();
00504 contribPool->Delete();
00505
00506 delete tspack->swl;
00507 delete tspack->rng;
00508 delete tspack->arena;
00509 delete tspack;
00510 }
00511
00512 Scene::~Scene() {
00513 delete camera;
00514 delete sampler;
00515 delete surfaceIntegrator;
00516 delete volumeIntegrator;
00517 delete contribPool;
00518 delete volumeRegion;
00519 for (u_int i = 0; i < lights.size(); ++i)
00520 delete lights[i];
00521 }
00522
00523 Scene::Scene(Camera *cam, SurfaceIntegrator *si,
00524 VolumeIntegrator *vi, Sampler *s,
00525 boost::shared_ptr<Primitive> accel, const vector<Light *> <s,
00526 const vector<string> &lg, VolumeRegion *vr) {
00527 filmOnly = false;
00528 lights = lts;
00529 lightGroups = lg;
00530 aggregate = accel;
00531 camera = cam;
00532 sampler = s;
00533 surfaceIntegrator = si;
00534 volumeIntegrator = vi;
00535 volumeRegion = vr;
00536 s_Timer.Reset();
00537 lastSamples = 0.;
00538 stat_Samples = 0.;
00539 stat_blackSamples = 0.;
00540 numberOfSamplesFromNetwork = 0.;
00541 lastTime = 0.;
00542 if (lts.size() == 0) {
00543 luxError(LUX_MISSINGDATA, LUX_SEVERE, "No light sources defined in scene; nothing to render. Exitting...");
00544 exit(1);
00545 }
00546
00547 bound = aggregate->WorldBound();
00548 if (volumeRegion) bound = Union(bound, volumeRegion->WorldBound());
00549 bound = Union(bound, camera->Bounds());
00550
00551
00552 seedBase = rand();
00553
00554 preprocessDone = false;
00555 suspendThreadsWhenDone = false;
00556 camera->film->RequestBufferGroups(lightGroups);
00557
00558 contribPool = NULL;
00559 tspack = NULL;
00560
00561 CurThreadSignal = PAUSE;
00562 }
00563
00564 Scene::Scene(Camera *cam) {
00565 filmOnly = true;
00566 for(u_int i = 0; i < cam->film->GetNumBufferGroups(); i++)
00567 lightGroups.push_back( cam->film->GetGroupName(i) );
00568 camera = cam;
00569 sampler = NULL;
00570 surfaceIntegrator = NULL;
00571 volumeIntegrator = NULL;
00572 volumeRegion = NULL;
00573 s_Timer.Reset();
00574 lastSamples = 0.;
00575 numberOfSamplesFromNetwork = 0.;
00576 lastTime = 0.;
00577
00578
00579 seedBase = rand();
00580
00581 preprocessDone = false;
00582 suspendThreadsWhenDone = false;
00583 numberOfSamplesFromNetwork = 0;
00584
00585 contribPool = NULL;
00586 tspack = NULL;
00587
00588 CurThreadSignal = PAUSE;
00589 }
00590
00591 const BBox &Scene::WorldBound() const {
00592 return bound;
00593 }
00594
00595 SWCSpectrum Scene::Li(const RayDifferential &ray,
00596 const Sample *sample, float *alpha) const {
00597
00598
00599
00600
00601
00602
00603 return 0.f;
00604 }
00605
00606 void Scene::Transmittance(const TsPack *tsp, const Ray &ray,
00607 const Sample *sample, SWCSpectrum *const L) const {
00608 volumeIntegrator->Transmittance(tsp, this, ray, sample, NULL, L);
00609 }