/* * (c) LSIIT, UMR CNRS/UdS * Authors: O. Génevaux, F. Larue. * * See licence.txt for additional information. */ #ifndef GLVIEWER_H #define GLVIEWER_H #include "GLViewerDefs.h" #include "../GPU/GPU.h" #include "DisplayableInterface.h" #include #include #include "MetricGrid.h" #include "PickedPoint.h" #include "UIData.h" #include "Frustum.h" class InfoBarManager; class Panel; class GLVIEWER_API GLViewer : public QOpenGLWidget { Q_OBJECT /******************\ | Internal type(s) | \******************/ public: struct RenderState { DisplayDoF DoF; QVector3D focusPoint; float fovY; float distToFocusPoint; float nearPlaneFactor; float farPlaneFactor; float zNear; float zFar; QMatrix4x4 viewRotationMatrix; QMatrix4x4 lightRotationMatrix; bool isOrthographic; bool isWireframeEnabled; bool isLightingEnabled; bool isLightTrackingEnabled; bool isCullingEnabled; MetricGrid metricGrid2D; MetricGrid metricGrid3D; unsigned int pointSize; }; class GLVIEWER_API NavigationControl { GLViewer *m_Viewer; public: inline NavigationControl( GLViewer *viewer ) : m_Viewer(viewer) {} inline GLViewer* GetViewer() const { return m_Viewer; } virtual void mouseMoveEvent( double dx, double dy, QMouseEvent *evt ); virtual void wheelEvent( double delta, QWheelEvent* evt ); virtual void mouseDoubleClickEvent( QMouseEvent *evt ); virtual bool keyPressEvent( QKeyEvent *evt ); virtual void updateProjectionMatrix( QMatrix4x4 &m ); virtual void updateViewMatrix( QMatrix4x4 &m ); }; protected: class DisplayableInfo; typedef std::map FactoryMap; typedef std::list DisplayableList; typedef std::map PriorityMap; typedef std::map DisplayableMap; using TimeMeasurement = std::chrono::high_resolution_clock::time_point; class DisplayableInfo { QMatrix4x4 userTransform; QMatrix4x4 packingTransform; QMatrix4x4 fullTransform; public: void Initialize( DisplayableInterface *displayable, DisplayableList::iterator priorityPos, UIParamSet ¶ms ); inline void SetUserTransform( const QMatrix4x4& tr ) { userTransform = tr; fullTransform = tr * packingTransform; } inline void SetPackingTransform( const QMatrix4x4& tr ) { packingTransform = tr; fullTransform = userTransform * tr; } inline const QMatrix4x4& GetTransform() const { return fullTransform; } DisplayableInterface *displayable; QVector selectionMgr; SelectionManager* currentSelectionMgr; DisplayableList::iterator posInPriorityList; Box3f boundingBox; }; enum SelectionToolName { SELECTION_TOOL_DISK = 0, SELECTION_TOOL_BOX , SELECTION_TOOL_LASSO , SELECTION_TOOL_END , }; /*******************\ | Class variable(s) | \*******************/ protected: static const int PICKING_WIN_RADIUS = 5; static const char* s_PickingVPG; static const char* s_PickingFPG; static const char* s_ZBufferVPG; static const char* s_ZBufferFPG; static QString s_MetricGrid2DSuffix; static QString s_MetricGrid3DSuffix; static QImage s_Logos[4]; bool m_IsDemoModeEnabled = false; QImage m_CurrentLogos[4]; void updateDemoModeLogos(); void displayDemoModeLogos(); public: static QVector3D BgTopColor; static QVector3D BgBottomColor; static QVector3D CoolColor; static QVector3D WarmColor; static QVector3D LightColor; static QVector3D AmbientColor; static QVector3D SpecularColor; static float Ambient; static float Specular; static float Shininess; /********************\ | Member variable(s) | \********************/ protected: RenderState m_View; QList m_NavigationCtrl; float m_SpeedFactor; float m_CtrlSpeedFactor; float m_ShiftSpeedFactor; QPoint m_PrevMousePos; QPoint m_ClickMousePos; FactoryMap m_Factories; DisplayableMap m_Displayables; PriorityMap m_DisplayablesByPriority; DisplayableList m_AddingOrder; QVBoxLayout *m_DisplayOptionsLayout; InfoBarManager *m_InfoBarManager; QList m_AnimationStartingQueue; QList m_AnimationStoppingQueue; TimeMeasurement m_AnimationFrameTime; QMap m_ActiveAnimations; bool m_AnimationsRunningAtPreviousFrame; float m_AnimationFrameRate; bool m_PerformanceCounterEnabled; bool m_SelectionEnabled; SelectionToolName m_SelectionCurrentToolName; SelectionTool::Context m_SelectionContext; SelectionTool* m_SelectionCurrentTool; std::vector m_SelectionTools; GPU::Shader m_PickingShader; GPU::Shader m_ZBufferShader; GPU::Texture2D m_SelectionDepthTexture; GPU::FrameBuffer m_SelectionDepthBuffer; SelectionZBufferUpdateMode m_SelectionZBufferUpdateMode; DisplayableInfo *m_BelowCursor; // View related transformations. bool m_MustUpdateFocal; double m_Focal; bool m_MustUpdateProjectionMatrix; QMatrix4x4 m_ProjectionMatrix; QMatrix4x4 m_ProjectionMatrixInverse; bool m_MustUpdateViewMatrix; QMatrix4x4 m_ViewMatrix; QMatrix4x4 m_ViewMatrixInverse; QMatrix4x4 m_ViewRotationMatrixInverse; QMatrix4x4 m_ViewProjectionMatrix; QMatrix4x4 m_ViewProjectionMatrixInverse; Frustum m_Frustum; bool m_ChangeNearPlaneMode; bool m_ChangeFarPlaneMode; bool m_IsSelectionAllowed; bool m_IsCursorInside; /*****************************\ | Constructor(s) / destructor | \*****************************/ public: GLViewer( DisplayDoF dof, QWidget *parent = NULL, Qt::WindowFlags f = 0 ); GLViewer( DisplayDoF dof, const QSurfaceFormat &format, QWidget *parent = NULL, Qt::WindowFlags f = 0 ); virtual ~GLViewer(); /********************\ | Member function(s) | \********************/ protected: void initMetricGrids(); virtual void enterEvent( QEvent *evt ); virtual void leaveEvent( QEvent* evt ); virtual void mousePressEvent( QMouseEvent *evt ); virtual void mouseReleaseEvent( QMouseEvent *evt ); virtual void mouseMoveEvent( QMouseEvent *evt ); virtual void wheelEvent( QWheelEvent *evt ); virtual void mouseDoubleClickEvent( QMouseEvent *evt ); virtual void keyPressEvent( QKeyEvent *evt ); virtual void keyReleaseEvent( QKeyEvent *evt ); virtual bool event( QEvent *evt ); void setupScene(); virtual void releaseScene() {} void updateSelectionMode( const Qt::KeyboardModifiers &modifiers ); DisplayableMap::iterator removeDisplayable_Internal( DisplayableMap::iterator &dmapIt ); void displayLabel( DisplayableInterface *d ); inline void setLightRotationMatrix( const QMatrix4x4& m ) { m_View.lightRotationMatrix = m; update(); } void repackDisplayables(); void manageAnimations(); void findObjectUnderCursor( const QPoint& cursor ); void clearObjectUnderCursor(); QMatrix4x4 reframedProjection( float viewportX, float viewportY, float viewportW, float viewportH ); void processSelection( DisplayableInfo &dInfo, BaseSelectionProcessor &proc ); public: void init( DisplayDoF dof ); inline void getRenderState( RenderState& state ) const { state = m_View; } void setRenderState( const RenderState& state ); inline NavigationControl* navigationControl() const { return m_NavigationCtrl.empty()? NULL : m_NavigationCtrl.front(); } void pushNavigationControl( NavigationControl* ctrl ); void popNavigationControl(); void clearNavigationControlStack(); inline QVector2D screenPosToClipCoord( const QPoint &screenPos ) { return QVector2D( 2.0f*screenPos.x()/width()-1.0f, 1.0f-2.0f*screenPos.y()/height() ); } virtual void initializeGL(); void paintGL(); virtual void resizeGL( int width, int height ); void setSelectionAllowed( bool allowed ); inline bool isSelectionAllowed() const { return m_IsSelectionAllowed; } inline void setParametersDisplayed( bool displayed ) { ((QWidget*) m_DisplayOptionsLayout->parent())->setVisible( displayed ); } inline bool areParametersDisplayed() const { return ((QWidget*) m_DisplayOptionsLayout->parent())->isVisible(); } inline float speedFactor() const { return m_SpeedFactor; } inline float ctrlSpeedFactor() const { return m_CtrlSpeedFactor; } inline float shiftSpeedFactor() const { return m_ShiftSpeedFactor; } inline const QVector3D& focusPoint() const { return m_View.focusPoint; } inline float distToFocusPoint() const { return m_View.distToFocusPoint; } inline float fovY() const { return m_View.fovY; } inline bool isProjectionOrthographic() const { return m_View.isOrthographic; } inline double focal() const { return m_Focal; } inline float zNear() const { return m_View.zNear; } inline float zFar() const { return m_View.zFar; } inline float pointSize() const { return m_View.pointSize; } inline DisplayDoF dof() const { return m_View.DoF; } inline const QMatrix4x4& projectionMatrix() const { return m_ProjectionMatrix; } inline const QMatrix4x4& projectionMatrixInverse() const { return m_ProjectionMatrixInverse; } inline const QMatrix4x4& viewMatrix() const { return m_ViewMatrix; } inline const QMatrix4x4& viewMatrixInverse() const { return m_ViewMatrixInverse; } inline const QMatrix4x4& viewRotationMatrix() const { return m_View.viewRotationMatrix; } inline const QMatrix4x4& viewRotationMatrixInverse() const { return m_ViewRotationMatrixInverse; } QMatrix4x4 modelMatrix( const DisplayableInterface *d ) const; inline QMatrix4x4 modelMatrixInverse( const DisplayableInterface *d ) const { return modelMatrix(d).inverted(); } inline const QMatrix4x4& viewProjectionMatrix() const { return m_ViewProjectionMatrix; } inline const QMatrix4x4& viewProjectionMatrixInverse() const { return m_ViewProjectionMatrixInverse; } inline QMatrix4x4 modelViewMatrix( const DisplayableInterface *d ) const { return viewMatrix() * modelMatrix(d); } inline QMatrix4x4 modelViewMatrixInverse( const DisplayableInterface *d ) const { return modelViewMatrix(d).inverted(); } inline QMatrix4x4 MVPMatrix( const DisplayableInterface *d ) const { return viewProjectionMatrix() * modelMatrix(d); } inline QMatrix4x4 MVPMatrixInverse( const DisplayableInterface *d ) const { return MVPMatrix(d).inverted(); } inline QVector3D rightAxis() const { return viewMatrix().row(0).toVector3D(); } inline QVector3D topAxis() const { return viewMatrix().row(1).toVector3D(); } inline QVector3D frontAxis() const { return -viewMatrix().row(2).toVector3D(); } inline const Frustum& frustum() const { return m_Frustum; } inline QVector3D viewpointLocation() const { auto& R = viewMatrix(); return R.transposed().mapVector( -R.column(3).toVector3D() ); } void pixelRay( int px, int py, QVector3D &rayOrig, QVector3D &rayDir ) const; QMatrix4x4 viewportMatrix( bool flipY = false ) const; inline QMatrix4x4 normalMatrix( const DisplayableInterface *d ) const { QMatrix4x4 m = modelViewMatrix(d); m(0,3) = m(1,3) = m(2,3) = 0.0f; return m; } inline const QMatrix4x4& lightRotationMatrix() const { return m_View.lightRotationMatrix; } inline QVector3D lightDirection() const { return m_View.lightRotationMatrix.column(2).toVector3D(); } inline bool isLightingEnabled() const { return m_View.isLightingEnabled; } inline bool isWireframeEnabled() const { return m_View.isWireframeEnabled; } inline bool isCullingEnabled() const { return m_View.isCullingEnabled; } inline bool isLightTrackingEye() const { return m_View.isLightTrackingEnabled; } inline void clearAllFactories() { m_Factories.clear(); } void populateDisplayerFactories( DisplayableFactoryInterface *plugin ); void populateDisplayerFactories( QList &plugins ); inline bool isDisplayed( GenericUIData *m ) const { return m_Displayables.find(m) != m_Displayables.end(); } inline bool isAbleToDisplay( GenericUIData *m ) const { return m_Factories.find(m->GetTypeString()) != m_Factories.end(); } inline DisplayableFactoryInterface* getFactory( const QString &type ) { FactoryMap::iterator f=m_Factories.find(type); return f==m_Factories.end()? NULL : f->second; } inline const DisplayableFactoryInterface* getFactory( const QString &type ) const { FactoryMap::const_iterator f=m_Factories.find(type); return f==m_Factories.end()? NULL : f->second; } inline DisplayableInterface* getDisplayable( const GenericUIData* m ) { DisplayableMap::iterator d=m_Displayables.find(m); return d==m_Displayables.end()? NULL : d->second.displayable; } inline DisplayableInterface* getDisplayable( const GenericUIData* m ) const { DisplayableMap::const_iterator d=m_Displayables.find(m); return d==m_Displayables.end()? NULL : d->second.displayable; } virtual void updateDisplayable( GenericUIData *m, bool resetSelectionManagers = true ); inline const DisplayableMap& getDisplayables() const { return m_Displayables; } inline DisplayableMap& getDisplayables() { return m_Displayables; } bool isDisplayableValid( DisplayableInterface *d ) const; void setTransform( GenericUIData *m, const QMatrix4x4 &xf ); virtual bool getPickedPoint( const float x, const float y, PickedPoint &picked, bool accurate ); void frameBox( Box3f &box, const QMatrix4x4 *xf = NULL ); virtual void frameItem( GenericUIData* item ); virtual void frameItems( QList &items ); virtual void frameAll(); Box3f sceneBox() const; inline bool isSelectionEnabled() const { return m_SelectionEnabled; } inline const SelectionTool& currentSelectionTool() const { return *m_SelectionCurrentTool; } void processSelection( BaseSelectionProcessor &proc ); void processSelection( QList &procList ); void processSelection( GenericUIData *m, BaseSelectionProcessor &proc ); void processSelection( DisplayableInterface *d, BaseSelectionProcessor &proc ); QVector2D screenCoords( float x, float y, float z ) const; inline QVector2D screenCoords( const QVector3D &v ) const { return screenCoords(v.x(),v.y(),v.z()); } inline void renderText( const QVector2D &v, const QString &text, const QFont &font = QFont(), Qt::Alignment align = 0 ) { renderText(v.x(),v.y(),text,font,align); } inline void renderText( const QVector3D &v, const QString &text, const QFont &font = QFont(), Qt::Alignment align = 0 ) { renderText(screenCoords(v),text,font,align); } inline void renderText( float x, float y, float z, const QString &text, const QFont &font = QFont(), Qt::Alignment align = 0 ) { renderText(screenCoords(x,y,z),text,font,align); } void renderText( float x, float y, const QString &text, const QFont &font = QFont(), Qt::Alignment align = 0 ); bool imageOfCurrentDisplay( const GenericUIData *m, QImage &renderResult ); void updateSelection( QList< GenericUIData*> selectedItems ); /**************\ | QT signal(s) | \**************/ signals: void distToFocusPointChanged( const float d ); void fovYChanged( const float fovY ); void focusPointChanged( const QVector3D &p ); void viewRotationMatrixUpdated( const QMatrix4x4 &deltaRot ); void cullingToggled( const bool cullingEnabled ); void screenSpaceTranslation( const QVector2D &tra ); void wireframeToggled( const bool wireframeEnabled ); void lightingToggled( const bool lightingEnabled ); void lightTrackingToggled( const bool trackingEnabled ); void keyPressed( QKeyEvent *evt ); void dataSelected( GenericUIData *d, Qt::KeyboardModifiers modifiers ); void pointSizeChanged( unsigned int size ); /************\ | QT slot(s) | \************/ public slots: inline void mustUpdateFocal() { m_MustUpdateFocal = true; update(); } inline void mustUpdateProjectionMatrix() { m_MustUpdateProjectionMatrix = true; update(); } inline void mustUpdateViewMatrix() { m_MustUpdateViewMatrix = true; update(); } inline void emitScreenSpaceTranslation( const QVector2D& tr) { emit screenSpaceTranslation(tr); } inline void emitViewRotationMatrixUpdated( const QMatrix4x4 &r ) { emit viewRotationMatrixUpdated(r); } virtual DisplayableInterface* addDisplayable( GenericUIData *m ); virtual void removeDisplayable( GenericUIData *m ); virtual void removeAllDisplayables(); void centerView(); void setSpeedFactor( const float speedFactor, const float ctrlSpeedFactor, const float shiftSpeedFactor ); void setSpeedFactor( const float speedFactor ); void setCtrlSpeedFactor( const float ctrlSpeedFactor ); void setShiftSpeedFactor( const float shiftSpeedFactor ); void increasePointSize(); void decreasePointSize(); void setPointSize( unsigned int size ); void setFocusPoint( const QVector3D& p ); void setDistToFocusPoint( const float d ); void setViewRotationMatrix( const QMatrix4x4& m ); void setFovY( float fovY ); void setOrthographic( bool ortho ); void setSelectionEnabled( bool enabled ); void setSelectionDisabled( bool disabled ); void toggleSelection(); void updateSelectionZBuffer(); void setSelectionEntity( SelectableEntity entity ); void clearSelection( SelectableEntity entities ); void updateSelection( SelectionTool &tool ); void setCullingEnabled( const bool enabled ); void toggleCulling(); void setWireframeEnabled( const bool enabled ); void setLightingEnabled( const bool enabled ); void setLightTrackingEnabled( const bool enabled ); void toggleWireframe(); void toggleLighting(); void toggleLightTracking(); inline void registerAnimation( DisplayableInterface *anim ) { m_AnimationStartingQueue.push_back( anim ); update(); } inline void unregisterAnimation( DisplayableInterface *anim ) { m_AnimationStoppingQueue .push_back( anim ); update(); } inline void setMetricGrid2DSuffix( const QString& suffix ) { s_MetricGrid2DSuffix = suffix; } inline void setMetricGrid3DSuffix( const QString& suffix ) { s_MetricGrid3DSuffix = suffix; } void setDemoModeEnabled( bool enabled ); inline void setDemoModeDisabled( bool disabled ) { setDemoModeEnabled( !disabled ); } }; #endif //GLVIEWER_H