/* * QGLViewer.h * $Id: QGLViewer.h,v 1.10 2001/11/20 16:23:48 guenth Exp $ * * Copyright (C) 1999, 2000 Markus Janich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * As a special exception to the GPL, the QGLViewer authors (Markus * Janich, Michael Meissner, Richard Guenther, Alexander Buck and Thomas * Woerner) give permission to link this program with Qt (non-)commercial * edition, and distribute the resulting executable, without including * the source code for the Qt (non-)commercial edition in the source * distribution. * */ // Description : Class QGLViewer // Purpose : Abstract class of a OpenGL viewer #ifndef __QGLVIEWER_H_ #define __QGLVIEWER_H_ // Qt /////// #include #include #include #include #include // System /////////// #include // for exit()-calls and 'getenv()' #include // Own /////////// #include "QGLSignalWidget.h" #include "CCamera.h" #include "CBoundingBox3D.h" // Forward declarations ////////////////////////// class QHBoxLayout; class QFrame; class QCursor; class QIconSet; class QPixmap; class QStereoCtrl; // for Qt 2.x compatibility #if QT_VERSION < 300 #define Q_CHECK_PTR CHECK_PTR #endif /// Abstract baseclass for GLViewers /** * This is an abstract class which defines the interface for * any derived OpenGL-viewers. * * @author Markus Janich * */ class QGLViewer: public QFrame { Q_OBJECT public: ////////////////// // PUBLIC ENUMS // ////////////////// /** An enum type for the different types of projection. */ enum ProjectionMode { parallel, /**< stands for parallel projection. */ perspective /**< stands for perspective projection. */ }; /** An enum type for the different types of saved cameras. */ enum CameraType { CurrentCam = 1, /**< selects the currently used camera. */ HomeCam = 2, /**< selects the home camera. */ BothCams = 3 /**< selects both cameras. */ }; /** An enum type for possible stereo modes */ enum StereoMode { STEREO_ON, /**< stereo is supported and activated */ STEREO_OFF, /**< stereo is deactivated */ STEREO_SIMULATE /**< stereo not supported but simulated */ }; /** Last mode provided mainly for development of new stereo controls. This mode can only be active if the m_fAllowStereoSimulation flag is set to true by calling allowStereoSimulation(true) */ /** An enum type for framebuffers */ enum StereoBuffer { MONO, /**< standard framebuffer (GL_BACK) */ STEREO_LEFT, /**< left stereo buffer (GL_BACK_LEFT) */ STEREO_RIGHT /**< left stereo buffer (GL_BACK_RIGHT) */ }; //////////////////// // PUBLIC METHODS // //////////////////// /** * Default Constructor. */ QGLViewer(QWidget * parent=0, const char * name=0, const QGLWidget * shareWidget = 0, WFlags f=0, bool viewertype=true, const QGLFormat &format=QGLFormat::defaultFormat()); /** * Constructor including a camera for the home position box of the scene. * \par NOTE: The current camera will also be set to the given homecam. */ QGLViewer(const CCamera &homecam, QWidget * parent=0, const char * name=0, const QGLWidget * shareWidget = 0, WFlags f=0, bool viewertype=true, const QGLFormat &format=QGLFormat::defaultFormat()); /** * Constructor including a boundingbox of the scene. * \par NOTE: The current camera is determined according to the BBox. */ QGLViewer(const CBoundingBox3D &bbox, QWidget * parent=0, const char * name=0, const QGLWidget * shareWidget = 0, WFlags f=0, bool viewertype=true, const QGLFormat &format=QGLFormat::defaultFormat()); /** * Default Destructor. */ virtual ~QGLViewer() {}; /** Sets the refresh rate of the context. * If there are more refresh calls like sltUpdateView() do * they were dropped. */ void setRefreshRate(int nFramesPerSecond); /** Returns the current refresh rate in frames per second. */ int getRefreshRate() { return m_nRefreshRate; }; /** * Sets boundingbox of the entire scene and fits the scene * to the view area if 'fUpdate' is set to 'true'. * It also sets the given boundingbox to both cameras so you don't * have to do that explicitly. * This method should be used whenever the scene changes (in size). */ virtual void setBoundingBox(const CBoundingBox3D &cBBox,bool fUpdate=false); /** * Sets the specified camera(s) and updates the view if necessary. */ virtual void setCamera(const CCamera &cCamera, CameraType which=CurrentCam); /** * The currently valid viewing camera is returned. */ CCamera& getCamera() { return m_cCurrentCamera; }; /** * The the pointer to the currently valid viewing camera is returned. */ CCamera *getCameraPtr() { return &m_cCurrentCamera; }; /** * Returns the currently active projection mode. */ virtual ProjectionMode getProjectionMode() { return (m_cCurrentCamera.getCameraType() == CCamera::orthographic) ? parallel : perspective; }; /** * Sets the flag that identifies the viewer as "full viewer" or not. * It should be reimplemented in the derived class for full functionality. * A "full viewer" is a viewer that have some buttons, slider or * other things for manipulating the camera. * If it is not a "full viewer" it only have a QGLWidget for the output. */ virtual void setFullViewer(bool state) { m_fFullViewer = state; }; /** * Returns the the value of the flag. * @see setFullViewer() */ bool isFullViewer() { return m_fFullViewer; }; /** * Returns a pointer to the OpenGL drawing-area. */ QGLSignalWidget *getDrawArea() { return m_pQGLWidget; }; /** * Makes this viewer the current viewer for OpenGL operations. */ void makeCurrent() { m_pQGLWidget->makeCurrent(); } /** * Disables/enables mouse events over the draw area if * fFlag = false/true. */ virtual void enableMouseEvents(bool fFlag) { m_fHandleMouseEvents = fFlag; }; /** * Returns the current rendermode. The initial value is GL_RENDER. */ GLenum getRenderMode() { return m_eRenderMode; } /** * Returns the pointer to the popup menu. */ QPopupMenu *getMainMenu() { return m_pqPopupMenu; }; /** * Adds a menu entry to the popup menu. */ int insertItem(const QString &text, const QObject *receiver, const char *member) { return m_pqPopupMenu->insertItem(text, receiver, member); }; /** * Same as above but with support for icons. */ int insertItem(const QIconSet &icon, const QString &text, const QObject *receiver, const char *member) { return m_pqPopupMenu->insertItem(icon, text, receiver, member); }; /** * Same as above but with support for pixmaps. */ int insertItem(const QPixmap &pixmap, const QString &text, const QObject *receiver, const char *member) { return m_pqPopupMenu->insertItem(pixmap, text, receiver, member); }; /** * Add a submenu to the popup menu. */ int insertItem(const QString &text, QPopupMenu *pqPopup) { return m_pqPopupMenu->insertItem(text, pqPopup); }; /** * Same as above but with pixmap. */ int insertItem(const QPixmap &pixmap, QPopupMenu *pqPopup) { return m_pqPopupMenu->insertItem(pixmap, pqPopup); }; /** * Returns 'true' if the item with identifier 'nID' * is enabled or 'false' if it is disabled. */ bool isItemEnabled(int nID) { return m_pqPopupMenu->isItemEnabled(nID); }; /** * Enables the menu item with identifier 'nID' if 'fEnable' is 'true', * or disables the item if 'fEnable' is 'false'. */ void setItemEnabled(int nID, bool fEnable) { m_pqPopupMenu->setItemEnabled(nID, fEnable); }; /** * Returns 'true' if the item with identifier 'nID' * is checked or 'false' if it is not. */ bool isItemChecked(int nID) { return m_pqPopupMenu->isItemChecked(nID); }; /** * Checks the menu item with identifier 'nID' if 'fCheck' is 'true', * or unchecks the item if 'fEnable' is 'false'. */ void setItemChecked(int nID, bool fCheck) { m_pqPopupMenu->setItemChecked(nID, fCheck); }; /** * Enables or disables stereo simulation.
* \par NOTE: In this version of QGLViewer stereo only functions * on a SGI workstation with the 'setmon\ command. * Have a look on the slot 'sltToggleStereo' in the * source code. */ void allowStereoSimulation( bool flag ) { m_fAllowStereoSimulation = flag; } /** * Return the state of the stereo mode. * @see StereoMode */ StereoMode getStereoMode() { return m_stereoMode; } public slots: ////////////////// // PUBLIC SLOTS // ////////////////// /** * Makes a redraw of the scene. (It also calls the paint * function that is connected with the signal 'sigRedrawGL()' * of the viewer.) */ virtual void sltUpdateView() { m_fRefresh = true; }; /** * Toggles between stereo on and off (if available). * Initially stereo is disabled */ virtual void sltToggleStereo(); /** * Modify camera that the entire scene resides within * the currently defined view frustum. */ virtual void sltViewAll(); signals: ///////////// // SIGNALS // ///////////// /** * This signal is emitted if the projectionmode has changed. */ void sigProjModeToggled(); /** * This signal is emitted if the rendermode has changed * so that the application knows that it should render the * scene again but in the new rendermode. */ void sigRenderModeChanged(); /** * This signal is ONLY emitted if the viewer is in GL_SELECT-mode and * any mousebutton was pressed. It should be used to transfer * object selections over the viewer to the application. For that * connect this signal to a slot of your application which does * all the stuff to get selected object(s). *
NOTE: For other things implement the ManageMousePress()-method in your * class derived from the QGLViewer-class which will be called in GL_RENDER-mode !!! */ void sigSelected(QMouseEvent *pqEvent); /** * This signal is ONLY emitted if the viewer is in GL_SELECT-mode and * any mousebutton was released. Similar to sigSelected( int, int). *
NOTE: For other things implement the ManageMouseRelease()-method in your * class derived from the QGLViewer-class which will be called in GL_RENDER-mode !!! */ void sigReleased(QMouseEvent *pqEvent); /** * This signal is ONLY emitted if the viewer is in GL_SELECT-mode and * the mouse was moveed. Similar to sigSelected( int, int). *
NOTE: For other things implement the ManageMouseMove()-method in your * class derived from the QGLViewer-class which will be called in GL_RENDER-mode !!! */ void sigMoved(QMouseEvent *pqEvent); /** * This signal is once emitted if the widget will be showed * and before any drawing were done. It comes originally * from the QGLSignalWidget inside the viewer and is just * passed through. */ void sigInitGL(); /** * This signal is emitted if the scene should be redrawed. * It comes originally from the QGLSignalWidget inside the * viewer and is just passed through. */ void sigRedrawGL(); /** * This signal is emitted if the widget was resized and * the scene should be redrawed. It comes originally * from the QGLSignalWidget inside the viewer and is just * passed through. */ void sigResizeGL(int nWidth, int nHeight); /** * This signal is emitted if the ratio of the current * camera has changed by the viewer. The new ratio * is passed by the parameter. */ void sigRatioChanged(double rdRatio); /** * This signal is emitted if the fovy angle of the current * camera has changed by the viewer. The new fovy angle * is passed by the parameter. */ void sigFovyChanged(double rdFovy); protected slots: ///////////////////// // PROTECTED SLOTS // ///////////////////// /** * Sets up the PROJECTION matrix depending on the projectionmode. */ virtual void sltSetProjectionMode(); /** * Set home position * The current camera is copied to the home camera. */ virtual void sltSetHome(); /** * Current viewing position is replaced by home viewing position. */ virtual void sltGoHome(); /** * Viewing can be toggled between parallel or perspective projection. */ virtual void sltToggleProjectionMode(); /** * Toggles the current rendermode between GL_RENDER and GL_SELECT and * sets the right mousecursor. The initial value is GL_RENDER. */ virtual void sltToggleRenderMode(); /** * This slot is for managing drop events over the signal widget. * The original implementation only magages dropped * 'QCameraDrag'-classes by setting the current camera. */ virtual void sltManageDrop(QDropEvent *pqEvent); /** * This slot is for managing drag-enter events over the signal widget. * The original implementation only calls 'accept()' if the * dragged was of 'class QCameraDrag'. */ virtual void sltManageDragEnter(QDragEnterEvent *pqEvent); /** * This slot is for managing drag-enter events over the signal widget. * The original implementation does nothing. */ virtual void sltManageDragLeave(QDragLeaveEvent *pqEvent); private slots: /////////////////// // PRIVATE SLOTS // /////////////////// /** * Does some initial stuff (especially sets the viewport size * and the projection matrix) before calling the 'ResizeGl()' * function of the application by sending a 'sigResizeGL()' signal. */ void sltResizeGL(int w, int h); /** * Does some initial stuff (especially sets the projection matrix) * before calling the 'PaintGl()' function of the application by * sending a 'sigRedrawGL()' signal. */ void sltPaintGL(); /** * Switches the mousepressevents between the two rendermodes. */ void sltSwitchMousePress(QMouseEvent *event) { if (m_eRenderMode == GL_SELECT) { emit(sigSelected(event)); } else { if (m_fHandleMouseEvents) ManageMousePress(event); } }; /** * Switches the mousereleaseevents between the two rendermodes. */ void sltSwitchMouseRelease(QMouseEvent *event) { if (m_eRenderMode == GL_SELECT) { emit(sigReleased(event)); } else { if (m_fHandleMouseEvents) ManageMouseRelease(event); } }; /** * Switches the mousereleaseevents between the two rendermodes. */ void sltSwitchMouseMove(QMouseEvent *event) { if (m_eRenderMode == GL_SELECT) { emit(sigMoved(event)); } else { if (m_fHandleMouseEvents) ManageMouseMove(event); } }; /** * Pops up the menu. */ void sltPopMenu(QMouseEvent *pqEvent); protected: /////////////////////// // PROTECTED METHODS // /////////////////////// /** * Instantiates the QGLSignalWidget and place it in a QFrame. The pointer of * the QFrame can be read with the function getQFrame(), see below. */ virtual void initQFrame(const char * name, const QGLWidget * shareWidget, WFlags f, const QGLFormat &format=QGLFormat::defaultFormat()); /** * Get pointer to QFrame. * This is necessary for the viewers derived from this abstract viewer class. * Since this class does only provide a member QGLWidget placed in a QFrame but no * layout. The viewer derived from this class is responsable for the layout. */ QFrame *getQFrame() { return m_pQFrame; } /** * Sets the frustum in the current OpenGL context. It automatically * recognizes if mono view or stereo simulation is switched on. */ void setFrustum(StereoBuffer buffer = QGLViewer::MONO); /** Sets the frustum for mono view. */ void setFrustumMono(); /** Sets the left frustum for stereo simulation. */ void setFrustumStereoLeft(); /** Sets the right frustum for stereo simulation. */ void setFrustumStereoRight(); /** * Sets the 'LookAt' parameters just like the OpenGL * command 'gluLookAt(...)'. But before setting it * 'glLoadIdentity()' for the model view matrix is called. */ void setLookAt(); /** * Has to be implemented in the derived class if you want to handle * any mousemovementevents over the QGLSignalWidget. * \par NOTE: This function will be ONLY CALLED if the viewer is in GL_RENDER-mode. */ virtual void ManageMouseMove(QMouseEvent *) {}; /** * Has to be implemented in derived class if you want to handle * any mousebutton press-events over the QGLSignalWidget. * \par NOTE: This function will be ONLY CALLED if the viewer is in GL_RENDER-mode. */ virtual void ManageMousePress(QMouseEvent *) {}; /** * Has to be implemented in derived class if you want to handle * any mousebutton release-events over the QGLSignalWidget. * \par NOTE: This function will be ONLY CALLED if the viewer is in GL_RENDER-mode. */ virtual void ManageMouseRelease(QMouseEvent *) {}; /** * Reimplements the mouse-press event function * inherited from QWidget. */ virtual void mousePressEvent (QMouseEvent *pqEvent); /** This method is called by the timer and makes an * redraw if there are any pending updates. */ virtual void timerEvent(QTimerEvent *pqEvent) { if (m_fRefresh && ((QTimerEvent *)pqEvent)->timerId() == m_nTimerID) { m_pQGLWidget->updateGL(); m_fRefresh = false; } }; /** Implement keypress event. */ //virtual void keyPressEvent( QKeyEvent * ) {}; /** Implement paint event */ //virtual void paintEvent(QPaintEvent *) {}; /** Implement resize event */ //virtual void resizeEvent(QResizeEvent *) {}; /** Implement mouse-release event */ //virtual void mouseReleaseEvent (QMouseEvent *event) {}; /** Implement mouse-move event */ //virtual void mouseMoveEvent (QMouseEvent *event) {}; private: ///////////////////// // PRIVATE METHODS // ///////////////////// /** * Initializes the two possible mousecursors over the * drawarea. The files for the pixmaps are loaded from * the directory where the enviromentvariable QGLVIEWER_PIX * point to. if nothing is found one standardcursor is used. * \par NOTE: Must be called after 'm_pQGLWidget' was initialized !!! */ void initCursors(); /** * Initializes the popup menu. */ void initPopupMenu(); /** * Makes all necessary connects. */ void initConnects(); /** * Sets the viewplane resolution of the current- and homecamera * according to the resolution of the viewport. */ virtual void setVPRes( int nWidth, int nHeight ); /////////////////////// // PROTECTED MEMBERS // /////////////////////// protected: CCamera m_cCurrentCamera; CCamera m_cHomeCamera; GLenum m_eRenderMode; bool m_fFullViewer; // GUI stuff QFrame *m_pQFrame; QGLSignalWidget *m_pQGLWidget; QHBoxLayout *m_pQHBoxLayout; QPopupMenu *m_pqPopupMenu; // pointer to the popupmenu QBitmap m_qMovePix, m_qSelectPix, m_qMoveMaskPix, m_qSelectMaskPix; QCursor *m_pqMoveCursor, *m_pqSelectCursor; /* Stereo stuff */ StereoMode m_stereoMode; bool m_fAllowStereoSimulation; QStereoCtrl *m_pStereoCtrl; ///////////////////// // PRIVATE MEMBERS // ///////////////////// private: bool m_fRefresh, m_fHandleMouseEvents; int m_nRefreshRate, m_nTimerID; }; #endif // __QGLVIEWER_H_