QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgs3dmapscene.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgs3dmapscene.cpp
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 #include "qgs3dmapscene.h"
17 
18 #include <Qt3DRender/QCamera>
19 #include <Qt3DRender/QMesh>
20 #include <Qt3DRender/QObjectPicker>
21 #include <Qt3DRender/QPickEvent>
22 #include <Qt3DRender/QPickingSettings>
23 #include <Qt3DRender/QPickTriangleEvent>
24 #include <Qt3DRender/QPointLight>
25 #include <Qt3DRender/QDirectionalLight>
26 #include <Qt3DRender/QRenderSettings>
27 #include <Qt3DRender/QSceneLoader>
28 #include <Qt3DExtras/QForwardRenderer>
29 #include <Qt3DExtras/QPhongMaterial>
30 #include <Qt3DExtras/QSphereMesh>
31 #include <Qt3DLogic/QFrameAction>
32 #include <Qt3DRender/QEffect>
33 #include <Qt3DRender/QTechnique>
34 #include <Qt3DRender/QRenderPass>
35 #include <Qt3DRender/QRenderState>
36 #include <Qt3DRender/QCullFace>
37 #include <Qt3DRender/QDepthTest>
38 #include <QSurface>
39 
40 #include <QOpenGLContext>
41 #include <QOpenGLFunctions>
42 #include <QTimer>
43 
44 #include "qgsapplication.h"
45 #include "qgsaabb.h"
46 #include "qgsabstract3dengine.h"
48 #include "qgs3dmapsettings.h"
49 #include "qgs3dutils.h"
50 #include "qgsabstract3drenderer.h"
51 #include "qgscameracontroller.h"
52 #include "qgschunkedentity_p.h"
53 #include "qgschunknode_p.h"
54 #include "qgseventtracing.h"
55 #include "qgsmeshlayer.h"
56 #include "qgsmeshlayer3drenderer.h"
57 #include "qgspoint3dsymbol.h"
58 #include "qgsrulebased3drenderer.h"
59 #include "qgssourcecache.h"
60 #include "qgsterrainentity_p.h"
61 #include "qgsterraingenerator.h"
63 #include "qgsvectorlayer.h"
67 
68 #include "qgslinematerial_p.h"
69 #include "qgs3dsceneexporter.h"
70 #include "qgsabstract3drenderer.h"
71 #include "qgs3dmapexportsettings.h"
72 #include "qgsmessageoutput.h"
73 
74 #include "qgsskyboxentity.h"
75 #include "qgsskyboxsettings.h"
76 
77 #include "qgswindow3dengine.h"
78 
80  : mMap( map )
81  , mEngine( engine )
82 {
83 
84  connect( &map, &Qgs3DMapSettings::backgroundColorChanged, this, &Qgs3DMapScene::onBackgroundColorChanged );
85  onBackgroundColorChanged();
86 
87  // TODO: strange - setting OnDemand render policy still keeps QGIS busy (Qt 5.9.0)
88  // actually it is more busy than with the default "Always" policy although there are no changes in the scene.
89  //mRenderer->renderSettings()->setRenderPolicy( Qt3DRender::QRenderSettings::OnDemand );
90 
91 #if QT_VERSION >= 0x050900
92  // we want precise picking of terrain (also bounding volume picking does not seem to work - not sure why)
93  mEngine->renderSettings()->pickingSettings()->setPickMethod( Qt3DRender::QPickingSettings::TrianglePicking );
94 #endif
95 
96  QRect viewportRect( QPoint( 0, 0 ), mEngine->size() );
97 
98  // Camera
99  float aspectRatio = ( float )viewportRect.width() / viewportRect.height();
100  mEngine->camera()->lens()->setPerspectiveProjection( mMap.fieldOfView(), aspectRatio, 10.f, 10000.0f );
101 
102  mFrameAction = new Qt3DLogic::QFrameAction();
103  connect( mFrameAction, &Qt3DLogic::QFrameAction::triggered,
104  this, &Qgs3DMapScene::onFrameTriggered );
105  addComponent( mFrameAction ); // takes ownership
106 
107  // Camera controlling
108  mCameraController = new QgsCameraController( this ); // attaches to the scene
109  mCameraController->setViewport( viewportRect );
110  mCameraController->setCamera( mEngine->camera() );
111  mCameraController->resetView( 1000 );
112 
113  addCameraViewCenterEntity( mEngine->camera() );
114  updateLights();
115 
116  // create terrain entity
117 
118  createTerrainDeferred();
119  connect( &map, &Qgs3DMapSettings::terrainGeneratorChanged, this, &Qgs3DMapScene::createTerrain );
120  connect( &map, &Qgs3DMapSettings::terrainVerticalScaleChanged, this, &Qgs3DMapScene::createTerrain );
121  connect( &map, &Qgs3DMapSettings::mapTileResolutionChanged, this, &Qgs3DMapScene::createTerrain );
122  connect( &map, &Qgs3DMapSettings::maxTerrainScreenErrorChanged, this, &Qgs3DMapScene::createTerrain );
123  connect( &map, &Qgs3DMapSettings::maxTerrainGroundErrorChanged, this, &Qgs3DMapScene::createTerrain );
124  connect( &map, &Qgs3DMapSettings::terrainShadingChanged, this, &Qgs3DMapScene::createTerrain );
125  connect( &map, &Qgs3DMapSettings::pointLightsChanged, this, &Qgs3DMapScene::updateLights );
126  connect( &map, &Qgs3DMapSettings::directionalLightsChanged, this, &Qgs3DMapScene::updateLights );
127  connect( &map, &Qgs3DMapSettings::showLightSourceOriginsChanged, this, &Qgs3DMapScene::updateLights );
128  connect( &map, &Qgs3DMapSettings::fieldOfViewChanged, this, &Qgs3DMapScene::updateCameraLens );
129  connect( &map, &Qgs3DMapSettings::renderersChanged, this, &Qgs3DMapScene::onRenderersChanged );
130  connect( &map, &Qgs3DMapSettings::skyboxSettingsChanged, this, &Qgs3DMapScene::onSkyboxSettingsChanged );
131  connect( &map, &Qgs3DMapSettings::shadowSettingsChanged, this, &Qgs3DMapScene::onShadowSettingsChanged );
132 
133  connect( QgsApplication::instance()->sourceCache(), &QgsSourceCache::remoteSourceFetched, this, [ = ]( const QString & url )
134  {
135  const QList<QgsMapLayer *> modelVectorLayers = mModelVectorLayers;
136  for ( QgsMapLayer *layer : modelVectorLayers )
137  {
138  QgsAbstract3DRenderer *renderer = layer->renderer3D();
139  if ( renderer )
140  {
141  if ( renderer->type() == QLatin1String( "vector" ) )
142  {
143  const QgsPoint3DSymbol *pointSymbol = static_cast< const QgsPoint3DSymbol * >( static_cast< QgsVectorLayer3DRenderer *>( renderer )->symbol() );
144  if ( pointSymbol->shapeProperties()[QStringLiteral( "model" )].toString() == url )
145  {
146  removeLayerEntity( layer );
147  addLayerEntity( layer );
148  }
149  }
150  else if ( renderer->type() == QLatin1String( "rulebased" ) )
151  {
152  const QgsRuleBased3DRenderer::RuleList rules = static_cast< QgsRuleBased3DRenderer *>( renderer )->rootRule()->descendants();
153  for ( auto rule : rules )
154  {
155  const QgsPoint3DSymbol *pointSymbol = dynamic_cast< const QgsPoint3DSymbol * >( rule->symbol() );
156  if ( pointSymbol->shapeProperties()[QStringLiteral( "model" )].toString() == url )
157  {
158  removeLayerEntity( layer );
159  addLayerEntity( layer );
160  break;
161  }
162  }
163  }
164  }
165  }
166  } );
167 
168  // create entities of renderers
169 
170  onRenderersChanged();
171 
172  // listen to changes of layers in order to add/remove 3D renderer entities
173  connect( &map, &Qgs3DMapSettings::layersChanged, this, &Qgs3DMapScene::onLayersChanged );
174 
175 
176 #if 0
177  ChunkedEntity *testChunkEntity = new ChunkedEntity( AABB( -500, 0, -500, 500, 100, 500 ), 2.f, 3.f, 7, new TestChunkLoaderFactory );
178  testChunkEntity->setEnabled( false );
179  testChunkEntity->setParent( this );
180  chunkEntities << testChunkEntity;
181 #endif
182 
183  connect( mCameraController, &QgsCameraController::cameraChanged, this, &Qgs3DMapScene::onCameraChanged );
184  connect( mCameraController, &QgsCameraController::viewportChanged, this, &Qgs3DMapScene::onCameraChanged );
185 
186 #if 0
187  // experiments with loading of existing 3D models.
188 
189  // scene loader only gets loaded only when added to a scene...
190  // it loads everything: geometries, materials, transforms, lights, cameras (if any)
191  Qt3DCore::QEntity *loaderEntity = new Qt3DCore::QEntity;
192  Qt3DRender::QSceneLoader *loader = new Qt3DRender::QSceneLoader;
193  loader->setSource( QUrl( "file:///home/martin/Downloads/LowPolyModels/tree.dae" ) );
194  loaderEntity->addComponent( loader );
195  loaderEntity->setParent( this );
196 
197  // mesh loads just geometry as one geometry...
198  // so if there are different materials (e.g. colors) used in the model, this information is lost
199  Qt3DCore::QEntity *meshEntity = new Qt3DCore::QEntity;
200  Qt3DRender::QMesh *mesh = new Qt3DRender::QMesh;
201  mesh->setSource( QUrl( "file:///home/martin/Downloads/LowPolyModels/tree.obj" ) );
202  meshEntity->addComponent( mesh );
203  Qt3DExtras::QPhongMaterial *material = new Qt3DExtras::QPhongMaterial;
204  material->setAmbient( Qt::red );
205  meshEntity->addComponent( material );
206  Qt3DCore::QTransform *meshTransform = new Qt3DCore::QTransform;
207  meshTransform->setScale( 1 );
208  meshEntity->addComponent( meshTransform );
209  meshEntity->setParent( this );
210 #endif
211  onSkyboxSettingsChanged();
212 
213  // force initial update of chunked entities
214  onCameraChanged();
215 }
216 
218 {
219  QgsRectangle extent = mMap.terrainGenerator()->extent();
220  float side = std::max( extent.width(), extent.height() );
221  mCameraController->resetView( side ); // assuming FOV being 45 degrees
222 }
223 
225 {
226  return mTerrain ? mTerrain->pendingJobsCount() : 0;
227 }
228 
230 {
231  int count = 0;
232  for ( QgsChunkedEntity *entity : qgis::as_const( mChunkEntities ) )
233  count += entity->pendingJobsCount();
234  return count;
235 }
236 
238 {
239  if ( mPickHandlers.isEmpty() )
240  {
241  // we need to add object pickers
242  for ( Qt3DCore::QEntity *entity : mLayerEntities.values() )
243  {
244  if ( QgsChunkedEntity *chunkedEntity = qobject_cast<QgsChunkedEntity *>( entity ) )
245  chunkedEntity->setPickingEnabled( true );
246  }
247  }
248 
249  mPickHandlers.append( pickHandler );
250 }
251 
253 {
254  mPickHandlers.removeOne( pickHandler );
255 
256  if ( mPickHandlers.isEmpty() )
257  {
258  // we need to remove pickers
259  for ( Qt3DCore::QEntity *entity : mLayerEntities.values() )
260  {
261  if ( QgsChunkedEntity *chunkedEntity = qobject_cast<QgsChunkedEntity *>( entity ) )
262  chunkedEntity->setPickingEnabled( false );
263  }
264  }
265 }
266 
267 void Qgs3DMapScene::onLayerEntityPickedObject( Qt3DRender::QPickEvent *pickEvent, QgsFeatureId fid )
268 {
269  QgsMapLayer *layer = mLayerEntities.key( qobject_cast<QgsChunkedEntity *>( sender() ) );
270  if ( !layer )
271  return;
272 
273  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
274  if ( !vlayer )
275  return;
276 
277  for ( Qgs3DMapScenePickHandler *pickHandler : qgis::as_const( mPickHandlers ) )
278  {
279  pickHandler->handlePickOnVectorLayer( vlayer, fid, pickEvent->worldIntersection(), pickEvent );
280  }
281 }
282 
283 float Qgs3DMapScene::worldSpaceError( float epsilon, float distance )
284 {
285  Qt3DRender::QCamera *camera = mCameraController->camera();
286  float fov = camera->fieldOfView();
287  QRect rect = mCameraController->viewport();
288  float screenSizePx = std::max( rect.width(), rect.height() ); // TODO: is this correct?
289 
290  // in qgschunkedentity_p.cpp there is inverse calculation (world space error to screen space error)
291  // with explanation of the math.
292  float frustumWidthAtDistance = 2 * distance * tan( fov / 2 );
293  float err = frustumWidthAtDistance * epsilon / screenSizePx;
294  return err;
295 }
296 
297 QgsChunkedEntity::SceneState _sceneState( QgsCameraController *cameraController )
298 {
299  Qt3DRender::QCamera *camera = cameraController->camera();
300  QgsChunkedEntity::SceneState state;
301  state.cameraFov = camera->fieldOfView();
302  state.cameraPos = camera->position();
303  QRect rect = cameraController->viewport();
304  state.screenSizePx = std::max( rect.width(), rect.height() ); // TODO: is this correct?
305  state.viewProjectionMatrix = camera->projectionMatrix() * camera->viewMatrix();
306  return state;
307 }
308 
309 void Qgs3DMapScene::onCameraChanged()
310 {
311  updateScene();
312  bool changedCameraPlanes = updateCameraNearFarPlanes();
313 
314  if ( changedCameraPlanes )
315  {
316  // repeat update of entities - because we have updated camera's near/far planes,
317  // the active nodes may have changed as well
318  updateScene();
319  updateCameraNearFarPlanes();
320  }
321 
322  onShadowSettingsChanged();
323 }
324 
325 void removeQLayerComponentsFromHierarchy( Qt3DCore::QEntity *entity )
326 {
327  QVector<Qt3DCore::QComponent *> toBeRemovedComponents;
328  for ( Qt3DCore::QComponent *component : entity->components() )
329  {
330  Qt3DRender::QLayer *layer = qobject_cast<Qt3DRender::QLayer *>( component );
331  if ( layer != nullptr )
332  toBeRemovedComponents.push_back( layer );
333  }
334  for ( Qt3DCore::QComponent *component : toBeRemovedComponents )
335  entity->removeComponent( component );
336  for ( Qt3DCore::QEntity *obj : entity->findChildren<Qt3DCore::QEntity *>() )
337  {
338  if ( obj != nullptr )
340  }
341 }
342 
343 void addQLayerComponentsToHierarchy( Qt3DCore::QEntity *entity, const QVector<Qt3DRender::QLayer *> layers )
344 {
345  for ( Qt3DRender::QLayer *layer : layers )
346  entity->addComponent( layer );
347  for ( Qt3DCore::QEntity *child : entity->findChildren<Qt3DCore::QEntity *>() )
348  {
349  if ( child != nullptr )
350  addQLayerComponentsToHierarchy( child, layers );
351  }
352 }
353 
354 void Qgs3DMapScene::updateScene()
355 {
356  QgsEventTracing::addEvent( QgsEventTracing::Instant, QStringLiteral( "3D" ), QStringLiteral( "Update Scene" ) );
357  for ( QgsChunkedEntity *entity : qgis::as_const( mChunkEntities ) )
358  {
359  if ( entity->isEnabled() )
360  entity->update( _sceneState( mCameraController ) );
361  }
362 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
363  QgsWindow3DEngine *windowEngine = qobject_cast<QgsWindow3DEngine *>( mEngine );
364  if ( windowEngine != nullptr )
365  {
366  QVector<Qt3DRender::QLayer *> layers;
367  layers.push_back( windowEngine->shadowRenderingFrameGraph()->castShadowsLayer() );
368  layers.push_back( windowEngine->shadowRenderingFrameGraph()->forwardRenderLayer() );
370  addQLayerComponentsToHierarchy( this, layers );
371  }
372 #endif
373  updateSceneState();
374 }
375 
376 bool Qgs3DMapScene::updateCameraNearFarPlanes()
377 {
378  // Update near and far plane from the terrain.
379  // this needs to be done with great care as we have kind of circular dependency here:
380  // active nodes are culled based on the current frustum (which involves near + far plane)
381  // and then based on active nodes we set near and far plane.
382  //
383  // All of this is just heuristics assuming that all other stuff is being rendered somewhere
384  // around the area where the terrain is.
385  //
386  // Near/far plane is setup in order to make best use of the depth buffer to avoid:
387  // 1. precision errors - if the range is too great
388  // 2. unwanted clipping of scene - if the range is too small
389 
390  if ( mTerrain )
391  {
392  Qt3DRender::QCamera *camera = cameraController()->camera();
393  QMatrix4x4 viewMatrix = camera->viewMatrix();
394  float fnear = 1e9;
395  float ffar = 0;
396 
397  QList<QgsChunkNode *> activeNodes = mTerrain->activeNodes();
398 
399  // it could be that there are no active nodes - they could be all culled or because root node
400  // is not yet loaded - we still need at least something to understand bounds of our scene
401  // so lets use the root node
402  if ( activeNodes.isEmpty() )
403  activeNodes << mTerrain->rootNode();
404 
405  Q_FOREACH ( QgsChunkNode *node, activeNodes )
406  {
407  // project each corner of bbox to camera coordinates
408  // and determine closest and farthest point.
409  QgsAABB bbox = node->bbox();
410  for ( int i = 0; i < 8; ++i )
411  {
412  QVector4D p( ( ( i >> 0 ) & 1 ) ? bbox.xMin : bbox.xMax,
413  ( ( i >> 1 ) & 1 ) ? bbox.yMin : bbox.yMax,
414  ( ( i >> 2 ) & 1 ) ? bbox.zMin : bbox.zMax, 1 );
415  QVector4D pc = viewMatrix * p;
416 
417  float dst = -pc.z(); // in camera coordinates, x grows right, y grows down, z grows to the back
418  if ( dst < fnear )
419  fnear = dst;
420  if ( dst > ffar )
421  ffar = dst;
422  }
423  }
424  if ( fnear < 1 )
425  fnear = 1; // does not really make sense to use negative far plane (behind camera)
426 
427  if ( fnear == 1e9 && ffar == 0 )
428  {
429  // the update didn't work out... this should not happen
430  // well at least temporarily use some conservative starting values
431  qDebug() << "oops... this should not happen! couldn't determine near/far plane. defaulting to 1...1e9";
432  fnear = 1;
433  ffar = 1e9;
434  }
435 
436  // set near/far plane - with some tolerance in front/behind expected near/far planes
437  float newFar = ffar * 2;
438  float newNear = fnear / 2;
439  if ( !qgsFloatNear( newFar, camera->farPlane() ) || !qgsFloatNear( newNear, camera->nearPlane() ) )
440  {
441  camera->setFarPlane( newFar );
442  camera->setNearPlane( newNear );
443  return true;
444  }
445  }
446  else
447  qDebug() << "no terrain - not setting near/far plane";
448 
449  return false;
450 }
451 
452 void Qgs3DMapScene::onFrameTriggered( float dt )
453 {
454  mCameraController->frameTriggered( dt );
455 
456  for ( QgsChunkedEntity *entity : qgis::as_const( mChunkEntities ) )
457  {
458  if ( entity->isEnabled() && entity->needsUpdate() )
459  {
460  QgsDebugMsgLevel( QStringLiteral( "need for update" ), 2 );
461  entity->update( _sceneState( mCameraController ) );
462  }
463  }
464 
465  updateSceneState();
466 }
467 
468 void Qgs3DMapScene::createTerrain()
469 {
470  if ( mTerrain )
471  {
472  mChunkEntities.removeOne( mTerrain );
473 
474  mTerrain->deleteLater();
475  mTerrain = nullptr;
476 
477  emit terrainEntityChanged();
478  }
479 
480  if ( !mTerrainUpdateScheduled )
481  {
482  // defer re-creation of terrain: there may be multiple invocations of this slot, so create the new entity just once
483  QTimer::singleShot( 0, this, &Qgs3DMapScene::createTerrainDeferred );
484  mTerrainUpdateScheduled = true;
485  setSceneState( Updating );
486  }
487 }
488 
489 void Qgs3DMapScene::createTerrainDeferred()
490 {
491  double tile0width = mMap.terrainGenerator()->extent().width();
492  int maxZoomLevel = Qgs3DUtils::maxZoomLevel( tile0width, mMap.mapTileResolution(), mMap.maxTerrainGroundError() );
493 
494  mTerrain = new QgsTerrainEntity( maxZoomLevel, mMap );
495  //mTerrain->setEnabled(false);
496  mTerrain->setParent( this );
497 
498  if ( mMap.showTerrainBoundingBoxes() )
499  mTerrain->setShowBoundingBoxes( true );
500 
501  mCameraController->setTerrainEntity( mTerrain );
502 
503  mChunkEntities << mTerrain;
504 
505  onCameraChanged(); // force update of the new terrain
506 
507  // make sure that renderers for layers are re-created as well
508  Q_FOREACH ( QgsMapLayer *layer, mMap.layers() )
509  {
510  // remove old entity - if any
511  removeLayerEntity( layer );
512 
513  // add new entity - if any 3D renderer
514  addLayerEntity( layer );
515  }
516 
517  mTerrainUpdateScheduled = false;
518 
519  connect( mTerrain, &QgsChunkedEntity::pendingJobsCountChanged, this, &Qgs3DMapScene::totalPendingJobsCountChanged );
520  connect( mTerrain, &QgsTerrainEntity::pendingJobsCountChanged, this, &Qgs3DMapScene::terrainPendingJobsCountChanged );
521 
522  emit terrainEntityChanged();
523 }
524 
525 void Qgs3DMapScene::onBackgroundColorChanged()
526 {
527  mEngine->setClearColor( mMap.backgroundColor() );
528 }
529 
530 void Qgs3DMapScene::updateLights()
531 {
532  for ( Qt3DCore::QEntity *entity : qgis::as_const( mLightEntities ) )
533  entity->deleteLater();
534  mLightEntities.clear();
535  for ( Qt3DCore::QEntity *entity : qgis::as_const( mLightOriginEntities ) )
536  entity->deleteLater();
537  mLightOriginEntities.clear();
538 
539  auto createLightOriginEntity = [ = ]( QVector3D translation, const QColor & color )->Qt3DCore::QEntity *
540  {
541  Qt3DCore::QEntity *originEntity = new Qt3DCore::QEntity;
542 
543  Qt3DCore::QTransform *trLightOriginCenter = new Qt3DCore::QTransform;
544  trLightOriginCenter->setTranslation( translation );
545  originEntity->addComponent( trLightOriginCenter );
546 
547  Qt3DExtras::QPhongMaterial *materialLightOriginCenter = new Qt3DExtras::QPhongMaterial;
548  materialLightOriginCenter->setAmbient( color );
549  originEntity->addComponent( materialLightOriginCenter );
550 
551  Qt3DExtras::QSphereMesh *rendererLightOriginCenter = new Qt3DExtras::QSphereMesh;
552  rendererLightOriginCenter->setRadius( 20 );
553  originEntity->addComponent( rendererLightOriginCenter );
554 
555  originEntity->setEnabled( true );
556  originEntity->setParent( this );
557 
558  return originEntity;
559  };
560 
561  const auto newPointLights = mMap.pointLights();
562  for ( const QgsPointLightSettings &pointLightSettings : newPointLights )
563  {
564  Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity;
565  Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform;
566  lightTransform->setTranslation( QVector3D( pointLightSettings.position().x(),
567  pointLightSettings.position().y(),
568  pointLightSettings.position().z() ) );
569 
570  Qt3DRender::QPointLight *light = new Qt3DRender::QPointLight;
571  light->setColor( pointLightSettings.color() );
572  light->setIntensity( pointLightSettings.intensity() );
573 
574  light->setConstantAttenuation( pointLightSettings.constantAttenuation() );
575  light->setLinearAttenuation( pointLightSettings.linearAttenuation() );
576  light->setQuadraticAttenuation( pointLightSettings.quadraticAttenuation() );
577 
578  lightEntity->addComponent( light );
579  lightEntity->addComponent( lightTransform );
580  lightEntity->setParent( this );
581  mLightEntities << lightEntity;
582 
583  if ( mMap.showLightSourceOrigins() )
584  mLightOriginEntities << createLightOriginEntity( lightTransform->translation(), pointLightSettings.color() );
585  }
586 
587  const auto newDirectionalLights = mMap.directionalLights();
588  for ( const QgsDirectionalLightSettings &directionalLightSettings : newDirectionalLights )
589  {
590  Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity;
591  Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform;
592 
593  Qt3DRender::QDirectionalLight *light = new Qt3DRender::QDirectionalLight;
594  light->setColor( directionalLightSettings.color() );
595  light->setIntensity( directionalLightSettings.intensity() );
596  QgsVector3D direction = directionalLightSettings.direction();
597  light->setWorldDirection( QVector3D( direction.x(), direction.y(), direction.z() ) );
598 
599  lightEntity->addComponent( light );
600  lightEntity->addComponent( lightTransform );
601  lightEntity->setParent( this );
602  mLightEntities << lightEntity;
603  }
604 
605  onShadowSettingsChanged();
606 }
607 
608 void Qgs3DMapScene::updateCameraLens()
609 {
610  mEngine->camera()->lens()->setFieldOfView( mMap.fieldOfView() );
611  onCameraChanged();
612 }
613 
614 void Qgs3DMapScene::onRenderersChanged()
615 {
616  // remove entities (if any)
617  qDeleteAll( mRenderersEntities );
618  mRenderersEntities.clear();
619 
620  // re-add entities from new set of renderers
621  const QList<QgsAbstract3DRenderer *> renderers = mMap.renderers();
622  for ( const QgsAbstract3DRenderer *renderer : renderers )
623  {
624  Qt3DCore::QEntity *newEntity = renderer->createEntity( mMap );
625  if ( newEntity )
626  {
627  newEntity->setParent( this );
628  finalizeNewEntity( newEntity );
629  mRenderersEntities[renderer] = newEntity;
630  }
631  }
632 }
633 
634 void Qgs3DMapScene::onLayerRenderer3DChanged()
635 {
636  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
637  Q_ASSERT( layer );
638 
639  // remove old entity - if any
640  removeLayerEntity( layer );
641 
642  // add new entity - if any 3D renderer
643  addLayerEntity( layer );
644 }
645 
646 void Qgs3DMapScene::onLayersChanged()
647 {
648  QSet<QgsMapLayer *> layersBefore = qgis::listToSet( mLayerEntities.keys() );
649  QList<QgsMapLayer *> layersAdded;
650  Q_FOREACH ( QgsMapLayer *layer, mMap.layers() )
651  {
652  if ( !layersBefore.contains( layer ) )
653  {
654  layersAdded << layer;
655  }
656  else
657  {
658  layersBefore.remove( layer );
659  }
660  }
661 
662  // what is left in layersBefore are layers that have been removed
663  Q_FOREACH ( QgsMapLayer *layer, layersBefore )
664  {
665  removeLayerEntity( layer );
666  }
667 
668  Q_FOREACH ( QgsMapLayer *layer, layersAdded )
669  {
670  addLayerEntity( layer );
671  }
672 }
673 
675 {
676  for ( auto layer : mLayerEntities.keys() )
677  {
678  if ( layer->temporalProperties()->isActive() )
679  {
680  removeLayerEntity( layer );
681  addLayerEntity( layer );
682  }
683  }
684 }
685 
686 void Qgs3DMapScene::addLayerEntity( QgsMapLayer *layer )
687 {
688  bool needsSceneUpdate = false;
689  QgsAbstract3DRenderer *renderer = layer->renderer3D();
690  if ( renderer )
691  {
692  // Fix vector layer's renderer to make sure the renderer is pointing to its layer.
693  // It has happened before that renderer pointed to a different layer (probably after copying a style).
694  // This is a bit of a hack and it should be handled in QgsMapLayer::setRenderer3D() but in qgis_core
695  // the vector layer 3D renderer classes are not available.
696  if ( layer->type() == QgsMapLayerType::VectorLayer &&
697  ( renderer->type() == QLatin1String( "vector" ) || renderer->type() == QLatin1String( "rulebased" ) ) )
698  {
699  static_cast<QgsAbstractVectorLayer3DRenderer *>( renderer )->setLayer( static_cast<QgsVectorLayer *>( layer ) );
700  if ( renderer->type() == QLatin1String( "vector" ) )
701  {
702  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
703  if ( vlayer->geometryType() == QgsWkbTypes::PointGeometry )
704  {
705  const QgsPoint3DSymbol *pointSymbol = static_cast< const QgsPoint3DSymbol * >( static_cast< QgsVectorLayer3DRenderer *>( renderer )->symbol() );
706  if ( pointSymbol->shape() == QgsPoint3DSymbol::Model )
707  {
708  mModelVectorLayers.append( layer );
709  }
710  }
711  }
712  else if ( renderer->type() == QLatin1String( "rulebased" ) )
713  {
714  const QgsRuleBased3DRenderer::RuleList rules = static_cast< QgsRuleBased3DRenderer *>( renderer )->rootRule()->descendants();
715  for ( auto rule : rules )
716  {
717  const QgsPoint3DSymbol *pointSymbol = dynamic_cast< const QgsPoint3DSymbol * >( rule->symbol() );
718  if ( pointSymbol && pointSymbol->shape() == QgsPoint3DSymbol::Model )
719  {
720  mModelVectorLayers.append( layer );
721  break;
722  }
723  }
724  }
725  }
726  else if ( layer->type() == QgsMapLayerType::MeshLayer && renderer->type() == QLatin1String( "mesh" ) )
727  {
728  QgsMeshLayer3DRenderer *meshRenderer = static_cast<QgsMeshLayer3DRenderer *>( renderer );
729  meshRenderer->setLayer( static_cast<QgsMeshLayer *>( layer ) );
730 
731  // Before entity creation, set the maximum texture size
732  // Not very clean, but for now, only place found in the workflow to do that simple
733  QgsMesh3DSymbol *sym = meshRenderer->symbol()->clone();
734  sym->setMaximumTextureSize( maximumTextureSize() );
735  meshRenderer->setSymbol( sym );
736  }
737 
738  Qt3DCore::QEntity *newEntity = renderer->createEntity( mMap );
739  if ( newEntity )
740  {
741  newEntity->setParent( this );
742  mLayerEntities.insert( layer, newEntity );
743 
744  finalizeNewEntity( newEntity );
745 
746  if ( QgsChunkedEntity *chunkedNewEntity = qobject_cast<QgsChunkedEntity *>( newEntity ) )
747  {
748  mChunkEntities.append( chunkedNewEntity );
749  needsSceneUpdate = true;
750 
751  chunkedNewEntity->setPickingEnabled( !mPickHandlers.isEmpty() );
752  connect( chunkedNewEntity, &QgsChunkedEntity::pickedObject, this, &Qgs3DMapScene::onLayerEntityPickedObject );
753 
754  connect( chunkedNewEntity, &QgsChunkedEntity::newEntityCreated, this, [this]( Qt3DCore::QEntity * entity )
755  {
756  finalizeNewEntity( entity );
757  } );
758 
759  connect( chunkedNewEntity, &QgsChunkedEntity::pendingJobsCountChanged, this, &Qgs3DMapScene::totalPendingJobsCountChanged );
760  }
761  }
762  }
763 
764  if ( needsSceneUpdate )
765  onCameraChanged(); // needed for chunked entities
766 
767  connect( layer, &QgsMapLayer::renderer3DChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
768 
769  if ( layer->type() == QgsMapLayerType::VectorLayer )
770  {
771  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
772  connect( vlayer, &QgsVectorLayer::selectionChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
773  }
774 
775  if ( layer->type() == QgsMapLayerType::MeshLayer )
776  {
777  connect( layer, &QgsMapLayer::rendererChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
778  }
779 
780 }
781 
782 void Qgs3DMapScene::removeLayerEntity( QgsMapLayer *layer )
783 {
784  Qt3DCore::QEntity *entity = mLayerEntities.take( layer );
785 
786  if ( QgsChunkedEntity *chunkedEntity = qobject_cast<QgsChunkedEntity *>( entity ) )
787  {
788  mChunkEntities.removeOne( chunkedEntity );
789  }
790 
791  if ( entity )
792  entity->deleteLater();
793 
794  disconnect( layer, &QgsMapLayer::renderer3DChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
795 
796  if ( layer->type() == QgsMapLayerType::VectorLayer )
797  {
798  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
799  disconnect( vlayer, &QgsVectorLayer::selectionChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
800  mModelVectorLayers.removeAll( layer );
801  }
802 
803  if ( layer->type() == QgsMapLayerType::MeshLayer )
804  {
805  disconnect( layer, &QgsMapLayer::rendererChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
806  }
807 }
808 
809 void Qgs3DMapScene::finalizeNewEntity( Qt3DCore::QEntity *newEntity )
810 {
811  // this is probably not the best place for material-specific configuration,
812  // maybe this could be more generalized when other materials need some specific treatment
813  for ( QgsLineMaterial *lm : newEntity->findChildren<QgsLineMaterial *>() )
814  {
815  connect( mCameraController, &QgsCameraController::viewportChanged, lm, [lm, this]
816  {
817  lm->setViewportSize( mCameraController->viewport().size() );
818  } );
819 
820  lm->setViewportSize( cameraController()->viewport().size() );
821  }
822  // configure billboard's viewport when the viewport is changed.
823  for ( QgsPoint3DBillboardMaterial *bm : newEntity->findChildren<QgsPoint3DBillboardMaterial *>() )
824  {
825  connect( mCameraController, &QgsCameraController::viewportChanged, bm, [bm, this]
826  {
827  bm->setViewportSize( mCameraController->viewport().size() );
828  } );
829 
830  bm->setViewportSize( mCameraController->viewport().size() );
831  }
832 }
833 
834 int Qgs3DMapScene::maximumTextureSize() const
835 {
836  QSurface *surface = mEngine->surface();
837  QOpenGLContext context;
838  context.create();
839  context.makeCurrent( surface );
840  QOpenGLFunctions openglFunctions( &context );
841  GLint size;
842  openglFunctions.glGetIntegerv( GL_MAX_TEXTURE_SIZE, &size );
843  return int( size );
844 }
845 
846 void Qgs3DMapScene::addCameraViewCenterEntity( Qt3DRender::QCamera *camera )
847 {
848  mEntityCameraViewCenter = new Qt3DCore::QEntity;
849 
850  Qt3DCore::QTransform *trCameraViewCenter = new Qt3DCore::QTransform;
851  mEntityCameraViewCenter->addComponent( trCameraViewCenter );
852  connect( camera, &Qt3DRender::QCamera::viewCenterChanged, this, [trCameraViewCenter, camera]
853  {
854  trCameraViewCenter->setTranslation( camera->viewCenter() );
855  } );
856 
857  Qt3DExtras::QPhongMaterial *materialCameraViewCenter = new Qt3DExtras::QPhongMaterial;
858  materialCameraViewCenter->setAmbient( Qt::red );
859  mEntityCameraViewCenter->addComponent( materialCameraViewCenter );
860 
861  Qt3DExtras::QSphereMesh *rendererCameraViewCenter = new Qt3DExtras::QSphereMesh;
862  rendererCameraViewCenter->setRadius( 10 );
863  mEntityCameraViewCenter->addComponent( rendererCameraViewCenter );
864 
865  mEntityCameraViewCenter->setEnabled( mMap.showCameraViewCenter() );
866  mEntityCameraViewCenter->setParent( this );
867 
868  connect( &mMap, &Qgs3DMapSettings::showCameraViewCenterChanged, this, [this]
869  {
870  mEntityCameraViewCenter->setEnabled( mMap.showCameraViewCenter() );
871  } );
872 }
873 
874 void Qgs3DMapScene::setSceneState( Qgs3DMapScene::SceneState state )
875 {
876  if ( mSceneState == state )
877  return;
878  mSceneState = state;
879  emit sceneStateChanged();
880 }
881 
882 void Qgs3DMapScene::updateSceneState()
883 {
884  if ( mTerrainUpdateScheduled )
885  {
886  setSceneState( Updating );
887  return;
888  }
889 
890  for ( QgsChunkedEntity *entity : qgis::as_const( mChunkEntities ) )
891  {
892  if ( entity->isEnabled() && entity->pendingJobsCount() > 0 )
893  {
894  setSceneState( Updating );
895  return;
896  }
897  }
898 
899  setSceneState( Ready );
900 }
901 
902 void Qgs3DMapScene::onSkyboxSettingsChanged()
903 {
904  QgsSkyboxSettings skyboxSettings = mMap.skyboxSettings();
905  if ( mSkybox != nullptr )
906  {
907  mSkybox->deleteLater();
908  mSkybox = nullptr;
909  }
910 
911  mEngine->setFrustumCullingEnabled( !mMap.isSkyboxEnabled() );
912 
913  if ( mMap.isSkyboxEnabled() )
914  {
915  QMap<QString, QString> faces;
916  switch ( skyboxSettings.skyboxType() )
917  {
919  faces = skyboxSettings.cubeMapFacesPaths();
920  mSkybox = new QgsCubeFacesSkyboxEntity(
921  faces[QStringLiteral( "posX" )], faces[QStringLiteral( "posY" )], faces[QStringLiteral( "posZ" )],
922  faces[QStringLiteral( "negX" )], faces[QStringLiteral( "negY" )], faces[QStringLiteral( "negZ" )],
923  this
924  );
925  break;
927  mSkybox = new QgsPanoramicSkyboxEntity( skyboxSettings.panoramicTexturePath(), this );
928  break;
929  }
930  }
931 }
932 
933 void Qgs3DMapScene::onShadowSettingsChanged()
934 {
935  QgsWindow3DEngine *windowEngine = dynamic_cast<QgsWindow3DEngine *>( mEngine );
936  if ( windowEngine == nullptr )
937  return;
938  QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = windowEngine->shadowRenderingFrameGraph();
939 
940  QList<QgsDirectionalLightSettings> directionalLights = mMap.directionalLights();
941  QgsShadowSettings shadowSettings = mMap.shadowSettings();
942  int selectedLight = shadowSettings.selectedDirectionalLight();
943  if ( shadowSettings.renderShadows() && selectedLight >= 0 && selectedLight < directionalLights.count() )
944  {
945  shadowRenderingFrameGraph->setShadowRenderingEnabled( true );
946  shadowRenderingFrameGraph->setShadowBias( shadowSettings.shadowBias() );
947  shadowRenderingFrameGraph->setShadowMapResolution( shadowSettings.shadowMapResolution() );
948  QgsDirectionalLightSettings light = directionalLights[selectedLight];
949  shadowRenderingFrameGraph->setupDirectionalLight( light, shadowSettings.maximumShadowRenderingDistance() );
950  }
951  else
952  shadowRenderingFrameGraph->setShadowRenderingEnabled( false );
953 }
954 
956 {
957  QVector<QString> notParsedLayers;
958  Qgs3DSceneExporter exporter;
959 
960  exporter.setTerrainResolution( exportSettings.terrrainResolution() );
961  exporter.setSmoothEdges( exportSettings.smoothEdges() );
962  exporter.setExportNormals( exportSettings.exportNormals() );
963  exporter.setExportTextures( exportSettings.exportTextures() );
964  exporter.setTerrainTextureResolution( exportSettings.terrainTextureResolution() );
965  exporter.setScale( exportSettings.scale() );
966 
967  for ( auto it = mLayerEntities.constBegin(); it != mLayerEntities.constEnd(); ++it )
968  {
969  QgsMapLayer *layer = it.key();
970  Qt3DCore::QEntity *rootEntity = it.value();
971  QgsMapLayerType layerType = layer->type();
972  switch ( layerType )
973  {
975  if ( !exporter.parseVectorLayerEntity( rootEntity, qobject_cast<QgsVectorLayer *>( layer ) ) )
976  notParsedLayers.push_back( layer->name() );
977  break;
983  notParsedLayers.push_back( layer->name() );
984  break;
985  }
986  }
987 
988  if ( mTerrain )
989  exporter.parseTerrain( mTerrain, "Terrain" );
990 
991  exporter.save( exportSettings.sceneName(), exportSettings.sceneFolderPath() );
992 
993  if ( !notParsedLayers.empty() )
994  {
995  QString message = tr( "The following layers were not exported:" ) + "\n";
996  for ( const QString &layerName : notParsedLayers )
997  message += layerName + "\n";
998  QgsMessageOutput::showMessage( tr( "3D exporter warning" ), message, QgsMessageOutput::MessageText );
999  }
1000 }
qgssourcecache.h
Qgs3DMapSettings::backgroundColorChanged
void backgroundColorChanged()
Emitted when the background color has changed.
Qgs3DSceneExporter::setScale
void setScale(float scale)
Sets the scale of the exported 3D model.
Definition: qgs3dsceneexporter.h:105
Qgs3DUtils::maxZoomLevel
static int maxZoomLevel(double tile0width, double tileResolution, double maxError)
Calculates the highest needed zoom level for tiles in quad-tree given width of the base tile (zoom le...
Definition: qgs3dutils.cpp:171
QgsRectangle::height
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
QgsPoint3DBillboardMaterial
3 Material of the billboard rendering for points in 3D map view.
Definition: qgspoint3dbillboardmaterial.h:37
Qgs3DMapSettings::showLightSourceOrigins
bool showLightSourceOrigins() const
Returns whether to show light source origins as a sphere (for debugging)
Definition: qgs3dmapsettings.h:358
QgsShadowSettings::maximumShadowRenderingDistance
double maximumShadowRenderingDistance() const
Returns the maximum shadow rendering distance accounted for when rendering shadows Objects further aw...
Definition: qgsshadowsettings.h:54
qgstessellatedpolygongeometry.h
qgsmessageoutput.h
QgsShadowRenderingFrameGraph::setShadowBias
void setShadowBias(float shadowBias)
Sets the shadow bias value.
Definition: qgsshadowrenderingframegraph.cpp:321
QgsVectorLayer3DRenderer
3D renderer that renders all features of a vector layer with the same 3D symbol.
Definition: qgsvectorlayer3drenderer.h:61
Qgs3DMapSettings::directionalLightsChanged
void directionalLightsChanged()
Emitted when the list of directional lights changes.
QgsCameraController::resetView
void resetView(float distance)
Move camera back to the initial position (looking down towards origin of world's coordinates)
Definition: qgscameracontroller.cpp:176
Qgs3DSceneExporter::save
void save(const QString &sceneName, const QString &sceneFolderPath)
Saves the scene to a .obj file.
Definition: qgs3dsceneexporter.cpp:650
Qgs3DMapScene::registerPickHandler
void registerPickHandler(Qgs3DMapScenePickHandler *pickHandler)
Registers an object that will get results of pick events on 3D entities. Does not take ownership of t...
Definition: qgs3dmapscene.cpp:237
QgsMapLayerType::MeshLayer
@ MeshLayer
Added in 3.2.
QgsMapLayerType::VectorLayer
@ VectorLayer
Qgs3DMapSettings::maxTerrainGroundError
float maxTerrainGroundError() const
Returns maximum ground error of terrain tiles in world units.
Definition: qgs3dmapsettings.cpp:537
QgsShadowRenderingFrameGraph::castShadowsLayer
Qt3DRender::QLayer * castShadowsLayer()
Returns a layer object used to indicate that an entity will cast shadows.
Definition: qgsshadowrenderingframegraph.h:77
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsAbstract3DRenderer::type
virtual QString type() const =0
Returns unique identifier of the renderer class (used to identify subclass)
QgsVector3D::y
double y() const
Returns Y coordinate.
Definition: qgsvector3d.h:51
qgsaabb.h
Qgs3DMapScene::terrainPendingJobsCountChanged
void terrainPendingJobsCountChanged()
Emitted when the number of terrain's pending jobs changes.
QgsAbstract3DRenderer
Base class for all renderers that may to participate in 3D view.
Definition: qgsabstract3drenderer.h:49
QgsVector3D
3 Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double preci...
Definition: qgsvector3d.h:32
Qgs3DMapSettings::showLightSourceOriginsChanged
void showLightSourceOriginsChanged()
Emitted when the flag whether light source origins are shown has changed.
QgsShadowSettings::shadowMapResolution
int shadowMapResolution() const
Returns the resolution of the shadow map texture used to generate the shadows.
Definition: qgsshadowsettings.h:67
Qgs3DMapSettings::mapTileResolution
int mapTileResolution() const
Returns resolution (in pixels) of the texture of a terrain tile.
Definition: qgs3dmapsettings.cpp:509
Qgs3DMapSettings::showCameraViewCenterChanged
void showCameraViewCenterChanged()
Emitted when the flag whether camera's view center is shown has changed.
qgs3dsceneexporter.h
Qgs3DSceneExporter::setSmoothEdges
void setSmoothEdges(bool smoothEdges)
Sets whether the triangles will look smooth.
Definition: qgs3dsceneexporter.h:81
QgsMapLayerType
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:68
QgsCameraController::frameTriggered
void frameTriggered(float dt)
Called internally from 3D scene when a new frame is generated. Updates camera according to keyboard/m...
Definition: qgscameracontroller.cpp:171
QgsMeshLayer3DRenderer::symbol
const QgsMesh3DSymbol * symbol() const
Returns 3D symbol associated with the renderer.
Definition: qgsmeshlayer3drenderer.cpp:68
Qgs3DSceneExporter::setExportNormals
void setExportNormals(bool exportNormals)
Sets whether the normals will be exported.
Definition: qgs3dsceneexporter.h:86
qgschunknode_p.h
Qgs3DSceneExporter::parseTerrain
void parseTerrain(QgsTerrainEntity *terrain, const QString &layer)
Creates terrain export objects from the terrain entity.
Definition: qgs3dsceneexporter.cpp:248
QgsSkyboxSettings
class containing the configuration of a skybox entity 3
Definition: qgsskyboxsettings.h:36
Qgs3DMapSettings::mapTileResolutionChanged
void mapTileResolutionChanged()
Emitted when the map tile resoulution has changed.
qgsskyboxsettings.h
QgsMesh3DSymbol
3 3D symbol that draws mesh geometry as planar triangles.
Definition: qgsmesh3dsymbol.h:44
QgsApplication::instance
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
Definition: qgsapplication.cpp:411
qgsabstract3drenderer.h
QgsAbstract3DEngine::setClearColor
virtual void setClearColor(const QColor &color)=0
Sets background color of the scene.
QgsAbstract3DEngine::size
virtual QSize size() const =0
Returns size of the engine's rendering area in pixels.
Qgs3DMapSettings::terrainGeneratorChanged
void terrainGeneratorChanged()
Emitted when the terrain generator has changed.
QgsAbstractVectorLayer3DRenderer
3 Base class for 3D renderers that are based on vector layers.
Definition: qgsabstractvectorlayer3drenderer.h:78
QgsAABB::zMax
float zMax
Definition: qgsaabb.h:83
QgsAABB::yMin
float yMin
Definition: qgsaabb.h:79
qgspoint3dbillboardmaterial.h
Qgs3DMapSettings::skyboxSettingsChanged
void skyboxSettingsChanged()
Emitted when skybox settings are changed.
Qgs3DMapScene::Updating
@ Updating
The scene is still being loaded/updated.
Definition: qgs3dmapscene.h:96
Qgs3DMapSettings::renderersChanged
void renderersChanged()
Emitted when the list of map's extra renderers have been modified.
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsShadowRenderingFrameGraph
3 Container class that holds different objects related to shadow rendering
Definition: qgsshadowrenderingframegraph.h:57
QgsMessageOutput::showMessage
virtual void showMessage(bool blocking=true)=0
display the message to the user and deletes itself
QgsSkyboxEntity::DistinctTexturesSkybox
@ DistinctTexturesSkybox
Definition: qgsskyboxentity.h:51
Qgs3DMapScene::sceneStateChanged
void sceneStateChanged()
Emitted when the scene's state has changed.
qgsapplication.h
qgslinematerial_p.h
Qgs3DMapSettings::maxTerrainScreenErrorChanged
void maxTerrainScreenErrorChanged()
Emitted when the maximum terrain screen error has changed.
qgseventtracing.h
QgsCameraController::camera
Qt3DRender::QCamera * camera
Definition: qgscameracontroller.h:62
Qgs3DMapExportSettings::exportTextures
bool exportTextures() const
Returns whether textures will be exported.
Definition: qgs3dmapexportsettings.h:51
qgs3dmapexportsettings.h
qgsmaplayertemporalproperties.h
Qgs3DMapScene::exportScene
void exportScene(const Qgs3DMapExportSettings &exportSettings)
Exports the scene according to the scene export settings.
Definition: qgs3dmapscene.cpp:955
Qgs3DSceneExporter
The Qgs3DSceneExporter class Entity that handles the exporting of 3D scene.
Definition: qgs3dsceneexporter.h:57
qgsmeshlayer3drenderer.h
qgsFloatNear
bool qgsFloatNear(float a, float b, float epsilon=4 *FLT_EPSILON)
Compare two floats (but allow some difference)
Definition: qgis.h:330
QgsMapLayer::renderer3D
QgsAbstract3DRenderer * renderer3D() const
Returns 3D renderer associated with the layer.
Definition: qgsmaplayer.cpp:1821
QgsTemporalProperty::isActive
bool isActive() const
Returns true if the temporal property is active.
Definition: qgstemporalproperty.cpp:36
Qgs3DMapExportSettings
The Qgs3DMapExportSettings class Manages the various settings the user can choose from when exporting...
Definition: qgs3dmapexportsettings.h:32
Qgs3DSceneExporter::setTerrainTextureResolution
void setTerrainTextureResolution(int resolution)
Sets the terrain texture resolution.
Definition: qgs3dsceneexporter.h:101
QgsVector3D::z
double z() const
Returns Z coordinate.
Definition: qgsvector3d.h:53
qgs3dutils.h
QgsVectorLayer::selectionChanged
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
Qgs3DMapScene::cameraController
QgsCameraController * cameraController()
Returns camera controller.
Definition: qgs3dmapscene.h:76
QgsSkyboxSettings::cubeMapFacesPaths
QMap< QString, QString > cubeMapFacesPaths() const
Returns a map containing the path of each texture specified by the user.
Definition: qgsskyboxsettings.h:58
Qgs3DMapExportSettings::smoothEdges
bool smoothEdges() const
Returns whether triangles edges will look smooth.
Definition: qgs3dmapexportsettings.h:47
removeQLayerComponentsFromHierarchy
void removeQLayerComponentsFromHierarchy(Qt3DCore::QEntity *entity)
Definition: qgs3dmapscene.cpp:325
qgschunkedentity_p.h
QgsPoint3DSymbol::Model
@ Model
Definition: qgspoint3dsymbol.h:86
QgsSkyboxSettings::skyboxType
QgsSkyboxEntity::SkyboxType skyboxType() const
Returns the type of the skybox.
Definition: qgsskyboxsettings.h:45
QgsMeshLayer
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:95
qgsterraingenerator.h
Qgs3DMapScene::updateTemporal
void updateTemporal()
Updates the temporale entities.
Definition: qgs3dmapscene.cpp:674
QgsMapLayerType::RasterLayer
@ RasterLayer
QgsShadowSettings::shadowBias
double shadowBias() const
Returns the shadow bias used to correct the numerical imprecision of shadows (for the depth test) Thi...
Definition: qgsshadowsettings.h:61
QgsPointLightSettings
3 Definition of a point light in a 3D map scene
Definition: qgspointlightsettings.h:39
Qgs3DMapScene::worldSpaceError
float worldSpaceError(float epsilon, float distance)
Given screen error (in pixels) and distance from camera (in 3D world coordinates),...
Definition: qgs3dmapscene.cpp:283
Qgs3DMapSettings::backgroundColor
QColor backgroundColor() const
Returns background color of the 3D map view.
Definition: qgs3dmapsettings.cpp:411
_sceneState
QgsChunkedEntity::SceneState _sceneState(QgsCameraController *cameraController)
Definition: qgs3dmapscene.cpp:297
Qgs3DMapSettings::terrainVerticalScaleChanged
void terrainVerticalScaleChanged()
Emitted when the vertical scale of the terrain has changed.
QgsMapLayer::temporalProperties
virtual QgsMapLayerTemporalProperties * temporalProperties()
Returns the layer's temporal properties.
Definition: qgsmaplayer.h:1203
QgsAABB::xMin
float xMin
Definition: qgsaabb.h:78
QgsCameraController::viewportChanged
void viewportChanged()
Emitted when viewport rectangle has been updated.
QgsAABB
3 Axis-aligned bounding box - in world coords.
Definition: qgsaabb.h:34
Qgs3DMapScene::unregisterPickHandler
void unregisterPickHandler(Qgs3DMapScenePickHandler *pickHandler)
Unregisters previously registered pick handler. Pick handler is not deleted. Also removes object pick...
Definition: qgs3dmapscene.cpp:252
qgsabstract3dengine.h
QgsShadowRenderingFrameGraph::forwardRenderLayer
Qt3DRender::QLayer * forwardRenderLayer()
Returns a layer object used to indicate that an entity will be rendered during the forward rendering ...
Definition: qgsshadowrenderingframegraph.h:79
QgsMeshLayer3DRenderer
3D renderer that renders all mesh triangles of a mesh layer.
Definition: qgsmeshlayer3drenderer.h:60
QgsCameraController::viewport
QRect viewport
Definition: qgscameracontroller.h:63
Qgs3DMapSettings
3 Definition of the world
Definition: qgs3dmapsettings.h:54
qgswindow3dengine.h
QgsCameraController::setCamera
void setCamera(Qt3DRender::QCamera *camera)
Assigns camera that should be controlled by this class. Called internally from 3D scene.
Definition: qgscameracontroller.cpp:71
Qgs3DMapExportSettings::sceneFolderPath
QString sceneFolderPath() const
Returns the scene folder path.
Definition: qgs3dmapexportsettings.h:43
Qgs3DMapScene::terrainEntityChanged
void terrainEntityChanged()
Emitted when the current terrain entity is replaced by a new one.
QgsWindow3DEngine::shadowRenderingFrameGraph
QgsShadowRenderingFrameGraph * shadowRenderingFrameGraph()
Returns the frame graph object.
Definition: qgswindow3dengine.h:63
Qgs3DMapSettings::fieldOfView
float fieldOfView() const
Returns the camera lens' field of view.
Definition: qgs3dmapsettings.h:393
Qgs3DMapSettings::fieldOfViewChanged
void fieldOfViewChanged()
Emitted when the camera lens field of view changes.
qgscameracontroller.h
QgsCameraController::setTerrainEntity
void setTerrainEntity(QgsTerrainEntity *te)
Connects to object picker attached to terrain entity.
Definition: qgscameracontroller.cpp:63
QgsAbstract3DEngine
3 Base class for 3D engine implementation.
Definition: qgsabstract3dengine.h:58
QgsMapLayer::rendererChanged
void rendererChanged()
Signal emitted when renderer is changed.
QgsAbstract3DRenderer::createEntity
virtual Qt3DCore::QEntity * createEntity(const Qgs3DMapSettings &map) const =0
Returns a 3D entity that will be used to show renderer's data in 3D scene.
Qgs3DMapSettings::pointLightsChanged
void pointLightsChanged()
Emitted when the list of point lights changes.
QgsSkyboxEntity::PanoramicSkybox
@ PanoramicSkybox
Definition: qgsskyboxentity.h:50
QgsAbstract3DEngine::camera
virtual Qt3DRender::QCamera * camera()=0
Returns pointer to the engine's camera entity.
QgsRuleBased3DRenderer::RuleList
QList< QgsRuleBased3DRenderer::Rule * > RuleList
Definition: qgsrulebased3drenderer.h:65
Qgs3DMapSettings::shadowSettingsChanged
void shadowSettingsChanged()
Emitted when shadow rendering settings are changed.
QgsMesh3DSymbol::clone
QgsMesh3DSymbol * clone() const override SIP_FACTORY
Returns a new instance of the symbol with the same settings.
Definition: qgsmesh3dsymbol.cpp:29
Qgs3DMapSettings::terrainGenerator
QgsTerrainGenerator * terrainGenerator() const
Returns terrain generator. It takes care of producing terrain tiles from the input data.
Definition: qgs3dmapsettings.h:272
qgsmeshlayer.h
qgsvectorlayer.h
QgsAbstract3DEngine::setFrustumCullingEnabled
virtual void setFrustumCullingEnabled(bool enabled)=0
Sets whether frustum culling is enabled (this should make rendering faster by not rendering entities ...
QgsShadowSettings::renderShadows
bool renderShadows() const
Returns whether shadow rendering is enabled.
Definition: qgsshadowsettings.h:44
qgsterrainentity_p.h
Qgs3DMapSettings::terrainShadingChanged
void terrainShadingChanged()
Emitted when terrain shading enabled flag or terrain shading material has changed.
Qgs3DMapScene::terrainPendingJobsCount
int terrainPendingJobsCount() const
Returns number of pending jobs of the terrain entity.
Definition: qgs3dmapscene.cpp:224
QgsCameraController::setViewport
void setViewport(QRect viewport)
Sets viewport rectangle. Called internally from 3D canvas. Allows conversion of mouse coordinates.
Definition: qgscameracontroller.cpp:84
QgsPoint3DSymbol::shape
Shape shape() const
Returns 3D shape for points.
Definition: qgspoint3dsymbol.h:96
qgs3dmapsettings.h
Qgs3DMapExportSettings::scale
float scale() const
Returns the scale of the exported model.
Definition: qgs3dmapexportsettings.h:55
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
Qgs3DMapSettings::shadowSettings
QgsShadowSettings shadowSettings() const
Returns the current configuration of shadows.
Definition: qgs3dmapsettings.h:426
QgsShadowSettings::selectedDirectionalLight
int selectedDirectionalLight() const
Returns the selected direcctional light used to cast shadows.
Definition: qgsshadowsettings.h:46
qgsskyboxentity.h
Qgs3DMapSettings::directionalLights
QList< QgsDirectionalLightSettings > directionalLights() const
Returns list of directional lights defined in the scene.
Definition: qgs3dmapsettings.h:375
Qgs3DMapScene::SceneState
SceneState
Enumeration of possible states of the 3D scene.
Definition: qgs3dmapscene.h:94
Qgs3DMapScene::Ready
@ Ready
The scene is fully loaded/updated.
Definition: qgs3dmapscene.h:95
qgsrulebased3drenderer.h
Qgs3DMapScene::totalPendingJobsCount
int totalPendingJobsCount() const
Returns number of pending jobs for all chunked entities.
Definition: qgs3dmapscene.cpp:229
Qgs3DMapScene::viewZoomFull
void viewZoomFull()
Resets camera view to show the whole scene (top view)
Definition: qgs3dmapscene.cpp:217
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsRectangle::width
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
qgspoint3dsymbol.h
QgsMapLayer
Base class for all map layer types.
Definition: qgsmaplayer.h:83
Qgs3DMapSettings::layers
QList< QgsMapLayer * > layers() const
Returns the list of 3D map layers to be rendered in the scene.
Definition: qgs3dmapsettings.cpp:460
Qgs3DMapSettings::renderers
QList< QgsAbstract3DRenderer * > renderers() const
Returns list of extra 3D renderers.
Definition: qgs3dmapsettings.h:325
Qgs3DMapScene::Qgs3DMapScene
Qgs3DMapScene(const Qgs3DMapSettings &map, QgsAbstract3DEngine *engine)
Constructs a 3D scene based on map settings and Qt 3D renderer configuration.
Definition: qgs3dmapscene.cpp:79
QgsAABB::yMax
float yMax
Definition: qgsaabb.h:82
QgsMapLayerType::VectorTileLayer
@ VectorTileLayer
Added in 3.14.
Qgs3DMapExportSettings::terrainTextureResolution
int terrainTextureResolution() const
Returns the terrain texture resolution.
Definition: qgs3dmapexportsettings.h:53
QgsShadowSettings
class containing the configuration of shadows rendering 3
Definition: qgsshadowsettings.h:35
qgs3dmapscenepickhandler.h
QgsMeshLayer3DRenderer::setLayer
void setLayer(QgsMeshLayer *layer)
Sets vector layer associated with the renderer.
Definition: qgsmeshlayer3drenderer.cpp:53
Qgs3DMapExportSettings::sceneName
QString sceneName() const
Returns the scene name.
Definition: qgs3dmapexportsettings.h:41
QgsMapLayer::name
QString name
Definition: qgsmaplayer.h:86
qgsvectorlayer3drenderer.h
QgsPoint3DSymbol::shapeProperties
QVariantMap shapeProperties() const
Returns a key-value dictionary of point shape properties.
Definition: qgspoint3dsymbol.h:101
Qgs3DMapSettings::showTerrainBoundingBoxes
bool showTerrainBoundingBoxes() const
Returns whether to display bounding boxes of terrain tiles (for debugging)
Definition: qgs3dmapsettings.h:330
QgsRuleBased3DRenderer
3 Rule-based 3D renderer.
Definition: qgsrulebased3drenderer.h:62
Qgs3DMapExportSettings::exportNormals
bool exportNormals() const
Returns whether normals will be exported.
Definition: qgs3dmapexportsettings.h:49
Qgs3DMapScene::totalPendingJobsCountChanged
void totalPendingJobsCountChanged()
Emitted when the total number of pending jobs changes.
QgsPanoramicSkyboxEntity
a skybox constructed from a panoramic image 3
Definition: qgsskyboxentity.h:77
QgsMesh3DSymbol::setMaximumTextureSize
void setMaximumTextureSize(int maximumTextureSize)
Sets the maximum texture size supported by the hardware Used to store the GL_MAX_TEXTURE_SIZE value t...
Definition: qgsmesh3dsymbol.cpp:261
QgsMeshLayer3DRenderer::setSymbol
void setSymbol(QgsMesh3DSymbol *symbol)
Sets 3D symbol associated with the renderer.
Definition: qgsmeshlayer3drenderer.cpp:63
QgsMessageOutput::MessageText
@ MessageText
Definition: qgsmessageoutput.h:47
QgsTerrainGenerator::extent
virtual QgsRectangle extent() const =0
extent of the terrain in terrain's CRS
Qgs3DMapSettings::showCameraViewCenter
bool showCameraViewCenter() const
Returns whether to show camera's view center as a sphere (for debugging)
Definition: qgs3dmapsettings.h:346
QgsShadowRenderingFrameGraph::setupDirectionalLight
void setupDirectionalLight(const QgsDirectionalLightSettings &light, float maximumShadowRenderingDistance)
Sets shadow rendering to use a directional light.
Definition: qgsshadowrenderingframegraph.cpp:279
QgsCameraController
3 Object that controls camera movement based on user input
Definition: qgscameracontroller.h:60
QgsAbstract3DEngine::renderSettings
virtual Qt3DRender::QRenderSettings * renderSettings()=0
Returns access to the engine's render settings (the frame graph can be accessed from here)
Qgs3DMapSettings::skyboxSettings
QgsSkyboxSettings skyboxSettings() const
Returns the current configuration of the skybox.
Definition: qgs3dmapsettings.h:420
QgsAABB::zMin
float zMin
Definition: qgsaabb.h:80
QgsAABB::xMax
float xMax
Definition: qgsaabb.h:81
QgsCameraController::cameraChanged
void cameraChanged()
Emitted when camera has been updated.
Qgs3DMapSettings::isSkyboxEnabled
bool isSkyboxEnabled() const
Returns whether the skybox is enabled.
Definition: qgs3dmapsettings.h:445
QgsVectorLayer::geometryType
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Definition: qgsvectorlayer.cpp:659
QgsShadowRenderingFrameGraph::setShadowRenderingEnabled
void setShadowRenderingEnabled(bool enabled)
Sets whether the shadow rendering is enabled.
Definition: qgsshadowrenderingframegraph.cpp:311
Qgs3DSceneExporter::parseVectorLayerEntity
bool parseVectorLayerEntity(Qt3DCore::QEntity *entity, QgsVectorLayer *layer)
Creates necessary export objects from entity if it represents valid vector layer entity Returns false...
Definition: qgs3dsceneexporter.cpp:183
QgsVector3D::x
double x() const
Returns X coordinate.
Definition: qgsvector3d.h:49
Qgs3DSceneExporter::setExportTextures
void setExportTextures(bool exportTextures)
Sets whether the textures will be exported.
Definition: qgs3dsceneexporter.h:91
QgsMapLayer::renderer3DChanged
void renderer3DChanged()
Signal emitted when 3D renderer associated with the layer has changed.
QgsWindow3DEngine
3 On-screen 3D engine: it creates OpenGL window (QWindow) and displays rendered 3D scene there.
Definition: qgswindow3dengine.h:50
Qgs3DMapSettings::maxTerrainGroundErrorChanged
void maxTerrainGroundErrorChanged()
Emitted when the maximum terrain ground error has changed.
QgsSkyboxSettings::panoramicTexturePath
QString panoramicTexturePath() const
Returns the panoramic texture path of a skybox of type "Panormaic skybox".
Definition: qgsskyboxsettings.h:50
Qgs3DMapExportSettings::terrrainResolution
int terrrainResolution() const
Returns the terrain resolution.
Definition: qgs3dmapexportsettings.h:45
QgsMapLayerType::PluginLayer
@ PluginLayer
Qgs3DMapScenePickHandler
3 Abstract base class for handlers that process pick events from a 3D map scene.
Definition: qgs3dmapscenepickhandler.h:36
Qgs3DMapSettings::pointLights
QList< QgsPointLightSettings > pointLights() const
Returns list of point lights defined in the scene.
Definition: qgs3dmapsettings.h:369
addQLayerComponentsToHierarchy
void addQLayerComponentsToHierarchy(Qt3DCore::QEntity *entity, const QVector< Qt3DRender::QLayer * > layers)
Definition: qgs3dmapscene.cpp:343
QgsCubeFacesSkyboxEntity
a skybox constructed from a 6 cube faces 3
Definition: qgsskyboxentity.h:101
qgs3dmapscene.h
QgsPoint3DSymbol
3 3D symbol that draws point geometries as 3D objects using one of the predefined shapes.
Definition: qgspoint3dsymbol.h:39
Qgs3DSceneExporter::setTerrainResolution
void setTerrainResolution(int resolution)
Sets the terrain resolution.
Definition: qgs3dsceneexporter.h:96
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QgsAbstract3DEngine::surface
virtual QSurface * surface() const =0
Returns the surface of the engine.
Qgs3DMapSettings::layersChanged
void layersChanged()
Emitted when the list of map layers for 3d rendering has changed.
QgsSourceCache::remoteSourceFetched
void remoteSourceFetched(const QString &url)
Emitted when the cache has finished retrieving a 3D model from a remote url.
QgsShadowRenderingFrameGraph::setShadowMapResolution
void setShadowMapResolution(int resolution)
Sets the resolution of the shadow map.
Definition: qgsshadowrenderingframegraph.cpp:327
QgsDirectionalLightSettings
3 Definition of a directional light in a 3D map scene
Definition: qgsdirectionallightsettings.h:33
QgsMapLayer::type
QgsMapLayerType type
Definition: qgsmaplayer.h:90