multi.C

00001 #include <X11/Xlib.h>
00002 
00003 #include <GL/gl.h>
00004 #include <GL/glu.h>
00005 
00006 #include <string>
00007 #include <iostream>
00008 
00009 #include <archon/math/vector.H>
00010 
00011 #include <archon/util/options.H>
00012 #include <archon/util/text.H>
00013 #include <archon/util/thread.H>
00014 
00015 #include <archon/display/window.H>
00016 #include <archon/display/context.H>
00017 
00018 #include <archon/render/exception.H>
00019 #include <archon/render/conductor.H>
00020 
00021 namespace Archon
00022 {
00023   namespace Render
00024   {
00025     namespace Test
00026     {
00027       bool   opt_help            = false;
00028       int    opt_viewMode        = 2;
00029       double opt_frameRate       = 30;
00030       double opt_windowSize      = 1;
00031       double opt_detailLevel     = 1;
00032       bool   opt_directRendering = true;
00033 
00034       unsigned adjust(unsigned val, unsigned min, double f)
00035       {
00036         return std::max(static_cast<unsigned>(f*val), min);
00037       }
00038 
00039       unsigned adjustDetail(unsigned val, unsigned min)
00040       {
00041         return adjust(val, min, opt_detailLevel);
00042       }
00043 
00044       Ref<Conductor> oneThreadMono(Ref<Display::Visual> visual, Ref<Renderer> renderer)
00045       {
00046         Ref<Display::Window> window = visual->newWindow(100, 100,
00047                                                         adjust(1000, 10, opt_windowSize),
00048                                                         adjust(1000, 10, opt_windowSize),
00049                                                         "One thread monoscopic view");
00050 
00051         Ref<View> view = View::create(renderer);
00052 
00053         Ref<Viewport> viewport = Viewport::create(view);
00054         Ref<Screen  >   screen = Screen  ::create(view);
00055         Ref<Eye     >      eye = Eye     ::create(view);
00056         Ref<Clip    >     clip = Clip    ::create(view);
00057 
00058         screen->set(Vector3(0, 0, -2),
00059                     Vector3(1, 0, 0), Vector3(0, 1, 0), 1, 1);
00060 
00061         Ref<Conductor> conductor = Conductor::create();
00062         Ref<Pipe> pipe = conductor->addPipe(visual);
00063         pipe->addChannel(conductor, view, window,
00064                          viewport, screen, eye, clip);
00065         return conductor;
00066       }
00067 
00068 
00069       Ref<Conductor> twoThreadMono(Ref<Display::Visual> visual, Ref<Renderer> renderer)
00070       {
00071         Ref<Display::Window> window = visual->newWindow(100, 100,
00072                                                         adjust(1000, 10, opt_windowSize),
00073                                                         adjust(1000, 10, opt_windowSize),
00074                                                         "Two thread monoscopic view");
00075 
00076         Ref<View> view = View::create(renderer);
00077 
00078         Ref<Viewport>  leftViewport = Viewport::create(view);
00079         Ref<Viewport> rightViewport = Viewport::create(view);
00080         Ref<Screen>      leftScreen =   Screen::create(view);
00081         Ref<Screen>     rightScreen =   Screen::create(view);
00082         Ref<Eye>                eye =      Eye::create(view);
00083         Ref<Clip>              clip =     Clip::create(view);
00084 
00085         leftViewport->set(0, 0, 0.5, 1);
00086         rightViewport->set(0.5, 0, 0.5, 1);
00087 
00088         leftScreen->set(Vector3(-0.5, 0, -2),
00089                         Vector3(1, 0, 0), Vector3(0, 1, 0), 0.5, 1);
00090         rightScreen->set(Vector3(0.5, 0, -2),
00091                          Vector3(1, 0, 0), Vector3(0, 1, 0), 0.5, 1);
00092 
00093         Ref<Conductor> conductor = Conductor::create();
00094 
00095         Ref<Pipe>  leftPipe = conductor->addPipe(visual);
00096         Ref<Pipe> rightPipe = conductor->addPipe(visual);
00097 
00098         leftPipe->addChannel(conductor, view, window,
00099                              leftViewport, leftScreen, eye, clip);
00100         rightPipe->addChannel(conductor, view, window,
00101                               rightViewport, rightScreen, eye, clip);
00102 
00103         return conductor;
00104       }
00105 
00106 
00107       Ref<Conductor> oneThreadPaperStereo(Ref<Display::Visual> visual, Ref<Renderer> renderer)
00108       {
00109         Ref<Display::Window> window = visual->newWindow(100, 100,
00110                                                         adjust(1500, 10, opt_windowSize),
00111                                                         adjust(750, 10, opt_windowSize),
00112                                                         "One thread paper stereo: Use a piece of paper");
00113 
00114         Ref<View> view = View::create(renderer);
00115 
00116         Ref<Viewport>  leftViewport = Viewport::create(view);
00117         Ref<Viewport> rightViewport = Viewport::create(view);
00118         Ref<Screen>      leftScreen =   Screen::create(view);
00119         Ref<Screen>     rightScreen =   Screen::create(view);
00120         Ref<Eye>            leftEye =      Eye::create(view);
00121         Ref<Eye>           rightEye =      Eye::create(view);
00122         Ref<Clip>              clip =     Clip::create(view);
00123 
00124         leftViewport->set(0, 0, 0.5, 1);
00125         rightViewport->set(0.5, 0, 0.5, 1);
00126 
00127         leftEye->set(Vector3(-1.5/7, 0, 0));
00128         rightEye->set(Vector3(+1.5/7, 0, 0));
00129 
00130         leftScreen->set(Vector3(-0.5, 0, -2),
00131                         Vector3(1, 0, 0), Vector3(0, 1, 0), 0.5, 0.5);
00132         rightScreen->set(Vector3(0.5, 0, -2),
00133                          Vector3(1, 0, 0), Vector3(0, 1, 0), 0.5, 0.5);
00134 
00135         Ref<Conductor> conductor = Conductor::create();
00136 
00137         Ref<Pipe> pipe = conductor->addPipe(visual);
00138 
00139         pipe->addChannel(conductor, view, window,
00140                          leftViewport, leftScreen, leftEye, clip);
00141         pipe->addChannel(conductor, view, window,
00142                          rightViewport, rightScreen, rightEye, clip);
00143 
00144         return conductor;
00145       }
00146 
00147       Ref<Conductor> twoThreadPaperStereo(Ref<Display::Visual> visual, Ref<Renderer> renderer)
00148       {
00149         Ref<Display::Window> window = visual->newWindow(100, 100,
00150                                                         adjust(1500, 10, opt_windowSize),
00151                                                         adjust(750, 10, opt_windowSize),
00152                                                         "Two thread paper stereo: Use a piece of paper");
00153 
00154         Ref<View> view = View::create(renderer);
00155 
00156         Ref<Viewport>  leftViewport = Viewport::create(view);
00157         Ref<Viewport> rightViewport = Viewport::create(view);
00158         Ref<Screen>      leftScreen =   Screen::create(view);
00159         Ref<Screen>     rightScreen =   Screen::create(view);
00160         Ref<Eye>            leftEye =      Eye::create(view);
00161         Ref<Eye>           rightEye =      Eye::create(view);
00162         Ref<Clip>              clip =     Clip::create(view);
00163 
00164         leftViewport->set(0, 0, 0.5, 1);
00165         rightViewport->set(0.5, 0, 0.5, 1);
00166 
00167         leftEye->set(Vector3(-1.5/7, 0, 0));
00168         rightEye->set(Vector3(+1.5/7, 0, 0));
00169 
00170         leftScreen->set(Vector3(-0.5, 0, -2),
00171                         Vector3(1, 0, 0), Vector3(0, 1, 0), 0.5, 0.5);
00172         rightScreen->set(Vector3(0.5, 0, -2),
00173                          Vector3(1, 0, 0), Vector3(0, 1, 0), 0.5, 0.5);
00174 
00175         Ref<Conductor> conductor = Conductor::create();
00176 
00177         Ref<Pipe>  leftPipe = conductor->addPipe(visual);
00178         Ref<Pipe> rightPipe = conductor->addPipe(visual);
00179 
00180         leftPipe->addChannel(conductor, view, window,
00181                              leftViewport, leftScreen, leftEye, clip);
00182         rightPipe->addChannel(conductor, view, window,
00183                               rightViewport, rightScreen, rightEye, clip);
00184 
00185         return conductor;
00186       }
00187 
00188       Ref<Conductor> splitScreenStereo(Ref<Display::Visual> visual, Ref<Renderer> renderer)
00189       {
00190         Ref<Display::Window> window = visual->newWindow(100, 100,
00191                                                         adjust(1000, 10, opt_windowSize),
00192                                                         adjust(1000, 10, opt_windowSize),
00193                                                         "Split screen stereoscopic view");
00194 
00195         Ref<View> view = View::create(renderer);
00196 
00197         Ref<Viewport>  leftViewport = Viewport::create(view);
00198         Ref<Viewport> rightViewport = Viewport::create(view);
00199         Ref<Screen>          screen =   Screen::create(view);
00200         Ref<Eye>            leftEye =      Eye::create(view);
00201         Ref<Eye>           rightEye =      Eye::create(view);
00202         Ref<Clip>              clip =     Clip::create(view);
00203 
00204         leftViewport->set(0, 0, 0.5, 1);
00205         rightViewport->set(0.5, 0, 0.5, 1);
00206 
00207         leftEye->set(Vector3(-1.0/20, 0, 0));
00208         rightEye->set(Vector3(+1.0/20, 0, 0));
00209 
00210         Ref<Conductor> conductor = Conductor::create();
00211 
00212         Ref<Pipe>  leftPipe = conductor->addPipe(visual);
00213         Ref<Pipe> rightPipe = conductor->addPipe(visual);
00214 
00215         leftPipe->addChannel(conductor, view, window,
00216                              leftViewport, screen, leftEye, clip);
00217         rightPipe->addChannel(conductor, view, window,
00218                               rightViewport, screen, rightEye, clip);
00219 
00220         return conductor;
00221       }
00222 
00223       Ref<Conductor> dualWindowStereo(Ref<Display::Visual> visual, Ref<Renderer> renderer)
00224       {
00225         Ref<Display::Window> leftWindow = visual->newWindow(100, 100,
00226                                                             adjust(500, 10, opt_windowSize),
00227                                                             adjust(500, 10, opt_windowSize),
00228                                                             "Left eye of stereoscopic view");
00229         Ref<Display::Window> rightWindow = visual->newWindow(100, 100,
00230                                                              adjust(500, 10, opt_windowSize),
00231                                                              adjust(500, 10, opt_windowSize),
00232                                                              "Right eye of stereoscopic view");
00233 
00234         Ref<View> view = View::create(renderer);
00235 
00236         Ref<Viewport> viewport = Viewport::create(view);
00237         Ref<Screen>   screen   =   Screen::create(view);
00238         Ref<Eye>      leftEye  =      Eye::create(view);
00239         Ref<Eye>      rightEye =      Eye::create(view);
00240         Ref<Clip>     clip     =     Clip::create(view);
00241 
00242         leftEye->set(Vector3(-1.0/5, 0, 0));
00243         rightEye->set(Vector3(+1.0/5, 0, 0));
00244 
00245         screen->set(1, M_PI/4, 10);
00246 
00247         Ref<Conductor> conductor = Conductor::create();
00248 
00249         Ref<Pipe>  leftPipe = conductor->addPipe(visual);
00250         Ref<Pipe> rightPipe = conductor->addPipe(visual);
00251 
00252         leftPipe->addChannel(conductor, view, leftWindow,
00253                              viewport, screen, leftEye, clip);
00254         rightPipe->addChannel(conductor, view, rightWindow,
00255                               viewport, screen, rightEye, clip);
00256 
00257         return conductor;
00258       }
00259 
00260 
00261       struct MyRenderer: Renderer
00262       {
00263         MyRenderer(): w(0) {}
00264 
00265         double w;
00266 
00267         void initOpenGlContext()
00268         {
00269           GLfloat v[4];
00270           v[3] = 1;
00271 
00272           glEnable(GL_LIGHTING);
00273           glEnable(GL_LIGHT0);
00274           glEnable(GL_DEPTH_TEST);
00275           glEnable(GL_COLOR_MATERIAL);
00276 
00277           v[0] = v[1] = v[2] = 0.2;
00278           glLightfv(GL_LIGHT0, GL_AMBIENT, v);
00279 
00280           v[0] = v[1] = v[2] = 0.9;
00281           glLightfv(GL_LIGHT0, GL_DIFFUSE, v);
00282 
00283           v[0] = v[1] = v[2] = 0.8;
00284           glLightfv(GL_LIGHT0, GL_SPECULAR, v);
00285 
00286           glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
00287           glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
00288           glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
00289 
00290           v[0] = 0.9; v[1] = 0.9; v[2] = 0.9;
00291           glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, v);
00292 
00293           glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 32);
00294 
00295           glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
00296         }
00297 
00298         void render()
00299         {
00300           /*
00301           glDisable(GL_LIGHTING);
00302           glBegin(GL_QUADS);
00303 
00304           glColor3f(1, 0, 0);
00305           glVertex3f(-0.9, 0.4, -2);
00306           glVertex3f(-0.9, 0.3, -2);
00307           glVertex3f(-0.8, 0.3, -2);
00308           glVertex3f(-0.8, 0.4, -2);
00309 
00310           glColor3f(0, 1, 0);
00311           glVertex3f(-0.2, 0.4, -2);
00312           glVertex3f(-0.2, 0.3, -2);
00313           glVertex3f(-0.1, 0.3, -2);
00314           glVertex3f(-0.1, 0.4, -2);
00315 
00316           glColor3f(0, 0, 1);
00317           glVertex3f(-0.9, -0.3, -2);
00318           glVertex3f(-0.9, -0.4, -2);
00319           glVertex3f(-0.8, -0.4, -2);
00320           glVertex3f(-0.8, -0.3, -2);
00321 
00322           glColor3f(1, 1, 0);
00323           glVertex3f(-0.2, -0.3, -2);
00324           glVertex3f(-0.2, -0.4, -2);
00325           glVertex3f(-0.1, -0.4, -2);
00326           glVertex3f(-0.1, -0.3, -2);
00327 
00328           glEnd();
00329           glEnable(GL_LIGHTING);
00330           */
00331 
00332           glTranslated(0, 0, -6);
00333           glRotated(10, 1, 0, 0);
00334 
00335           GLfloat v[4];
00336           v[3] = 1;
00337 
00338           v[0] = 5; v[1] = 20; v[2] = -5;
00339           glLightfv(GL_LIGHT0, GL_POSITION, v);
00340 
00341           glRotated(w/M_PI*180, 0, 1, 0);
00342 
00343           GLUquadric *quadric = gluNewQuadric();
00344 
00345           glPushMatrix();
00346           glColor3f(0.1, 0.9, 0.9);
00347           glTranslated(0, 0, -16);
00348           gluCylinder(quadric, 0.2, 0.2, 1.6,
00349                       adjustDetail(50, 3), adjustDetail(25, 1));
00350           glPopMatrix();
00351 
00352           glPushMatrix();
00353           glColor3f(0.2, 0.2, 0.8);
00354           glTranslated(0, 0, -12.5);
00355           gluCylinder(quadric, 0.2, 0.2, 1.6,
00356                       adjustDetail(50, 3), adjustDetail(25, 1));
00357           glPopMatrix();
00358 
00359           glPushMatrix();
00360           glColor3f(0.9, 0.1, 0.9);
00361           glTranslated(0, 0, -9);
00362           gluCylinder(quadric, 0.2, 0.2, 1.6,
00363                       adjustDetail(50, 3), adjustDetail(25, 1));
00364           glPopMatrix();
00365 
00366           glPushMatrix();
00367           glColor3f(0.2, 0.2, 0.8);
00368           glTranslated(0, 0, -5.5);
00369           gluCylinder(quadric, 0.2, 0.2, 1.6,
00370                       adjustDetail(50, 3), adjustDetail(25, 1));
00371           glPopMatrix();
00372 
00373           glPushMatrix();
00374           glColor3f(0.9, 0.9, 0.1);
00375           glTranslated(0, 0, -2);
00376           gluCylinder(quadric, 0.2, 0.2, 1.6,
00377                       adjustDetail(50, 3), adjustDetail(25, 1));
00378           glPopMatrix();
00379 
00380           glPushMatrix();
00381           glColor3f(0.2, 0.2, 0.8);
00382           glTranslated(0, 0, 1.5);
00383           gluCylinder(quadric, 0.2, 0.2, 1.6,
00384                       adjustDetail(50, 3), adjustDetail(25, 1));
00385           glPopMatrix();
00386 
00387           glPushMatrix();
00388           glColor3f(0.8, 0.3, 0.3);
00389           glTranslated(-0.07, 0, -60.5);
00390           gluCylinder(quadric, 0.02, 0.02, 64,
00391                       adjustDetail(25, 3), adjustDetail(200, 1));
00392           glPopMatrix();
00393 
00394           glPushMatrix();
00395           glColor3f(0.8, 0.3, 0.3);
00396           glTranslated(+0.07, 0, -60.5);
00397           gluCylinder(quadric, 0.02, 0.02, 64,
00398                       adjustDetail(25, 3), adjustDetail(200, 1));
00399           glPopMatrix();
00400 
00401           gluDeleteQuadric(quadric);
00402         }
00403       };
00404 
00405       void measureFrameRate()
00406       {
00407         static Time next = Time::now() + Time(10.0);
00408         static double frames = 0;
00409 
00410         ++frames;
00411 
00412         while(Time::now() >= next)
00413         {
00414           cerr << "Frame rate (f/s): " << frames/10 << "\n";
00415           frames = 0;
00416           next += Time(10.0);
00417         }
00418       }
00419 
00420       int main(int argc, const char *argv[])
00421       {
00422         Options o;
00423 
00424         o.addSwitch("h", "help", opt_help, true,
00425                     "Describe the parameters");
00426         o.addConfig("m", "view-mode", opt_viewMode, opt_viewMode,
00427                     "0 for one thread mono, 1 for two thread mono, "
00428                     "2 for one thread paper stereo, 3 for two thread "
00429                     "paper stereo, 4 for split screen stereo and 5 for "
00430                     "dual window stereo.",
00431                     Options::wantArg_always, Options::range(0, 6));
00432         o.addConfig("f", "frame-rate", opt_frameRate, opt_frameRate,
00433                     "Upper limit on number of frames per second.",
00434                     Options::wantArg_always);
00435         o.addConfig("s", "window-size", opt_windowSize, opt_windowSize,
00436                     "A window size modifier 1 corresponds to normal size.",
00437                     Options::wantArg_always);
00438         o.addConfig("d", "detail-level", opt_detailLevel, opt_detailLevel,
00439                     "A detail level modifier, 1 corresponds to normal level of detail.",
00440                     Options::wantArg_always);
00441         o.addConfig("D", "direct-rendering", opt_directRendering, opt_directRendering,
00442                     "Attempt to establist direct rendering contexts to gain performance.",
00443                     Options::wantArg_always);
00444         
00445         if(o.processCommandLine(argc, argv))
00446         {
00447           cerr << "Try --help\n";
00448           return 1;
00449         }
00450   
00451         if(opt_help)
00452         {
00453           cout <<
00454             "Test Application for the Archon::Render library\n"
00455             "by Brian Kristiansen & Kristian Spangsege\n"
00456             "\n"
00457             "Synopsis: " << argv[0] << "\n"
00458             "\n"
00459             "Available options:\n";
00460           cout << o.list();
00461           return 0;
00462         }
00463 
00464         if(argc > 1)
00465         {
00466           cerr << "Too many aguments\n";
00467           cerr << "Try --help\n";
00468           return 1;
00469         }
00470 
00471         Ref<Display::Implementation> implementation = Display::getDefaultImplementation();
00472         Ref<Display::Connection> connection = implementation->newConnection();
00473         Ref<Display::Screen> screen = connection->getDefaultScreen();
00474         Ref<Display::Visual> visual = screen->chooseVisual();
00475 
00476         Ref<MyRenderer> myRenderer = new MyRenderer;
00477 
00478         Ref<Conductor> conductor =
00479           opt_viewMode == 0 ? oneThreadMono(visual, myRenderer) :
00480           opt_viewMode == 1 ? twoThreadMono(visual, myRenderer) :
00481           opt_viewMode == 2 ? oneThreadPaperStereo(visual, myRenderer) :
00482           opt_viewMode == 3 ? twoThreadPaperStereo(visual, myRenderer) :
00483           opt_viewMode == 4 ? splitScreenStereo(visual, myRenderer) :
00484           dualWindowStereo(visual, myRenderer);
00485 
00486         Time timePerFrame;
00487         timePerFrame.setNanoSeconds(long(1E9/opt_frameRate));
00488 
00489         Time t = Time::now();
00490         for(;;)
00491         {
00492           measureFrameRate();
00493 
00494           conductor->render();
00495 
00496           myRenderer->w += 2*M_PI/opt_frameRate/10;
00497 
00498           t += timePerFrame;
00499           Thread::sleepUntil(t);
00500         }
00501 
00502         return 0;
00503       }
00504     }
00505   }
00506 }
00507 
00508 int main(int argc, const char *argv[]) throw()
00509 {
00510   using namespace Archon::Utilities;
00511 
00512   std::set_unexpected(Exception::terminal<Archon::Render::exceptionCatchInfo>);
00513   std::set_terminate (Exception::terminal<Archon::Render::exceptionCatchInfo>);
00514 
00515   if(!XInitThreads()) ARCHON_THROW1(ResourceException, "Unable to enter thread safe X11 mode");
00516 
00517   return Archon::Render::Test::main(argc, argv);
00518 }

Generated on Sun Jul 30 22:55:43 2006 for Archon by  doxygen 1.4.4