00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "lux.h"
00026 #include "scene.h"
00027 #include "context.h"
00028 #include "dynload.h"
00029 #include "api.h"
00030 #include "camera.h"
00031 #include "light.h"
00032 #include "shape.h"
00033 #include "volume.h"
00034 #include "material.h"
00035 #include "stats.h"
00036 #include "renderfarm.h"
00037 #include "fleximage.h"
00038
00039 #include <boost/iostreams/filtering_stream.hpp>
00040 #include <boost/iostreams/filtering_streambuf.hpp>
00041 #include <boost/iostreams/copy.hpp>
00042 #include <boost/iostreams/filter/zlib.hpp>
00043
00044 using namespace boost::iostreams;
00045 using namespace lux;
00046
00047 Context *Context::activeContext;
00048
00049
00050 #define VERIFY_INITIALIZED(func) \
00051 if (currentApiState == STATE_UNINITIALIZED) { \
00052 std::stringstream ss; \
00053 ss<<"luxInit() must be called before calling '"<<func<<"'. Ignoring."; \
00054 luxError(LUX_NOTSTARTED,LUX_SEVERE,ss.str().c_str()); \
00055 return; \
00056 }
00057 #define VERIFY_OPTIONS(func) \
00058 VERIFY_INITIALIZED(func); \
00059 if (currentApiState == STATE_WORLD_BLOCK) { \
00060 std::stringstream ss; \
00061 ss<<"Options cannot be set inside world block; '"<<func<<"' not allowed. Ignoring."; \
00062 luxError(LUX_NESTING,LUX_ERROR,ss.str().c_str()); \
00063 return; \
00064 }
00065 #define VERIFY_WORLD(func) \
00066 VERIFY_INITIALIZED(func); \
00067 if (currentApiState == STATE_OPTIONS_BLOCK) { \
00068 std::stringstream ss; \
00069 ss<<"Scene description must be inside world block; '"<<func<<"' not allowed. Ignoring."; \
00070 luxError(LUX_NESTING,LUX_ERROR,ss.str().c_str()); \
00071 return; \
00072 }
00073
00074
00075 void Context::init() {
00076
00077 terminated = false;
00078 currentApiState = STATE_OPTIONS_BLOCK;
00079 luxCurrentScene = NULL;
00080 luxCurrentSceneReady = false;
00081 curTransform = Transform();
00082 namedCoordinateSystems.clear();
00083 renderOptions = new RenderOptions;
00084 graphicsState = new GraphicsState;
00085 namedmaterials.clear();
00086 pushedGraphicsStates.clear();
00087 pushedTransforms.clear();
00088 renderFarm = new RenderFarm();
00089 filmOverrideParams = NULL;
00090 }
00091
00092 void Context::free() {
00093
00094 if (luxCurrentScene) {
00095 delete luxCurrentScene;
00096 luxCurrentScene = NULL;
00097 luxCurrentSceneReady = false;
00098 }
00099
00100 if (renderOptions) {
00101 delete renderOptions;
00102 renderOptions = NULL;
00103 }
00104
00105 if (graphicsState) {
00106 delete graphicsState;
00107 graphicsState = NULL;
00108 }
00109
00110 if (renderFarm) {
00111 delete renderFarm;
00112 renderFarm = NULL;
00113 }
00114
00115 if (filmOverrideParams) {
00116 delete filmOverrideParams;
00117 filmOverrideParams = NULL;
00118 }
00119 }
00120
00121
00122
00123 void Context::addServer(const string &n) {
00124
00125 renderFarm->connect(n);
00126
00127
00128 if(getServerCount() == 1 && luxCurrentScene)
00129 renderFarm->startFilmUpdater(luxCurrentScene);
00130 }
00131
00132 void Context::removeServer(const string &n) {
00133 renderFarm->disconnect(n);
00134
00135
00136 if(getServerCount() == 0)
00137 renderFarm->stopFilmUpdater();
00138 }
00139
00140 int Context::getServerCount() {
00141 if (!renderFarm)
00142 return 0;
00143
00144 return renderFarm->getServerCount();
00145 }
00146
00147 int Context::getRenderingServersStatus(RenderingServerInfo *info, int maxInfoCount) {
00148 if (!renderFarm)
00149 return 0;
00150
00151 return renderFarm->getServersStatus(info, maxInfoCount);
00152 }
00153
00154 void Context::cleanup() {
00155 renderFarm->send("luxCleanup");
00156
00157 StatsCleanup();
00158
00159 if (currentApiState == STATE_UNINITIALIZED)
00160 luxError(LUX_NOTSTARTED,LUX_ERROR,"luxCleanup() called without luxInit().");
00161 else if (currentApiState == STATE_WORLD_BLOCK)
00162 luxError(LUX_ILLSTATE,LUX_ERROR,"luxCleanup() called while inside world block.");
00163
00164
00165 free();
00166
00167
00168 init();
00169 }
00170
00171 void Context::identity() {
00172 VERIFY_INITIALIZED("Identity");
00173 renderFarm->send("luxIdentity");
00174 curTransform = Transform();
00175 }
00176
00177 void Context::translate(float dx, float dy, float dz) {
00178 VERIFY_INITIALIZED("Translate");
00179 renderFarm->send("luxTranslate", dx, dy, dz);
00180 curTransform = curTransform * Translate(Vector(dx, dy, dz));
00181 }
00182
00183 void Context::transform(float tr[16]) {
00184 VERIFY_INITIALIZED("Transform");
00185 renderFarm->send("luxTransform", tr);
00186 boost::shared_ptr<Matrix4x4> o(new Matrix4x4(
00187 tr[0], tr[4], tr[8], tr[12],
00188 tr[1], tr[5], tr[9], tr[13],
00189 tr[2], tr[6], tr[10], tr[14],
00190 tr[3], tr[7], tr[11], tr[15]));
00191 curTransform = Transform(o);
00192 }
00193 void Context::concatTransform(float tr[16]) {
00194 VERIFY_INITIALIZED("ConcatTransform");
00195 renderFarm->send("luxConcatTransform", tr);
00196 boost::shared_ptr<Matrix4x4> o(new Matrix4x4(tr[0], tr[4], tr[8], tr[12],
00197 tr[1], tr[5], tr[9], tr[13],
00198 tr[2], tr[6], tr[10], tr[14],
00199 tr[3], tr[7], tr[11], tr[15]));
00200 curTransform = curTransform * Transform(o);
00201 }
00202 void Context::rotate(float angle, float dx, float dy, float dz) {
00203 VERIFY_INITIALIZED("Rotate");
00204 renderFarm->send("luxRotate", angle, dx, dy, dz);
00205 curTransform = curTransform * Rotate(angle, Vector(dx, dy, dz));
00206 }
00207 void Context::scale(float sx, float sy, float sz) {
00208 VERIFY_INITIALIZED("Scale");
00209 renderFarm->send("luxScale", sx, sy, sz);
00210 curTransform = curTransform * Scale(sx, sy, sz);
00211 }
00212 void Context::lookAt(float ex, float ey, float ez, float lx, float ly, float lz,
00213 float ux, float uy, float uz) {
00214 VERIFY_INITIALIZED("LookAt");
00215 renderFarm->send("luxLookAt", ex, ey, ez, lx, ly, lz, ux, uy, uz);
00216
00217 curTransform = curTransform * LookAt(Point(ex, ey, ez), Point(lx, ly, lz),
00218 Vector(ux, uy, uz));
00219 }
00220 void Context::coordinateSystem(const string &n) {
00221 VERIFY_INITIALIZED("CoordinateSystem");
00222 renderFarm->send("luxCoordinateSystem", n);
00223 namedCoordinateSystems[n] = curTransform;
00224 }
00225 void Context::coordSysTransform(const string &n) {
00226 VERIFY_INITIALIZED("CoordSysTransform");
00227 renderFarm->send("luxCoordSysTransform", n);
00228 if (namedCoordinateSystems.find(n) != namedCoordinateSystems.end())
00229 curTransform = namedCoordinateSystems[n];
00230 }
00231 void Context::setEpsilon(const float minValue, const float maxValue)
00232 {
00233 VERIFY_INITIALIZED("SetEpsilon");
00234 renderFarm->send("luxSetEpsilon", minValue, maxValue);
00235 MachineEpsilon::SetMin(minValue);
00236 MachineEpsilon::SetMax(maxValue);
00237 }
00238 void Context::enableDebugMode() {
00239 VERIFY_OPTIONS("EnableDebugMode");
00240
00241 renderOptions->debugMode = true;
00242 }
00243
00244 void Context::disableRandomMode() {
00245 VERIFY_OPTIONS("DisableRandomMode")
00246 ;
00247
00248 renderOptions->randomMode = false;
00249 }
00250
00251 void Context::pixelFilter(const string &n, const ParamSet ¶ms) {
00252 VERIFY_OPTIONS("PixelFilter");
00253 renderFarm->send("luxPixelFilter", n, params);
00254 renderOptions->FilterName = n;
00255 renderOptions->FilterParams = params;
00256 }
00257 void Context::film(const string &type, const ParamSet ¶ms) {
00258 VERIFY_OPTIONS("Film");
00259 renderFarm->send("luxFilm", type, params);
00260 renderOptions->FilmParams = params;
00261 renderOptions->FilmName = type;
00262 if( filmOverrideParams ) {
00263 renderOptions->FilmParams.Add( *filmOverrideParams );
00264 }
00265 }
00266 void Context::sampler(const string &n, const ParamSet ¶ms) {
00267 VERIFY_OPTIONS("Sampler");
00268 renderFarm->send("luxSampler", n, params);
00269 renderOptions->SamplerName = n;
00270 renderOptions->SamplerParams = params;
00271 }
00272 void Context::accelerator(const string &n, const ParamSet ¶ms) {
00273 VERIFY_OPTIONS("Accelerator");
00274 renderFarm->send("luxAccelerator", n, params);
00275 renderOptions->AcceleratorName = n;
00276 renderOptions->AcceleratorParams = params;
00277 }
00278 void Context::surfaceIntegrator(const string &n, const ParamSet ¶ms) {
00279 VERIFY_OPTIONS("SurfaceIntegrator");
00280 renderFarm->send("luxSurfaceIntegrator", n, params);
00281 renderOptions->SurfIntegratorName = n;
00282 renderOptions->SurfIntegratorParams = params;
00283 }
00284 void Context::volumeIntegrator(const string &n, const ParamSet ¶ms) {
00285 VERIFY_OPTIONS("VolumeIntegrator");
00286 renderFarm->send("luxVolumeIntegrator", n, params);
00287 renderOptions->VolIntegratorName = n;
00288 renderOptions->VolIntegratorParams = params;
00289 }
00290 void Context::camera(const string &n, const ParamSet ¶ms) {
00291 VERIFY_OPTIONS("Camera");
00292 renderFarm->send("luxCamera", n, params);
00293
00294 renderOptions->CameraName = n;
00295 renderOptions->CameraParams = params;
00296 renderOptions->WorldToCamera = curTransform;
00297 namedCoordinateSystems["camera"] = curTransform.GetInverse();
00298
00299 string endTransform = params.FindOneString("endtransform", "");
00300
00301
00302 if (namedCoordinateSystems.find(endTransform) != namedCoordinateSystems.end())
00303 renderOptions->WorldToCameraEnd = namedCoordinateSystems[endTransform];
00304 else
00305 renderOptions->WorldToCameraEnd = curTransform;
00306
00307 }
00308 void Context::worldBegin() {
00309 VERIFY_OPTIONS("WorldBegin");
00310 renderFarm->send("luxWorldBegin");
00311 currentApiState = STATE_WORLD_BLOCK;
00312 curTransform = Transform();
00313 namedCoordinateSystems["world"] = curTransform;
00314 }
00315 void Context::attributeBegin() {
00316 VERIFY_WORLD("AttributeBegin");
00317 renderFarm->send("luxAttributeBegin");
00318 pushedGraphicsStates.push_back(*graphicsState);
00319 pushedTransforms.push_back(curTransform);
00320 }
00321 void Context::attributeEnd() {
00322 VERIFY_WORLD("AttributeEnd");
00323 renderFarm->send("luxAttributeEnd");
00324 if (!pushedGraphicsStates.size()) {
00325 luxError(LUX_ILLSTATE,LUX_ERROR,"Unmatched luxAttributeEnd() encountered. Ignoring it.");
00326 return;
00327 }
00328 *graphicsState = pushedGraphicsStates.back();
00329 curTransform = pushedTransforms.back();
00330 pushedGraphicsStates.pop_back();
00331 pushedTransforms.pop_back();
00332 }
00333 void Context::transformBegin() {
00334
00335
00336
00337 renderFarm->send("luxTransformBegin");
00338 pushedTransforms.push_back(curTransform);
00339 }
00340 void Context::transformEnd() {
00341
00342
00343
00344 renderFarm->send("luxTransformEnd");
00345 if (!pushedTransforms.size()) {
00346 luxError(LUX_ILLSTATE,LUX_ERROR,"Unmatched luxTransformEnd() encountered. Ignoring it.");
00347 return;
00348 }
00349 curTransform = pushedTransforms.back();
00350 pushedTransforms.pop_back();
00351 }
00352 void Context::texture(const string &n, const string &type, const string &texname,
00353 const ParamSet ¶ms) {
00354 VERIFY_WORLD("Texture");
00355 renderFarm->send("luxTexture", n, type, texname, params);
00356
00357 TextureParams tp(params, params, graphicsState->floatTextures,
00358 graphicsState->colorTextures);
00359 if (type == "float") {
00360
00361 if (graphicsState->floatTextures.find(n)
00362 != graphicsState->floatTextures.end()) {
00363
00364 std::stringstream ss;
00365 ss<<"Texture '"<<n<<"' being redefined.";
00366 luxError(LUX_SYNTAX,LUX_WARNING,ss.str().c_str());
00367 }
00368 boost::shared_ptr<Texture<float> > ft = MakeFloatTexture(texname,
00369 curTransform, tp);
00370 if (ft)
00371 graphicsState->floatTextures[n] = ft;
00372 } else if (type == "color") {
00373
00374 if (graphicsState->colorTextures.find(n)
00375 != graphicsState->colorTextures.end()) {
00376
00377 std::stringstream ss;
00378 ss<<"Texture '"<<n<<"' being redefined.";
00379 luxError(LUX_SYNTAX,LUX_WARNING,ss.str().c_str());
00380 }
00381 boost::shared_ptr<Texture<SWCSpectrum> > st = MakeSWCSpectrumTexture(texname,
00382 curTransform, tp);
00383 if (st)
00384 graphicsState->colorTextures[n] = st;
00385 } else {
00386
00387 std::stringstream ss;
00388 ss<<"Texture type '"<<type<<"' unknown";
00389 luxError(LUX_SYNTAX,LUX_ERROR,ss.str().c_str());
00390 }
00391
00392 }
00393 void Context::material(const string &n, const ParamSet ¶ms) {
00394 VERIFY_WORLD("Material");
00395 renderFarm->send("luxMaterial", n, params);
00396 graphicsState->material = n;
00397 graphicsState->materialParams = params;
00398 }
00399
00400 void Context::makenamedmaterial(const string &n, const ParamSet ¶ms) {
00401 VERIFY_WORLD("MakeNamedMaterial");
00402 renderFarm->send("luxMakeNamedMaterial", n, params);
00403 NamedMaterial nm;
00404 nm.material = n;
00405 nm.materialParams = params;
00406 namedmaterials.push_back(nm);
00407 }
00408
00409 void Context::namedmaterial(const string &n, const ParamSet ¶ms) {
00410 VERIFY_WORLD("NamedMaterial");
00411 renderFarm->send("luxNamedMaterial", n, params);
00412 bool found = false;
00413 for(unsigned int i=0; i<namedmaterials.size(); i++)
00414 if(namedmaterials[i].material == n) {
00415 string type = namedmaterials[i].materialParams.FindOneString("type", "matte");
00416 ParamSet nparams = namedmaterials[i].materialParams;
00417 nparams.EraseString("type");
00418 material(type, nparams);
00419 found = true;
00420 }
00421
00422 if(!found) {
00423 std::stringstream ss;
00424 ss<<"NamedMaterial named '"<<n<<"' unknown";
00425 luxError(LUX_SYNTAX,LUX_ERROR,ss.str().c_str());
00426 }
00427 }
00428
00429 void Context::lightGroup(const string &n, const ParamSet ¶ms)
00430 {
00431 VERIFY_WORLD("LightGroup");
00432 renderFarm->send("luxLightGroup", n, params);
00433
00434 u_int i = 0;
00435 for (;i < renderOptions->lightGroups.size(); ++i) {
00436 if (n == renderOptions->lightGroups[i])
00437 break;
00438 }
00439 if (i == renderOptions->lightGroups.size())
00440 renderOptions->lightGroups.push_back(n);
00441 graphicsState->currentLightGroup = n;
00442 }
00443
00444
00445 void Context::lightSource(const string &n, const ParamSet ¶ms) {
00446 VERIFY_WORLD("LightSource");
00447 renderFarm->send("luxLightSource", n, params);
00448
00449 TextureParams tp(params, graphicsState->materialParams,
00450 graphicsState->floatTextures, graphicsState->colorTextures);
00451 u_int lg = GetActiveLightGroup();
00452
00453 if (n == "sunsky") {
00454
00455 Light *lt_sun = MakeLight("sun", curTransform, params, tp);
00456 if (lt_sun == NULL) {
00457 luxError(LUX_SYNTAX,LUX_ERROR,"luxLightSource: light type sun unknown.");
00458 graphicsState->currentLightPtr0 = NULL;
00459 } else {
00460 renderOptions->lights.push_back(lt_sun);
00461 graphicsState->currentLight = n;
00462 graphicsState->currentLightPtr0 = lt_sun;
00463 lt_sun->group = lg;
00464 }
00465 Light *lt_sky = MakeLight("sky", curTransform, params, tp);
00466 if (lt_sky == NULL) {
00467 luxError(LUX_SYNTAX,LUX_ERROR,"luxLightSource: light type sky unknown.");
00468 graphicsState->currentLightPtr1 = NULL;
00469 } else {
00470 renderOptions->lights.push_back(lt_sky);
00471 graphicsState->currentLight = n;
00472 graphicsState->currentLightPtr1 = lt_sky;
00473 lt_sky->group = lg;
00474 }
00475 } else {
00476
00477 Light *lt = MakeLight(n, curTransform, params, tp);
00478 if (lt == NULL) {
00479
00480
00481 std::stringstream ss;
00482 ss<<"luxLightSource: light type '"<<n<<"' unknown";
00483 luxError(LUX_SYNTAX,LUX_ERROR,ss.str().c_str());
00484 } else {
00485 renderOptions->lights.push_back(lt);
00486 graphicsState->currentLight = n;
00487 graphicsState->currentLightPtr0 = lt;
00488 graphicsState->currentLightPtr1 = NULL;
00489 lt->group = lg;
00490 }
00491 }
00492 }
00493
00494 void Context::areaLightSource(const string &n, const ParamSet ¶ms) {
00495 VERIFY_WORLD("AreaLightSource");
00496 renderFarm->send("luxAreaLightSource", n, params);
00497
00498 graphicsState->areaLight = n;
00499 graphicsState->areaLightParams = params;
00500 }
00501
00502 void Context::portalShape(const string &n, const ParamSet ¶ms) {
00503 VERIFY_WORLD("PortalShape");
00504 renderFarm->send("luxPortalShape", n, params);
00505
00506 boost::shared_ptr<Shape> sh = MakeShape(n, curTransform,
00507 graphicsState->reverseOrientation, params);
00508 if (!sh)
00509 return;
00510 params.ReportUnused();
00511
00512
00513
00514
00515
00516
00517 if (graphicsState->currentLight != "") {
00518 if (graphicsState->currentLightPtr0)
00519 graphicsState->currentLightPtr0->AddPortalShape(sh);
00520
00521 if (graphicsState->currentLightPtr1)
00522 graphicsState->currentLightPtr1->AddPortalShape(sh);
00523 }
00524 }
00525
00526 boost::shared_ptr<Material> Context::makematerial(const ParamSet& shapeparams, bool force) {
00527
00528 TextureParams mp(shapeparams, graphicsState->materialParams,
00529 graphicsState->floatTextures, graphicsState->colorTextures);
00530 boost::shared_ptr<Material> mtl = MakeMaterial(graphicsState->material, curTransform, mp);
00531 if (!mtl && force) {
00532 mtl = MakeMaterial("matte", curTransform, mp);
00533 if (!mtl)
00534 luxError(LUX_BUG,LUX_SEVERE,"Unable to create \"matte\" material?!");
00535 }
00536
00537
00538 if(mtl && graphicsState->material == "mix") {
00539 makemixmaterial(shapeparams, graphicsState->materialParams, mtl);
00540 }
00541 return mtl;
00542 }
00543
00544 void Context::makemixmaterial(const ParamSet& shapeparams, const ParamSet& materialparams, boost::shared_ptr<Material> mtl) {
00545
00546 string namedmaterial1 = materialparams.FindOneString("namedmaterial1", "-");
00547 bool found = false;
00548 for(unsigned int i=0; i<namedmaterials.size(); i++)
00549 if(namedmaterials[i].material == namedmaterial1) {
00550 string type = namedmaterials[i].materialParams.FindOneString("type", "matte");
00551 ParamSet nparams = namedmaterials[i].materialParams;
00552 nparams.EraseString("type");
00553 TextureParams mp1(shapeparams, nparams,
00554 graphicsState->floatTextures, graphicsState->colorTextures);
00555 boost::shared_ptr<Material> mtl1 = MakeMaterial(type, curTransform, mp1);
00556
00557 if(type == "mix")
00558 makemixmaterial(shapeparams, nparams, mtl1);
00559
00560 mtl->SetChild1(mtl1);
00561 found = true;
00562 }
00563 if(!found) {
00564 std::stringstream ss;
00565 ss<<"MixMaterial: NamedMaterial1 named '"<<namedmaterial1<<"' unknown";
00566 luxError(LUX_SYNTAX,LUX_ERROR,ss.str().c_str());
00567 }
00568
00569
00570 string namedmaterial2 = materialparams.FindOneString("namedmaterial2", "-");
00571 found = false;
00572 for(unsigned int i=0; i<namedmaterials.size(); i++)
00573 if(namedmaterials[i].material == namedmaterial2) {
00574 string type = namedmaterials[i].materialParams.FindOneString("type", "matte");
00575 ParamSet nparams = namedmaterials[i].materialParams;
00576 nparams.EraseString("type");
00577 TextureParams mp1(shapeparams, nparams,
00578 graphicsState->floatTextures, graphicsState->colorTextures);
00579 boost::shared_ptr<Material> mtl2 = MakeMaterial(type, curTransform, mp1);
00580
00581 if(type == "mix")
00582 makemixmaterial(shapeparams, nparams, mtl2);
00583
00584 mtl->SetChild2(mtl2);
00585 found = true;
00586 }
00587 if(!found) {
00588 std::stringstream ss;
00589 ss<<"MixMaterial: NamedMaterial2 named '"<<namedmaterial1<<"' unknown";
00590 luxError(LUX_SYNTAX,LUX_ERROR,ss.str().c_str());
00591 }
00592 }
00593
00594 void Context::shape(const string &n, const ParamSet ¶ms) {
00595 VERIFY_WORLD("Shape");
00596 renderFarm->send("luxShape", n, params);
00597
00598 boost::shared_ptr<Shape> sh = MakeShape(
00599 n,
00600 curTransform,
00601 graphicsState->reverseOrientation,
00602 params);
00603 if (!sh)
00604 return;
00605 params.ReportUnused();
00606
00607
00608 AreaLight *area= NULL;
00609 if (graphicsState->areaLight != "") {
00610 TextureParams amp(params, graphicsState->areaLightParams,
00611 graphicsState->floatTextures, graphicsState->colorTextures);
00612 u_int lg = GetActiveLightGroup();
00613 area = MakeAreaLight(graphicsState->areaLight, curTransform,
00614 graphicsState->areaLightParams, amp, sh);
00615 if (area)
00616 area->group = lg;
00617 }
00618
00619
00620 boost::shared_ptr<Material> mtl = makematerial(params, true);
00621
00622
00623 sh->SetMaterial(mtl);
00624 boost::shared_ptr<Primitive> prim;
00625 if(area) {
00626
00627 prim = boost::shared_ptr<Primitive>(new AreaLightPrimitive(sh, area));
00628 }
00629 else
00630 prim = sh;
00631 if (renderOptions->currentInstance) {
00632 if (area)
00633 luxError(LUX_UNIMPLEMENT,LUX_WARNING,"Area lights not supported with object instancing");
00634 renderOptions->currentInstance->push_back(prim);
00635 } else {
00636 renderOptions->primitives.push_back(prim);
00637 if (area) {
00638
00639 renderOptions->lights.push_back(area);
00640 }
00641 }
00642 }
00643 void Context::reverseOrientation() {
00644 VERIFY_WORLD("ReverseOrientation");
00645 renderFarm->send("luxReverseOrientation");
00646 graphicsState->reverseOrientation = !graphicsState->reverseOrientation;
00647 }
00648 void Context::volume(const string &n, const ParamSet ¶ms) {
00649 VERIFY_WORLD("Volume");
00650 renderFarm->send("luxVolume", n, params);
00651 VolumeRegion *vr = MakeVolumeRegion(n, curTransform, params);
00652 if (vr)
00653 renderOptions->volumeRegions.push_back(vr);
00654 }
00655 void Context::objectBegin(const string &n) {
00656 VERIFY_WORLD("ObjectBegin");
00657 renderFarm->send("luxObjectBegin", n);
00658 luxAttributeBegin();
00659 if (renderOptions->currentInstance)
00660 luxError(LUX_NESTING,LUX_ERROR,"ObjectBegin called inside of instance definition");
00661 renderOptions->instances[n] = vector<boost::shared_ptr<Primitive> >();
00662 renderOptions->currentInstance = &renderOptions->instances[n];
00663 }
00664 void Context::objectEnd() {
00665 VERIFY_WORLD("ObjectEnd");
00666 renderFarm->send("luxObjectEnd");
00667 if (!renderOptions->currentInstance)
00668 luxError(LUX_NESTING,LUX_ERROR,"ObjectEnd called outside of instance definition");
00669 renderOptions->currentInstance = NULL;
00670 luxAttributeEnd();
00671 }
00672 void Context::objectInstance(const string &n) {
00673 VERIFY_WORLD("ObjectInstance");
00674 renderFarm->send("luxObjectInstance", n);
00675
00676 if (renderOptions->currentInstance) {
00677 luxError(LUX_NESTING,LUX_ERROR,"ObjectInstance can't be called inside instance definition");
00678 return;
00679 }
00680 if (renderOptions->instances.find(n) == renderOptions->instances.end()) {
00681
00682 std::stringstream ss;
00683 ss<<"Unable to find instance named '"<<n<<"'";
00684 luxError(LUX_BADTOKEN,LUX_ERROR,ss.str().c_str());
00685 return;
00686 }
00687 vector<boost::shared_ptr<Primitive> > &in = renderOptions->instances[n];
00688 if (in.size() == 0)
00689 return;
00690 if( in.size() == 1 && !in[0]->CanIntersect() ) {
00691 boost::shared_ptr<Primitive> prim = in[0];
00692 in.clear();
00693 prim->Refine(in, PrimitiveRefinementHints(false), prim);
00694 }
00695 if (in.size() > 1 || !in[0]->CanIntersect()) {
00696
00697 boost::shared_ptr<Primitive> accel(MakeAccelerator(
00698 renderOptions->AcceleratorName, in,
00699 renderOptions->AcceleratorParams));
00700 if (!accel)
00701 accel = boost::shared_ptr<Primitive>(MakeAccelerator("kdtree", in, ParamSet()));
00702 if (!accel)
00703 luxError(LUX_BUG,LUX_SEVERE,"Unable to find \"kdtree\" accelerator");
00704 in.clear();
00705 in.push_back(accel);
00706 }
00707
00708
00709 ParamSet params;
00710 boost::shared_ptr<Material> mat = makematerial(params, false);
00711
00712 boost::shared_ptr<Primitive> o(new InstancePrimitive(in[0], curTransform, mat));
00713 renderOptions->primitives.push_back(o);
00714 }
00715
00716 void Context::motionInstance(const string &n, float startTime, float endTime, const string &toTransform) {
00717 VERIFY_WORLD("MotionInstance");
00718 renderFarm->send("luxMotionInstance", n, startTime, endTime, toTransform);
00719
00720 if (renderOptions->currentInstance) {
00721 luxError(LUX_NESTING,LUX_ERROR,"MotionInstance can't be called inside instance definition");
00722 return;
00723 }
00724 if (renderOptions->instances.find(n) == renderOptions->instances.end()) {
00725
00726 std::stringstream ss;
00727 ss<<"Unable to find instance named '"<<n<<"'";
00728 luxError(LUX_BADTOKEN,LUX_ERROR,ss.str().c_str());
00729 return;
00730 }
00731 vector<boost::shared_ptr<Primitive> > &in = renderOptions->instances[n];
00732 if (in.size() == 0)
00733 return;
00734 if( in.size() == 1 && !in[0]->CanIntersect() ) {
00735 boost::shared_ptr<Primitive> prim = in[0];
00736 in.clear();
00737 prim->Refine(in, PrimitiveRefinementHints(false), prim);
00738 }
00739 if (in.size() > 1 || !in[0]->CanIntersect()) {
00740
00741 boost::shared_ptr<Primitive> accel(MakeAccelerator(
00742 renderOptions->AcceleratorName, in,
00743 renderOptions->AcceleratorParams));
00744 if (!accel)
00745 accel = boost::shared_ptr<Primitive>(MakeAccelerator("kdtree", in, ParamSet()));
00746 if (!accel)
00747 luxError(LUX_BUG,LUX_SEVERE,"Unable to find \"kdtree\" accelerator");
00748 in.clear();
00749 in.push_back(accel);
00750 }
00751
00752
00753 Transform EndTransform;
00754 if (namedCoordinateSystems.find(toTransform) != namedCoordinateSystems.end())
00755 EndTransform = namedCoordinateSystems[toTransform];
00756 else {
00757 luxError(LUX_BUG,LUX_SEVERE,"Unable to find named CoordinateSystem for MotionInstance.");
00758 }
00759
00760
00761
00762 ParamSet params;
00763 boost::shared_ptr<Material> mat = makematerial(params, false);
00764
00765 boost::shared_ptr<Primitive> o(new MotionPrimitive(in[0], curTransform, EndTransform, startTime, endTime));
00766 renderOptions->primitives.push_back(o);
00767 }
00768
00769
00770
00771 void Context::worldEnd() {
00772 VERIFY_WORLD("WorldEnd");
00773 renderFarm->send("luxWorldEnd");
00774 renderFarm->flush();
00775
00776
00777
00778 boost::mutex::scoped_lock lock(renderingMutex);
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 while (pushedGraphicsStates.size()) {
00789 luxError(LUX_NESTING, LUX_WARNING, "Missing end to luxAttributeBegin()");
00790 pushedGraphicsStates.pop_back();
00791 pushedTransforms.pop_back();
00792 }
00793 if (!terminated) {
00794
00795 luxCurrentScene = renderOptions->MakeScene();
00796 if (luxCurrentScene) {
00797
00798 if (renderFarm->getServerCount() > 0)
00799 renderFarm->startFilmUpdater(luxCurrentScene);
00800
00801 luxCurrentScene->Render();
00802
00803
00804 if(getServerCount() > 0) {
00805
00806 activeContext->renderFarm->stopFilmUpdater();
00807
00808 activeContext->renderFarm->updateFilm(luxCurrentScene);
00809
00810 activeContext->renderFarm->disconnectAll();
00811 }
00812
00813
00814 luxCurrentScene->camera->film->WriteImage((ImageType)(IMAGE_FILEOUTPUT|IMAGE_FRAMEBUFFER));
00815 }
00816 }
00817
00818
00819
00820 currentApiState = STATE_OPTIONS_BLOCK;
00821 StatsPrint(stdout);
00822 curTransform = Transform();
00823 namedCoordinateSystems.erase(namedCoordinateSystems.begin(),
00824 namedCoordinateSystems.end());
00825 }
00826
00827 Scene *Context::RenderOptions::MakeScene() const {
00828
00829 Filter *filter = MakeFilter(FilterName, FilterParams);
00830 Film *film = MakeFilm(FilmName, FilmParams, filter);
00831 if (std::string(FilmName)=="film")
00832 luxError(LUX_NOERROR,LUX_WARNING,"Warning: Legacy PBRT 'film' does not provide tonemapped output or GUI film display. Use 'multifilm' instead.");
00833 Camera *camera = MakeCamera(CameraName, WorldToCamera, WorldToCameraEnd, CameraParams, film);
00834 Sampler *sampler = MakeSampler(SamplerName, SamplerParams, film);
00835 SurfaceIntegrator *surfaceIntegrator = MakeSurfaceIntegrator(
00836 SurfIntegratorName, SurfIntegratorParams);
00837 VolumeIntegrator *volumeIntegrator = MakeVolumeIntegrator(
00838 VolIntegratorName, VolIntegratorParams);
00839 boost::shared_ptr<Primitive> accelerator = MakeAccelerator(AcceleratorName, primitives,
00840 AcceleratorParams);
00841 if (!accelerator) {
00842 ParamSet ps;
00843 accelerator = MakeAccelerator("kdtree", primitives, ps);
00844 }
00845 if (!accelerator)
00846 luxError(LUX_BUG,LUX_SEVERE,"Unable to find \"kdtree\" accelerator");
00847
00848 VolumeRegion *volumeRegion;
00849 if (volumeRegions.size() == 0)
00850 volumeRegion = NULL;
00851 else if (volumeRegions.size() == 1)
00852 volumeRegion = volumeRegions[0];
00853 else
00854 volumeRegion = new AggregateVolume(volumeRegions);
00855
00856 if (!camera || !sampler || !film || !accelerator || !filter
00857 || !surfaceIntegrator || !volumeIntegrator) {
00858 luxError(LUX_BUG,LUX_SEVERE,"Unable to create scene due to missing plug-ins");
00859 return NULL;
00860 }
00861 Scene *ret = new Scene(camera,
00862 surfaceIntegrator, volumeIntegrator,
00863 sampler, accelerator, lights, lightGroups, volumeRegion);
00864
00865 primitives.clear();
00866 lights.clear();
00867 volumeRegions.clear();
00868 currentInstance = NULL;
00869 instances.clear();
00870
00871
00872 if (debugMode || !randomMode)
00873 ret->seedBase = 1000;
00874
00875 return ret;
00876 }
00877
00878
00879 void Context::loadFLM(const string &flmFileName) {
00880
00881 Film* flm = FlexImageFilm::CreateFilmFromFLM(flmFileName);
00882 if(!flm) {
00883 luxError(LUX_BUG,LUX_SEVERE,"Unable to create film");
00884 return;
00885 }
00886
00887 Transform dummyTransform;
00888 ParamSet dummyParams;
00889 Camera *cam = MakeCamera("perspective", dummyTransform, dummyTransform, dummyParams, flm);
00890 if(!cam) {
00891 luxError(LUX_BUG,LUX_SEVERE,"Unable to create dummy camera");
00892 delete flm;
00893 return;
00894 }
00895 luxCurrentScene = new Scene( cam );
00896 sceneReady();
00897 }
00898 void Context::saveFLM(const string &flmFileName) {
00899 luxCurrentScene->SaveFLM(flmFileName);
00900 }
00901
00902 void Context::overrideResumeFLM(const string &flmFileName) {
00903 if( !filmOverrideParams ) {
00904 filmOverrideParams = new ParamSet();
00905 }
00906 const bool boolTrue = true;
00907 const bool boolFalse = false;
00908 const string filename = flmFileName.substr(0, flmFileName.length() - 4);
00909 filmOverrideParams->AddBool("write_resume_flm", &boolTrue);
00910 filmOverrideParams->AddBool("restart_resume_flm", &boolFalse);
00911 filmOverrideParams->AddString("filename", &filename);
00912 }
00913
00914
00915 void Context::start() {
00916 luxCurrentScene->Start();
00917 }
00918
00919 void Context::pause() {
00920 luxCurrentScene->Pause();
00921 }
00922
00923 void Context::setHaltSamplePerPixel(int haltspp, bool haveEnoughSamplePerPixel,
00924 bool suspendThreadsWhenDone) {
00925 FlexImageFilm *fif = (FlexImageFilm *)luxCurrentScene->camera->film;
00926 fif->haltSamplePerPixel = haltspp;
00927 fif->enoughSamplePerPixel = haveEnoughSamplePerPixel;
00928 luxCurrentScene->suspendThreadsWhenDone = suspendThreadsWhenDone;
00929 }
00930
00931 void Context::wait() {
00932 boost::mutex::scoped_lock lock(renderingMutex);
00933 }
00934
00935 void Context::exit() {
00936 if(getServerCount() > 0) {
00937
00938 activeContext->renderFarm->stopFilmUpdater();
00939
00940 activeContext->renderFarm->updateFilm(luxCurrentScene);
00941
00942 activeContext->renderFarm->disconnectAll();
00943 }
00944
00945 terminated = true;
00946
00947
00948 MachineEpsilon::SetMin(DEFAULT_EPSILON_MIN);
00949 MachineEpsilon::SetMax(DEFAULT_EPSILON_MAX);
00950
00951 if (!luxCurrentScene)
00952 return;
00953
00954 luxCurrentScene->Exit();
00955 }
00956
00957
00958 int Context::addThread() {
00959 return luxCurrentScene->AddThread();
00960 }
00961
00962 void Context::removeThread() {
00963 luxCurrentScene->RemoveThread();
00964 }
00965
00966 int Context::getRenderingThreadsStatus(RenderingThreadInfo *info, int maxInfoCount) {
00967 if (!luxCurrentScene)
00968 return 0;
00969
00970 return luxCurrentScene->getThreadsStatus(info, maxInfoCount);
00971 }
00972
00973
00974 void Context::updateFramebuffer() {
00975 luxCurrentScene->UpdateFramebuffer();
00976 }
00977
00978 unsigned char* Context::framebuffer() {
00979 return luxCurrentScene->GetFramebuffer();
00980 }
00981
00982
00983 void Context::getHistogramImage(unsigned char *outPixels, int width, int height, int options){
00984 luxCurrentScene->getHistogramImage(outPixels, width, height, options);
00985 }
00986
00987
00988 void Context::SetParameterValue(luxComponent comp, luxComponentParameters param, double value, int index) {
00989 luxCurrentScene->SetParameterValue(comp, param, value, index);
00990 }
00991 double Context::GetParameterValue(luxComponent comp, luxComponentParameters param, int index) {
00992 return luxCurrentScene->GetParameterValue(comp, param, index);
00993 }
00994 double Context::GetDefaultParameterValue(luxComponent comp, luxComponentParameters param, int index) {
00995 return luxCurrentScene->GetDefaultParameterValue(comp, param, index);
00996 }
00997 void Context::SetStringParameterValue(luxComponent comp, luxComponentParameters param, const string& value, int index) {
00998 return luxCurrentScene->SetStringParameterValue(comp, param, value, index);
00999 }
01000 string Context::GetStringParameterValue(luxComponent comp, luxComponentParameters param, int index) {
01001 return luxCurrentScene->GetStringParameterValue(comp, param, index);
01002 }
01003 string Context::GetDefaultStringParameterValue(luxComponent comp, luxComponentParameters param, int index) {
01004 return luxCurrentScene->GetDefaultStringParameterValue(comp, param, index);
01005 }
01006
01007 u_int Context::GetActiveLightGroup() {
01008 if(graphicsState->currentLightGroup == "")
01009 graphicsState->currentLightGroup = "default";
01010 u_int lg = 0;
01011 for (;lg < renderOptions->lightGroups.size(); ++lg) {
01012 if (graphicsState->currentLightGroup == renderOptions->lightGroups[lg])
01013 break;
01014 }
01015 if (lg == renderOptions->lightGroups.size()) {
01016 if(graphicsState->currentLightGroup == "default") {
01017 renderOptions->lightGroups.push_back("default");
01018 lg = renderOptions->lightGroups.size() - 1;
01019 }
01020 else {
01021 std::stringstream ss;
01022 ss << "Undefined lightgroup '" << graphicsState->currentLightGroup << "', ";
01023 ss << "using 'default' instead";
01024 luxError(LUX_BADFILE,LUX_ERROR, ss.str().c_str());
01025 graphicsState->currentLightGroup == "";
01026 lg = getActiveLightGroup();
01027 }
01028 }
01029 return lg;
01030 }
01031
01032 double Context::statistics(const string &statName) {
01033 if (statName=="sceneIsReady") return (luxCurrentScene!=NULL && luxCurrentSceneReady && !luxCurrentScene->IsFilmOnly());
01034 else if (statName=="filmIsReady") return (luxCurrentScene!=NULL && luxCurrentScene->IsFilmOnly());
01035 else if (statName=="terminated") return terminated;
01036 else if (luxCurrentScene!=NULL) return luxCurrentScene->Statistics(statName);
01037 else return 0;
01038 }
01039 void Context::sceneReady() {
01040 luxCurrentSceneReady = true;
01041 }
01042
01043 void Context::transmitFilm(std::basic_ostream<char> &stream) {
01044 luxCurrentScene->camera->film->TransmitFilm(stream);
01045 }
01046
01047 void Context::updateFilmFromNetwork() {
01048 renderFarm->updateFilm(luxCurrentScene);
01049 }
01050 void Context::setNetworkServerUpdateInterval(int updateInterval)
01051 {
01052 activeContext->renderFarm->serverUpdateInterval = updateInterval;
01053 }
01054 int Context::getNetworkServerUpdateInterval()
01055 {
01056 return activeContext->renderFarm->serverUpdateInterval;
01057 }