scene_view.C

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #include <GL/gl.h>
00021 
00022 #include <archon/math/vector.H>
00023 #include <archon/util/time.H>
00024 #include <archon/util/mutex.H>
00025 #include <archon/util/window.H>
00026 #include <archon/util/keyboard.H>
00027 #include <archon/util/mouse.H>
00028 #include <archon/util/color.H>
00029 #include <archon/util/mutex.H>
00030 #include <archon/util/text.H>
00031 
00032 #include <archon/x3d/server/x3d.H>
00033 #include <archon/x3d/server/server.H>
00034 
00035 #include <archon/3dconsole/exception.H>
00036 #include <archon/3dconsole/scene_view.H>
00037 
00038 #include <unistd.h>
00039 
00040 namespace Archon
00041 {
00042   using namespace Math;
00043   using namespace Utilities;
00044 
00045   namespace Console3d
00046   {
00047 
00048     void get_scene(const X3D::Scene *,
00049                    vector<pair<Vector3, const X3D::LightNode *> > &);
00050 
00051     class WindowQuitHandler: public Window::WindowHandler
00052     {
00053       bool &quitFlag;
00054 
00055     public:
00056       WindowQuitHandler(bool &quitFlag): quitFlag(quitFlag) {}
00057 
00058       void quit()
00059       {
00060         quitFlag = true;
00061       }
00062     };
00063 
00064     void drawDepthMarker(double depth)
00065     {
00066       const double d = 20;
00067 
00068       glDisable(GL_POINT_SMOOTH);
00069       glDisable(GL_LINE_SMOOTH);
00070       glPointSize(5);
00071       glLineWidth(1);
00072       glColor3f(1, 1, 1);
00073 
00074       glBegin(GL_POINTS);
00075       glVertex3f(0, 0, -depth);
00076       glEnd();
00077 
00078       for(int i=1; i<10; ++i)
00079       {
00080         glBegin(GL_LINE_LOOP);
00081 
00082         glVertex3f(+d*i, -d*i, -depth);
00083         glVertex3f(+d*i, +d*i, -depth);
00084         glVertex3f(-d*i, +d*i, -depth);
00085         glVertex3f(-d*i, -d*i, -depth);
00086 
00087         glEnd();
00088       }
00089     }
00090 
00091     static const char *defaultMouseCursorData[] =
00092     {
00093       //width height num_colors chars_per_pixel
00094       "    32    32        3            1",
00095       //colors
00096       "X c #000000",
00097       ". c #ffffff",
00098       "  c None",
00099       //pixels
00100       "                                ",
00101       "                                ",
00102       "                                ",
00103       "                                ",
00104       "                                ",
00105       "                                ",
00106       "        XX             XX       ",
00107       "       X..X           X..X      ",
00108       "       X...X         X...X      ",
00109       "        X...X       X...X       ",
00110       "         X...X     X...X        ",
00111       "          X...X   X...X         ",
00112       "           X...X X...X          ",
00113       "            X..X X..X           ",
00114       "             XX   XX            ",
00115       "                                ",
00116       "             XX   XX            ",
00117       "            X..X X..X           ",
00118       "           X...X X...X          ",
00119       "          X...X   X...X         ",
00120       "         X...X     X...X        ",
00121       "        X...X       X...X       ",
00122       "       X...X         X...X      ",
00123       "       X..X           X..X      ",
00124       "        XX             XX       ",
00125       "                                ",
00126       "                                ",
00127       "                                ",
00128       "                                ",
00129       "                                ",
00130       "                                ",
00131       "                                ",
00132       "16,15"
00133     };
00134 
00135     static const char *sensorMouseCursorData[] =
00136     {
00137       //width height num_colors chars_per_pixel
00138       "    32    32        3            1",
00139       //colors
00140       "X c #000000",
00141       ". c #ffffff",
00142       "  c None",
00143       //pixels
00144       "                                ",
00145       "                                ",
00146       "                                ",
00147       "                                ",
00148       "                                ",
00149       "              XXXXX             ",
00150       "            XX.....XX           ",
00151       "          XX..XXXXX..XX         ",
00152       "         X..X      XX..X        ",
00153       "        X..X         X..X       ",
00154       "        X.X           X.X       ",
00155       "       X.X             X.X      ",
00156       "       X.X             X.X      ",
00157       "      X.X       X       X.X     ",
00158       "      X.X      X.X      X.X     ",
00159       "      X.X     X...X     X.X     ",
00160       "      X.X      X.X      X.X     ",
00161       "      X.X       X       X.X     ",
00162       "       X.X             X.X      ",
00163       "       X.X             X.X      ",
00164       "        X.X           X.X       ",
00165       "        X..X         X..X       ",
00166       "         X..XX     XX..X        ",
00167       "          XX..XXXXX..XX         ",
00168       "            XX.....XX           ",
00169       "              XXXXX             ",
00170       "                                ",
00171       "                                ",
00172       "                                ",
00173       "                                ",
00174       "                                ",
00175       "                                ",
00176       "16,15"
00177     };
00178 
00179     struct ViewState
00180     {
00181       bool showDepthMarker;
00182 
00183       KeyboardEvents::Dispatcher *keyboardDispatcher;
00184       MouseEvents::Dispatcher *mouseDispatcher;
00185       Window *window;
00186       X3D::Viewer *viewer;
00187       string initialViewpointName;
00188       CoordSystem3x3 defaultViewpoint;
00189 
00190       Vector3 trackballPos;
00191       double trackballRadius;
00192       bool sensorMode;
00193       bool mousePositionChanged;
00194       Ref<Window::MouseCursor> defaultMouseCursor;
00195       Ref<Window::MouseCursor> sensorMouseCursor;
00196 
00197       ViewState(KeyboardEvents::Dispatcher *k,
00198                 MouseEvents::Dispatcher *m,
00199                 Window *w,
00200                 X3D::Viewer *viewer,
00201                 string initialViewpointName,
00202                 const CoordSystem3x3 &defaultViewpoint):
00203         showDepthMarker(false),
00204         keyboardDispatcher(k),
00205         mouseDispatcher(m),
00206         window(w),
00207         viewer(viewer),
00208         initialViewpointName(initialViewpointName),
00209         defaultViewpoint(defaultViewpoint),
00210         trackballRadius((window->getWidth() < window->getHeight() ?
00211                          window->getWidth() : window->getHeight())/2-1),
00212         sensorMode(false),
00213         mousePositionChanged(false),
00214         defaultMouseCursor(w->newMouseCursor(defaultMouseCursorData)),
00215         sensorMouseCursor(w->newMouseCursor(sensorMouseCursorData))
00216       {
00217       }
00218 
00223       Vector3 findTrackballPos(unsigned x, unsigned y)
00224       {
00225         Vector3 p(x-window->getWidth()/2.0, window->getHeight()/2.0-y, 0);
00226         p /= trackballRadius;
00227         double s = p.squareSum();
00228 
00229         // Clamp to sphere
00230         if(s>1)
00231         {
00232           p /= sqrt(s);
00233           s = 1;
00234         }
00235 
00236         p[2] = sqrt(1-s);
00237         return p;
00238       }
00239 
00240       void depthMarkerModeOn()
00241       {
00242         showDepthMarker = true;
00243         mouseDispatcher->setMode(4);
00244         keyboardDispatcher->setMode(1);
00245       }
00246 
00247       void depthMarkerModeOff()
00248       {
00249         showDepthMarker = false;
00250         mouseDispatcher->setMode(0);
00251         keyboardDispatcher->setMode(0);
00252       }
00253 
00254       void trackballMode(unsigned x, unsigned y, bool press)
00255       {
00256         mouseDispatcher->setMode(press ? 1 : 0);
00257         keyboardDispatcher->setMode(press ? 1 : 0);
00258         trackballPos = findTrackballPos(x, y);
00259       }
00260 
00261       void trackballDepthMode(unsigned x, unsigned y, bool press)
00262       {
00263         if(press)
00264         {
00265           if(showDepthMarker)
00266           {
00267             showDepthMarker = false;
00268             mouseDispatcher->setMode(0);
00269             keyboardDispatcher->setMode(0);
00270           }
00271           else
00272           {
00273             showDepthMarker = true;
00274             mouseDispatcher->setMode(4);
00275             keyboardDispatcher->setMode(1);
00276           }
00277         }
00278       }
00279 
00280       void trackballChangeDepthMode(unsigned x, unsigned y, bool press)
00281       {
00282         mouseDispatcher->setMode(press ? 5 : 4);
00283       }
00284 
00285       void travelMode(unsigned, unsigned, bool press)
00286       {
00287         mouseDispatcher->setMode(press ? 2 : 0);
00288         keyboardDispatcher->setMode(press ? 1 : 0);
00289       }
00290 
00291       void yawAndPitchMode(unsigned, unsigned, bool press)
00292       {
00293         mouseDispatcher->setMode(press ? 3 : 0);
00294         keyboardDispatcher->setMode(press ? 1 : 0);
00295       }
00296 
00297       void changeDepth(unsigned xAbs, unsigned yAbs, int xRel, int yRel)
00298       {
00299         viewer->setDepthOfRotation(viewer->getDepthOfRotation() + yRel);
00300       }
00301 
00306       void trackballRoll(unsigned xAbs, unsigned yAbs, int xRel, int yRel)
00307       {
00308         Vector3 p = findTrackballPos(xAbs, yAbs);
00309 
00310         if(p == trackballPos) return;
00311 
00312         Vector3 d = Vector3(0, 0, -viewer->getDepthOfRotation());
00313         CoordSystem3x3 &view = viewer->manipViewCoordSystem();
00314         view.translate(d);
00315         view.basis.rotate(Rotation3(normalize(trackballPos * p), -2*acos(dot(trackballPos, p))));
00316         view.translate(-d);
00317         trackballPos = p;
00318       }
00319 
00320       void travel(unsigned xAbs, unsigned yAbs, int xRel, int yRel)
00321       {
00322         //      double zRel = yRel * viewer->manipDepthOfRotation()/100;
00323 
00324         viewer->setDepthOfRotation(viewer->getDepthOfRotation() + yRel);
00325         CoordSystem3x3 &view = viewer->manipViewCoordSystem();
00326         view.translate(Vector3(0, 0, yRel));
00327       }
00328 
00329       void yawAndPitch(unsigned xAbs, unsigned yAbs, int xRel, int yRel)
00330       {
00331         CoordSystem3x3 &view = viewer->manipViewCoordSystem();
00332         view.basis.yaw(M_PI*xRel/1000);
00333         view.basis.pitch(M_PI*yRel/1000);
00334       }
00335 
00336       void resetViewpoint()
00337       {
00338         viewer->resetViewpoint(initialViewpointName, defaultViewpoint);
00339       }
00340 
00341       void disregardSensorsOn()
00342       {
00343         viewer->setDisregardSensors(true);
00344       }
00345 
00346       void disregardSensorsOff()
00347       {
00348         viewer->setDisregardSensors(false);
00349       }
00350 
00351       void sensorTrack(unsigned, unsigned, int, int)
00352       {
00353         mousePositionChanged = true;
00354       }
00355 
00356       void sensorActivate(unsigned, unsigned, bool press)
00357       {
00358         viewer->setPointingDeviceActive(press);
00359       }
00360 
00361       void toggleHeadLight()
00362       {
00363         viewer->setHeadLight(!viewer->getHeadLight());
00364       }
00365 
00366       void toggleShowLightSources()
00367       {
00368         viewer->setShowLightSources(!viewer->getShowLightSources());
00369       }
00370 
00371       void toggleWireframeMode()
00372       {
00373         viewer->setWireframeMode(!viewer->getWireframeMode());
00374       }
00375 
00376       void toggleEnableTexture()
00377       {
00378         viewer->setEnableTexture(!viewer->getEnableTexture());
00379       }
00380 
00381       void toggleShowNormals()
00382       {
00383         viewer->setShowNormals(!viewer->getShowNormals());
00384       }
00385 
00386       void toggleTextAsQuadsMode()
00387       {
00388         viewer->setTextAsQuadsMode(!viewer->getTextAsQuadsMode());
00389       }
00390 
00391       void toggleSeparateSpecularColorMode()
00392       {
00393         viewer->setSeparateSpecularColorMode(!viewer->getSeparateSpecularColorMode());
00394         cerr << "SeparateSpecularColor: " << viewer->getSeparateSpecularColorMode() << "\n";
00395       }
00396 
00397       void toggleLightModelLocalViewerMode()
00398       {
00399         viewer->setLightModelLocalViewerMode(!viewer->getLightModelLocalViewerMode());
00400         cerr << "LightModelLocalViewer: " << viewer->getLightModelLocalViewerMode() << "\n";
00401       }
00402     };
00403 
00404     void viewScene(Ref<X3D::Server> server,
00405                    string initialViewpointName,
00406                    const CoordSystem3x3 &viewCoordSystem,
00407                    double fieldOfView,
00408                    double depthOfRotation,
00409                    const Vector4 &backgroundColor,
00410                    int xResolution, int yResolution,
00411                    bool fullScreen,
00412                    bool showLightSources,
00413                    bool headLight,
00414                    bool wireframeMode,
00415                    bool enableTexture,
00416                    bool useMipmapedTextures,
00417                    bool showNormals,
00418                    bool textAsQuadsMode,
00419                    int subdivisionX,
00420                    int subdivisionY,
00421                    double frameRate)
00422     {
00423       bool quit = false;
00424       KeyboardEvents::Dispatcher kDisp(2);
00425 
00426       /*
00427        * Mouse modes
00428        *
00429        * mode  description    button 1         button 2          button 3
00430        * ----------------------------------------------------------------------
00431        *  0    default        trackball (1)    travel            yaw/pitch
00432        *                      depth marker (4) 
00433        *  1    trackball
00434        *  2    travel
00435        *  3    yaw/pitch
00436        *  4    depth marker   depth adjust (5)
00437        *                      default (0)
00438        *  5    depth adjust
00439        *  6    over sensor    activate
00440        * ----------------------------------------------------------------------
00441        */
00442       MouseEvents::Dispatcher mDisp(3, 7, 2);
00443       WindowQuitHandler windowQuitHandler(quit);
00444       Window window(xResolution, yResolution, 32, fullScreen, true,
00445                     &kDisp, &mDisp, &windowQuitHandler);
00446 
00447       X3D::Viewer viewer(server, xResolution, yResolution,
00448                          useMipmapedTextures,
00449                          initialViewpointName,
00450                          viewCoordSystem,
00451                          fieldOfView,
00452                          depthOfRotation,
00453                          backgroundColor,
00454                          subdivisionX, subdivisionY,
00455                          headLight,
00456                          showLightSources,
00457                          showNormals,
00458                          textAsQuadsMode,
00459                          wireframeMode, enableTexture);
00460 
00461       viewer.setInitialPointingDevicePosition2D(Vector2(window.getMouseX(), window.getMouseY()));
00462       window.discardEventQueue();
00463 
00464       ViewState state(&kDisp, &mDisp, &window, &viewer,
00465                       initialViewpointName, viewCoordSystem);
00466 
00467       window.setMouseCursor(state.defaultMouseCursor);
00468 
00469       KeyboardEvents::MethodCall<ViewState>
00470         kDepthMarker(&state,
00471                      &Console3d::ViewState::depthMarkerModeOn,
00472                      &Console3d::ViewState::depthMarkerModeOff);
00473       KeyboardEvents::VarAssign<bool> kQuit(quit, true, true);
00474       KeyboardEvents::MethodCall<ViewState> kResetViewpoint
00475         (&state, &ViewState::resetViewpoint, 0);
00476       KeyboardEvents::MethodCall<ViewState> kDisregardSensors
00477         (&state, &ViewState::disregardSensorsOn, &ViewState::disregardSensorsOff);
00478       KeyboardEvents::MethodCall<ViewState> kHeadLight
00479         (&state, &ViewState::toggleHeadLight, 0);
00480       KeyboardEvents::MethodCall<ViewState> kShowLightSources
00481         (&state, &ViewState::toggleShowLightSources, 0);
00482       KeyboardEvents::MethodCall<ViewState> kWireframeMode
00483         (&state, &ViewState::toggleWireframeMode, 0);
00484       KeyboardEvents::MethodCall<ViewState> kEnableTexture
00485         (&state, &ViewState::toggleEnableTexture, 0);
00486       KeyboardEvents::MethodCall<ViewState> kShowNormals
00487         (&state, &ViewState::toggleShowNormals, 0);
00488       KeyboardEvents::MethodCall<ViewState> kTextAsQuadsMode
00489         (&state, &ViewState::toggleTextAsQuadsMode, 0);
00490       KeyboardEvents::MethodCall<ViewState> kSeparateSpecularColorMode
00491         (&state, &ViewState::toggleSeparateSpecularColorMode, 0);
00492       KeyboardEvents::MethodCall<ViewState> kLightModelLocalViewerMode
00493         (&state, &ViewState::toggleLightModelLocalViewerMode, 0);
00494 
00495       kDisp.setHandler(key_z, &kDepthMarker, 0);
00496       kDisp.setHandler(key_escape, &kQuit, 0);
00497       kDisp.setHandler(key_space, &kDisregardSensors, 0);
00498       kDisp.setHandler(key_home, &kResetViewpoint, 0);
00499       kDisp.setHandler(key_h, &kHeadLight, 0);
00500       kDisp.setHandler(key_l, &kShowLightSources, 0);
00501       kDisp.setHandler(key_w, &kWireframeMode, 0);
00502       kDisp.setHandler(key_t, &kEnableTexture, 0);
00503       kDisp.setHandler(key_n, &kShowNormals, 0);
00504       kDisp.setHandler(key_e, &kTextAsQuadsMode, 0);
00505       kDisp.setHandler(key_f1, &kSeparateSpecularColorMode, 0);
00506       kDisp.setHandler(key_f2, &kLightModelLocalViewerMode, 0);
00507 
00508       MouseEvents::MotionMethod<ViewState>
00509         mTrackballRoll(&state, &Console3d::ViewState::trackballRoll);
00510       MouseEvents::MotionMethod<ViewState>
00511         mTravel(&state, &Console3d::ViewState::travel);
00512       MouseEvents::MotionMethod<ViewState>
00513         mYawAndPitch(&state, &Console3d::ViewState::yawAndPitch);
00514       MouseEvents::MotionMethod<ViewState>
00515         mChangeDepth(&state, &Console3d::ViewState::changeDepth);
00516       MouseEvents::MotionMethod<ViewState>
00517         mSensorTrack(&state, &Console3d::ViewState::sensorTrack);
00518       MouseEvents::ButtonMethod<ViewState>
00519         mTrackballMode(&state, &Console3d::ViewState::trackballMode);
00520       MouseEvents::ButtonMethod<ViewState>
00521         mTrackballDepthMode(&state, &Console3d::ViewState::trackballDepthMode);
00522       MouseEvents::ButtonMethod<ViewState>
00523         mTrackballChangeDepthMode(&state, &Console3d::ViewState::trackballChangeDepthMode);
00524       MouseEvents::ButtonMethod<ViewState>
00525         mTravelMode(&state, &Console3d::ViewState::travelMode);
00526       MouseEvents::ButtonMethod<ViewState>
00527         mYawAndPitchMode(&state, &Console3d::ViewState::yawAndPitchMode);
00528       MouseEvents::ButtonMethod<ViewState>
00529         mActivateSensor(&state, &Console3d::ViewState::sensorActivate);
00530 
00531       mDisp.setMulticlickLimit(0, 2);
00532 
00533       // Mode 0 (default)
00534       mDisp.setMotionHandler(&mSensorTrack, 0);
00535       mDisp.setButtonHandler(0, &mTrackballMode,      0, 1);
00536       mDisp.setButtonHandler(0, &mTrackballDepthMode, 0, 2);
00537       mDisp.setButtonHandler(1, &mTravelMode,         0, 1);
00538       mDisp.setButtonHandler(2, &mYawAndPitchMode,    0, 1);
00539 
00540       // Mode 1 (trackball)
00541       mDisp.setMotionHandler(&mTrackballRoll, 1);
00542 
00543       // Mode 2 (travel)
00544       mDisp.setMotionHandler(&mTravel, 2);
00545 
00546       // Mode 3 (yaw/pitch)
00547       mDisp.setMotionHandler(&mYawAndPitch, 3);
00548 
00549       // Mode 4 (depth marker)
00550       mDisp.setButtonHandler(0, &mTrackballChangeDepthMode, 4, 1);
00551       mDisp.setButtonHandler(0, &mTrackballDepthMode,       4, 2);
00552 
00553       // Mode 5 (depth adjust)
00554       mDisp.setMotionHandler(&mChangeDepth, 5);
00555 
00556       // Mode 6 (over sensor)
00557       mDisp.setMotionHandler(&mSensorTrack, 6);
00558       mDisp.setButtonHandler(0, &mActivateSensor, 6, 1);
00559 
00560 
00561       Time timePerFrame;
00562       timePerFrame.setNanoSeconds(long(1E9/frameRate));
00563 
00564       // A magic workaround for something that seems like a weird bug
00565       // in ATIs fglrx driver version 8.10.19.
00566       //glMatrixMode(GL_TEXTURE);
00567       //glScalef(1, 1, 1);
00568       //glMatrixMode(GL_MODELVIEW);
00569 
00570       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00571       glEnable(GL_BLEND);
00572 
00573       while(!quit)
00574       {
00575         Time start = Time::now();
00576 
00577         window.executeEventQueue(Time::now().getMilliSeconds());
00578 
00579         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
00580 
00581         glDisable(GL_LIGHTING);
00582         glDisable(GL_TEXTURE_2D);
00583 
00584         if(state.showDepthMarker)
00585         {
00586           glLoadIdentity();
00587           drawDepthMarker(viewer.getDepthOfRotation());
00588         }
00589 
00590         if(state.mousePositionChanged)
00591         {
00592           if(mDisp.getMode() == 0 || mDisp.getMode() == 6)
00593             viewer.setPointingDevicePosition2D(Vector2(window.getMouseX(),
00594                                                        window.getMouseY()));
00595           state.mousePositionChanged = false;
00596         }
00597 
00598         viewer.renderFrame();
00599 
00600         bool overOrDrag = viewer.getOverStatus() || viewer.getDragStatus();
00601 
00602         if(overOrDrag && mDisp.getMode() != 6)
00603         {
00604           window.setMouseCursor(state.sensorMouseCursor);
00605           mDisp.setMode(6);
00606           mDisp.setMulticlickLimit(0, 1);
00607           kDisp.setMode(1);
00608         }
00609         else if(!overOrDrag && mDisp.getMode() == 6)
00610         {
00611           window.setMouseCursor(state.defaultMouseCursor);
00612           mDisp.setMode(0);
00613           mDisp.setMulticlickLimit(0, 2);
00614           kDisp.setMode(0);
00615         }
00616 
00617         int e = glGetError();
00618         if(e) ARCHON_THROW1(InternalException, "GL error: "+Text::toString(e));
00619 
00620         window.swapBuffers();
00621 
00622         Time used = Time::now()-start;
00623         Thread::sleep(timePerFrame-used);
00624       }
00625     }
00626   }
00627 }

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