00001 #include "winexam.h"
00002
00007 #include <glutm/glut.h>
00008
00009 #include <glt/matrix.h>
00010
00011 #include <cstddef>
00012 #include <cmath>
00013 #include <iostream>
00014 using namespace std;
00015
00016 GlutWindowExaminer::GlutWindowExaminer(const std::string &title,int width,int height,int x,int y,unsigned int displayMode)
00017 : GlutWindow(title,width,height,x,y,displayMode),
00018 _mouseZoom(true),
00019 _mousePan(true),
00020 _mouseRotate(true),
00021 _mouseMode(MODE_MOUSE_ONLY),
00022 _mouseLeft(false),
00023 _mouseMiddle(false),
00024 _mouseRight(false),
00025 _mouseX(0),
00026 _mouseY(0),
00027 _oldCursor(0)
00028 {
00029 glMatrixMode(GL_MODELVIEW);
00030 glLoadIdentity();
00031 }
00032
00033 GlutWindowExaminer::~GlutWindowExaminer()
00034 {
00035 }
00036
00037 bool &GlutWindowExaminer::mouseZoom() { return _mouseZoom; }
00038 bool &GlutWindowExaminer::mousePan() { return _mousePan; }
00039 bool &GlutWindowExaminer::mouseRotate() { return _mouseRotate; }
00040
00041 GlutWindowExaminer::MouseMode &GlutWindowExaminer::mouseMode() { return _mouseMode; }
00042
00043 Vector &GlutWindowExaminer::referencePoint() { return _referencePoint; }
00044
00045 bool
00046 GlutWindowExaminer::mousePressed() const
00047 {
00048 return _mouseLeft || _mouseMiddle || _mouseRight;
00049 }
00050
00051 Vector GlutWindowExaminer::xAxisOfRotation() const
00052 {
00053 return _viewMatrixInverse*VectorX - _viewMatrixInverse*Vector0;
00054 }
00055
00056 Vector GlutWindowExaminer::yAxisOfRotation() const
00057 {
00058 return _viewMatrixInverse*VectorY - _viewMatrixInverse*Vector0;
00059 }
00060
00061 Vector GlutWindowExaminer::axisOfRotation(const Vector &v) const
00062 {
00063 return _viewMatrixInverse*v - _viewMatrixInverse*Vector0;
00064 }
00065
00066 void GlutWindowExaminer::OnPreDisplay()
00067 {
00068 glMatrixMode(GL_MODELVIEW);
00069 glLoadIdentity();
00070 _viewMatrix.glMultMatrix();
00071 }
00072
00073 void GlutWindowExaminer::OnOpen()
00074 {
00075 GlutWindow::OnOpen();
00076 OnOrient(_viewMatrix,_viewMatrixInverse);
00077 }
00078
00079 void GlutWindowExaminer::OnClose()
00080 {
00081 GlutWindow::OnClose();
00082 }
00083
00084 void GlutWindowExaminer::OnReshape(int w, int h)
00085 {
00086 GlutWindow::OnReshape(w,h);
00087 _ortho.set(w,h);
00088 OnOrient(_viewMatrix,_viewMatrixInverse);
00089 }
00090
00091 void GlutWindowExaminer::OnKeyboard(unsigned char key, int x, int y)
00092 {
00093 bool draw = true;
00094
00095 switch (key)
00096 {
00097 case 'i': if (_mouseZoom) _viewMatrix = matrixScale(1.2) * _viewMatrix; break;
00098 case 'o': if (_mouseZoom) _viewMatrix = matrixScale(1.0/1.2) * _viewMatrix; break;
00099
00100 case 'g': if (_mousePan) _viewMatrix = _viewMatrix * matrixTranslate(VectorY* 0.1); break;
00101 case 'b': if (_mousePan) _viewMatrix = _viewMatrix * matrixTranslate(VectorY*-0.1); break;
00102 case 'n': if (_mousePan) _viewMatrix = _viewMatrix * matrixTranslate(VectorX*-0.1); break;
00103 case 'm': if (_mousePan) _viewMatrix = _viewMatrix * matrixTranslate(VectorX* 0.1); break;
00104 case 'f': if (_mousePan) _viewMatrix = _viewMatrix * matrixTranslate(VectorZ* 0.1); break;
00105 case 'v': if (_mousePan) _viewMatrix = _viewMatrix * matrixTranslate(VectorZ*-0.1); break;
00106
00107 case 'a': if (_mouseRotate) _viewMatrix = matrixRotate(xAxisOfRotation(),10.0) * _viewMatrix; break;
00108 case 'z': if (_mouseRotate) _viewMatrix = matrixRotate(xAxisOfRotation(),-10.0) * _viewMatrix; break;
00109 case 'x': if (_mouseRotate) _viewMatrix = matrixRotate(yAxisOfRotation(),10.0) * _viewMatrix; break;
00110 case 'c': if (_mouseRotate) _viewMatrix = matrixRotate(yAxisOfRotation(),-10.0) * _viewMatrix; break;
00111
00112 case 'q':
00113 case 27: close(); return;
00114
00115 default:
00116 GlutWindow::OnKeyboard(key,x,y);
00117 draw = false;
00118 }
00119
00120 if (draw)
00121 {
00122 _viewMatrixInverse = _viewMatrix.inverse();
00123 postRedisplay();
00124 OnOrient(_viewMatrix,_viewMatrixInverse);
00125 }
00126 }
00127
00128 void
00129 GlutWindowExaminer::OnSpecial(int key, int x, int y)
00130 {
00131 GlutWindow::OnSpecial(key,x,y);
00132
00133 bool draw = true;
00134
00135 switch (key)
00136 {
00137 case GLUT_KEY_HOME: _viewMatrix = Matrix(); break;
00138 default:
00139 draw = false;
00140 }
00141
00142 if (draw)
00143 {
00144 _viewMatrixInverse = _viewMatrix.inverse();
00145 postRedisplay();
00146 OnOrient(_viewMatrix,_viewMatrixInverse);
00147 }
00148 }
00149
00150 void GlutWindowExaminer::OnMenu(int value)
00151 {
00152 GlutWindow::OnMenu(value);
00153 }
00154
00155 void GlutWindowExaminer::OnMouse(int button, int state, int x, int y)
00156 {
00157
00158
00159 _mouseX = x;
00160 _mouseY = y;
00161
00162
00163
00164 if (!mousePressed())
00165 {
00166
00167
00168 _wasIdle = getIdle();
00169 setIdle(false);
00170 _oldCursor = getCursor();
00171 }
00172
00173
00174
00175 if (state==GLUT_UP)
00176 switch (button)
00177 {
00178 case GLUT_LEFT_BUTTON: _mouseLeft = false; break;
00179 case GLUT_MIDDLE_BUTTON: _mouseMiddle = false; break;
00180 case GLUT_RIGHT_BUTTON: _mouseRight = false; break;
00181 }
00182 else
00183 {
00184 _referencePoint = getReferencePoint(x,y,dragPos(x,y),_viewMatrix,_viewMatrixInverse);
00185
00186 switch (button)
00187 {
00188 case GLUT_LEFT_BUTTON: _mouseLeft = true; break;
00189 case GLUT_MIDDLE_BUTTON: _mouseMiddle = true; break;
00190 case GLUT_RIGHT_BUTTON: _mouseRight = true; break;
00191 }
00192 }
00193
00194
00195
00196 if (!mousePressed())
00197 {
00198 setIdle(_wasIdle);
00199 setCursor(_oldCursor);
00200 }
00201
00202
00203
00204 _dragPosPrev = dragPos(x,y);
00205 }
00206
00207 void GlutWindowExaminer::OnMotion(int x, int y)
00208 {
00209 bool changed = false;
00210
00211 const int dx = x - _mouseX;
00212 const int dy = y - _mouseY;
00213
00214 if (dx==0 && dy==0)
00215 return;
00216
00217 bool zoom = false;
00218 bool pan = false;
00219 bool rotate = false;
00220
00221 switch (_mouseMode)
00222 {
00223
00224
00225
00226
00227 default:
00228 case MODE_MOUSE_ONLY:
00229 zoom = _mouseZoom && (_mouseMiddle || (_mouseLeft && _mouseRight));
00230 pan = _mousePan && _mouseRight && !zoom;
00231 rotate = _mouseRotate && _mouseLeft && !zoom;
00232 break;
00233
00234
00235
00236
00237
00238 case MODE_MOUSE_RIGHT:
00239 zoom = _mouseZoom && _mouseRight && getCtrlModifier();
00240 pan = _mousePan && _mouseRight && getShiftModifier() && !zoom;
00241 rotate = _mouseRotate && _mouseRight && !zoom && !pan;
00242 break;
00243 }
00244
00245 if (zoom)
00246 {
00247
00248
00249 _viewMatrix =
00250 matrixTranslate(-_referencePoint) *
00251 matrixScale(exp(double(dy)*0.01)) *
00252 matrixTranslate(_referencePoint) *
00253 _viewMatrix;
00254
00255 setCursor(GLUT_CURSOR_UP_DOWN);
00256
00257 changed = true;
00258 }
00259 else
00260 if (rotate)
00261 {
00262
00263
00264 Vector axis;
00265 real angle = 0.0;
00266
00267 if (getAltModifier())
00268 {
00269
00270
00271
00272 axis = VectorZ;
00273 angle = -dy/(_viewport.height()+1.0)*720.0;
00274 }
00275 else
00276 {
00277
00278
00279
00280
00281 axis = xProduct(Vector(real(dx),real(-dy),0.0),VectorZ);
00282 angle = axis.length()/(_viewport.width()+1.0)*180.0;
00283 }
00284
00285 _viewMatrix =
00286 matrixTranslate(-_referencePoint) *
00287 matrixRotate(axisOfRotation(axis),angle) *
00288 matrixTranslate(_referencePoint) *
00289 _viewMatrix;
00290
00291 setCursor(GLUT_CURSOR_CYCLE);
00292
00293 changed = true;
00294 }
00295 else
00296 if (pan)
00297 {
00298
00299
00300 const Vector pos = dragPos(x,y);
00301
00302 if (getAltModifier())
00303 _viewMatrix = _viewMatrix * matrixTranslate(VectorZ*dy/_viewport.height()*(_ortho.zFar()-_ortho.zNear()));
00304 else
00305 _viewMatrix = _viewMatrix * matrixTranslate(pos-_dragPosPrev);
00306
00307 _dragPosPrev = pos;
00308
00309 setCursor(GLUT_CURSOR_CROSSHAIR);
00310
00311 changed = true;
00312 }
00313
00314
00315
00316 _mouseX = x;
00317 _mouseY = y;
00318
00319 if (changed)
00320 {
00321 _viewMatrixInverse = _viewMatrix.inverse();
00322 postRedisplay();
00323 OnOrient(_viewMatrix,_viewMatrixInverse);
00324 }
00325 }
00326
00327 Vector
00328 GlutWindowExaminer::dragPos(const int x,const int y) const
00329 {
00330
00331
00332
00333
00334 real wx = real(x-_viewport.x())/real(_viewport.width());
00335 real wy = real(y-_viewport.y())/real(_viewport.height());
00336
00337 wx = _ortho.left() + wx*(_ortho.right() -_ortho.left());
00338 wy = _ortho.top() + wy*(_ortho.bottom()-_ortho.top());
00339
00340 return Vector(wx,wy,_ortho.zNear());
00341 }
00342
00343 Vector
00344 GlutWindowExaminer::getReferencePoint(int x,int y,const Vector &pos,const Matrix &modelView,const Matrix &modelViewInverse) const
00345 {
00346 return Vector0;
00347 }
00348
00349 void
00350 GlutWindowExaminer::OnPassiveMotion(int x, int y)
00351 {
00352 }
00353
00354 void
00355 GlutWindowExaminer::OnOrient(const Matrix &viewing,const Matrix &inverse)
00356 {
00357 }