00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00094 " 32 32 3 1",
00095
00096 "X c #000000",
00097 ". c #ffffff",
00098 " c None",
00099
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
00138 " 32 32 3 1",
00139
00140 "X c #000000",
00141 ". c #ffffff",
00142 " c None",
00143
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
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
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
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
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
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
00541 mDisp.setMotionHandler(&mTrackballRoll, 1);
00542
00543
00544 mDisp.setMotionHandler(&mTravel, 2);
00545
00546
00547 mDisp.setMotionHandler(&mYawAndPitch, 3);
00548
00549
00550 mDisp.setButtonHandler(0, &mTrackballChangeDepthMode, 4, 1);
00551 mDisp.setButtonHandler(0, &mTrackballDepthMode, 4, 2);
00552
00553
00554 mDisp.setMotionHandler(&mChangeDepth, 5);
00555
00556
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
00565
00566
00567
00568
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 }