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 "api.h"
00026 #include "paramset.h"
00027 #include "color.h"
00028 #include "scene.h"
00029 #include "film.h"
00030 #include "dynload.h"
00031 #include "volume.h"
00032 #include <map>
00033 using std::map;
00034 #if (_MSC_VER >= 1400) // NOBOOK
00035 #include <stdio.h>
00036 #define snprintf _snprintf // NOBOOK
00037 #endif // NOBOOK
00038
00039 struct RenderOptions {
00040
00041 RenderOptions();
00042 Scene *MakeScene() const;
00043
00044 string FilterName;
00045 ParamSet FilterParams;
00046 string FilmName;
00047 ParamSet FilmParams;
00048 string SamplerName;
00049 ParamSet SamplerParams;
00050 string AcceleratorName;
00051 ParamSet AcceleratorParams;
00052 string SurfIntegratorName, VolIntegratorName;
00053 ParamSet SurfIntegratorParams, VolIntegratorParams;
00054 string CameraName;
00055 ParamSet CameraParams;
00056 Transform WorldToCamera;
00057 bool gotSearchPath;
00058 mutable vector<Light *> lights;
00059 mutable vector<Reference<Primitive> > primitives;
00060 mutable vector<VolumeRegion *> volumeRegions;
00061 map<string, vector<Reference<Primitive> > > instances;
00062 vector<Reference<Primitive> > *currentInstance;
00063 };
00064 RenderOptions::RenderOptions() {
00065
00066 FilterName = "mitchell";
00067 FilmName = "image";
00068 SamplerName = "bestcandidate";
00069 AcceleratorName = "kdtree";
00070 SurfIntegratorName = "directlighting";
00071 VolIntegratorName = "emission";
00072 CameraName = "perspective";
00073 char *searchEnv = getenv("PBRT_SEARCHPATH");
00074 if (searchEnv == NULL) {
00075 Warning("PBRT_SEARCHPATH not set in your environment.\n"
00076 "pbrt won't be able to find plugins if "
00077 "no SearchPath in input file.\n"
00078 "PBRT_SEARCHPATH should be a "
00079 "\"%s\"-separated list of directories.\n",
00080 PBRT_PATH_SEP);
00081 gotSearchPath = false;
00082 }
00083 else {
00084 UpdatePluginPath(searchEnv);
00085 gotSearchPath = true;
00086 }
00087 currentInstance = NULL;
00088 }
00089 struct GraphicsState {
00090
00091 GraphicsState();
00092
00093 map<string, Reference<Texture<float> > >
00094 floatTextures;
00095 map<string, Reference<Texture<Spectrum> > >
00096 spectrumTextures;
00097 ParamSet materialParams;
00098 string material;
00099 ParamSet areaLightParams;
00100 string areaLight;
00101 bool reverseOrientation;
00102 };
00103 GraphicsState::GraphicsState() {
00104
00105 material = "matte";
00106 reverseOrientation = false;
00107 }
00108
00109 #define STATE_UNINITIALIZED 0
00110 #define STATE_OPTIONS_BLOCK 1
00111 #define STATE_WORLD_BLOCK 2
00112 static int currentApiState = STATE_UNINITIALIZED;
00113 static Transform curTransform;
00114 static map<string, Transform> namedCoordinateSystems;
00115 static RenderOptions *renderOptions = NULL;
00116 static GraphicsState graphicsState;
00117 static vector<GraphicsState> pushedGraphicsStates;
00118 static vector<Transform> pushedTransforms;
00119
00120 #define VERIFY_INITIALIZED(func) \
00121 if (currentApiState == STATE_UNINITIALIZED) { \
00122 Error("pbrtInit() must be before calling \"%s()\". " \
00123 "Ignoring.", func); \
00124 return; \
00125 } else
00126 #define VERIFY_OPTIONS(func) \
00127 VERIFY_INITIALIZED(func); \
00128 if (currentApiState == STATE_WORLD_BLOCK) { \
00129 Error("Options cannot be set inside world block; " \
00130 "\"%s\" not allowed. Ignoring.", func); \
00131 return; \
00132 } else
00133 #define VERIFY_WORLD(func) \
00134 VERIFY_INITIALIZED(func); \
00135 if (currentApiState == STATE_OPTIONS_BLOCK) { \
00136 Error("Scene description must be inside world block; " \
00137 "\"%s\" not allowed. Ignoring.", func); \
00138 return; \
00139 } else
00140
00141 COREDLL void pbrtInit() {
00142
00143
00144
00145
00146 #ifdef FAST_INT
00147 #if defined(__linux__) && defined(__i386__)
00148 int cword = _FPU_MASK_DM | _FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_PM |
00149 _FPU_MASK_UM | _FPU_MASK_IM | _FPU_DOUBLE | _FPU_RC_NEAREST;
00150 _FPU_SETCW(cword);
00151 #endif
00152 #if defined(WIN32)
00153 _control87(_PC_53, MCW_PC);
00154 #endif
00155 #endif // FAST_INT
00156
00157 if (currentApiState != STATE_UNINITIALIZED)
00158 Error("pbrtInit() has already been called.");
00159 currentApiState = STATE_OPTIONS_BLOCK;
00160 renderOptions = new RenderOptions;
00161 graphicsState = GraphicsState();
00162 }
00163 COREDLL void pbrtCleanup() {
00164 StatsCleanup();
00165
00166 if (currentApiState == STATE_UNINITIALIZED)
00167 Error("pbrtCleanup() called without pbrtInit().");
00168 else if (currentApiState == STATE_WORLD_BLOCK)
00169 Error("pbrtCleanup() called while inside world block.");
00170 currentApiState = STATE_UNINITIALIZED;
00171 delete renderOptions;
00172 renderOptions = NULL;
00173 }
00174 COREDLL void pbrtIdentity() {
00175 VERIFY_INITIALIZED("Identity");
00176 curTransform = Transform();
00177 }
00178 COREDLL void pbrtTranslate(float dx, float dy, float dz) {
00179 VERIFY_INITIALIZED("Translate");
00180 curTransform =
00181 curTransform * Translate(Vector(dx, dy, dz));
00182 }
00183 COREDLL void pbrtTransform(float tr[16]) {
00184 VERIFY_INITIALIZED("Transform");
00185 curTransform = Transform(new Matrix4x4(
00186 tr[0], tr[4], tr[8], tr[12],
00187 tr[1], tr[5], tr[9], tr[13],
00188 tr[2], tr[6], tr[10], tr[14],
00189 tr[3], tr[7], tr[11], tr[15]));
00190 }
00191 COREDLL void pbrtConcatTransform(float tr[16]) {
00192 VERIFY_INITIALIZED("ConcatTransform");
00193 curTransform = curTransform * Transform(
00194 new Matrix4x4(tr[0], tr[4], tr[8], tr[12],
00195 tr[1], tr[5], tr[9], tr[13],
00196 tr[2], tr[6], tr[10], tr[14],
00197 tr[3], tr[7], tr[11], tr[15]));
00198 }
00199 COREDLL void pbrtRotate(float angle, float dx, float dy, float dz) {
00200 VERIFY_INITIALIZED("Rotate");
00201 curTransform = curTransform * Rotate(angle, Vector(dx, dy, dz));
00202 }
00203 COREDLL void pbrtScale(float sx, float sy, float sz) {
00204 VERIFY_INITIALIZED("Scale");
00205 curTransform = curTransform * Scale(sx, sy, sz);
00206 }
00207 COREDLL void pbrtLookAt(float ex, float ey, float ez, float lx, float ly,
00208 float lz, float ux, float uy, float uz) {
00209 VERIFY_INITIALIZED("LookAt");
00210 curTransform = curTransform * LookAt(Point(ex, ey, ez), Point(lx, ly, lz),
00211 Vector(ux, uy, uz));
00212 }
00213 COREDLL void pbrtCoordinateSystem(const string &name) {
00214 VERIFY_INITIALIZED("CoordinateSystem");
00215 namedCoordinateSystems[name] = curTransform;
00216 }
00217 COREDLL void pbrtCoordSysTransform(const string &name) {
00218 VERIFY_INITIALIZED("CoordSysTransform");
00219 if (namedCoordinateSystems.find(name) !=
00220 namedCoordinateSystems.end())
00221 curTransform = namedCoordinateSystems[name];
00222 }
00223 COREDLL void pbrtPixelFilter(const string &name,
00224 const ParamSet ¶ms) {
00225 VERIFY_OPTIONS("PixelFilter");
00226 renderOptions->FilterName = name;
00227 renderOptions->FilterParams = params;
00228 }
00229 COREDLL void pbrtFilm(const string &type, const ParamSet ¶ms) {
00230 VERIFY_OPTIONS("Film");
00231 renderOptions->FilmParams = params;
00232 renderOptions->FilmName = type;
00233 }
00234 COREDLL void pbrtSampler(const string &name, const ParamSet ¶ms) {
00235 VERIFY_OPTIONS("Sampler");
00236 renderOptions->SamplerName = name;
00237 renderOptions->SamplerParams = params;
00238 }
00239 COREDLL void pbrtAccelerator(const string &name, const ParamSet ¶ms) {
00240 VERIFY_OPTIONS("Accelerator");
00241 renderOptions->AcceleratorName = name;
00242 renderOptions->AcceleratorParams = params;
00243 }
00244 COREDLL void pbrtSurfaceIntegrator(const string &name, const ParamSet ¶ms) {
00245 VERIFY_OPTIONS("SurfaceIntegrator");
00246 renderOptions->SurfIntegratorName = name;
00247 renderOptions->SurfIntegratorParams = params;
00248 }
00249 COREDLL void pbrtVolumeIntegrator(const string &name, const ParamSet ¶ms) {
00250 VERIFY_OPTIONS("VolumeIntegrator");
00251 renderOptions->VolIntegratorName = name;
00252 renderOptions->VolIntegratorParams = params;
00253 }
00254 COREDLL void pbrtCamera(const string &name,
00255 const ParamSet ¶ms) {
00256 VERIFY_OPTIONS("Camera");
00257 renderOptions->CameraName = name;
00258 renderOptions->CameraParams = params;
00259 renderOptions->WorldToCamera = curTransform;
00260 namedCoordinateSystems["camera"] =
00261 curTransform.GetInverse();
00262 }
00263 COREDLL void pbrtSearchPath(const string &path) {
00264 VERIFY_OPTIONS("SearchPath");
00265 UpdatePluginPath(path);
00266 renderOptions->gotSearchPath = true;
00267 }
00268 COREDLL void pbrtWorldBegin() {
00269 VERIFY_OPTIONS("WorldBegin");
00270 currentApiState = STATE_WORLD_BLOCK;
00271 curTransform = Transform();
00272 namedCoordinateSystems["world"] = curTransform;
00273 }
00274 COREDLL void pbrtAttributeBegin() {
00275 VERIFY_WORLD("AttributeBegin");
00276 pushedGraphicsStates.push_back(graphicsState);
00277 pushedTransforms.push_back(curTransform);
00278 }
00279 COREDLL void pbrtAttributeEnd() {
00280 VERIFY_WORLD("AttributeEnd");
00281 if (!pushedGraphicsStates.size()) {
00282 Error("Unmatched pbrtAttributeEnd() encountered. "
00283 "Ignoring it.");
00284 return;
00285 }
00286 graphicsState = pushedGraphicsStates.back();
00287 curTransform = pushedTransforms.back();
00288 pushedGraphicsStates.pop_back();
00289 pushedTransforms.pop_back();
00290 }
00291 COREDLL void pbrtTransformBegin() {
00292 VERIFY_WORLD("TransformBegin");
00293 pushedTransforms.push_back(curTransform);
00294 }
00295 COREDLL void pbrtTransformEnd() {
00296 VERIFY_WORLD("TransformEnd");
00297 if (!pushedTransforms.size()) {
00298 Error("Unmatched pbrtTransformEnd() encountered. "
00299 "Ignoring it.");
00300 return;
00301 }
00302 curTransform = pushedTransforms.back();
00303 pushedTransforms.pop_back();
00304 }
00305 COREDLL void pbrtTexture(const string &name,
00306 const string &type,
00307 const string &texname,
00308 const ParamSet ¶ms) {
00309 VERIFY_WORLD("Texture");
00310 TextureParams tp(params, params,
00311 graphicsState.floatTextures,
00312 graphicsState.spectrumTextures);
00313 if (type == "float") {
00314
00315 if (graphicsState.floatTextures.find(name) !=
00316 graphicsState.floatTextures.end())
00317 Warning("Texture \"%s\" being redefined", name.c_str());
00318 Reference<Texture<float> > ft = MakeFloatTexture(texname,
00319 curTransform, tp);
00320 if (ft) graphicsState.floatTextures[name] = ft;
00321 }
00322 else if (type == "color") {
00323
00324 if (graphicsState.spectrumTextures.find(name) != graphicsState.spectrumTextures.end())
00325 Warning("Texture \"%s\" being redefined", name.c_str());
00326 Reference<Texture<Spectrum> > st = MakeSpectrumTexture(texname,
00327 curTransform, tp);
00328 if (st) graphicsState.spectrumTextures[name] = st;
00329 }
00330 else
00331 Error("Texture type \"%s\" unknown.", type.c_str());
00332 }
00333 COREDLL void pbrtMaterial(const string &name, const ParamSet ¶ms) {
00334 VERIFY_WORLD("Material");
00335 graphicsState.material = name;
00336 graphicsState.materialParams = params;
00337 }
00338 COREDLL void pbrtLightSource(const string &name,
00339 const ParamSet ¶ms) {
00340 VERIFY_WORLD("LightSource");
00341 Light *lt = MakeLight(name, curTransform, params);
00342 if (lt == NULL)
00343 Error("pbrtLightSource: light type "
00344 "\"%s\" unknown.", name.c_str());
00345 else
00346 renderOptions->lights.push_back(lt);
00347 }
00348 COREDLL void pbrtAreaLightSource(const string &name,
00349 const ParamSet ¶ms) {
00350 VERIFY_WORLD("AreaLightSource");
00351 graphicsState.areaLight = name;
00352 graphicsState.areaLightParams = params;
00353 }
00354 COREDLL void pbrtShape(const string &name,
00355 const ParamSet ¶ms) {
00356 VERIFY_WORLD("Shape");
00357 Reference<Shape> shape = MakeShape(name,
00358 curTransform, graphicsState.reverseOrientation,
00359 params);
00360 if (!shape) return;
00361 params.ReportUnused();
00362
00363 AreaLight *area = NULL;
00364 if (graphicsState.areaLight != "")
00365 area = MakeAreaLight(graphicsState.areaLight,
00366 curTransform, graphicsState.areaLightParams, shape);
00367
00368 TextureParams mp(params,
00369 graphicsState.materialParams,
00370 graphicsState.floatTextures,
00371 graphicsState.spectrumTextures);
00372 Reference<Texture<float> > bump = NULL;
00373 Reference<Material> mtl =
00374 MakeMaterial(graphicsState.material,
00375 curTransform, mp);
00376 if (!mtl)
00377 mtl = MakeMaterial("matte", curTransform, mp);
00378 if (!mtl)
00379 Severe("Unable to create \"matte\" material?!");
00380
00381 Reference<Primitive> prim =
00382 new GeometricPrimitive(shape, mtl, area);
00383 if (renderOptions->currentInstance) {
00384 if (area)
00385 Warning("Area lights not supported "
00386 "with object instancing");
00387 renderOptions->currentInstance->push_back(prim);
00388 }
00389 else {
00390 renderOptions->primitives.push_back(prim);
00391 if (area != NULL) {
00392
00393 renderOptions->lights.push_back(area);
00394 }
00395 }
00396 }
00397 COREDLL void pbrtReverseOrientation() {
00398 VERIFY_WORLD("ReverseOrientation");
00399 graphicsState.reverseOrientation =
00400 !graphicsState.reverseOrientation;
00401 }
00402 COREDLL void pbrtVolume(const string &name,
00403 const ParamSet ¶ms) {
00404 VERIFY_WORLD("Volume");
00405 VolumeRegion *vr = MakeVolumeRegion(name,
00406 curTransform, params);
00407 if (vr) renderOptions->volumeRegions.push_back(vr);
00408 }
00409 COREDLL void pbrtObjectBegin(const string &name) {
00410 VERIFY_WORLD("ObjectBegin");
00411 pbrtAttributeBegin();
00412 if (renderOptions->currentInstance)
00413 Error("ObjectBegin called inside "
00414 "of instance definition");
00415 renderOptions->instances[name] =
00416 vector<Reference<Primitive> >();
00417 renderOptions->currentInstance =
00418 &renderOptions->instances[name];
00419 }
00420 COREDLL void pbrtObjectEnd() {
00421 VERIFY_WORLD("ObjectEnd");
00422 if (!renderOptions->currentInstance)
00423 Error("ObjectEnd called outside "
00424 "of instance definition");
00425 renderOptions->currentInstance = NULL;
00426 pbrtAttributeEnd();
00427 }
00428 COREDLL void pbrtObjectInstance(const string &name) {
00429 VERIFY_WORLD("ObjectInstance");
00430
00431 if (renderOptions->currentInstance) {
00432 Error("ObjectInstance can't be called inside instance definition");
00433 return;
00434 }
00435 if (renderOptions->instances.find(name) == renderOptions->instances.end()) {
00436 Error("Unable to find instance named \"%s\"", name.c_str());
00437 return;
00438 }
00439 vector<Reference<Primitive> > &in =
00440 renderOptions->instances[name];
00441 if (in.size() == 0) return;
00442 if (in.size() > 1 || !in[0]->CanIntersect()) {
00443
00444 Reference<Primitive> accel =
00445 MakeAccelerator(renderOptions->AcceleratorName,
00446 in, renderOptions->AcceleratorParams);
00447 if (!accel)
00448 accel = MakeAccelerator("kdtree", in, ParamSet());
00449 if (!accel)
00450 Severe("Unable to find \"kdtree\" accelerator");
00451 in.erase(in.begin(), in.end());
00452 in.push_back(accel);
00453 }
00454 Reference<Primitive> prim = new InstancePrimitive(in[0],
00455 curTransform);
00456 renderOptions->primitives.push_back(prim);
00457 }
00458 COREDLL void pbrtWorldEnd() {
00459 VERIFY_WORLD("WorldEnd");
00460
00461 if (!renderOptions->gotSearchPath)
00462 Severe("PBRT_SEARCHPATH environment variable "
00463 "wasn't set and a plug-in\n"
00464 "search path wasn't given in the "
00465 "input (with the SearchPath "
00466 "directive).\n");
00467
00468 while (pushedGraphicsStates.size()) {
00469 Warning("Missing end to pbrtAttributeBegin()");
00470 pushedGraphicsStates.pop_back();
00471 pushedTransforms.pop_back();
00472 }
00473
00474 Scene *scene = renderOptions->MakeScene();
00475 if (scene) scene->Render();
00476 delete scene;
00477
00478 currentApiState = STATE_OPTIONS_BLOCK;
00479 StatsPrint(stdout);
00480 curTransform = Transform();
00481 namedCoordinateSystems.erase(namedCoordinateSystems.begin(),
00482 namedCoordinateSystems.end());
00483 }
00484 Scene *RenderOptions::MakeScene() const {
00485
00486 Filter *filter = MakeFilter(FilterName, FilterParams);
00487 Film *film = MakeFilm(FilmName, FilmParams, filter);
00488 Camera *camera = MakeCamera(CameraName, CameraParams,
00489 WorldToCamera, film);
00490 Sampler *sampler = MakeSampler(SamplerName, SamplerParams, film);
00491 SurfaceIntegrator *surfaceIntegrator = MakeSurfaceIntegrator(SurfIntegratorName,
00492 SurfIntegratorParams);
00493 VolumeIntegrator *volumeIntegrator = MakeVolumeIntegrator(VolIntegratorName,
00494 VolIntegratorParams);
00495 Primitive *accelerator = MakeAccelerator(AcceleratorName,
00496 primitives, AcceleratorParams);
00497 if (!accelerator) {
00498 ParamSet ps;
00499 accelerator = MakeAccelerator("kdtree", primitives, ps);
00500 }
00501 if (!accelerator)
00502 Severe("Unable to find \"kdtree\" accelerator");
00503
00504 VolumeRegion *volumeRegion;
00505 if (volumeRegions.size() == 0)
00506 volumeRegion = NULL;
00507 else if (volumeRegions.size() == 1)
00508 volumeRegion = volumeRegions[0];
00509 else
00510 volumeRegion = new AggregateVolume(volumeRegions);
00511
00512 if (!camera || !sampler || !film || !accelerator ||
00513 !filter || !surfaceIntegrator || !volumeIntegrator) {
00514 Severe("Unable to create scene due "
00515 "to missing plug-ins");
00516 return NULL;
00517 }
00518 Scene *ret = new Scene(camera,
00519 surfaceIntegrator, volumeIntegrator,
00520 sampler, accelerator, lights, volumeRegion);
00521
00522 primitives.erase(primitives.begin(),
00523 primitives.end());
00524 lights.erase(lights.begin(),
00525 lights.end());
00526 volumeRegions.erase(volumeRegions.begin(),
00527 volumeRegions.end());
00528 return ret;
00529 }