Main Page Class Hierarchy Compound List File List Compound Members File Members

RadMain.cc

Go to the documentation of this file.
00001 /*
00002 File: RadMain.cc
00003 
00004 Function: Implements "Radiator"
00005 
00006 Provides command line-driven program for running 
00007 various radiosity methods. 
00008 
00009 Author(s): Andrew Willmott
00010 
00011 Copyright: (c) 1997-2000, Andrew Willmott
00012 
00013 Notes: 
00014 */
00015 
00016 #ifdef CL_HAS_NEW
00017 #include <new>
00018 #endif
00019 #include <unistd.h>
00020 #include <fstream.h>
00021 #include <signal.h>
00022 
00023 #include "cl/ArgParse.h"
00024 
00025 #include "RadMethod.h"
00026 
00027 #include "cl/String.h"
00028 #include "gcl/Avars.h"
00029 #include "gcl/SceneLang.h"
00030 #include "gcl/Readers.h"
00031 
00032 #include "BuildDate.h"
00033 
00034  class RadMain
00035 {
00036 public:
00037 Void SetOptions(Int argc, Char *argv[]);
00038 Void DoRadiosity();
00039 
00040  RadControl radOpts;
00041  Int size;
00042  Int dumpObj;
00043  Int dumpSL;
00044  Int noDirect;
00045  Int normalise;
00046  Char *sceneFile;
00047  String outFile;
00048 
00049  static Int frame;
00050 };
00051 
00052  static char *defMethodName[] = 
00053 {
00054 "none",
00055 "mat",
00056 "prog",
00057 "hprog",
00058 "hier",
00059 "ana"
00060 };
00061 
00062  static char *defBasisName[] = 
00063 { 
00064 "none",
00065 "haar",
00066 "f2",
00067 "f3",
00068 "m2",
00069 "m3"
00070 };
00071 
00072 
00073 // --- Utilities --------------------------------------------------------------
00074 
00075  static void LogToFile(const FileName &logFile)
00076 // capture stdout & copy it to a run file
00077 {
00078 int filedes[2], count;
00079 char buffer[1024];
00080 FILE *log;
00081 
00082 if (pipe(filedes) == -1)
00083 {
00084 perror("logger: pipe");
00085 return;
00086 }
00087 
00088 fflush(stdout);
00089 
00090 if (fork() != 0)
00091 {
00092 if (dup2(filedes[1], fileno(stdout)) == -1)
00093 perror("logger: dup");
00094 if (close(filedes[0]) == -1)
00095 perror("logger: c0");
00096 
00097 return;
00098 }
00099 
00100 close(filedes[1]);
00101 log = logFile.FOpen("w");
00102 
00103 while ((count = read(filedes[0], buffer, 1024)) > 0)
00104 {
00105 write(1, buffer, count);
00106 fwrite(buffer, 1, count, log);
00107 }
00108 if (count == -1)
00109 perror("logger: read");
00110 
00111 fclose(log);
00112 close(filedes[0]);
00113 
00114 exit(0);
00115 }
00116 
00117  static Void RadHandleInterrupt(Int a)
00118 {
00119 // On reception of a SIGHUP, stop simulation.
00120 cerr << "received interrupt " << a << ": stopping simulation" << endl;
00121 gRadControl->limitTime = 0;
00122 }
00123 
00124  static Void RadHandleCont(Int a)
00125 {
00126 // On reception of a SIGCONT, print status info
00127 cerr << "received interrupt " << a << ": printing status" << endl;
00128 gRadControl->radObject->lastTime = gRadControl->radObject->totTime
00129 - gRadControl->sliceTime;
00130 }
00131 
00132  static Array<Char*> gAvarNames;
00133  static Array<GCLReal> gAvarVals;
00134 
00135  static Int avarArg(int argc, char **argv)
00136 {
00137 Int i;
00138 GCLReal val;
00139 
00140 if (argc % 2 == 1)
00141 {
00142 cerr << "Wrong number of avar arguments." << endl;
00143 exit(1);
00144 }
00145 
00146 for (i = 0; i < argc; i += 2)
00147 {
00148 val = atof(argv[i + 1]);
00149 if (argv[i] == StrConst("frame"))
00150 RadMain::frame = (Int) val;
00151 gAvarNames.Append(argv[i]);
00152 gAvarVals.Append(val);
00153 }
00154 
00155 return(0);
00156 }
00157 
00158 
00159 // --- RadMain methods --------------------------------------------------------
00160 
00161 Int RadMain::frame = -1;
00162 
00163  Void RadMain::SetOptions(Int argc, Char *argv[])
00164 {
00165 Int hier, prog, mat, hprog, ana;
00166 Int haar, f2, f3, m2, m3, noClusFlag;
00167 Int schedFlag, interFlag, twoStageFlag, fcrFlag = false;
00168 Int ambient, viq, bestPass, bestVisPass;
00169 Int noBF, noGraded, noAnchor, refAllLinks, conjGrad;
00170 Int visnone, vis1, vis16, vis44;
00171 Int updateScene, dumpMatrix, dumpScenes, dumpTree;
00172 Int meshRnd, meshNL, meshFix, meshNoConnect, meshNoGrid;
00173 Int version;
00174 Double meshComp, rtComp;
00175 String usage;
00176 Arg_form *arg_format;
00177 
00178 // Set default arguments
00179 
00180 size = 400;
00181 frame = -1;
00182 sceneFile = 0;
00183 radOpts.outFile = 0;
00184 meshComp = 1.0;
00185 rtComp = -1.0;
00186 
00187 usage.Printf("Usage: %s [options], where options are as follows:", 
00188 argv[0]);
00189 
00190 // Create arg form
00191 
00192 arg_format = arg_to_form(0,
00193 "-v", ARG_FLAG(&version), "show current version",
00194 "[%S]", &sceneFile, "input scene file",
00195 
00196 // methods
00197 
00198 "", 
00199 "\n--- Methods --------------------------------------------------------------------\n",
00200 "-mat", ARG_FLAG(&mat), "use matrix radiosity",
00201 "-prog", ARG_FLAG(&prog), "use progressive radiosity",
00202 "-hprog", ARG_FLAG(&hprog), "use progressive radiosity with substructuring",
00203 "-hier", ARG_FLAG(&hier), "use hierarchical radiosity",
00204 "-ana", ARG_FLAG(&ana), "use 1st-order analytical solver",
00205 
00206 // method params
00207 
00208 "", 
00209 "\n--- Params ---------------------------------------------------------------------\n",
00210 "-sub %F", &radOpts.patchSubdivs, "set patch subdivision density",
00211 "-esub %F", &radOpts.eltSubdivs, "set element subdivision density",
00212 "-alpha %F", &radOpts.alpha, "set alpha",
00213 "-error %F", &radOpts.error, "set termination error",
00214 "-ferr %F", &radOpts.kFError, "set ff error",
00215 "-aerr %F", &radOpts.kAError, "set min patch size",
00216 "-derr %F", &radOpts.dFError, "set singularity threshold",
00217 
00218 // bases
00219 
00220 
00221 // visibility, form factor eval
00222 
00223 "", 
00224 "\n--- Visibility------------------------------------------------------------------\n",
00225 "-verr %F", &radOpts.visError, "wavelet visibility error",
00226 "-quadLevel %d", &radOpts.quadLevel, "quadrature level",
00227 "-visInQuad", ARG_FLAG(&viq), "do visibility testing in quadrature",
00228 
00229 "-vis_none", ARG_FLAG(&visnone), "no visibility testing",
00230 "-vis_1", ARG_FLAG(&vis1), "single ray visibility", 
00231 "-vis_16", ARG_FLAG(&vis16), "use 16 rays from source -> centre of dest",
00232 "-vis_44", ARG_FLAG(&vis44), "use 16 rays distributed over both patches",
00233 "-visReuseArea %F", &radOpts.forceVisReuseArea, 
00234 "area below which to reuse visibility samples",
00235 "-favourReceiver %F", &radOpts.favourReceiver,
00236 "amount by which to favour subdividing receiver",
00237 
00238 // meshing
00239 
00240 "", 
00241 "\n--- Meshing --------------------------------------------------------------------\n",
00242 "-mesh_share", ARG_FLAG(&meshFix), "ensure all coincident mesh vertices are shared",
00243 "-mesh_noAnchor", ARG_FLAG(&noAnchor), "don't enforce elimination of t-vertices",
00244 "-mesh_noGrading", ARG_FLAG(&noGraded), "don't enforce a graded mesh",
00245 "-mesh_noConnect", ARG_FLAG(&meshNoConnect), "don't calculate mesh connectivity",
00246 "-mesh_noGrid", ARG_FLAG(&meshNoGrid), "don't use gridding, only hierarchical refinement",
00247 "-mesh_nonLin", ARG_FLAG(&meshNL), "mesh more heavily at edges",
00248 "-mesh_random", ARG_FLAG(&meshRnd), "vary 'sub' parameter randomly",
00249 
00250 // MRM complexity
00251 
00252 "", 
00253 "\n--- Complexity -----------------------------------------------------------------\n",
00254 "-meshComp %F", &meshComp, "complexity for creating radiosity mesh",
00255 "-rtComp %F", &rtComp, "complexity for raytracing (if different.)",
00256 
00257 // misc
00258 
00259 "", 
00260 "\n--- Misc -----------------------------------------------------------------------\n",
00261 "-conjGrad", ARG_FLAG(&conjGrad), "use conjugate gradient solver (matrix radiosity)",
00262 "-ambient", ARG_FLAG(&ambient), "add ambient term",
00263 "-maxShots %d", &radOpts.maxShots, "max shooting steps to perform",
00264 "-noDirect", ARG_FLAG(&noDirect), "no direct illumination",
00265 "-no_refWait", ARG_FLAG(&refAllLinks), "don't wait for all links to be refined before stopping",
00266 "-normalise", ARG_FLAG(&normalise), "rescale scene first",
00267 
00268 // cluster + FCR
00269 
00270 "", 
00271 "\n--- Cluster/FCR ------------------------------------------------------------\n",
00272 "-doFinal", ARG_FLAG(&bestPass), "do final 'best' pass",
00273 "-finLevels %d", &radOpts.bestLevels, " extra levels to subdivide",
00274 "-finVis", ARG_FLAG(&bestVisPass), " recalc visibility",
00275 "-noCluster", ARG_FLAG(&noClusFlag), "don't use clustering",
00276 "-scheduled", ARG_FLAG(&schedFlag), "use scheduled solver [default]",
00277 "-interleaved", ARG_FLAG(&interFlag), "use interleaved solver",
00278 "-twoStage", ARG_FLAG(&twoStageFlag), "use two-stage solver",
00279 "-schedIters %d", &radOpts.schedIterations, "max scheduled iterations to perform",
00280 
00281 
00282 // avars
00283 
00284 "", 
00285 "\n--- Avars ----------------------------------------------------------------------\n",
00286 "-set", ARG_SUBR(avarArg), "set avar, e.g. -set light 0.5 height 0.2",
00287 
00288 // Output options
00289 
00290 "", 
00291 "\n--- Output ---------------------------------------------------------------------\n",
00292 "-slice %F", &radOpts.sliceTime, "time slice: output stats at this interval",
00293 "-limit %F", &radOpts.limitTime, "time limit: halt after this much time",
00294 "-dumpObj", ARG_FLAG(&dumpObj), "output final mesh as .obj [default]",
00295 "-dumpSL", ARG_FLAG(&dumpSL), "output final mesh as .sl",
00296 "-updateScene", ARG_FLAG(&updateScene), "update final mesh file at each slice",
00297 "-dumpScenes", ARG_FLAG(&dumpScenes), "output separate numbered mesh file for each slice",
00298 "-dumpMatrix", ARG_FLAG(&dumpMatrix), "output form-factor matrix",
00299 "-dumpHier", ARG_FLAG(&dumpTree), "output solution hierarchy",
00300 "-o %S", &radOpts.outFile, "output file name",
00301 
00302 
00303 // Examples
00304 "", 
00305 "\n--- Examples -------------------------------------------------------------------\n",
00306 "", "radiator my-scene.sl -hprog -error 0.001 -ferr 0.01",
00307 "", "killall -HUP radiator stops simulation",
00308 "", "killall -CONT radiator print simulation status",
00309 0
00310 );
00311 
00312 // Do arg parsing
00313 if (argc == 1)
00314 {
00315 fprintf(stderr, "%s\n%s\n\n%s\n\n",
00316 RadGetVersion().CString(),
00317 "(c) Andrew Willmott <ajw+rad@cs.cmu.edu> 2000",
00318 usage.CString()
00319 );
00320 
00321 arg_form_print(arg_format);
00322 exit(0);
00323 }
00324 if (arg_parse_argv(argc, argv, arg_format) < 0)
00325 exit(1);
00326 
00327 // Process arguments
00328 
00329 if (version)
00330 {
00331 cout << RadGetVersion() << endl;
00332 cout << "Built on " << kBuildDate << endl;
00333 cout << "A radiosity engine, (c) Andrew Willmott <ajw+rad@cs.cmu.edu> 1999" << endl;
00334 exit(0);
00335 }
00336 
00337 if (!sceneFile)
00338 {
00339 cout << "No scene file specified!" << endl;
00340 exit(1);
00341 }
00342 
00343 radOpts.cluster = !noClusFlag;
00344 radOpts.bestPass = bestPass;
00345 radOpts.bestVisPass = bestVisPass;
00346 radOpts.dumpScenes = dumpScenes; 
00347 radOpts.updateScene = updateScene;
00348 radOpts.dumpTree = dumpTree;
00349 radOpts.drawMatrix = dumpMatrix;
00350 
00351 if (!dumpSL && !dumpScenes)
00352 dumpObj = true;
00353 
00354 
00355 if (ana) 
00356 radOpts.method = kAnalytical;
00357 else if (hier) 
00358 radOpts.method = kHierarchical;
00359 else if (hprog)
00360 radOpts.method = kProgSubstruct;
00361 else if (prog)
00362 radOpts.method = kProgressive;
00363 else if (mat)
00364 radOpts.method = kMatrix;
00365 else
00366 // default to progressive radiosity with substructuring
00367 radOpts.method = kProgSubstruct;
00368 
00369 if (vis44)
00370 radOpts.visibility = vis_4x4;
00371 else if (vis16)
00372 radOpts.visibility = vis_16x1;
00373 else if (vis1)
00374 radOpts.visibility = vis_1;
00375 else if (visnone)
00376 radOpts.visibility = vis_none;
00377 else
00378 radOpts.visibility = vis_4x4;
00379 
00380 if (meshRnd)
00381 radOpts.mesh = mesh_random;
00382 if (meshNL)
00383 radOpts.mesh = mesh_nonlin;
00384 radOpts.fixMesh = meshFix;
00385 radOpts.connectMesh = !meshNoConnect;
00386 radOpts.noGridMesh = meshNoGrid;
00387 
00388 if (!radOpts.outFile)
00389 // make up a name for the output file
00390 {
00391 FileName inFile;
00392 
00393 inFile.SetPath(sceneFile);
00394 
00395 if (fcrFlag)
00396 outFile = "fcr";
00397 else if (hier)
00398 outFile = defBasisName[radOpts.basis];
00399 else
00400 outFile = defMethodName[radOpts.method];
00401 
00402 outFile = outFile + "-" + inFile.GetFile();
00403 }
00404 else
00405 outFile = radOpts.outFile;
00406 
00407 if (frame >= 0)
00408 // add a frame number
00409 outFile = outFile + String().Printf("-%04d", frame);
00410 
00411 radOpts.outFile = outFile;
00412 // XXX make optional?
00413 if (true)
00414 LogToFile(FileName().SetPath(outFile).SetExtension("run"));
00415 
00416 
00417 if (interFlag)
00418 radOpts.solver = sv_interleaved;
00419 else if (twoStageFlag)
00420 radOpts.solver = sv_twoStage;
00421 else
00422 radOpts.solver = sv_scheduled;
00423 
00424 radOpts.useConjGrad = conjGrad;
00425 radOpts.ambient = ambient;
00426 radOpts.graded = !noGraded;
00427 radOpts.anchor = !noAnchor;
00428 radOpts.refAllLinks = !refAllLinks;
00429 radOpts.visInQuad = viq;
00430 
00431 radOpts.meshComplexity = meshComp;
00432 if (rtComp >= 0.0)
00433 radOpts.rtComplexity = rtComp;
00434 else
00435 radOpts.rtComplexity = meshComp;
00436 }
00437 
00438 
00439  Void RadMain::DoRadiosity()
00440 {
00441 Int i;
00442 scScenePtr scene;
00443 RadMethod *radMethod = 0;
00444 CreateAvarList makeAvarList;
00445 FileName path;
00446 
00447 cout << RadGetVersion() << endl;
00448 slInit();
00449 gRadControl = &radOpts;
00450 
00451 path.SetPath(sceneFile);
00452 scene = SceneReader::Load(path);
00453 
00454 if (!scene)
00455 {
00456 cerr << "Couldn't read file: " << sceneFile << endl;
00457 exit(1);
00458 }
00459 
00460 // Set avars...
00461 
00462 
00463 scene->ApplyAction(makeAvarList);
00464 
00465 #ifdef DEBUG
00466 cout << "set avars:" << endl;
00467 for (i = 0; i < gAvarNames.NumItems(); i++)
00468 cout << "avar " << gAvarNames[i] << " = " << gAvarVals[i] << endl;
00469 cout << "scene avars:" << endl;
00470 for (i = 0; i < makeAvarList.avarList->NumItems(); i++)
00471 cout << makeAvarList.avarList->Item(i).name << " = " 
00472 << makeAvarList.avarList->Item(i).value << endl;
00473 #endif
00474 
00475 scene->Set(makeAvarList.avarList);
00476 
00477 for (i = 0; i < gAvarNames.NumItems(); i++)
00478 if (!makeAvarList.avarList->SetAvar(gAvarNames[i], gAvarVals[i]))
00479 cerr << "No such avar in scene: " << gAvarNames[i] 
00480 << " (ignoring) " << endl;
00481 
00482 // Create radiosity method
00483 
00484 radMethod = RadMethod::NewRadMethod();
00485 
00486 // Run radiosity method...
00487 
00488 if (radMethod)
00489 {
00490 if (normalise)
00491 scene->Normalise();
00492 radMethod->SetScene(scene);
00493 radMethod->Render();
00494 if (noDirect)
00495 radMethod->RemoveDirect();
00496 
00497 // Output scene file
00498 
00499 if (dumpObj)
00500 {
00501 cerr << "Saving final mesh as " + radOpts.outFile + ".obj" << endl;
00502 radMethod->WriteObjFile(radOpts.outFile + ".obj");
00503 }
00504 if (dumpSL)
00505 {
00506 cerr << "Saving final mesh as " + radOpts.outFile + ".sl" << endl;
00507 radMethod->WriteSLFile(radOpts.outFile + ".sl");
00508 }
00509 }
00510 else
00511 cerr << "Sorry, that method has not been compiled in!" << endl;
00512 }
00513 
00514  main(int argc, char **argv)
00515 {
00516 RadMain app;
00517 
00518 #ifdef CL_HAS_NEW
00519 try
00520 {
00521 #endif
00522 app.SetOptions(argc, argv);
00523 signal(SIGHUP, RadHandleInterrupt);
00524 signal(SIGCONT, RadHandleCont);
00525 app.DoRadiosity();
00526 #ifdef CL_HAS_NEW
00527 }
00528 catch (bad_alloc)
00529 {
00530 cout << "EXCEPTION: out of (virtual) memory." << endl;
00531 return(-1);
00532 }
00533 #endif
00534 
00535 return(0);
00536 }

Generated at Sat Aug 5 00:26:53 2000 for Radiator by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000

AltStyle によって変換されたページ (->オリジナル) /