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