00001 /*
00002 File: RadVis.cc
00003
00004 Function: GUI front end for the various radiosity methods. Allows
00005 visualisation of the methods.
00006
00007 Author(s): Andrew Willmott
00008
00009 Copyright: (c) 1997-2000, Andrew Willmott
00010 */
00011
00012
00013
00014 #include "TestScene.h"
00015
00016 #include "MatRad.h"
00017 #include "ProgRad.h"
00018 #include "HProgRad.h"
00019 #include "HierRad.h"
00020
00021 #include "RadPane.h"
00022 #include "RadScene.h"
00023 #include "Examiner.h"
00024
00025 #include "gcl/XGraphicsSystem.h"
00026 #include "gcl/Forms.h"
00027 #include "gcl/SceneLang.h"
00028 #include "gcl/Avars.h"
00029 #include "gcl/Readers.h"
00030 #include "gcl/EPSRenderer.h"
00031 #include "gcl/MesaRenderer.h"
00032
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035 #include "cl/ArgParse.h"
00036
00037 // classes derived from fdesign.
00038 #include "theForms.h"
00039
00040 class RadForm;
00041
00042 // --- exponential slider -----------------------------------------------------
00043
00044 // provides exponential-based slider more suited to error metrics
00045 // basically steps down through 0.9 .. 0.1, 0.09 .. 0.01, etc.
00046
00047 static double eslider_map(double val)
00048 {
00049 double d = floor(val - 0.05);
00050
00051 return(pow(10.0, d + 1.0) * (val - d));
00052 }
00053
00054 static char *esliderFilt(FL_OBJECT *, double val, int prec)
00055 {
00056 static char result[32];
00057
00058 val = eslider_map(val);
00059 sprintf(result, "%.*g", prec, val);
00060
00061 return(result);
00062 }
00063
00064 double fl_get_eslider_value(FL_OBJECT *obj)
00065 {
00066 return(eslider_map(fl_get_slider_value(obj)));
00067 }
00068
00069 double fl_set_eslider_value(FL_OBJECT *obj, double val)
00070 {
00071 }
00072
00073 // --- Options Panels --------------------------------------------------------
00074
00075
00076 class TransportPanel : public TransportForm
00077 {
00078 public:
00079 TransportPanel(RadForm *radform) : TransportForm(), parent(radform) {};
00080
00081 Void Event(FL_OBJECT *object);
00082
00083 RadForm *parent;
00084 };
00085
00086 class RenderPanel : public RenderForm
00087 {
00088 public:
00089 RenderPanel(RadForm *radform) : RenderForm(), parent(radform) {};
00090
00091 Void Event(FL_OBJECT *object);
00092
00093 RadForm *parent;
00094 };
00095
00096
00097 // --- AvarPanel --------------------------------------------------------------
00098
00099
00100 class AvarPanel : public AvarForm
00101 {
00102 public:
00103 Void Init();
00104 Void Event(FL_OBJECT *object);
00105 Void SetScene(scScenePtr scene);
00106 Void Dump(ostream &s);
00107
00108 scAvarList *avarList;
00109 ScenePane *scenePane;
00110 };
00111
00112 Void AvarPanel::Init()
00113 {
00114 fl_set_slider_bounds(avarSlider, 0, 1);
00115 fl_set_slider_value(avarSlider, 1);
00116 }
00117
00118 Void AvarPanel::SetScene(scScenePtr scene)
00119 {
00120 Int i;
00121 CreateAvarList avarGrabber;
00122
00123 scene->ApplyAction(avarGrabber);
00124 avarList = avarGrabber.avarList;
00125
00126 fl_clear_browser(avarBrowser);
00127
00128 for (i = 0; i < avarList->NumItems(); i++)
00129 fl_add_browser_line(avarBrowser, (*avarList)[i].name);
00130 }
00131
00132 Void AvarPanel::Dump(ostream &s)
00133 {
00134 Int i;
00135
00136 for (i = 0; i < avarList->NumItems(); i++)
00137 cout << (*avarList)[i].name << " = " << (*avarList)[i].value << endl;
00138 }
00139
00140 Void AvarPanel::Event(FL_OBJECT *object)
00141 {
00142 if (object == avarBrowser)
00143 {
00144 if (fl_get_browser(object) > 0)
00145 {
00146 Avar &avar = (*avarList)[fl_get_browser(avarBrowser) - 1];
00147
00148 fl_set_slider_bounds(avarSlider, avar.upperBound,
00149 avar.lowerBound);
00150 fl_set_slider_value(avarSlider, avar.value);
00151 }
00152 }
00153 else if (object == avarSlider)
00154 {
00155 if (fl_get_browser(avarBrowser) > 0)
00156 {
00157 (*avarList)[fl_get_browser(avarBrowser) - 1].value =
00158 fl_get_slider_value(avarSlider);
00159 if (scenePane)
00160 scenePane->Redraw();
00161 }
00162 }
00163 else if (object == dismiss)
00164 Hide();
00165 else if (object == dump)
00166 Dump(cout);
00167 }
00168
00169
00170 // --- The radvis main pane! --------------------------------------------------
00171
00172
00173 class RadForm : public RadVisMainForm
00174 {
00175 public:
00176
00177 RadForm();
00178
00179 Int Main(Int argc, Char **argv);
00180 Void InitOptions(Int argc, Char **argv,
00181 RadControl &options, Char **scenePathP);
00182
00183 Void Event(FL_OBJECT *object);
00184 Void Init(const Char *scenePath);
00185 Void SetupControls();
00186 Void SetupMenus();
00187 Void SetFormOptions();
00188 // set form controls from options field
00189 Void GetFormOptions();
00190 // set options field from form controls
00191
00192 Void SamplePatch(Matd &samples);
00193 Void SampleFF(Matd &samples);
00194 Void UpdateMethodOptions(Int a, Int b);
00195 Void RenderMode(Bool on);
00196
00197 Void UpdateRadScene();
00198 Void UpdateScene();
00199 scScenePtr LoadScene();
00200 scScenePtr LoadScene(const Char *path);
00201
00202 // Commands
00203
00204 Void Go();
00205 Void Reset();
00206 Void ChooseMethod();
00207 Void SceneSelect();
00208 Void DumpImage();
00209 Void DumpEPS();
00210 Void DumpObjFile();
00211 Void DumpSLFile();
00212 Void DumpCamera();
00213 Void StartHelp();
00214
00215 // Fields
00216
00217 Int oldMethodChoice;
00218
00219 scScenePtr scene;
00220 scScenePtr matrixScene;
00221 RadMethod *radMethod;
00222 RadControl options;
00223
00224 RadScenePane mainPane;
00225 ScenePane2D matrixPane;
00226
00227 AvarPanel avarPanel;
00228 TransportPanel transPanel;
00229 RenderPanel renderPanel;
00230
00231 FormsGraphicsSystem *fgs;
00232 Bool sceneSet;
00233 Colour bgColour;
00234 };
00235
00236
00237 // --- RadMethod form methods -------------------------------------------------------
00238
00239
00240 RadForm::RadForm() :
00241 RadVisMainForm(),
00242 scene(0),
00243 transPanel(this),
00244 renderPanel(this),
00245 fgs(0)
00246 {
00247 #ifdef DEBUG
00248 title = "Radiosity Visualisation (Debug)";
00249 #else
00250 title = "Radiosity Visualisation";
00251 #endif
00252 gRadControl = &options;
00253 }
00254
00255 Void RadForm::Init(const Char *scenePath)
00256 {
00257 fgs->CreateFormsPane((XEventPane*) &mainPane, box1);
00258 fgs->CreateFormsPane(&matrixPane, box2);
00259
00260 SetupControls();
00261 SetupMenus();
00262 SetFormOptions();
00263
00264 // Enable/Disable the right controls.
00265
00266 UpdateMethodOptions(kMatrix, kNoMethod);
00267 UpdateMethodOptions(kProgressive, kNoMethod);
00268 UpdateMethodOptions(kProgSubstruct, kNoMethod);
00269 UpdateMethodOptions(kHierarchical, kNoMethod);
00270 UpdateMethodOptions(kAnalytical, kNoMethod);
00271 UpdateMethodOptions(kNoMethod, options.method);
00272
00273 slInit();
00274 if (scenePath)
00275 scene = LoadScene(scenePath);
00276 else
00277 {
00278 options.drawMatrix = true;
00279 options.cluster = false;
00280 scene = BoxScene();
00281 }
00282
00283 // Set up the radiosity method and the view pane.
00284
00285 mainPane.SetBgColour(bgColour);
00286 mainPane.SetParent(this);
00287 sceneSet = false;
00288 // get into 'reset' state...
00289 Reset();
00290
00291 oldMethodChoice = 0;
00292 radMethod = RadMethod::NewRadMethod();
00293 radMethod->SetDisplay(&mainPane, fgs);
00294
00295 radMethod->matDisplay = &matrixPane;
00296 radMethod->out1 = comment;
00297 radMethod->out2 = debug1;
00298 radMethod->out3 = debug2;
00299
00300 matrixPane.SetBgColour(bgColour);
00301 matrixScene = slBeginObject("matrix");
00302 slObject(new scMatrixDisplay((Void **) &radMethod));
00303 slEndObject();
00304 matrixPane.SetScene(matrixScene);
00305 matrixPane.Redraw();
00306 }
00307
00308 Void RadForm::SetupMenus()
00309 {
00310 // Set up the menus
00311
00312 fl_set_choice_fontsize(methodChoice, FL_SMALL_SIZE);
00313 fl_set_choice_fontstyle(methodChoice, FL_BOLD_STYLE);
00314 fl_set_choice_fontsize(basis, FL_SMALL_SIZE);
00315 fl_set_choice_fontstyle(basis, FL_BOLD_STYLE);
00316 fl_set_choice_fontsize(transPanel.visMethod, FL_TINY_SIZE);
00317 fl_set_choice_fontsize(transPanel.quadLevel, FL_TINY_SIZE);
00318 }
00319
00320 Void RadForm::SetupControls()
00321 {
00322 // Set values for the various UI components
00323
00324 fl_set_slider_bounds(patchSubdivs, 0.0, 20);
00325 fl_set_slider_value(patchSubdivs, 1.0);
00326 fl_set_slider_return(patchSubdivs, 0);
00327
00328 fl_set_slider_bounds(eltSubdivs, 0.2, 20);
00329 fl_set_slider_value(eltSubdivs, 0.5);
00330 fl_set_slider_return(eltSubdivs, 0);
00331
00332 fl_set_slider_bounds(alphaLevel, 1, 2);
00333 fl_set_slider_value(alphaLevel, 1);
00334 fl_set_slider_return(alphaLevel, 0);
00335
00336 fl_set_slider_bounds(error, -7.0, 0.0);
00337 fl_set_slider_step(error, 0.1);
00338 fl_set_slider_precision(error, 4);
00339 fl_set_slider_filter(error, esliderFilt);
00340 fl_set_slider_value(error, -3.0);
00341
00342 fl_set_slider_bounds(kFError, -7.0, 0.0);
00343 fl_set_slider_step(kFError, 0.1);
00344 fl_set_slider_precision(kFError, 4);
00345 fl_set_slider_filter(kFError, esliderFilt);
00346 fl_set_slider_value(kFError, -2.0);
00347
00348 fl_set_slider_bounds(kAError, -7.0, 2.0);
00349 fl_set_slider_step(kAError, 0.1);
00350 fl_set_slider_precision(kAError, 4);
00351 fl_set_slider_filter(kAError, esliderFilt);
00352 fl_set_slider_value(kAError, -6.0);
00353
00354 fl_set_counter_bounds(plotRes, 1, 32);
00355 fl_set_counter_step(plotRes, 1, 1);
00356 fl_set_counter_value(plotRes, 6);
00357
00358 fl_set_counter_bounds(renderPanel.maxIter, 1, 16);
00359 fl_set_counter_step(renderPanel.maxIter, 1, 1);
00360 fl_set_counter_bounds(renderPanel.bestLevels, -1, 8);
00361 fl_set_counter_step(renderPanel.bestLevels, 1, 1);
00362
00363 my_deactivate(examRad); // Deactivate plot buttons.
00364 my_deactivate(examFF);
00365 }
00366
00367 #include "SetGet.cc"
00368
00369 Void RadForm::SampleFF(Matd &samples)
00370 // Sample the form factor values from the currently selected source patch over
00371 // the currently selected destination patch.
00372 {
00373 Int i, j;
00374 RadElem *to = mainPane.selPatch[0];
00375 RadElem *from = mainPane.selPatch[1];
00376 Coord place;
00377 Vector x, y;
00378 Point point;
00379 Int density;
00380
00381 if (options.method == kHierarchical &&
00382 (options.basis == kFlatlet3 || options.basis == kMultiwavelet3))
00383 density = (Int) (fl_get_counter_value(plotRes) * 3);
00384 else
00385 density = (Int) (fl_get_counter_value(plotRes) * 4);
00386
00387 samples.SetSize(density + 1, density + 1);
00388 x = to->Vertex(2) - to->Vertex(1);
00389 y = to->Vertex(0) - to->Vertex(1);
00390
00391 for (i = 0; i <= density; i++)
00392 for (j = 0; j <= density; j++)
00393 {
00394 if (i == 0)
00395 place[0] = 1e-6;
00396 else
00397 place[0] = i / GCLReal(density) - 1e-6;
00398
00399 if (j == 0)
00400 place[1] = 1e-6;
00401 else
00402 place[1] = j / GCLReal(density) - 1e-6;
00403
00404 point = x * place[0] + y * place[1] + to->Vertex(1);
00405 samples[i][j] =
00406 from->ApproxPatchFactor(point, to->Normal());
00407 }
00408 }
00409
00410 Void RadForm::SamplePatch(Matd &samples)
00411 // Sample the currently selected patch.
00412 {
00413 Int i, j;
00414 RadElem *leaf;
00415 Coord place;
00416 Int density;
00417
00418 if (options.method == kHierarchical && (options.basis == kFlatlet3 ||
00419 options.basis == kMultiwavelet3))
00420 density = (Int) fl_get_counter_value(plotRes) * 9;
00421 else
00422 density = (Int) fl_get_counter_value(plotRes) * 8;
00423
00424 samples.SetSize(density, density);
00425
00426 for (i = 0; i < density; i++)
00427 for (j = 0; j < density; j++)
00428 {
00429 place[0] = GCLReal(i) / GCLReal(density - 1);
00430 place[1] = GCLReal(j) / GCLReal(density - 1);
00431
00432 samples[i][j] = len((mainPane.selPatch[0])->Sample(place));
00433 }
00434 }
00435
00436
00437 Void RadForm::UpdateMethodOptions(Int oldMethod, Int newMethod)
00438 {
00439 switch (oldMethod)
00440 {
00441 case kMatrix:
00442 my_deactivate(alphaLevel);
00443 my_deactivate(patchSubdivs);
00444 break;
00445 case kProgressive:
00446 my_deactivate(alphaLevel);
00447 my_deactivate(patchSubdivs);
00448 my_deactivate(error);
00449 break;
00450 case kProgSubstruct:
00451 my_deactivate(error);
00452 my_deactivate(alphaLevel);
00453 my_deactivate(eltSubdivs);
00454 my_deactivate(patchSubdivs);
00455 my_deactivate(kFError);
00456 my_deactivate(kAError);
00457 break;
00458 case kHierarchical:
00459 my_deactivate(alphaLevel);
00460 my_deactivate(basis);
00461 my_deactivate(error);
00462 my_deactivate(kFError);
00463 my_deactivate(kAError);
00464 break;
00465 case kAnalytical:
00466 my_deactivate(patchSubdivs);
00467 break;
00468 }
00469
00470 switch (newMethod)
00471 {
00472 case kMatrix:
00473 my_activate(alphaLevel);
00474 my_activate(patchSubdivs);
00475 break;
00476 case kProgressive:
00477 my_activate(alphaLevel);
00478 my_activate(patchSubdivs);
00479 my_activate(error);
00480 break;
00481 case kProgSubstruct:
00482 my_activate(error);
00483 my_activate(alphaLevel);
00484 my_activate(eltSubdivs);
00485 my_activate(patchSubdivs);
00486 my_activate(kFError);
00487 my_activate(kAError);
00488 break;
00489 case kHierarchical:
00490 my_activate(alphaLevel);
00491 my_deactivate(basis);
00492 my_activate(error);
00493 my_activate(kFError);
00494 my_activate(kAError);
00495 break;
00496 case kAnalytical:
00497 my_activate(patchSubdivs);
00498 }
00499 }
00500
00501 Void RadForm::RenderMode(Bool on)
00502 {
00503 if (!on)
00504 {
00505 UpdateMethodOptions(kNoMethod, options.method);
00506 my_activate(goBtn);
00507 my_activate(avar);
00508 my_activate(exitBtn);
00509 my_activate(methodChoice);
00510 }
00511 else
00512 {
00513 UpdateMethodOptions(options.method, kNoMethod);
00514 my_deactivate(goBtn);
00515 my_deactivate(avar);
00516 my_deactivate(exitBtn);
00517 my_deactivate(methodChoice);
00518 }
00519 }
00520
00521 scScenePtr RadForm::LoadScene()
00522 {
00523 const Char *result;
00524
00525 result = fl_show_fselector("Please pick a scene file", 0, "*.*", 0);
00526 return(LoadScene(result));
00527 }
00528
00529 scScenePtr RadForm::LoadScene(const Char *path)
00530 {
00531 scScenePtr scene = 0;
00532 FileName filename;
00533
00534 if (path)
00535 {
00536 filename.SetPath(path);
00537 scene = SceneReader::Load(filename);
00538 if (scene)
00539 scene->Normalise();
00540 }
00541
00542 if (!scene)
00543 scene = BoxScene();
00544
00545 return(scene);
00546 }
00547
00548 // --- Event Handling ---------------------------------------------------------
00549
00550 static const Char *gHelpURL =
00551 "http://www.cs.cmu.edu/~radiosity/radvis-help.html";
00552
00553 Void RadForm::StartHelp()
00554 {
00555 String line;
00556 Int err;
00557 StatusForm status;
00558 Char *netscape = "netscape";
00559
00560 // Fire up nutscape, if necessary, and target the help URL.
00561 // XXX Should change this to use exec*() and wait()...
00562
00563 status.Show();
00564 Field(status.heading) << "Help" << show;
00565 Field(status.body) << "Opening " << gHelpURL << show;
00566 line.Printf("%s -remote 'openURL(%s, new-window)'", netscape, gHelpURL);
00567 err = system(line);
00568
00569 if (err)
00570 {
00571 Field(status.body) << "remote failed (" << err << ")" << show;
00572 line.Printf("%s %s&", netscape, gHelpURL);
00573 Field(status.body) << "Starting Netscape..." << show;
00574 err = system(line);
00575 if (err)
00576 cout << "Could not invoke Netscape: help is available at "
00577 << gHelpURL << show;
00578 else
00579 Field(status.body) << "All systems go..." << show;
00580 }
00581 else
00582 Field(status.body) << "All systems go." << show;
00583
00584 sleep(2);
00585 status.Hide();
00586 }
00587
00588 Void RadForm::UpdateRadScene()
00589 {
00590 GetFormOptions();
00591
00592 Int saveWire = options.wire;
00593 options.wire = true;
00594 if (!sceneSet)
00595 {
00596 radMethod->SetScene(scene);
00597 mainPane.SetHeadlight(false);
00598 mainPane.SetScene(radMethod->GetScene());
00599 }
00600 else
00601 radMethod->ResetOptions();
00602
00603 mainPane.Redraw();
00604 options.wire = saveWire;
00605 sceneSet = true;
00606
00607 SetFormOptions();
00608 }
00609
00610 Void RadForm::ChooseMethod()
00611 {
00612 // Change the selected radiosity method
00613
00614 if (oldMethodChoice != fl_get_choice(methodChoice))
00615 {
00616 delete radMethod;
00617 UpdateMethodOptions(oldMethodChoice, fl_get_choice(methodChoice));
00618
00619 GetFormOptions();
00620 radMethod = RadMethod::NewRadMethod();
00621 radMethod->SetDisplay(&mainPane, fgs);
00622 radMethod->matDisplay = &matrixPane;
00623 radMethod->out1 = comment;
00624 radMethod->out2 = debug1;
00625 radMethod->out3 = debug2;
00626
00627 if (options.method >= kHierarchical)
00628 options.visibility = vis_4x4;
00629 else
00630 options.visibility = vis_1;
00631
00632 sceneSet = false;
00633 Reset();
00634 oldMethodChoice = fl_get_choice(methodChoice);
00635 }
00636 }
00637
00638 Void RadForm::Reset()
00639 {
00640 // reset the current radiosity run
00641
00642 options.stop = true;
00643 options.step = false;
00644 options.pause = false;
00645 options.pvData = 0;
00646 my_deactivate(examRad); // Deactivate plot buttons.
00647 my_deactivate(examFF);
00648 fl_set_button(pause, options.pause);
00649
00650 // go back to the original scene.
00651
00652 sceneSet = false;
00653 mainPane.SetHeadlight(true);
00654 mainPane.SetScene(scene);
00655 avarPanel.scenePane = 0;
00656 Field(comment) << "Current scene: " << scene->Label() << show;
00657 SetFormOptions();
00658 }
00659
00660 Void RadForm::Go()
00661 {
00662 // Render the current scene.
00663
00664 RenderMode(true);
00665 options.stop = false;
00666
00667 // Make sure the scene has been attached to the renderer.
00668
00669 UpdateRadScene();
00670 // avarPanel.Hide(); XXX need to fix xforms error msg before we can
00671 // do this.
00672
00673 // Doooo it...
00674
00675 radMethod->Render();
00676
00677 RenderMode(false);
00678 }
00679
00680 Void RadForm::SceneSelect()
00681 {
00682 // we default to showing the matrix, and no volume clustering
00683 // for simple scenes.
00684 options.drawMatrix = true;
00685 options.cluster = false;
00686
00687 switch(fl_get_choice(sceneSelect))
00688 {
00689 case 1:
00690 scene = BoxScene(); break;
00691 case 2:
00692 scene = ParallelScene(); break;
00693 case 3:
00694 scene = SidelightScene(); break;
00695 case 4:
00696 scene = BlockerScene(); break;
00697 case 5:
00698 scene = AbuttingScene(); break;
00699 case 6:
00700 scene = TableScene();
00701 options.drawMatrix = false;
00702 options.cluster = true;
00703 break;
00704 case 7:
00705 scene = BoxScene(1); break;
00706 default:
00707 scene = LoadScene();
00708 options.drawMatrix = false;
00709 options.cluster = true;
00710 break;
00711 }
00712
00713 sceneSet = false;
00714 Reset();
00715 }
00716
00717 Void RadForm::DumpImage()
00718 {
00719 const Char *result;
00720 RGBAImage image;
00721 FileName imageFile;
00722
00723 result = fl_show_fselector("Saving main image...", 0, "*.tiff,*.tif,*.ppm",
00724 "radvis.tif");
00725 mainPane.Redraw();
00726
00727 if (result)
00728 {
00729 imageFile.SetPath(result);
00730 imageFile.MakeUnique();
00731 cout << "*** dumping image to " << result << endl;
00732
00733 #ifdef GCL_MESA
00734 MesaRenderer mr;
00735 RGBAImage hqImage;
00736 Int xsize = 400, ysize = 400;
00737
00738 image.SetSize(2 * xsize, 2 * ysize);
00739 hqImage.SetSize(xsize, ysize);
00740 mr.Init(image);
00741 mr.SetHeadlight(false);
00742 mr.SetDoubleSided(true);
00743 mr.SetBgColour(bgColour);
00744 mr.Clear().Draw(mainPane.ItsScene()).Show();
00745 image.DownSample(hqImage);
00746
00747 hqImage.Save(imageFile);
00748 #else
00749 mainPane.GetImage(image);
00750 image.Save(imageFile);
00751 #endif
00752 }
00753 }
00754
00755 Void RadForm::DumpObjFile()
00756 {
00757 const Char *result;
00758
00759 result = fl_show_fselector("Saving wavefront file...", 0, "*.obj,*.obj.gz",
00760 "radvis.obj");
00761 mainPane.Redraw();
00762
00763 if (result)
00764 {
00765 cout << "*** dumping wavefront file to " << result << endl;
00766
00767 radMethod->WriteObjFile(FileName().SetPath(result).MakeUnique().GetPath());
00768 }
00769 }
00770
00771 Void RadForm::DumpSLFile()
00772 {
00773 const Char *result;
00774
00775 result = fl_show_fselector("Saving SL file...", 0, "*.sl",
00776 "out.sl");
00777 mainPane.Redraw();
00778
00779 if (result)
00780 {
00781 cout << "*** dumping GCL 'SL' file to " << result << endl;
00782
00783 radMethod->WriteSLFile(result);
00784 }
00785 }
00786
00787 Void RadForm::DumpEPS()
00788 {
00789 const Char *result;
00790 ofstream fout;
00791
00792 result = fl_show_fselector("Saving main image...", 0, "*.eps", "radvis.eps");
00793
00794 if (result)
00795 {
00796 EPSRenderer eps;
00797 cout << "*** dumping eps file to " << result << endl;
00798
00799 eps.Attach(FileName().SetPath(result).MakeUnique().GetPath());
00800 eps.Clear().Draw(mainPane.ItsScene()).Show();
00801 }
00802 }
00803
00804 Void RadForm::DumpCamera()
00805 {
00806 const Char *result;
00807 ofstream fout;
00808
00809 result = fl_show_fselector(
00810 "Saving camera file...", 0, "*.cam", "out.cam");
00811
00812 if (result)
00813 {
00814 cout << "*** saving camera to " << result << endl;
00815 fout.open(result);
00816 if (fout)
00817 ((scCamera*) mainPane.ItsCamera())->Print(fout);
00818 else
00819 perror("Couldn't open output file");
00820 }
00821
00822
00823 }
00824
00825 Void RadForm::Event(FL_OBJECT *object)
00826 {
00827 // Handle UI events. This should be split out into (many) different
00828 // routines!
00829
00830 if (object == exitBtn)
00831 {
00832 // Our work here is done.
00833 fgs->SignalDone();
00834 }
00835 else if (object == goBtn)
00836 Go();
00837 else if (object == methodChoice)
00838 ChooseMethod();
00839 else if (object == resetBtn)
00840 Reset();
00841 else if (object == step)
00842 {
00843 options.step = true;
00844 options.pause = true;
00845 fl_set_button(pause, options.pause);
00846 }
00847 else if (object == sceneSelect)
00848 SceneSelect();
00849 else if (object == save)
00850 {
00851 switch(fl_get_menu(save))
00852 {
00853 case 1:
00854 DumpImage();
00855 break;
00856 case 2:
00857 DumpEPS();
00858 break;
00859 case 3:
00860 DumpSLFile();
00861 break;
00862 case 4:
00863 DumpObjFile();
00864 }
00865 }
00866 else if (
00867 object == gouraudBtn ||
00868 object == textureBtn ||
00869 object == wireFrame ||
00870 object == patchView ||
00871 object == funcView ||
00872 object == anchor ||
00873 object == animation
00874 )
00875 {
00876 // These are option-changing controls: we update the options and redraw
00877 // the scene in case it or the way of drawing it has changed.
00878
00879 GetFormOptions();
00880 mainPane.Redraw();
00881
00882 }
00883 if (object == methodOpts)
00884 {
00885 Int item = fl_get_menu(methodOpts);
00886 if (item == 9)
00887 {
00888 renderPanel.Show();
00889 return;
00890 }
00891
00892 GetFormOptions();
00893 }
00894 else if (
00895 object == patchSubdivs ||
00896 object == eltSubdivs
00897 )
00898 {
00899 // notify rad object that meshing parameters have changed
00900 UpdateRadScene();
00901 }
00902 else if (object == avar)
00903 {
00904 sceneSet = false;
00905 Reset();
00906
00907 // Show the avar panel
00908
00909 avarPanel.Show();
00910 if (avarPanel.scenePane == 0)
00911 {
00912 avarPanel.SetScene(scene);
00913 avarPanel.scenePane = &mainPane;
00914 scene->Set(avarPanel.avarList);
00915 avarPanel.Init();
00916 }
00917 }
00918 else if (object == examRad && mainPane.selPatch[0])
00919 {
00920 Examiner *newPlot = new Examiner;
00921
00922 newPlot->Show();
00923 newPlot->Init(*fgs, &mainPane);
00924 SamplePatch(newPlot->plot->samples);
00925 newPlot->plotPane.SetBgColour(bgColour);
00926 newPlot->plotPane.Redraw();
00927 }
00928 else if (object == examFF && mainPane.selPatch[0] && mainPane.selPatch[1])
00929 {
00930 Examiner *newPlot = new Examiner;
00931
00932 newPlot->Show();
00933 newPlot->Init(*fgs, &mainPane);
00934 newPlot->plotPane.SetBgColour(bgColour);
00935 SampleFF(newPlot->plot->samples);
00936 newPlot->plotPane.Redraw();
00937 }
00938 else if (object == ffShow)
00939 transPanel.Show();
00940 else if (object == msgPick)
00941 {
00942 if (mainPane.selPatch[0])
00943 my_activate(examRad);
00944 else
00945 my_deactivate(examRad);
00946
00947 if (mainPane.selPatch[0] && mainPane.selPatch[1])
00948 my_activate(examFF);
00949 else
00950 my_deactivate(examFF);
00951
00952 matrixPane.Redraw();
00953 }
00954 else if (object == help)
00955 StartHelp();
00956 else
00957 GetFormOptions();
00958 }
00959
00960
00961 // --- Options panel stuff ----------------------------------------------------
00962
00963
00964 Void TransportPanel::Event(FL_OBJECT *object)
00965 {
00966 // nice & simple -- just hide the form if 'OK' is
00967 // clicked.
00968
00969 if (object == dismiss)
00970 Hide();
00971 else
00972 parent->GetFormOptions();
00973 };
00974
00975 Void RenderPanel::Event(FL_OBJECT *object)
00976 {
00977 // nice & simple -- just hide the form if 'OK' is
00978 // clicked.
00979
00980 if (object == dismiss)
00981 Hide();
00982 else
00983 parent->GetFormOptions();
00984 };
00985
00986
00987 // --- Main -------------------------------------------------------------------
00988
00989
00990 Void RadForm::InitOptions(Int argc, Char **argv, RadControl &options,
00991 Char **scenePathP)
00992 {
00993 Int ndm, meshRnd, meshNonLin, tri1, tri2, vers, help, noFork;
00994 ArgForm *arg_format;
00995 Double grey, clr[3];
00996 Double meshComp = 0.1;
00997
00998 grey = -1.0;
00999 clr[0] = 0.4; clr[1] = 0.5; clr[2] = 0.6;
01000
01001 arg_format = arg_to_form(0,
01002 "[%S]", scenePathP, "Specify scene file",
01003 "-v", ARG_FLAG(&vers), "Print version & object info",
01004 "-h", ARG_FLAG(&help), "Help",
01005 "-noMatrix", ARG_FLAG(&ndm), "Turn off matrix display",
01006 "-bgr %F", &grey, "Set background grey level",
01007 "-bgc %F %F %F", clr, clr + 1, clr + 2, "Set colour background",
01008 "-meshComp %F", &meshComp, "Specify initial mesh complexity",
01009 "-meshRandom", ARG_FLAG(&meshRnd), "Vary the mesh density",
01010 "-meshNonLin", ARG_FLAG(&meshNonLin), "Mesh more heavily at edges",
01011 "-tri1", ARG_FLAG(&tri1), "Triangulate built-ins (1)",
01012 "-tri2", ARG_FLAG(&tri2), "Triangulate built-ins (2)",
01013 "-noFork", ARG_FLAG(&noFork), "Don't run in the background",
01014 0
01015 );
01016
01017 if (arg_parse_argv(argc, argv, arg_format) < 0 || help)
01018 {
01019 String usage;
01020
01021 usage.Printf("Usage: %s [options], where options are as follows:",
01022 argv[0]);
01023
01024 fprintf(stderr, "%s, Visualisation front end\n%s\n\n%s\n\n",
01025 RadGetVersion().CString(),
01026 "(c) Andrew Willmott <ajw+rad@cs.cmu.edu> 2000",
01027 usage.CString()
01028 );
01029 arg_form_print(arg_format);
01030 cerr << endl;
01031 SceneReader::PrintSupportedFormats(cerr);
01032 exit(1);
01033 }
01034
01035 if (vers)
01036 {
01037 cout << "Radvis version " << RadGetVersion() << endl;
01038 exit(1);
01039 }
01040
01041 #ifndef DEBUG
01042 if (!noFork && fork())
01043 exit(0);
01044 #endif
01045
01046 if (tri1)
01047 gQuadType = 1;
01048 else if (tri2)
01049 gQuadType = 2;
01050
01051 options.drawMatrix = !ndm;
01052 if (meshRnd)
01053 options.mesh = mesh_random;
01054 if (meshNonLin)
01055 options.mesh = mesh_nonlin;
01056
01057 scMRModel::SetComplexity(meshComp);
01058
01059
01060 if (grey >= 0.0)
01061 bgColour = cWhite * grey;
01062 else if (clr[0] >= 0.0)
01063 bgColour = Colour(clr[0], clr[1], clr[2]);
01064 }
01065
01066 Int RadForm::Main(Int argc, Char **argv)
01067 {
01068 Char *scenePath = 0;
01069
01070 InitOptions(argc, argv, options, &scenePath);
01071
01072 Show();
01073 Init(scenePath);
01074
01075 fgs->Run();
01076
01077 return(0);
01078 }
01079
01080 main(Int argc, Char **argv)
01081 {
01082 // 'cause this calls fl_initialise, it must be created before...
01083 FormsGraphicsSystem fgs(argc, argv);
01084 // the radForm object.
01085 RadForm radForm;
01086 radForm.fgs = &fgs;
01087
01088 // let's boogie.
01089 return(radForm.Main(argc, argv));
01090 }