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 }