$search
00001 /********************************************************************* 00002 * 00003 * Software License Agreement (BSD License) 00004 * 00005 * Copyright (c) 2011, Robert Bosch LLC. 00006 * All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 00012 * * Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * * Redistributions in binary form must reproduce the above 00015 * copyright notice, this list of conditions and the following 00016 * disclaimer in the documentation and/or other materials provided 00017 * with the distribution. 00018 * * Neither the name of the Robert Bosch nor the names of its 00019 * contributors may be used to endorse or promote products derived 00020 * from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00025 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00026 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00027 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00028 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00029 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00030 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00032 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00033 * POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 *********************************************************************/ 00036 00037 // needed by Visual C++ 00038 #define NOMINMAX 00039 00040 #include <QtGui/QtGui> 00041 #include <QtOpenGL/QtOpenGL> 00042 00043 #include <algorithm> 00044 00045 #include <iostream> 00046 #include <fstream> 00047 #include "vlr/glWidget.h" 00048 00049 namespace vlr { 00050 00051 GLWidget::GLWidget(QGLFormat glFormat, QWidget *parent) 00052 : QGLWidget(glFormat, parent), 00053 windowWidth(width()), windowHeight(height()), fps(DEFAULT_FPS), 00054 userDisplayFunction(NULL), userKeyboardFunction(NULL), userMouseFunction(NULL), userMotionFunction(NULL), 00055 zoomSensitivity(DEFAULT_ZOOM_SENSITIVITY), 00056 rotateSensitivity(DEFAULT_ROTATE_SENSITIVITY), 00057 moveSensitivity(DEFAULT_MOVE_SENSITIVITY), 00058 minZoomRange(DEFAULT_MIN_ZOOM_RANGE), 00059 cameraFov(DEFAULT_CAMERA_FOV), 00060 minClipRange(DEFAULT_MIN_CLIP_RANGE), 00061 maxClipRange(DEFAULT_MAX_CLIP_RANGE), 00062 refresh_required(true), gl_initialized_(false) 00063 { 00064 memcpy(ambientLight, ambientLightDefault, sizeof(ambientLightDefault)); 00065 memcpy(diffuseLight, diffuseLightDefault, sizeof(diffuseLightDefault)); 00066 memcpy(specularLight, specularLightDefault, sizeof(specularLightDefault)); 00067 memcpy(lightPosition, lightPositionDefault, sizeof(lightPositionDefault)); 00068 00069 cameraPose.state = IDLE; 00070 cameraPose.pan = 0; 00071 cameraPose.tilt = 0; 00072 cameraPose.distance = 10.0; 00073 cameraPose.xOffset = 0; 00074 cameraPose.yOffset = 0; 00075 cameraPose.zOffset = 0; 00076 00077 cameraPose.zoom = 1; 00078 cameraPose.warp_x = 1; 00079 cameraPose.warp_y = 1; 00080 } 00081 00082 GLWidget::~GLWidget() {} 00083 00084 QSize GLWidget::minimumSizeHint() const 00085 { 00086 return QSize(50, 50); 00087 } 00088 00089 QSize GLWidget::sizeHint() const 00090 { 00091 return QSize(400, 400); 00092 } 00093 00094 void GLWidget::resizeGL(int w, int h) 00095 { 00096 if(!gl_initialized_) {return;} 00097 00098 makeCurrent(); 00099 int tx = 0, ty = 0, tw = w, th = h; 00100 glViewport(tx, ty, tw, th); 00101 00102 windowWidth = tw; 00103 windowHeight = th; 00104 00105 init3DMode(tw, th, cameraFov, minClipRange, maxClipRange); 00106 requestRedraw(); 00107 } 00108 00109 void GLWidget::paintGL(void) 00110 { 00111 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 00112 refresh_required=false; 00113 } 00114 00115 void GLWidget::rotateCamera(double dx, double dy) 00116 { 00117 cameraPose.pan -= float(dx * rotateSensitivity); 00118 cameraPose.tilt += float(dy * rotateSensitivity); 00119 00120 if (cameraPose.tilt < 0) {cameraPose.tilt = 0;} 00121 else if (cameraPose.tilt > 89.0) {cameraPose.tilt = 89.0;} 00122 } 00123 00124 void GLWidget::zoomCamera(double dy) 00125 { 00126 cameraPose.distance -= float(dy * zoomSensitivity* cameraPose.distance); 00127 cameraPose.distance = float(std::max(double(cameraPose.distance), minZoomRange)); 00128 } 00129 00130 void GLWidget::moveCamera(double dx, double dy) 00131 { 00132 cameraPose.xOffset += float(-dy * cos(rad(cameraPose.pan)) *moveSensitivity* cameraPose.distance); 00133 cameraPose.yOffset += float(-dy * sin(rad(cameraPose.pan)) *moveSensitivity* cameraPose.distance); 00134 cameraPose.xOffset += float( dx * cos(rad(cameraPose.pan - 90.0)) *moveSensitivity 00135 * cameraPose.distance); 00136 cameraPose.yOffset += float(dx * sin(rad(cameraPose.pan - 90.0)) *moveSensitivity 00137 * cameraPose.distance); 00138 } 00139 00140 void GLWidget::setCameraParams(double zoomSensitivity_, double rotateSensitivity_, double moveSensitivity_, double minZoomRange_, 00141 double cameraFov, double minClipRange_, double maxClipRange_) 00142 { 00143 zoomSensitivity = zoomSensitivity_; 00144 rotateSensitivity = rotateSensitivity_; 00145 moveSensitivity = moveSensitivity_; 00146 minZoomRange = minZoomRange_; 00147 cameraFov = cameraFov; 00148 minClipRange = minClipRange_; 00149 maxClipRange = maxClipRange_; 00150 00151 requestRedraw(); 00152 } 00153 00154 void GLWidget::setInitialCameraPos(float pan, float tilt, float range, float xOffset, float yOffset, float zOffset) 00155 { 00156 cameraPose.pan = pan; 00157 cameraPose.tilt = tilt; 00158 cameraPose.distance = range; 00159 cameraPose.xOffset = xOffset; 00160 cameraPose.yOffset = yOffset; 00161 cameraPose.zOffset = zOffset; 00162 } 00163 00164 void GLWidget::initializeGL(void) 00165 { 00166 glEnable(GL_DEPTH_TEST); 00167 glShadeModel(GL_SMOOTH); 00168 glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); 00169 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); 00170 glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight); 00171 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); 00172 glEnable(GL_LIGHT0); 00173 glDisable(GL_LIGHTING); 00174 glEnable(GL_NORMALIZE); 00175 00176 connect(&timer, SIGNAL(timeout()), this, SLOT(redraw(void))); 00177 00178 timer.start(DISPLAY_REFRESH_DELAY_MS); 00179 gl_initialized_=true; 00180 } 00181 00182 void GLWidget::setDisplayFunction(DisplayFunction func) {userDisplayFunction = func;} 00183 00184 void GLWidget::setMouseFunction(MouseFunction func) {userMouseFunction = func;} 00185 00186 void GLWidget::setMotionFunction(MotionFunction func) {userMotionFunction = func;} 00187 00188 void GLWidget::requestRedraw() {refresh_required=true;} 00189 00190 void GLWidget::redraw() 00191 { 00192 if (refresh_required) 00193 { 00194 updateGL(); 00195 } 00196 } 00197 00198 void GLWidget::init3DMode(int w, int h, double& fovY, double& zNear, double& zFar) 00199 { 00200 glEnable(GL_DEPTH_TEST); 00201 glMatrixMode(GL_PROJECTION); 00202 glLoadIdentity(); 00203 gluPerspective(fovY, w / (float)h, zNear, zFar); 00204 glMatrixMode(GL_MODELVIEW); 00205 glLoadIdentity(); 00206 } 00207 00208 00209 void GLWidget::activate3DMode() 00210 { 00211 float cpan, ctilt, cameraX, cameraY, cameraZ; 00212 00213 /* setup camera view */ 00214 cpan = rad(cameraPose.pan); 00215 ctilt = rad(cameraPose.tilt); 00216 cameraX = cameraPose.distance * cos(cpan) * cos(ctilt); 00217 cameraY = cameraPose.distance * sin(cpan) * cos(ctilt); 00218 cameraZ = cameraPose.distance * sin(ctilt); 00219 00220 init3DMode(windowWidth, windowHeight, cameraFov, minClipRange, maxClipRange); 00221 00222 glViewport(0, 0, (GLsizei)windowWidth, (GLsizei)windowHeight); 00223 gluLookAt(cameraX + cameraPose.xOffset, cameraY + cameraPose.yOffset, cameraZ + cameraPose.zOffset, cameraPose.xOffset, 00224 cameraPose.yOffset, cameraPose.zOffset, 0, 0, 1); 00225 } 00226 00227 void GLWidget::activate2DMode() { 00228 glDisable(GL_DEPTH_TEST); 00229 glMatrixMode(GL_PROJECTION); 00230 glLoadIdentity(); 00231 // gluOrtho2D(0.0, (GLfloat)windowWidth, 0.0, (GLfloat)windowHeight); 00232 glOrtho(0.0, (GLfloat)windowWidth, 0.0, (GLfloat)windowHeight, -1000, 1000); 00233 glMatrixMode(GL_MODELVIEW); 00234 glLoadIdentity(); 00235 } 00236 void GLWidget::recenter() 00237 { 00238 cameraPose.xOffset = 0; 00239 cameraPose.yOffset = 0; 00240 cameraPose.zOffset = 0; 00241 } 00242 00243 void GLWidget::pickPoint(int mouseX, int mouseY, double *scene_x, double *scene_y) 00244 { 00245 double cx = windowWidth / 2.0; 00246 double cy = windowHeight / 2.0; 00247 double pan = rad(-90.0 - cameraPose.pan); 00248 double tilt = rad(90.0 - cameraPose.tilt); 00249 double d = cameraPose.distance; 00250 double f = cy / tan(rad(cameraFov / 2.0)); 00251 00252 double px = (mouseX - cx) * cos(tilt) * d /(cos(tilt) * f + sin(tilt) * mouseY - sin(tilt) * cy); 00253 double py = -(mouseY - cy) * d /(cos(tilt) * f + sin(tilt) * mouseY - sin(tilt) * cy); 00254 00255 // rotate by pan, add offset 00256 *scene_x = px * cos(pan) + py * sin(pan) + cameraPose.xOffset; 00257 *scene_y = -px * sin(pan) + py * cos(pan) + cameraPose.yOffset; 00258 } 00259 00260 void GLWidget::mousePressEvent(QMouseEvent* event) { 00261 lastMouseX = event->x(); 00262 lastMouseY = event->y(); 00263 } 00264 00265 void GLWidget::mouseReleaseEvent(QMouseEvent*) {} 00266 00267 void GLWidget::mouseMoveEvent(QMouseEvent *event) 00268 { 00269 int dx = event->x() - lastMouseX; 00270 int dy = event->y() - lastMouseY; 00271 00272 if (event->buttons() & Qt::LeftButton) {rotateCamera(dx, dy);} 00273 else if (event->buttons() & Qt::MidButton) {moveCamera(dx, dy);} 00274 else if (event->buttons() & Qt::RightButton) {zoomCamera(dy);} 00275 00276 if (userMotionFunction) {userMotionFunction(int(event->x()), int(event->y()));} 00277 lastMouseX = event->x(); 00278 lastMouseY = event->y(); 00279 00280 requestRedraw(); 00281 } 00282 00283 const float GLWidget::ambientLightDefault[4] = {0, 0, 0, 0}; 00284 const float GLWidget::diffuseLightDefault[4] = {1, 1, 1, 1}; 00285 const float GLWidget::specularLightDefault[4] = {1, 1, 1, 1}; 00286 const float GLWidget::lightPositionDefault[4] = {0, 0, 100, 0}; 00287 00288 00289 } // namespace vlr