1 /*************************************************************************** 2 qgscameracontroller.h 3 -------------------------------------- 4 Date : July 2017 5 Copyright : (C) 2017 by Martin Dobias 6 Email : wonder dot sk at gmail dot com 7 *************************************************************************** 8 * * 9 * This program is free software; you can redistribute it and/or modify * 10 * it under the terms of the GNU General Public License as published by * 11 * the Free Software Foundation; either version 2 of the License, or * 12 * (at your option) any later version. * 13 * * 14 ***************************************************************************/ 15 16 #ifndef QGSCAMERACONTROLLER_H 17 #define QGSCAMERACONTROLLER_H 18 19 #include "qgis_3d.h" 20 21 #include <QPointer> 22 #include <QRect> 23 #include <Qt3DCore/QEntity> 24 25 namespace Qt3DInput 26 { 27 class QKeyEvent; 28 class QKeyboardDevice; 29 class QKeyboardHandler; 30 class QMouseEvent; 31 class QMouseDevice; 32 class QMouseHandler; 33 class QWheelEvent; 34 } 35 36 namespace Qt3DRender 37 { 38 class QCamera; 39 class QPickEvent; 40 } 41 42 #include "qgscamerapose.h" 43 44 class QDomDocument; 45 class QDomElement; 46 47 class QgsCameraPose; 48 class QgsTerrainEntity; 49 class QgsVector3D; 50 51 #define SIP_NO_FILE 52 53 /** 54 * \ingroup 3d 55 * \brief Object that controls camera movement based on user input 56 * \note Not available in Python bindings 57 * \since QGIS 3.0 58 */ 59 class _3D_EXPORT QgsCameraController : public Qt3DCore::QEntity 60 { 61 Q_OBJECT 62 Q_PROPERTY( Qt3DRender::QCamera *camera READ camera WRITE setCamera NOTIFY cameraChanged ) 63 Q_PROPERTY( QRect viewport READ viewport WRITE setViewport NOTIFY viewportChanged ) 64 public: 65 //! Constructs the camera controller with optional parent node that will take ownership 66 QgsCameraController( Qt3DCore::QNode *parent = nullptr ); 67 68 //! Returns camera that is being controlled camera()69 Qt3DRender::QCamera *camera() const { return mCamera; } 70 //! Returns viewport rectangle viewport()71 QRect viewport() const { return mViewport; } 72 73 /** 74 * Connects to object picker attached to terrain entity. Called internally from 3D scene. 75 * This allows camera controller understand how far from the camera is the terrain under mouse cursor. 76 * Also it allows adjustment of camera's view center to a point on terrain. 77 */ 78 void setTerrainEntity( QgsTerrainEntity *te ); 79 80 //! Assigns camera that should be controlled by this class. Called internally from 3D scene. 81 void setCamera( Qt3DRender::QCamera *camera ); 82 //! Sets viewport rectangle. Called internally from 3D canvas. Allows conversion of mouse coordinates. 83 void setViewport( QRect viewport ); 84 //! Called internally from 3D scene when a new frame is generated. Updates camera according to keyboard/mouse input 85 void frameTriggered( float dt ); 86 87 //! Move camera back to the initial position (looking down towards origin of world's coordinates) 88 void resetView( float distance ); 89 90 //! Sets camera to look down towards given point in world coordinate, in given distance from plane with zero elevation 91 void setViewFromTop( float worldX, float worldY, float distance, float yaw = 0 ); 92 93 //! Returns the point in the world coordinates towards which the camera is looking 94 QgsVector3D lookingAtPoint() const; 95 96 /** 97 * Sets the complete camera configuration: the point towards it is looking (in 3D world coordinates), the distance 98 * of the camera from the point, pitch angle in degrees (0 = looking from the top, 90 = looking from the side) and 99 * yaw angle in degrees. 100 * \since QGIS 3.4 101 */ 102 void setLookingAtPoint( const QgsVector3D &point, float distance, float pitch, float yaw ); 103 104 /** 105 * Sets camera pose 106 * \since QGIS 3.4 107 */ 108 void setCameraPose( const QgsCameraPose &camPose ); 109 110 /** 111 * Returns camera pose 112 * \since QGIS 3.4 113 */ cameraPose()114 QgsCameraPose cameraPose() const { return mCameraPose; } 115 116 /** 117 * Returns distance of the camera from the point it is looking at. 118 * \since QGIS 3.4 119 */ distance()120 float distance() const { return mCameraPose.distanceFromCenterPoint(); } 121 122 /** 123 * Returns pitch angle in degrees (0 = looking from the top, 90 = looking from the side). 124 * The angle should range from 0 to 180. 125 * \since QGIS 3.4 126 */ pitch()127 float pitch() const { return mCameraPose.pitchAngle(); } 128 129 /** 130 * Returns yaw angle in degrees. Yaw value of zero means the camera is pointing towards north. 131 * The angle should range from 0 to 360. 132 * \since QGIS 3.4 133 */ yaw()134 float yaw() const { return mCameraPose.headingAngle(); } 135 136 //! Writes camera configuration to the given DOM element 137 QDomElement writeXml( QDomDocument &doc ) const; 138 //! Reads camera configuration from the given DOM element 139 void readXml( const QDomElement &elem ); 140 141 //! Zoom the map by \a factor 142 void zoom( float factor ); 143 //! Tilt up the view by \a deltaPitch around the view center (camera moves) 144 void tiltUpAroundViewCenter( float deltaPitch ); 145 //! Rotate clockwise the view by \a deltaYaw around the view center (camera moves) 146 void rotateAroundViewCenter( float deltaYaw ); 147 //! Set camera heading to \a angle (used for rotating the view) 148 void setCameraHeadingAngle( float angle ); 149 //! Move the map by \a tx and \a ty 150 void moveView( float tx, float ty ); 151 152 private: 153 void rotateCamera( float diffPitch, float diffYaw ); 154 void updateCameraFromPose( bool centerPointChanged = false ); 155 156 signals: 157 //! Emitted when camera has been updated 158 void cameraChanged(); 159 //! Emitted when viewport rectangle has been updated 160 void viewportChanged(); 161 162 private slots: 163 void onPositionChanged( Qt3DInput::QMouseEvent *mouse ); 164 void onWheel( Qt3DInput::QWheelEvent *wheel ); 165 void onMousePressed( Qt3DInput::QMouseEvent *mouse ); 166 void onMouseReleased( Qt3DInput::QMouseEvent *mouse ); 167 void onKeyPressed( Qt3DInput::QKeyEvent *event ); 168 void onKeyReleased( Qt3DInput::QKeyEvent *event ); 169 void onPickerMousePressed( Qt3DRender::QPickEvent *pick ); 170 171 private: 172 //! Camera that is being controlled 173 Qt3DRender::QCamera *mCamera = nullptr; 174 //! used for computation of translation when dragging mouse 175 QRect mViewport; 176 //! height of terrain when mouse button was last pressed - for camera control 177 float mLastPressedHeight = 0; 178 179 QPointer<QgsTerrainEntity> mTerrainEntity; 180 181 //! Keeps definition of the camera's position and towards where it is looking 182 QgsCameraPose mCameraPose; 183 184 //! Last mouse position recorded 185 QPoint mMousePos; 186 187 //! Delegates mouse events to the attached MouseHandler objects 188 Qt3DInput::QMouseDevice *mMouseDevice = nullptr; 189 Qt3DInput::QKeyboardDevice *mKeyboardDevice = nullptr; 190 191 Qt3DInput::QMouseHandler *mMouseHandler = nullptr; 192 Qt3DInput::QKeyboardHandler *mKeyboardHandler = nullptr; 193 194 }; 195 196 #endif // QGSCAMERACONTROLLER_H 197