00001 /* 00002 File: Viewer.cc 00003 00004 Function: Generic viewer for gcl library 00005 00006 Author(s): Andrew Willmott 00007 00008 Copyright: (c) 1995-2000, Andrew Willmott 00009 00010 Notes: 00011 */ 00012 00013 #include "cl/ArgParse.h" 00014 #include "gcl/GCLApp.h" 00015 #include "gcl/ScenePane.h" 00016 #include "gcl/EPSRenderer.h" 00017 #include "gcl/MRModel.h" 00018 #include "gcl/Readers.h" 00019 #include "gcl/Writers.h" 00020 #include "cl/Timer.h" 00021 #ifdef GCL_MESA 00022 #include "gcl/MesaRenderer.h" 00023 #endif 00024 00025 #include <unistd.h> 00026 00027 #define GCL_WATCH_FILE 00028 00029 #define DBG_COUT if (0) cerr 00030 00031 00032 // --- Viewer Pane ------------------------------------------------------------ 00033 00034 00035 enum SDCmd 00036 { 00037 sdNone, 00038 sdHelp, 00039 sdReload, 00040 sdNext, 00041 sdPrev, 00042 sdDumpEPS, 00043 sdDumpPic, 00044 sdDumpHQPic, 00045 sdDumpScene, 00046 sdDumpTree, 00047 sdDumpCMB, 00048 sdQuit 00049 }; 00050 00051 class DrawScenePane : public ScenePane 00052 { 00053 public: 00054 DrawScenePane(); 00055 00056 Void HandleKey(Char c); 00057 Void EndDrag(Coord end, Int modifiers); 00058 Void PrintSceneInfo(); 00059 Void TimeFrame(); 00060 00061 SDCmd command; 00062 Int hierSync; 00063 }; 00064 00065 DrawScenePane::DrawScenePane() : 00066 ScenePane(), 00067 command(sdNone), 00068 hierSync(false) 00069 { 00070 } 00071 00072 Void DrawScenePane::EndDrag(Coord end, Int modifiers) 00073 { 00074 ScenePane::EndDrag(end, modifiers); 00075 00076 if (hierSync && (modifiers & wmButton3)) 00077 { 00078 command = sdDumpTree; 00079 xgs->SignalDone(); 00080 } 00081 } 00082 00083 Void DrawScenePane::HandleKey(Char c) 00084 { 00085 Bool finished = true; 00086 00087 switch (c) 00088 { 00089 case 'h': 00090 case '?': 00091 command = sdHelp; 00092 break; 00093 case 'e': 00094 command = sdDumpEPS; 00095 break; 00096 case 'd': 00097 command = sdDumpPic; 00098 break; 00099 #ifdef GCL_MESA 00100 case 'D': 00101 command = sdDumpHQPic; 00102 break; 00103 #endif 00104 case 's': 00105 command = sdDumpScene; 00106 break; 00107 case '|': 00108 command = sdDumpTree; 00109 break; 00110 case 'B': 00111 command = sdDumpCMB; 00112 break; 00113 case 'r': 00114 command = sdReload; 00115 break; 00116 case ',': 00117 case 0x1D: 00118 command = sdPrev; 00119 break; 00120 case ' ': 00121 case '.': 00122 case 0x1C: 00123 command = sdNext; 00124 break; 00125 case 'q': 00126 case 0x1B: 00127 command = sdQuit; 00128 break; 00129 case 'i': 00130 PrintSceneInfo(); 00131 finished = false; 00132 break; 00133 case 't': 00134 TimeFrame(); 00135 finished = false; 00136 break; 00137 case 'c': 00138 itsCamera->PrintAvars(false); 00139 finished = false; 00140 break; 00141 case 'k': 00142 itsCamera->PrintAvars(true); 00143 finished = false; 00144 break; 00145 case 'R': 00146 // print radiance camera params 00147 { 00148 ItsCamera()->GetViewDirParams(); 00149 00150 Point lookFrom = ItsCamera()->position; 00151 Point lookDir = ItsCamera()->viewDir; 00152 Point lookUp = ItsCamera()->up; 00153 00154 printf("rview -vtv -vp %g %g %g -vd %g %g %g -vu %g %g %g -vh %g -vv %g -vo 0 -va 0 -vs 0 -vl 0\n", 00155 lookFrom[0], lookFrom[1], lookFrom[2], 00156 lookDir[0], lookDir[1], lookDir[2], 00157 lookUp[0], lookUp[1], lookUp[2], 00158 ItsCamera()->fov * 2.0, ItsCamera()->fov * 2.0 00159 ); 00160 } 00161 finished = false; 00162 break; 00163 00164 default: 00165 ScenePane::HandleKey(c); 00166 finished = false; 00167 } 00168 00169 if (finished) 00170 xgs->SignalDone(); 00171 } 00172 00173 Void DrawScenePane::PrintSceneInfo() 00174 { 00175 Int i; 00176 FindDecInfo decInfo; 00177 00178 ItsScene()->Decimate(decInfo, DecTris); 00179 00180 cout << "Scene info:" << endl; 00181 cout << " " << decInfo.numTris << " triangles" << endl; 00182 cout << " " << decInfo.numPolys << " polygons" << endl; 00183 00184 for (i = 0; i < models.NumModels(); i++) 00185 { 00186 if (models.Model(i)->clusters.NumItems() > 0) 00187 { 00188 cout << " Model " << i << " has " << models.Model(i)->currentClusters 00189 << " clusters out of " << models.Model(i)->faces.NumItems() 00190 << ", and " << models.Model(i)->rootClusters.NumItems() << " root clusters" << endl; 00191 } 00192 if (models.Model(i)->vertices.NumItems() > 0) 00193 cout << " Model " << i << " has " << models.Model(i)->currentFaces 00194 << " faces out of " << models.Model(i)->faces.NumItems() << endl; 00195 } 00196 } 00197 00198 Void DrawScenePane::TimeFrame() 00199 { 00200 ProgramTimer timer; 00201 Float time; 00202 Int i, count = 0; 00203 00204 cout << "timing redraw rate" << endl; 00205 timer.StartTimer(); 00206 cout << timer.GetTimer() << endl; 00207 00208 while (timer.GetTimer() < 10.0) 00209 { 00210 Clear().Draw(ItsScene()).Show(); 00211 count++; 00212 } 00213 00214 cout << timer.GetTimer() << endl; 00215 time = timer.GetTimer(); 00216 00217 timer.StartTimer(); 00218 cout << timer.GetTimer() << endl; 00219 for (i = 0; i < count; i++) 00220 ; 00221 cout << timer.GetTimer() << endl; 00222 time -= timer.GetTimer(); 00223 time /= count; 00224 00225 cout << "frame drawing time: " << time << " seconds" << endl; 00226 cout << "frames per second: " << 1.0 / time << endl; 00227 } 00228 00229 00230 // --- ViewerApp -------------------------------------------------------------- 00231 00233 00234 class ViewerApp : public GCLApp 00235 { 00236 public: 00237 00238 Void PrintKeys(); 00239 Void SetOptions(Int argc, Char **argv); 00240 Int Run(); 00241 Void DrawScene(); 00242 Void SetupModels(scScenePtr scene); 00243 00244 // options 00245 Char *output; 00246 Int window; 00247 Int ord; 00248 Int noFork; 00249 Double clusComp; 00250 Double meshComp; 00251 Int noLight; 00252 Int hierSync; 00253 00254 // fields 00255 XGraphicsSystem *xgs; 00256 DrawScenePane *displayPane; 00257 }; 00258 00259 Void ViewerApp::PrintKeys() 00260 { 00261 cout << "Viewer control:" << endl 00262 << " mouse 1 -- rotation" << endl 00263 << " shift+mouse 1 -- zoom" << endl 00264 << " mouse 2 -- translate x & y" << endl 00265 << " shift+mouse 2 -- translate z" << endl 00266 << " mouse 3 -- adjust scene complexity" << endl 00267 << endl 00268 << " . space - move on to next scene file" << endl 00269 << " , - move back to previous scene file" << endl 00270 << endl 00271 << " w - toggle wireframe" << endl 00272 << " 0 - turn off lighting" << endl 00273 << " 1 - turn on lighting" << endl 00274 << " ) - single-sided polygons" << endl 00275 << " ! - double-sided polygons" << endl 00276 << endl 00277 << " G - toggle grid" << endl 00278 << " A - toggle axes" << endl 00279 << " S - simplest model" << endl 00280 << " C - complex model" << endl 00281 << " F - toggle display of faces" << endl 00282 << " V - toggle visualisation of vertices/face clusters" << endl 00283 << " X - toggle colouring of face clusters" << endl 00284 << endl 00285 << " d - save image" << endl 00286 << " D - save super-sampled image" << endl 00287 << " s - save scene file" << endl 00288 << " e - save eps file" << endl 00289 << " i - print scene information" << endl 00290 << " c - save camera parameters" << endl 00291 << " q esc - quit" << endl 00292 << endl; 00293 } 00294 00295 Void ViewerApp::SetOptions(Int argc, Char **argv) 00296 { 00297 ArgForm *arg_format, *argForm2; 00298 Double grey, clr[3], defClr[3]; 00299 Int size; 00300 Int formats; 00301 Int keys; 00302 Int avgClus; 00303 00304 size = 400; 00305 xsize = -1; 00306 ysize = -1; 00307 output = 0; 00308 grey = 0.5; 00309 clr[0] = -1; 00310 defClr[0] = -1; 00311 clusComp = -1.0; 00312 meshComp = -1.0; 00313 00314 arg_format = arg_to_form(0, 00315 "", 00316 "Usage: slview file1 file2 ... [options]", 00317 "", ARG_SUBR(GetFileArgs), 00318 "", 00319 "-o %S", &output, 00320 "Set output file", 00321 "-bgr %F", &grey, 00322 "Set background grey level", 00323 "-bgc %F %F %F", clr, clr + 1, clr + 2, 00324 "Set colour background", 00325 "-defClr %F %F %F", defClr, defClr + 1, defClr + 2, 00326 "Set default model colour", 00327 "-noFork", ARG_FLAG(&noFork), 00328 "Don't fork into background.", 00329 "-avgClus", ARG_FLAG(&avgClus), 00330 "Colour parent clusters according to average of children.", 00331 "-set", ARG_SUBR(GetAvarArgs), 00332 "Set avar, e.g. -set light 0.5 height 0.2", 00333 "-clusComp %F", &clusComp, 00334 "Set face cluster complexity", 00335 "-meshComp %F", &meshComp, 00336 "Set model complexity", 00337 "-noLight", ARG_FLAG(&noLight), 00338 "Don't use headlight", 00339 "-hierSync", ARG_FLAG(&hierSync), 00340 "Keep hierarchy file in sync", 00341 "-controls", ARG_FLAG(&keys), 00342 "List keyboard and mouse controls", 00343 "-formats", ARG_FLAG(&formats), 00344 "List supported file formats", 00345 00346 // Output options 00347 "-size %d", &size, 00348 "Set window size", 00349 "-xysize %d %d", &xsize, &ysize, 00350 "Set output size", 00351 0); 00352 00353 argForm2 = arg_to_form(0, 00354 "-noScale", ARG_FLAG(&noScale), 00355 "Don't rescale scene.", 00356 "-zup", ARG_FLAG(&zUp), 00357 "z axis is up (default is y axis.)", 00358 "-zdown", ARG_FLAG(&zDown), 00359 "z axis is down", 00360 0); 00361 00362 arg_form_append(arg_format, argForm2); 00363 00364 if (argc == 1) 00365 { 00366 arg_form_print(arg_format); 00367 cout << endl; 00368 exit(0); 00369 } 00370 00371 if (arg_parse_argv(argc, argv, arg_format) < 0) 00372 exit(1); 00373 00374 if (formats) 00375 { 00376 SceneReader::PrintSupportedFormats(cout); 00377 Image::PrintSupportedFormats(cout); 00378 exit(0); 00379 } 00380 00381 if (keys) 00382 { 00383 PrintKeys(); 00384 exit(0); 00385 } 00386 00387 if (!avgClus) 00388 MRModel::sAvgClusColours = false; 00389 00390 if (clr[0] < 0) 00391 bgColour = cWhite * grey; 00392 else 00393 bgColour = Colour(clr[0], clr[1], clr[2]); 00394 00395 if (defClr[0] >= 0) 00396 scPrimitive::sDefaultColour = Colour(defClr[0], defClr[1], defClr[2]); 00397 00398 if (xsize < 0) 00399 xsize = size; 00400 if (ysize < 0) 00401 ysize = size; 00402 } 00403 00404 Int ViewerApp::Run() 00405 { 00406 if (numFiles < 1) 00407 return(1); 00408 00409 xgs = new XGraphicsSystem; 00410 slInit(); 00411 00412 #ifndef DEBUG 00413 if (!noFork && fork()) 00414 return(0); 00415 #endif 00416 00417 DrawScene(); 00418 00419 return(0); 00420 } 00421 00422 Void ViewerApp::SetupModels(scScenePtr scene) 00423 { 00424 Int i; 00425 00426 if (meshComp >= 0.0) 00427 scMRModel::SetComplexity(meshComp); 00428 else if (clusComp >= 0.0) 00429 { 00430 MRModelsFinder models; 00431 00432 scene->ApplyAction(models); 00433 00434 scMRModel::SetComplexity(clusComp); 00435 00436 for (i = 0; i < models.NumModels(); i++) 00437 { 00438 models.Model(i)->showFaces = false; 00439 models.Model(i)->showMeta = true; 00440 models.Model(i)->AdaptComplexity(clusComp); 00441 } 00442 } 00443 } 00444 00445 Void ViewerApp::DrawScene() 00446 { 00447 Int i, j; 00448 RGBAImage image; 00449 FileName sceneFile, outFile, saveFile; 00450 ofstream fout; 00451 Bool window = false, reload; 00452 00453 scene = 0; 00454 displayPane = new DrawScenePane(); 00455 displayPane->SetBgColour(bgColour); 00456 displayPane->hierSync = hierSync; 00457 itsScenePane = displayPane; 00458 00459 i = 0; 00460 reload = true; 00461 00462 while (displayPane->command != sdQuit) 00463 { 00464 if (reload) 00465 { 00466 delete scene; 00467 sceneFile.SetPath(files[i]); 00468 00469 ReadScene(sceneFile); 00470 if (!scene && !window) 00471 exit(1); 00472 00473 if (!itsCamera) 00474 { 00475 itsCamera = (scCamera*) scene->FindFirst(aCamera); 00476 if (!itsCamera) 00477 itsCamera = new scCamera; 00478 scene->Set(itsCamera); 00479 } 00480 00481 SetAvars(scene); 00482 SetupModels(scene); 00483 00484 if (output) 00485 outFile.SetPath(output); 00486 else 00487 { 00488 outFile = sceneFile; 00489 outFile.SetDir("."); 00490 outFile.SetExtension(""); 00491 } 00492 sceneFile.AddCompExt(); // add the compression extension so we 00493 // can watch the file 00494 } 00495 00496 // we do this here to avoid creating a window until we know we've 00497 // successfully read the file. 00498 if (!window) 00499 { 00500 xgs->CreateWindow(displayPane, files[0], 00501 xsize, ysize); 00502 displayPane->SetHeadlight(!noLight); 00503 window = true; 00504 } 00505 00506 if (reload) 00507 { 00508 displayPane->SetScene(scene); 00509 displayPane->SetTitle(files[i]); 00510 reload = false; 00511 } 00512 00513 // spin while the user manipulates the scene 00514 00515 #ifndef GCL_WATCH_FILE 00516 xgs->Run(); 00517 #else 00518 Long timeStamp; 00519 00520 displayPane->command = sdNone; 00521 timeStamp = sceneFile.GetTimeStamp(); 00522 00523 while (true) 00524 { 00525 xgs->RunFor(1.0); // check once a second 00526 if (displayPane->command != sdNone) 00527 break; 00528 00529 if (sceneFile.GetTimeStamp() > timeStamp) 00530 { 00531 displayPane->command = sdReload; 00532 break; 00533 } 00534 } 00535 #endif 00536 00537 switch (displayPane->command) 00538 { 00539 case sdQuit: 00540 break; 00541 case sdHelp: 00542 PrintKeys(); 00543 break; 00544 case sdReload: 00545 reload = true; 00546 break; 00547 case sdPrev: 00548 if (i > 0) 00549 i--; 00550 else 00551 i = numFiles - 1; 00552 reload = true; 00553 break; 00554 case sdNext: 00555 i++; 00556 if (i == numFiles) 00557 i = 0; 00558 reload = true; 00559 break; 00560 case sdDumpPic: 00561 saveFile = outFile; 00562 if (saveFile.GetExtension() == "") 00563 saveFile.SetExtension("tif"); 00564 saveFile.MakeUnique(); 00565 cout << "*** saving image to " << saveFile.GetPath() << endl; 00566 displayPane->GetImage(image); 00567 image.Save(saveFile); 00568 break; 00569 #ifdef GCL_MESA 00570 case sdDumpHQPic: 00571 { 00572 MesaRenderer mr; 00573 RGBAImage hqImage; 00574 00575 saveFile = outFile; 00576 if (saveFile.GetExtension() == "") 00577 saveFile.SetExtension("tif"); 00578 saveFile.MakeUnique(); 00579 cout << "*** saving high quality image to " << saveFile.GetPath() << endl; 00580 00581 image.SetSize(2 * xsize, 2 * ysize); 00582 hqImage.SetSize(xsize, ysize); 00583 mr.Init(image); 00584 mr.SetHeadlight(!noLight); 00585 mr.SetBgColour(bgColour); 00586 mr.Clear().Draw(displayPane->ItsScene()).Show(); 00587 image.DownSample(hqImage); 00588 hqImage.Save(saveFile); 00589 } 00590 break; 00591 #endif 00592 case sdDumpScene: 00593 saveFile = outFile; 00594 if (saveFile.GetExtension() == "") 00595 saveFile.SetExtension("sl"); 00596 saveFile.MakeUnique(); 00597 cout << "*** saving scene to " << saveFile.GetPath() << endl; 00598 SceneWriter().Save(displayPane->ItsScene(), saveFile); 00599 break; 00600 case sdDumpTree: 00601 saveFile = outFile; 00602 saveFile.SetExtension("hier"); 00603 // saveFile.MakeUnique(); 00604 cout << "*** saving .hier file to " << saveFile.GetPath() << endl; 00605 00606 if (displayPane->models.NumModels() > 0) 00607 displayPane->models.Model(0)->DumpFCH(saveFile.GetPath()); 00608 break; 00609 case sdDumpCMB: 00610 if (displayPane->models.NumModels() > 0) 00611 displayPane->models.Model(0)->WriteBinary(); 00612 break; 00613 case sdDumpEPS: 00614 EPSRenderer eps; 00615 00616 saveFile = outFile; 00617 saveFile.SetExtension("eps"); 00618 saveFile.MakeUnique(); 00619 cout << "*** saving EPS file to " << saveFile.GetPath() << endl; 00620 eps.itsPlot.level2 = true; 00621 eps.Attach(saveFile.GetPath()); 00622 eps.Clear().Draw(displayPane->ItsScene()).Show(); 00623 break; 00624 } 00625 } 00626 } 00627 00628 // ---------------------------------------------------------------------------- 00629 00630 main(Int argc, Char **argv) 00631 { 00632 ViewerApp app; 00633 00634 app.SetOptions(argc, argv); 00635 00636 return(app.Run()); 00637 }