1 /*************************************************************************** 2 qgs3dmapscene.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 QGS3DMAPSCENE_H 17 #define QGS3DMAPSCENE_H 18 19 #include "qgis_3d.h" 20 21 #include <Qt3DCore/QEntity> 22 23 #include "qgsfeatureid.h" 24 #include "qgsshadowrenderingframegraph.h" 25 #include "qgsray3d.h" 26 #include "qgscameracontroller.h" 27 28 namespace Qt3DRender 29 { 30 class QRenderSettings; 31 class QCamera; 32 class QPickEvent; 33 class QObjectPicker; 34 } 35 36 namespace Qt3DLogic 37 { 38 class QFrameAction; 39 } 40 41 namespace Qt3DExtras 42 { 43 class QForwardRenderer; 44 class QSkyboxEntity; 45 } 46 47 class QgsAbstract3DEngine; 48 class QgsAbstract3DRenderer; 49 class QgsMapLayer; 50 class Qgs3DMapScenePickHandler; 51 class Qgs3DMapSettings; 52 class QgsTerrainEntity; 53 class QgsChunkedEntity; 54 class QgsSkyboxEntity; 55 class QgsSkyboxSettings; 56 class Qgs3DMapExportSettings; 57 class QgsShadowRenderingFrameGraph; 58 class QgsPostprocessingEntity; 59 class QgsChunkNode; 60 61 #define SIP_NO_FILE 62 63 /** 64 * \ingroup 3d 65 * \brief Entity that encapsulates our 3D scene - contains all other entities (such as terrain) as children. 66 * \note Not available in Python bindings 67 * \since QGIS 3.0 68 */ 69 class _3D_EXPORT Qgs3DMapScene : public Qt3DCore::QEntity 70 { 71 Q_OBJECT 72 public: 73 //! Constructs a 3D scene based on map settings and Qt 3D renderer configuration 74 Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine *engine ); 75 76 //! Returns camera controller cameraController()77 QgsCameraController *cameraController() { return mCameraController; } 78 //! Returns terrain entity (may be temporarily NULLPTR) terrainEntity()79 QgsTerrainEntity *terrainEntity() { return mTerrain; } 80 81 //! Resets camera view to show the whole scene (top view) 82 void viewZoomFull(); 83 84 //! Returns number of pending jobs of the terrain entity 85 int terrainPendingJobsCount() const; 86 87 /** 88 * Returns number of pending jobs for all chunked entities 89 * \since QGIS 3.12 90 */ 91 int totalPendingJobsCount() const; 92 93 //! Enumeration of possible states of the 3D scene 94 enum SceneState 95 { 96 Ready, //!< The scene is fully loaded/updated 97 Updating, //!< The scene is still being loaded/updated 98 }; 99 100 //! Returns the current state of the scene sceneState()101 SceneState sceneState() const { return mSceneState; } 102 103 //! Registers an object that will get results of pick events on 3D entities. Does not take ownership of the pick handler. Adds object picker components to 3D entities. 104 void registerPickHandler( Qgs3DMapScenePickHandler *pickHandler ); 105 //! Unregisters previously registered pick handler. Pick handler is not deleted. Also removes object picker components from 3D entities. 106 void unregisterPickHandler( Qgs3DMapScenePickHandler *pickHandler ); 107 108 /** 109 * Given screen error (in pixels) and distance from camera (in 3D world coordinates), this function 110 * estimates the error in world space. Takes into account camera's field of view and the screen (3D view) size. 111 */ 112 float worldSpaceError( float epsilon, float distance ); 113 114 //! Exports the scene according to the scene export settings 115 void exportScene( const Qgs3DMapExportSettings &exportSettings ); 116 117 /** 118 * Returns the active chunk nodes of \a layer 119 * 120 * \since QGIS 3.18 121 */ 122 QVector<const QgsChunkNode *> getLayerActiveChunkNodes( QgsMapLayer *layer ) SIP_SKIP; 123 124 /** 125 * Returns the scene extent in the map's CRS 126 * 127 * \since QGIS 3.20 128 */ 129 QgsRectangle sceneExtent(); 130 signals: 131 //! Emitted when the current terrain entity is replaced by a new one 132 void terrainEntityChanged(); 133 //! Emitted when the number of terrain's pending jobs changes 134 void terrainPendingJobsCountChanged(); 135 136 /** 137 * Emitted when the total number of pending jobs changes 138 * \since QGIS 3.12 139 */ 140 void totalPendingJobsCountChanged(); 141 //! Emitted when the scene's state has changed 142 void sceneStateChanged(); 143 144 //! Emitted when the FPS count changes 145 void fpsCountChanged( float fpsCount ); 146 //! Emitted when the FPS counter is activated or deactivated 147 void fpsCounterEnabledChanged( bool fpsCounterEnabled ); 148 149 public slots: 150 //! Updates the temporale entities 151 void updateTemporal(); 152 153 private slots: 154 void onCameraChanged(); 155 void onFrameTriggered( float dt ); 156 void createTerrain(); 157 void onLayerRenderer3DChanged(); 158 void onLayersChanged(); 159 void createTerrainDeferred(); 160 void onBackgroundColorChanged(); 161 void onLayerEntityPickedObject( Qt3DRender::QPickEvent *pickEvent, QgsFeatureId fid ); 162 void updateLights(); 163 void updateCameraLens(); 164 void onRenderersChanged(); 165 void onSkyboxSettingsChanged(); 166 void onShadowSettingsChanged(); 167 void onEyeDomeShadingSettingsChanged(); 168 void onDebugShadowMapSettingsChanged(); 169 void onDebugDepthMapSettingsChanged(); 170 void onCameraMovementSpeedChanged(); 171 172 bool updateCameraNearFarPlanes(); 173 174 private: 175 void addLayerEntity( QgsMapLayer *layer ); 176 void removeLayerEntity( QgsMapLayer *layer ); 177 void addCameraViewCenterEntity( Qt3DRender::QCamera *camera ); 178 void setSceneState( SceneState state ); 179 void updateSceneState(); 180 void updateScene(); 181 void finalizeNewEntity( Qt3DCore::QEntity *newEntity ); 182 int maximumTextureSize() const; 183 184 private: 185 const Qgs3DMapSettings &mMap; 186 QgsAbstract3DEngine *mEngine = nullptr; 187 //! Provides a way to have a synchronous function executed each frame 188 Qt3DLogic::QFrameAction *mFrameAction = nullptr; 189 QgsCameraController *mCameraController = nullptr; 190 QgsTerrainEntity *mTerrain = nullptr; 191 QList<QgsChunkedEntity *> mChunkEntities; 192 //! Entity that shows view center - useful for debugging camera issues 193 Qt3DCore::QEntity *mEntityCameraViewCenter = nullptr; 194 //! Keeps track of entities that belong to a particular layer 195 QMap<QgsMapLayer *, Qt3DCore::QEntity *> mLayerEntities; 196 QMap<const QgsAbstract3DRenderer *, Qt3DCore::QEntity *> mRenderersEntities; 197 bool mTerrainUpdateScheduled = false; 198 SceneState mSceneState = Ready; 199 //! List of currently registered pick handlers (used by identify tool) 200 QList<Qgs3DMapScenePickHandler *> mPickHandlers; 201 //! List of lights in the scene 202 QList<Qt3DCore::QEntity *> mLightEntities; 203 //! List of light origins in the scene 204 QList<Qt3DCore::QEntity *> mLightOriginEntities; 205 QList<QgsMapLayer *> mModelVectorLayers; 206 QgsSkyboxEntity *mSkybox = nullptr; 207 }; 208 209 #endif // QGS3DMAPSCENE_H 210