QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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/QRenderSettings>
25 #include <Qt3DRender/QSceneLoader>
26 #include <Qt3DExtras/QForwardRenderer>
27 #include <Qt3DExtras/QPhongMaterial>
28 #include <Qt3DExtras/QPhongAlphaMaterial>
29 #include <Qt3DExtras/QDiffuseSpecularMaterial>
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 #include <QUrl>
40 #include <QtMath>
41 
42 #include <QOpenGLContext>
43 #include <QOpenGLFunctions>
44 #include <QTimer>
45 
46 #include "qgs3daxis.h"
47 #include "qgslogger.h"
48 #include "qgsapplication.h"
49 #include "qgsaabb.h"
50 #include "qgsabstract3dengine.h"
52 #include "qgs3dmapsettings.h"
53 #include "qgs3dutils.h"
54 #include "qgsabstract3drenderer.h"
55 #include "qgscameracontroller.h"
56 #include "qgschunkedentity_p.h"
57 #include "qgschunknode_p.h"
58 #include "qgseventtracing.h"
59 #include "qgsmeshlayer.h"
60 #include "qgsmeshlayer3drenderer.h"
61 #include "qgspoint3dsymbol.h"
62 #include "qgsrulebased3drenderer.h"
63 #include "qgspointcloudlayer.h"
65 #include "qgssourcecache.h"
66 #include "qgsterrainentity_p.h"
67 #include "qgsterraingenerator.h"
69 #include "qgsvectorlayer.h"
73 
74 #include "qgslinematerial_p.h"
75 #include "qgs3dsceneexporter.h"
76 #include "qgsabstract3drenderer.h"
77 #include "qgs3dmapexportsettings.h"
78 #include "qgsmessageoutput.h"
79 
80 #include "qgsskyboxentity.h"
81 #include "qgsskyboxsettings.h"
82 
83 #include "qgswindow3dengine.h"
85 #include "qgspointcloudlayer.h"
87 
89  : mMap( map )
90  , mEngine( engine )
91 {
92 
93  connect( &map, &Qgs3DMapSettings::backgroundColorChanged, this, &Qgs3DMapScene::onBackgroundColorChanged );
94  onBackgroundColorChanged();
95 
96  // The default render policy in Qt3D is "Always" - i.e. the 3D map scene gets refreshed up to 60 fps
97  // even if there's no change. Switching to "on demand" should only re-render when something has changed
98  // and we save quite a lot of resources
99  mEngine->renderSettings()->setRenderPolicy( Qt3DRender::QRenderSettings::OnDemand );
100 
101  // we want precise picking of terrain (also bounding volume picking does not seem to work - not sure why)
102  mEngine->renderSettings()->pickingSettings()->setPickMethod( Qt3DRender::QPickingSettings::TrianglePicking );
103 
104  QRect viewportRect( QPoint( 0, 0 ), mEngine->size() );
105 
106  // Camera
107  float aspectRatio = ( float )viewportRect.width() / viewportRect.height();
108  mEngine->camera()->lens()->setPerspectiveProjection( mMap.fieldOfView(), aspectRatio, 10.f, 10000.0f );
109 
110  mFrameAction = new Qt3DLogic::QFrameAction();
111  connect( mFrameAction, &Qt3DLogic::QFrameAction::triggered,
112  this, &Qgs3DMapScene::onFrameTriggered );
113  addComponent( mFrameAction ); // takes ownership
114 
115  // Camera controlling
116  mCameraController = new QgsCameraController( this ); // attaches to the scene
117  mCameraController->setViewport( viewportRect );
118  mCameraController->setCamera( mEngine->camera() );
119  mCameraController->resetView( 1000 );
120 
121  addCameraViewCenterEntity( mEngine->camera() );
122  addCameraRotationCenterEntity( mCameraController );
123  updateLights();
124 
125  // create terrain entity
126 
127  createTerrainDeferred();
128  connect( &map, &Qgs3DMapSettings::terrainGeneratorChanged, this, &Qgs3DMapScene::createTerrain );
129  connect( &map, &Qgs3DMapSettings::terrainVerticalScaleChanged, this, &Qgs3DMapScene::createTerrain );
130  connect( &map, &Qgs3DMapSettings::mapTileResolutionChanged, this, &Qgs3DMapScene::createTerrain );
131  connect( &map, &Qgs3DMapSettings::maxTerrainScreenErrorChanged, this, &Qgs3DMapScene::createTerrain );
132  connect( &map, &Qgs3DMapSettings::maxTerrainGroundErrorChanged, this, &Qgs3DMapScene::createTerrain );
133  connect( &map, &Qgs3DMapSettings::terrainShadingChanged, this, &Qgs3DMapScene::createTerrain );
134  connect( &map, &Qgs3DMapSettings::lightSourcesChanged, this, &Qgs3DMapScene::updateLights );
135  connect( &map, &Qgs3DMapSettings::showLightSourceOriginsChanged, this, &Qgs3DMapScene::updateLights );
136  connect( &map, &Qgs3DMapSettings::fieldOfViewChanged, this, &Qgs3DMapScene::updateCameraLens );
137  connect( &map, &Qgs3DMapSettings::projectionTypeChanged, this, &Qgs3DMapScene::updateCameraLens );
138  connect( &map, &Qgs3DMapSettings::renderersChanged, this, &Qgs3DMapScene::onRenderersChanged );
139  connect( &map, &Qgs3DMapSettings::skyboxSettingsChanged, this, &Qgs3DMapScene::onSkyboxSettingsChanged );
140  connect( &map, &Qgs3DMapSettings::shadowSettingsChanged, this, &Qgs3DMapScene::onShadowSettingsChanged );
141  connect( &map, &Qgs3DMapSettings::eyeDomeLightingEnabledChanged, this, &Qgs3DMapScene::onEyeDomeShadingSettingsChanged );
142  connect( &map, &Qgs3DMapSettings::eyeDomeLightingStrengthChanged, this, &Qgs3DMapScene::onEyeDomeShadingSettingsChanged );
143  connect( &map, &Qgs3DMapSettings::eyeDomeLightingDistanceChanged, this, &Qgs3DMapScene::onEyeDomeShadingSettingsChanged );
144  connect( &map, &Qgs3DMapSettings::debugShadowMapSettingsChanged, this, &Qgs3DMapScene::onDebugShadowMapSettingsChanged );
145  connect( &map, &Qgs3DMapSettings::debugDepthMapSettingsChanged, this, &Qgs3DMapScene::onDebugDepthMapSettingsChanged );
147  connect( &map, &Qgs3DMapSettings::cameraMovementSpeedChanged, this, &Qgs3DMapScene::onCameraMovementSpeedChanged );
148  connect( &map, &Qgs3DMapSettings::cameraNavigationModeChanged, this, &Qgs3DMapScene::onCameraNavigationModeChanged );
149  connect( &map, &Qgs3DMapSettings::debugOverlayEnabledChanged, this, &Qgs3DMapScene::onDebugOverlayEnabledChanged );
150 
151  connect( &map, &Qgs3DMapSettings::axisSettingsChanged, this, &Qgs3DMapScene::on3DAxisSettingsChanged );
152 
153  connect( QgsApplication::sourceCache(), &QgsSourceCache::remoteSourceFetched, this, [ = ]( const QString & url )
154  {
155  const QList<QgsMapLayer *> modelVectorLayers = mModelVectorLayers;
156  for ( QgsMapLayer *layer : modelVectorLayers )
157  {
158  QgsAbstract3DRenderer *renderer = layer->renderer3D();
159  if ( renderer )
160  {
161  if ( renderer->type() == QLatin1String( "vector" ) )
162  {
163  const QgsPoint3DSymbol *pointSymbol = static_cast< const QgsPoint3DSymbol * >( static_cast< QgsVectorLayer3DRenderer *>( renderer )->symbol() );
164  if ( pointSymbol->shapeProperties()[QStringLiteral( "model" )].toString() == url )
165  {
166  removeLayerEntity( layer );
167  addLayerEntity( layer );
168  }
169  }
170  else if ( renderer->type() == QLatin1String( "rulebased" ) )
171  {
172  const QgsRuleBased3DRenderer::RuleList rules = static_cast< QgsRuleBased3DRenderer *>( renderer )->rootRule()->descendants();
173  for ( auto rule : rules )
174  {
175  const QgsPoint3DSymbol *pointSymbol = dynamic_cast< const QgsPoint3DSymbol * >( rule->symbol() );
176  if ( pointSymbol->shapeProperties()[QStringLiteral( "model" )].toString() == url )
177  {
178  removeLayerEntity( layer );
179  addLayerEntity( layer );
180  break;
181  }
182  }
183  }
184  }
185  }
186  } );
187 
188  // create entities of renderers
189 
190  onRenderersChanged();
191 
192  // listen to changes of layers in order to add/remove 3D renderer entities
193  connect( &map, &Qgs3DMapSettings::layersChanged, this, &Qgs3DMapScene::onLayersChanged );
194 
195 
196 #if 0
197  ChunkedEntity *testChunkEntity = new ChunkedEntity( AABB( -500, 0, -500, 500, 100, 500 ), 2.f, 3.f, 7, new TestChunkLoaderFactory );
198  testChunkEntity->setEnabled( false );
199  testChunkEntity->setParent( this );
200  chunkEntities << testChunkEntity;
201 #endif
202 
203  connect( mCameraController, &QgsCameraController::cameraChanged, this, &Qgs3DMapScene::onCameraChanged );
204  connect( mCameraController, &QgsCameraController::viewportChanged, this, &Qgs3DMapScene::onCameraChanged );
205 
206 #if 0
207  // experiments with loading of existing 3D models.
208 
209  // scene loader only gets loaded only when added to a scene...
210  // it loads everything: geometries, materials, transforms, lights, cameras (if any)
211  Qt3DCore::QEntity *loaderEntity = new Qt3DCore::QEntity;
212  Qt3DRender::QSceneLoader *loader = new Qt3DRender::QSceneLoader;
213  loader->setSource( QUrl( "file:///home/martin/Downloads/LowPolyModels/tree.dae" ) );
214  loaderEntity->addComponent( loader );
215  loaderEntity->setParent( this );
216 
217  // mesh loads just geometry as one geometry...
218  // so if there are different materials (e.g. colors) used in the model, this information is lost
219  Qt3DCore::QEntity *meshEntity = new Qt3DCore::QEntity;
220  Qt3DRender::QMesh *mesh = new Qt3DRender::QMesh;
221  mesh->setSource( QUrl( "file:///home/martin/Downloads/LowPolyModels/tree.obj" ) );
222  meshEntity->addComponent( mesh );
223  Qt3DExtras::QPhongMaterial *material = new Qt3DExtras::QPhongMaterial;
224  material->setAmbient( Qt::red );
225  meshEntity->addComponent( material );
226  Qt3DCore::QTransform *meshTransform = new Qt3DCore::QTransform;
227  meshTransform->setScale( 1 );
228  meshEntity->addComponent( meshTransform );
229  meshEntity->setParent( this );
230 #endif
231  onSkyboxSettingsChanged();
232 
233  // force initial update of chunked entities
234  onCameraChanged();
235  // force initial update of eye dome shading
236  onEyeDomeShadingSettingsChanged();
237  // force initial update of debugging setting of preview quads
238  onDebugShadowMapSettingsChanged();
239  onDebugDepthMapSettingsChanged();
240 
241  mCameraController->setCameraNavigationMode( mMap.cameraNavigationMode() );
242  onCameraMovementSpeedChanged();
243 
244  on3DAxisSettingsChanged();
245 }
246 
248 {
249  QgsRectangle extent = sceneExtent();
250  float side = std::max( extent.width(), extent.height() );
251  float a = side / 2.0f / std::sin( qDegreesToRadians( cameraController()->camera()->fieldOfView() ) / 2.0f );
252  // Note: the 1.5 multiplication is to move the view upwards to look better
253  mCameraController->resetView( 1.5 * std::sqrt( a * a - side * side ) ); // assuming FOV being 45 degrees
254 }
255 
257 {
258  QgsPointXY center = extent.center();
259  QgsVector3D centerWorld = mMap.mapToWorldCoordinates( QVector3D( center.x(), center.y(), 0 ) );
260  QgsVector3D p1 = mMap.mapToWorldCoordinates( QVector3D( extent.xMinimum(), extent.yMinimum(), 0 ) );
261  QgsVector3D p2 = mMap.mapToWorldCoordinates( QVector3D( extent.xMaximum(), extent.yMaximum(), 0 ) );
262 
263  float xSide = std::abs( p1.x() - p2.x() );
264  float ySide = std::abs( p1.z() - p2.z() );
265  if ( xSide < ySide )
266  {
267  float fov = 2 * std::atan( std::tan( qDegreesToRadians( cameraController()->camera()->fieldOfView() ) / 2 ) * cameraController()->camera()->aspectRatio() );
268  float r = xSide / 2.0f / std::tan( fov / 2.0f );
269  mCameraController->setViewFromTop( centerWorld.x(), centerWorld.z(), r );
270  }
271  else
272  {
273  float fov = qDegreesToRadians( cameraController()->camera()->fieldOfView() );
274  float r = ySide / 2.0f / std::tan( fov / 2.0f );
275  mCameraController->setViewFromTop( centerWorld.x(), centerWorld.z(), r );
276  }
277 }
278 
280 {
281  Qt3DRender::QCamera *camera = mCameraController->camera();
282  const QRect viewport = mCameraController->viewport();
283  QVector<QgsPointXY> extent;
284  QVector<int> pointsOrder = { 0, 1, 3, 2 };
285  for ( int i : pointsOrder )
286  {
287  const QPoint p( ( ( i >> 0 ) & 1 ) ? 0 : viewport.width(), ( ( i >> 1 ) & 1 ) ? 0 : viewport.height() );
288  QgsRay3D ray = Qgs3DUtils::rayFromScreenPoint( p, viewport.size(), camera );
289  QVector3D dir = ray.direction();
290  if ( dir.y() == 0.0 )
291  dir.setY( 0.000001 );
292  double t = - ray.origin().y() / dir.y();
293  if ( t < 0 )
294  {
295  // If the projected point is on the back of the camera we choose the farthest point in the front
296  t = camera->farPlane();
297  }
298  else
299  {
300  // If the projected point is on the front of the camera we choose the closest between it and farthest point in the front
301  t = std::min<float>( t, camera->farPlane() );
302  }
303  QVector3D planePoint = ray.origin() + t * dir;
304  QgsVector3D pMap = mMap.worldToMapCoordinates( planePoint );
305  extent.push_back( QgsPointXY( pMap.x(), pMap.y() ) );
306  }
307  return extent;
308 }
309 
311 {
312  return mTerrain ? mTerrain->pendingJobsCount() : 0;
313 }
314 
316 {
317  int count = 0;
318  for ( QgsChunkedEntity *entity : std::as_const( mChunkEntities ) )
319  count += entity->pendingJobsCount();
320  return count;
321 }
322 
324 {
325  if ( mPickHandlers.isEmpty() )
326  {
327  // we need to add object pickers
328  for ( Qt3DCore::QEntity *entity : mLayerEntities.values() )
329  {
330  if ( QgsChunkedEntity *chunkedEntity = qobject_cast<QgsChunkedEntity *>( entity ) )
331  chunkedEntity->setPickingEnabled( true );
332  }
333  }
334 
335  mPickHandlers.append( pickHandler );
336 }
337 
339 {
340  mPickHandlers.removeOne( pickHandler );
341 
342  if ( mPickHandlers.isEmpty() )
343  {
344  // we need to remove pickers
345  for ( Qt3DCore::QEntity *entity : mLayerEntities.values() )
346  {
347  if ( QgsChunkedEntity *chunkedEntity = qobject_cast<QgsChunkedEntity *>( entity ) )
348  chunkedEntity->setPickingEnabled( false );
349  }
350  }
351 }
352 
353 void Qgs3DMapScene::onLayerEntityPickedObject( Qt3DRender::QPickEvent *pickEvent, QgsFeatureId fid )
354 {
355  QgsMapLayer *layer = mLayerEntities.key( qobject_cast<QgsChunkedEntity *>( sender() ) );
356  if ( !layer )
357  return;
358 
359  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
360  if ( !vlayer )
361  return;
362 
363  for ( Qgs3DMapScenePickHandler *pickHandler : std::as_const( mPickHandlers ) )
364  {
365  pickHandler->handlePickOnVectorLayer( vlayer, fid, pickEvent->worldIntersection(), pickEvent );
366  }
367 }
368 
369 float Qgs3DMapScene::worldSpaceError( float epsilon, float distance )
370 {
371  Qt3DRender::QCamera *camera = mCameraController->camera();
372  float fov = camera->fieldOfView();
373  QRect rect = mCameraController->viewport();
374  float screenSizePx = std::max( rect.width(), rect.height() ); // TODO: is this correct?
375 
376  // in qgschunkedentity_p.cpp there is inverse calculation (world space error to screen space error)
377  // with explanation of the math.
378  float frustumWidthAtDistance = 2 * distance * tan( fov / 2 );
379  float err = frustumWidthAtDistance * epsilon / screenSizePx;
380  return err;
381 }
382 
383 QgsChunkedEntity::SceneState _sceneState( QgsCameraController *cameraController )
384 {
385  Qt3DRender::QCamera *camera = cameraController->camera();
386  QgsChunkedEntity::SceneState state;
387  state.cameraFov = camera->fieldOfView();
388  state.cameraPos = camera->position();
389  QRect rect = cameraController->viewport();
390  state.screenSizePx = std::max( rect.width(), rect.height() ); // TODO: is this correct?
391  state.viewProjectionMatrix = camera->projectionMatrix() * camera->viewMatrix();
392  return state;
393 }
394 
395 void Qgs3DMapScene::onCameraChanged()
396 {
397  if ( mMap.projectionType() == Qt3DRender::QCameraLens::OrthographicProjection )
398  {
399  QRect viewportRect( QPoint( 0, 0 ), mEngine->size() );
400  const float viewWidthFromCenter = mCameraController->distance();
401  const float viewHeightFromCenter = viewportRect.height() * viewWidthFromCenter / viewportRect.width();
402  mEngine->camera()->lens()->setOrthographicProjection( -viewWidthFromCenter, viewWidthFromCenter, -viewHeightFromCenter, viewHeightFromCenter, mEngine->camera()->nearPlane(), mEngine->camera()->farPlane() );
403  }
404 
405  updateScene();
406  bool changedCameraPlanes = updateCameraNearFarPlanes();
407 
408  if ( changedCameraPlanes )
409  {
410  // repeat update of entities - because we have updated camera's near/far planes,
411  // the active nodes may have changed as well
412  updateScene();
413  updateCameraNearFarPlanes();
414  }
415 
416  onShadowSettingsChanged();
417 
418  QVector<QgsPointXY> extent2D = viewFrustum2DExtent();
419  emit viewed2DExtentFrom3DChanged( extent2D );
420 }
421 
422 void removeQLayerComponentsFromHierarchy( Qt3DCore::QEntity *entity )
423 {
424  QVector<Qt3DCore::QComponent *> toBeRemovedComponents;
425  for ( Qt3DCore::QComponent *component : entity->components() )
426  {
427  Qt3DRender::QLayer *layer = qobject_cast<Qt3DRender::QLayer *>( component );
428  if ( layer != nullptr )
429  toBeRemovedComponents.push_back( layer );
430  }
431  for ( Qt3DCore::QComponent *component : toBeRemovedComponents )
432  entity->removeComponent( component );
433  for ( Qt3DCore::QEntity *obj : entity->findChildren<Qt3DCore::QEntity *>() )
434  {
435  if ( obj != nullptr )
437  }
438 }
439 
440 void addQLayerComponentsToHierarchy( Qt3DCore::QEntity *entity, const QVector<Qt3DRender::QLayer *> &layers )
441 {
442  for ( Qt3DRender::QLayer *layer : layers )
443  entity->addComponent( layer );
444  for ( Qt3DCore::QEntity *child : entity->findChildren<Qt3DCore::QEntity *>() )
445  {
446  if ( child != nullptr )
447  addQLayerComponentsToHierarchy( child, layers );
448  }
449 }
450 
451 void Qgs3DMapScene::updateScene()
452 {
453  QgsEventTracing::addEvent( QgsEventTracing::Instant, QStringLiteral( "3D" ), QStringLiteral( "Update Scene" ) );
454  for ( QgsChunkedEntity *entity : std::as_const( mChunkEntities ) )
455  {
456  if ( entity->isEnabled() )
457  entity->update( _sceneState( mCameraController ) );
458  }
459  updateSceneState();
460 }
461 
462 static void _updateNearFarPlane( const QList<QgsChunkNode *> &activeNodes, const QMatrix4x4 &viewMatrix, float &fnear, float &ffar )
463 {
464  for ( QgsChunkNode *node : activeNodes )
465  {
466  // project each corner of bbox to camera coordinates
467  // and determine closest and farthest point.
468  QgsAABB bbox = node->bbox();
469  for ( int i = 0; i < 8; ++i )
470  {
471  QVector4D p( ( ( i >> 0 ) & 1 ) ? bbox.xMin : bbox.xMax,
472  ( ( i >> 1 ) & 1 ) ? bbox.yMin : bbox.yMax,
473  ( ( i >> 2 ) & 1 ) ? bbox.zMin : bbox.zMax, 1 );
474 
475  QVector4D pc = viewMatrix * p;
476 
477 
478  float dst = -pc.z(); // in camera coordinates, x grows right, y grows down, z grows to the back
479  fnear = std::min( fnear, dst );
480  ffar = std::max( ffar, dst );
481  }
482  }
483 }
484 
485 bool Qgs3DMapScene::updateCameraNearFarPlanes()
486 {
487  // Update near and far plane from the terrain.
488  // this needs to be done with great care as we have kind of circular dependency here:
489  // active nodes are culled based on the current frustum (which involves near + far plane)
490  // and then based on active nodes we set near and far plane.
491  //
492  // All of this is just heuristics assuming that all other stuff is being rendered somewhere
493  // around the area where the terrain is.
494  //
495  // Near/far plane is setup in order to make best use of the depth buffer to avoid:
496  // 1. precision errors - if the range is too great
497  // 2. unwanted clipping of scene - if the range is too small
498 
499  Qt3DRender::QCamera *camera = cameraController()->camera();
500  QMatrix4x4 viewMatrix = camera->viewMatrix();
501  float fnear = 1e9;
502  float ffar = 0;
503  QList<QgsChunkNode *> activeNodes;
504  if ( mTerrain )
505  activeNodes = mTerrain->activeNodes();
506 
507  // it could be that there are no active nodes - they could be all culled or because root node
508  // is not yet loaded - we still need at least something to understand bounds of our scene
509  // so lets use the root node
510  if ( mTerrain && activeNodes.isEmpty() )
511  activeNodes << mTerrain->rootNode();
512 
513  _updateNearFarPlane( activeNodes, viewMatrix, fnear, ffar );
514 
515  // Also involve all the other chunked entities to make sure that they will not get
516  // clipped by the near or far plane
517  for ( QgsChunkedEntity *e : std::as_const( mChunkEntities ) )
518  {
519  if ( e != mTerrain )
520  {
521  QList<QgsChunkNode *> activeEntityNodes = e->activeNodes();
522  if ( activeEntityNodes.empty() )
523  activeEntityNodes << e->rootNode();
524  _updateNearFarPlane( activeEntityNodes, viewMatrix, fnear, ffar );
525  }
526  }
527 
528  if ( fnear < 1 )
529  fnear = 1; // does not really make sense to use negative far plane (behind camera)
530 
531  // when zooming in a lot, fnear can become smaller than ffar. This should not happen
532  if ( fnear > ffar )
533  std::swap( fnear, ffar );
534 
535  if ( fnear == 1e9 && ffar == 0 )
536  {
537  // the update didn't work out... this should not happen
538  // well at least temporarily use some conservative starting values
539  qWarning() << "oops... this should not happen! couldn't determine near/far plane. defaulting to 1...1e9";
540  fnear = 1;
541  ffar = 1e9;
542  }
543 
544  // set near/far plane - with some tolerance in front/behind expected near/far planes
545  float newFar = ffar * 2;
546  float newNear = fnear / 2;
547  if ( !qgsFloatNear( newFar, camera->farPlane() ) || !qgsFloatNear( newNear, camera->nearPlane() ) )
548  {
549  camera->setFarPlane( newFar );
550  camera->setNearPlane( newNear );
551  return true;
552  }
553 
554  return false;
555 }
556 
557 void Qgs3DMapScene::onFrameTriggered( float dt )
558 {
559  mCameraController->frameTriggered( dt );
560 
561  for ( QgsChunkedEntity *entity : std::as_const( mChunkEntities ) )
562  {
563  if ( entity->isEnabled() && entity->needsUpdate() )
564  {
565  QgsDebugMsgLevel( QStringLiteral( "need for update" ), 2 );
566  entity->update( _sceneState( mCameraController ) );
567  }
568  }
569 
570  updateSceneState();
571 
572  // lock changing the FPS counter to 5 fps
573  static int frameCount = 0;
574  static float accumulatedTime = 0.0f;
575 
576  if ( !mMap.isFpsCounterEnabled() )
577  {
578  frameCount = 0;
579  accumulatedTime = 0;
580  return;
581  }
582 
583  frameCount++;
584  accumulatedTime += dt;
585  if ( accumulatedTime >= 0.2f )
586  {
587  float fps = ( float )frameCount / accumulatedTime;
588  frameCount = 0;
589  accumulatedTime = 0.0f;
590  emit fpsCountChanged( fps );
591  }
592 }
593 
594 void Qgs3DMapScene::createTerrain()
595 {
596  if ( mTerrain )
597  {
598  mChunkEntities.removeOne( mTerrain );
599 
600  mTerrain->deleteLater();
601  mTerrain = nullptr;
602  }
603 
604  if ( !mTerrainUpdateScheduled )
605  {
606  // defer re-creation of terrain: there may be multiple invocations of this slot, so create the new entity just once
607  QTimer::singleShot( 0, this, &Qgs3DMapScene::createTerrainDeferred );
608  mTerrainUpdateScheduled = true;
609  setSceneState( Updating );
610  }
611  else
612  {
613  emit terrainEntityChanged();
614  }
615 }
616 
617 void Qgs3DMapScene::createTerrainDeferred()
618 {
619  if ( mMap.terrainRenderingEnabled() && mMap.terrainGenerator() )
620  {
621  double tile0width = mMap.terrainGenerator()->extent().width();
622  int maxZoomLevel = Qgs3DUtils::maxZoomLevel( tile0width, mMap.mapTileResolution(), mMap.maxTerrainGroundError() );
623  QgsAABB rootBbox = mMap.terrainGenerator()->rootChunkBbox( mMap );
624  float rootError = mMap.terrainGenerator()->rootChunkError( mMap );
625  mMap.terrainGenerator()->setupQuadtree( rootBbox, rootError, maxZoomLevel );
626 
627  mTerrain = new QgsTerrainEntity( mMap );
628  mTerrain->setParent( this );
629  mTerrain->setShowBoundingBoxes( mMap.showTerrainBoundingBoxes() );
630 
631  mCameraController->setTerrainEntity( mTerrain );
632 
633  mChunkEntities << mTerrain;
634 
635  connect( mTerrain, &QgsChunkedEntity::pendingJobsCountChanged, this, &Qgs3DMapScene::totalPendingJobsCountChanged );
636  connect( mTerrain, &QgsTerrainEntity::pendingJobsCountChanged, this, &Qgs3DMapScene::terrainPendingJobsCountChanged );
637  }
638  else
639  {
640  mTerrain = nullptr;
641  mCameraController->setTerrainEntity( mTerrain );
642  }
643 
644  // make sure that renderers for layers are re-created as well
645  const QList<QgsMapLayer *> layers = mMap.layers();
646  for ( QgsMapLayer *layer : layers )
647  {
648  // remove old entity - if any
649  removeLayerEntity( layer );
650 
651  // add new entity - if any 3D renderer
652  addLayerEntity( layer );
653  }
654 
655  emit terrainEntityChanged();
656  onCameraChanged(); // force update of the new terrain
657  mTerrainUpdateScheduled = false;
658 }
659 
660 void Qgs3DMapScene::onBackgroundColorChanged()
661 {
662  mEngine->setClearColor( mMap.backgroundColor() );
663 }
664 
665 void Qgs3DMapScene::updateLights()
666 {
667  for ( Qt3DCore::QEntity *entity : std::as_const( mLightEntities ) )
668  entity->deleteLater();
669  mLightEntities.clear();
670 
671  const QList< QgsLightSource * > newLights = mMap.lightSources();
672  for ( const QgsLightSource *source : newLights )
673  {
674  mLightEntities.append( source->createEntity( mMap, this ) );
675  }
676 
677  onShadowSettingsChanged();
678 }
679 
680 void Qgs3DMapScene::updateCameraLens()
681 {
682  mEngine->camera()->lens()->setFieldOfView( mMap.fieldOfView() );
683  mEngine->camera()->lens()->setProjectionType( mMap.projectionType() );
684  onCameraChanged();
685 }
686 
687 void Qgs3DMapScene::onRenderersChanged()
688 {
689  // remove entities (if any)
690  qDeleteAll( mRenderersEntities );
691  mRenderersEntities.clear();
692 
693  // re-add entities from new set of renderers
694  const QList<QgsAbstract3DRenderer *> renderers = mMap.renderers();
695  for ( const QgsAbstract3DRenderer *renderer : renderers )
696  {
697  Qt3DCore::QEntity *newEntity = renderer->createEntity( mMap );
698  if ( newEntity )
699  {
700  newEntity->setParent( this );
701  finalizeNewEntity( newEntity );
702  mRenderersEntities[renderer] = newEntity;
703  }
704  }
705 }
706 
707 void Qgs3DMapScene::onLayerRenderer3DChanged()
708 {
709  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
710  Q_ASSERT( layer );
711 
712  // remove old entity - if any
713  removeLayerEntity( layer );
714 
715  // add new entity - if any 3D renderer
716  addLayerEntity( layer );
717 }
718 
719 void Qgs3DMapScene::onLayersChanged()
720 {
721  QSet<QgsMapLayer *> layersBefore = qgis::listToSet( mLayerEntities.keys() );
722  QList<QgsMapLayer *> layersAdded;
723  const QList<QgsMapLayer *> layers = mMap.layers();
724  for ( QgsMapLayer *layer : layers )
725  {
726  if ( !layersBefore.contains( layer ) )
727  {
728  layersAdded << layer;
729  }
730  else
731  {
732  layersBefore.remove( layer );
733  }
734  }
735 
736  // what is left in layersBefore are layers that have been removed
737  for ( QgsMapLayer *layer : std::as_const( layersBefore ) )
738  {
739  removeLayerEntity( layer );
740  }
741 
742  for ( QgsMapLayer *layer : std::as_const( layersAdded ) )
743  {
744  addLayerEntity( layer );
745  }
746 }
747 
749 {
750  for ( auto layer : mLayerEntities.keys() )
751  {
752  if ( layer->temporalProperties()->isActive() )
753  {
754  removeLayerEntity( layer );
755  addLayerEntity( layer );
756  }
757  }
758 }
759 
760 void Qgs3DMapScene::addLayerEntity( QgsMapLayer *layer )
761 {
762  bool needsSceneUpdate = false;
763  QgsAbstract3DRenderer *renderer = layer->renderer3D();
764  if ( renderer )
765  {
766  // Fix vector layer's renderer to make sure the renderer is pointing to its layer.
767  // It has happened before that renderer pointed to a different layer (probably after copying a style).
768  // This is a bit of a hack and it should be handled in QgsMapLayer::setRenderer3D() but in qgis_core
769  // the vector layer 3D renderer classes are not available.
770  if ( layer->type() == QgsMapLayerType::VectorLayer &&
771  ( renderer->type() == QLatin1String( "vector" ) || renderer->type() == QLatin1String( "rulebased" ) ) )
772  {
773  static_cast<QgsAbstractVectorLayer3DRenderer *>( renderer )->setLayer( static_cast<QgsVectorLayer *>( layer ) );
774  if ( renderer->type() == QLatin1String( "vector" ) )
775  {
776  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
777  if ( vlayer->geometryType() == QgsWkbTypes::PointGeometry )
778  {
779  const QgsPoint3DSymbol *pointSymbol = static_cast< const QgsPoint3DSymbol * >( static_cast< QgsVectorLayer3DRenderer *>( renderer )->symbol() );
780  if ( pointSymbol->shape() == QgsPoint3DSymbol::Model )
781  {
782  mModelVectorLayers.append( layer );
783  }
784  }
785  }
786  else if ( renderer->type() == QLatin1String( "rulebased" ) )
787  {
788  const QgsRuleBased3DRenderer::RuleList rules = static_cast< QgsRuleBased3DRenderer *>( renderer )->rootRule()->descendants();
789  for ( auto rule : rules )
790  {
791  const QgsPoint3DSymbol *pointSymbol = dynamic_cast< const QgsPoint3DSymbol * >( rule->symbol() );
792  if ( pointSymbol && pointSymbol->shape() == QgsPoint3DSymbol::Model )
793  {
794  mModelVectorLayers.append( layer );
795  break;
796  }
797  }
798  }
799  }
800  else if ( layer->type() == QgsMapLayerType::MeshLayer && renderer->type() == QLatin1String( "mesh" ) )
801  {
802  QgsMeshLayer3DRenderer *meshRenderer = static_cast<QgsMeshLayer3DRenderer *>( renderer );
803  meshRenderer->setLayer( static_cast<QgsMeshLayer *>( layer ) );
804 
805  // Before entity creation, set the maximum texture size
806  // Not very clean, but for now, only place found in the workflow to do that simple
807  QgsMesh3DSymbol *sym = meshRenderer->symbol()->clone();
808  sym->setMaximumTextureSize( maximumTextureSize() );
809  meshRenderer->setSymbol( sym );
810  }
811  else if ( layer->type() == QgsMapLayerType::PointCloudLayer && renderer->type() == QLatin1String( "pointcloud" ) )
812  {
813  QgsPointCloudLayer3DRenderer *pointCloudRenderer = static_cast<QgsPointCloudLayer3DRenderer *>( renderer );
814  pointCloudRenderer->setLayer( static_cast<QgsPointCloudLayer *>( layer ) );
815  }
816 
817  Qt3DCore::QEntity *newEntity = renderer->createEntity( mMap );
818  if ( newEntity )
819  {
820  newEntity->setParent( this );
821  mLayerEntities.insert( layer, newEntity );
822 
823  finalizeNewEntity( newEntity );
824 
825  if ( QgsChunkedEntity *chunkedNewEntity = qobject_cast<QgsChunkedEntity *>( newEntity ) )
826  {
827  mChunkEntities.append( chunkedNewEntity );
828  needsSceneUpdate = true;
829 
830  chunkedNewEntity->setPickingEnabled( !mPickHandlers.isEmpty() );
831  connect( chunkedNewEntity, &QgsChunkedEntity::pickedObject, this, &Qgs3DMapScene::onLayerEntityPickedObject );
832 
833  connect( chunkedNewEntity, &QgsChunkedEntity::newEntityCreated, this, [this]( Qt3DCore::QEntity * entity )
834  {
835  finalizeNewEntity( entity );
836  } );
837 
838  connect( chunkedNewEntity, &QgsChunkedEntity::pendingJobsCountChanged, this, &Qgs3DMapScene::totalPendingJobsCountChanged );
839  }
840  }
841  }
842 
843  if ( needsSceneUpdate )
844  onCameraChanged(); // needed for chunked entities
845 
846  connect( layer, &QgsMapLayer::request3DUpdate, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
847 
848  if ( layer->type() == QgsMapLayerType::VectorLayer )
849  {
850  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
851  connect( vlayer, &QgsVectorLayer::selectionChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
852  connect( vlayer, &QgsVectorLayer::layerModified, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
853  }
854 
855  if ( layer->type() == QgsMapLayerType::MeshLayer )
856  {
857  connect( layer, &QgsMapLayer::rendererChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
858  }
859 
860  if ( layer->type() == QgsMapLayerType::PointCloudLayer )
861  {
862  QgsPointCloudLayer *pclayer = qobject_cast<QgsPointCloudLayer *>( layer );
863  connect( pclayer, &QgsPointCloudLayer::renderer3DChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
864  connect( pclayer, &QgsPointCloudLayer::subsetStringChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
865  }
866 }
867 
868 void Qgs3DMapScene::removeLayerEntity( QgsMapLayer *layer )
869 {
870  Qt3DCore::QEntity *entity = mLayerEntities.take( layer );
871 
872  if ( QgsChunkedEntity *chunkedEntity = qobject_cast<QgsChunkedEntity *>( entity ) )
873  {
874  mChunkEntities.removeOne( chunkedEntity );
875  }
876 
877  if ( entity )
878  entity->deleteLater();
879 
880  disconnect( layer, &QgsMapLayer::request3DUpdate, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
881 
882  if ( layer->type() == QgsMapLayerType::VectorLayer )
883  {
884  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
885  disconnect( vlayer, &QgsVectorLayer::selectionChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
886  disconnect( vlayer, &QgsVectorLayer::layerModified, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
887  mModelVectorLayers.removeAll( layer );
888  }
889 
890  if ( layer->type() == QgsMapLayerType::MeshLayer )
891  {
892  disconnect( layer, &QgsMapLayer::rendererChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
893  }
894 
895  if ( layer->type() == QgsMapLayerType::PointCloudLayer )
896  {
897  QgsPointCloudLayer *pclayer = qobject_cast<QgsPointCloudLayer *>( layer );
898  disconnect( pclayer, &QgsPointCloudLayer::renderer3DChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
899  disconnect( pclayer, &QgsPointCloudLayer::subsetStringChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
900  }
901 }
902 
903 void Qgs3DMapScene::finalizeNewEntity( Qt3DCore::QEntity *newEntity )
904 {
905  // this is probably not the best place for material-specific configuration,
906  // maybe this could be more generalized when other materials need some specific treatment
907  for ( QgsLineMaterial *lm : newEntity->findChildren<QgsLineMaterial *>() )
908  {
909  connect( mCameraController, &QgsCameraController::viewportChanged, lm, [lm, this]
910  {
911  lm->setViewportSize( mCameraController->viewport().size() );
912  } );
913 
914  lm->setViewportSize( cameraController()->viewport().size() );
915  }
916  // configure billboard's viewport when the viewport is changed.
917  for ( QgsPoint3DBillboardMaterial *bm : newEntity->findChildren<QgsPoint3DBillboardMaterial *>() )
918  {
919  connect( mCameraController, &QgsCameraController::viewportChanged, bm, [bm, this]
920  {
921  bm->setViewportSize( mCameraController->viewport().size() );
922  } );
923 
924  bm->setViewportSize( mCameraController->viewport().size() );
925  }
926 
927 
928  // Finalize adding the 3D transparent objects by adding the layer components to the entities
929  QgsShadowRenderingFrameGraph *frameGraph = mEngine->frameGraph();
930  Qt3DRender::QLayer *layer = frameGraph->transparentObjectLayer();
931  for ( Qt3DExtras::QDiffuseSpecularMaterial *ph : newEntity->findChildren<Qt3DExtras::QDiffuseSpecularMaterial *>() )
932  {
933  if ( ph->diffuse().value<QColor>().alphaF() == 1.0f )
934  continue;
935  Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( ph->parent() );
936  if ( !entity )
937  continue;
938  if ( entity->components().contains( layer ) )
939  continue;
940  entity->addComponent( layer );
941  }
942 }
943 
944 int Qgs3DMapScene::maximumTextureSize() const
945 {
946  QSurface *surface = mEngine->surface();
947  QOpenGLContext context;
948  context.create();
949  bool success = context.makeCurrent( surface );
950 
951  if ( success )
952  {
953  QOpenGLFunctions openglFunctions = QOpenGLFunctions( &context );
954 
955  GLint size;
956  openglFunctions.initializeOpenGLFunctions();
957  openglFunctions.glGetIntegerv( GL_MAX_TEXTURE_SIZE, &size );
958  return int( size );
959  }
960  else
961  {
962  return 4096; //we can't have a context to defined the max texture size, we use this reasonable value
963  }
964 
965 }
966 
967 void Qgs3DMapScene::addCameraViewCenterEntity( Qt3DRender::QCamera *camera )
968 {
969  mEntityCameraViewCenter = new Qt3DCore::QEntity;
970 
971  Qt3DCore::QTransform *trCameraViewCenter = new Qt3DCore::QTransform;
972  mEntityCameraViewCenter->addComponent( trCameraViewCenter );
973  connect( camera, &Qt3DRender::QCamera::viewCenterChanged, this, [trCameraViewCenter, camera]
974  {
975  trCameraViewCenter->setTranslation( camera->viewCenter() );
976  } );
977 
978  Qt3DExtras::QPhongMaterial *materialCameraViewCenter = new Qt3DExtras::QPhongMaterial;
979  materialCameraViewCenter->setAmbient( Qt::red );
980  mEntityCameraViewCenter->addComponent( materialCameraViewCenter );
981 
982  Qt3DExtras::QSphereMesh *rendererCameraViewCenter = new Qt3DExtras::QSphereMesh;
983  rendererCameraViewCenter->setRadius( 10 );
984  mEntityCameraViewCenter->addComponent( rendererCameraViewCenter );
985 
986  mEntityCameraViewCenter->setEnabled( mMap.showCameraViewCenter() );
987  mEntityCameraViewCenter->setParent( this );
988 
989  connect( &mMap, &Qgs3DMapSettings::showCameraViewCenterChanged, this, [this]
990  {
991  mEntityCameraViewCenter->setEnabled( mMap.showCameraViewCenter() );
992  } );
993 }
994 
995 void Qgs3DMapScene::setSceneState( Qgs3DMapScene::SceneState state )
996 {
997  if ( mSceneState == state )
998  return;
999  mSceneState = state;
1000  emit sceneStateChanged();
1001 }
1002 
1003 void Qgs3DMapScene::updateSceneState()
1004 {
1005  if ( mTerrainUpdateScheduled )
1006  {
1007  setSceneState( Updating );
1008  return;
1009  }
1010 
1011  for ( QgsChunkedEntity *entity : std::as_const( mChunkEntities ) )
1012  {
1013  if ( entity->isEnabled() && entity->pendingJobsCount() > 0 )
1014  {
1015  setSceneState( Updating );
1016  return;
1017  }
1018  }
1019 
1020  setSceneState( Ready );
1021 }
1022 
1023 void Qgs3DMapScene::onSkyboxSettingsChanged()
1024 {
1025  QgsSkyboxSettings skyboxSettings = mMap.skyboxSettings();
1026  if ( mSkybox != nullptr )
1027  {
1028  mSkybox->deleteLater();
1029  mSkybox = nullptr;
1030  }
1031 
1032  mEngine->setFrustumCullingEnabled( !mMap.isSkyboxEnabled() );
1033 
1034  if ( mMap.isSkyboxEnabled() )
1035  {
1036  QMap<QString, QString> faces;
1037  switch ( skyboxSettings.skyboxType() )
1038  {
1040  faces = skyboxSettings.cubeMapFacesPaths();
1041  mSkybox = new QgsCubeFacesSkyboxEntity(
1042  faces[QStringLiteral( "posX" )], faces[QStringLiteral( "posY" )], faces[QStringLiteral( "posZ" )],
1043  faces[QStringLiteral( "negX" )], faces[QStringLiteral( "negY" )], faces[QStringLiteral( "negZ" )],
1044  this
1045  );
1046  break;
1048  mSkybox = new QgsPanoramicSkyboxEntity( skyboxSettings.panoramicTexturePath(), this );
1049  break;
1050  }
1051  }
1052 }
1053 
1054 void Qgs3DMapScene::onShadowSettingsChanged()
1055 {
1056  QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = mEngine->frameGraph();
1057 
1058  const QList< QgsLightSource * > lightSources = mMap.lightSources();
1059  QList< QgsDirectionalLightSettings * > directionalLightSources;
1060  for ( QgsLightSource *source : lightSources )
1061  {
1062  if ( source->type() == Qgis::LightSourceType::Directional )
1063  {
1064  directionalLightSources << qgis::down_cast< QgsDirectionalLightSettings * >( source );
1065  }
1066  }
1067 
1068  QgsShadowSettings shadowSettings = mMap.shadowSettings();
1069  int selectedLight = shadowSettings.selectedDirectionalLight();
1070  if ( shadowSettings.renderShadows() && selectedLight >= 0 && selectedLight < directionalLightSources.count() )
1071  {
1072  shadowRenderingFrameGraph->setShadowRenderingEnabled( true );
1073  shadowRenderingFrameGraph->setShadowBias( shadowSettings.shadowBias() );
1074  shadowRenderingFrameGraph->setShadowMapResolution( shadowSettings.shadowMapResolution() );
1075  QgsDirectionalLightSettings light = *directionalLightSources.at( selectedLight );
1076  shadowRenderingFrameGraph->setupDirectionalLight( light, shadowSettings.maximumShadowRenderingDistance() );
1077  }
1078  else
1079  shadowRenderingFrameGraph->setShadowRenderingEnabled( false );
1080 }
1081 
1082 void Qgs3DMapScene::onDebugShadowMapSettingsChanged()
1083 {
1084  QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = mEngine->frameGraph();
1085  shadowRenderingFrameGraph->setupShadowMapDebugging( mMap.debugShadowMapEnabled(), mMap.debugShadowMapCorner(), mMap.debugShadowMapSize() );
1086 }
1087 
1088 void Qgs3DMapScene::onDebugDepthMapSettingsChanged()
1089 {
1090  QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = mEngine->frameGraph();
1091  shadowRenderingFrameGraph->setupDepthMapDebugging( mMap.debugDepthMapEnabled(), mMap.debugDepthMapCorner(), mMap.debugDepthMapSize() );
1092 }
1093 
1094 void Qgs3DMapScene::onDebugOverlayEnabledChanged()
1095 {
1096  QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = mEngine->frameGraph();
1097  shadowRenderingFrameGraph->setDebugOverlayEnabled( mMap.isDebugOverlayEnabled() );
1098 }
1099 
1100 void Qgs3DMapScene::onEyeDomeShadingSettingsChanged()
1101 {
1102  QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = mEngine->frameGraph();
1103 
1104  bool edlEnabled = mMap.eyeDomeLightingEnabled();
1105  double edlStrength = mMap.eyeDomeLightingStrength();
1106  double edlDistance = mMap.eyeDomeLightingDistance();
1107  shadowRenderingFrameGraph->setupEyeDomeLighting( edlEnabled, edlStrength, edlDistance );
1108 }
1109 
1110 void Qgs3DMapScene::onCameraMovementSpeedChanged()
1111 {
1112  mCameraController->setCameraMovementSpeed( mMap.cameraMovementSpeed() );
1113 }
1114 
1115 void Qgs3DMapScene::onCameraNavigationModeChanged()
1116 {
1117  mCameraController->setCameraNavigationMode( mMap.cameraNavigationMode() );
1118 }
1119 
1121 {
1122  QVector<QString> notParsedLayers;
1123  Qgs3DSceneExporter exporter;
1124 
1125  exporter.setTerrainResolution( exportSettings.terrrainResolution() );
1126  exporter.setSmoothEdges( exportSettings.smoothEdges() );
1127  exporter.setExportNormals( exportSettings.exportNormals() );
1128  exporter.setExportTextures( exportSettings.exportTextures() );
1129  exporter.setTerrainTextureResolution( exportSettings.terrainTextureResolution() );
1130  exporter.setScale( exportSettings.scale() );
1131 
1132  for ( auto it = mLayerEntities.constBegin(); it != mLayerEntities.constEnd(); ++it )
1133  {
1134  QgsMapLayer *layer = it.key();
1135  Qt3DCore::QEntity *rootEntity = it.value();
1136  QgsMapLayerType layerType = layer->type();
1137  switch ( layerType )
1138  {
1140  if ( !exporter.parseVectorLayerEntity( rootEntity, qobject_cast<QgsVectorLayer *>( layer ) ) )
1141  notParsedLayers.push_back( layer->name() );
1142  break;
1150  notParsedLayers.push_back( layer->name() );
1151  break;
1152  }
1153  }
1154 
1155  if ( mTerrain )
1156  exporter.parseTerrain( mTerrain, "Terrain" );
1157 
1158  exporter.save( exportSettings.sceneName(), exportSettings.sceneFolderPath() );
1159 
1160  if ( !notParsedLayers.empty() )
1161  {
1162  QString message = tr( "The following layers were not exported:" ) + "\n";
1163  for ( const QString &layerName : notParsedLayers )
1164  message += layerName + "\n";
1165  QgsMessageOutput::showMessage( tr( "3D exporter warning" ), message, QgsMessageOutput::MessageText );
1166  }
1167 }
1168 
1169 QVector<const QgsChunkNode *> Qgs3DMapScene::getLayerActiveChunkNodes( QgsMapLayer *layer )
1170 {
1171  QVector<const QgsChunkNode *> chunks;
1172  if ( !mLayerEntities.contains( layer ) ) return chunks;
1173  if ( QgsChunkedEntity *c = qobject_cast<QgsChunkedEntity *>( mLayerEntities[ layer ] ) )
1174  {
1175  for ( QgsChunkNode *n : c->activeNodes() )
1176  chunks.push_back( n );
1177  }
1178  return chunks;
1179 }
1180 
1182 {
1183  QgsRectangle extent;
1184  extent.setMinimal();
1185 
1186  for ( QgsMapLayer *layer : mLayerEntities.keys() )
1187  {
1188  Qt3DCore::QEntity *layerEntity = mLayerEntities[ layer ];
1189  QgsChunkedEntity *c = qobject_cast<QgsChunkedEntity *>( layerEntity );
1190  if ( !c )
1191  continue;
1192  QgsChunkNode *chunkNode = c->rootNode();
1193  QgsAABB bbox = chunkNode->bbox();
1194  QgsRectangle layerExtent = Qgs3DUtils::worldToLayerExtent( bbox, layer->crs(), mMap.origin(), mMap.crs(), mMap.transformContext() );
1195  extent.combineExtentWith( layerExtent );
1196  }
1197 
1198  if ( mMap.terrainRenderingEnabled() )
1199  {
1200  if ( QgsTerrainGenerator *terrainGenerator = mMap.terrainGenerator() )
1201  {
1202  QgsRectangle terrainExtent = terrainGenerator->extent();
1203  QgsCoordinateTransform terrainToMapTransform( terrainGenerator->crs(), mMap.crs(), QgsProject::instance() );
1204  terrainToMapTransform.setBallparkTransformsAreAppropriate( true );
1205  terrainExtent = terrainToMapTransform.transformBoundingBox( terrainExtent );
1206  extent.combineExtentWith( terrainExtent );
1207  }
1208  }
1209 
1210  return extent;
1211 }
1212 
1213 void Qgs3DMapScene::addCameraRotationCenterEntity( QgsCameraController *controller )
1214 {
1215  mEntityRotationCenter = new Qt3DCore::QEntity;
1216 
1217  Qt3DCore::QTransform *trCameraViewCenter = new Qt3DCore::QTransform;
1218  mEntityRotationCenter->addComponent( trCameraViewCenter );
1219  Qt3DExtras::QPhongMaterial *materialCameraViewCenter = new Qt3DExtras::QPhongMaterial;
1220  materialCameraViewCenter->setAmbient( Qt::blue );
1221  mEntityRotationCenter->addComponent( materialCameraViewCenter );
1222  Qt3DExtras::QSphereMesh *rendererCameraViewCenter = new Qt3DExtras::QSphereMesh;
1223  rendererCameraViewCenter->setRadius( 10 );
1224  mEntityRotationCenter->addComponent( rendererCameraViewCenter );
1225  mEntityRotationCenter->setEnabled( true );
1226  mEntityRotationCenter->setParent( this );
1227 
1228  connect( controller, &QgsCameraController::cameraRotationCenterChanged, this, [trCameraViewCenter]( QVector3D center )
1229  {
1230  trCameraViewCenter->setTranslation( center );
1231  } );
1232 
1233  mEntityRotationCenter->setEnabled( mMap.showCameraRotationCenter() );
1234 
1235  connect( &mMap, &Qgs3DMapSettings::showCameraRotationCenterChanged, this, [this]
1236  {
1237  mEntityRotationCenter->setEnabled( mMap.showCameraRotationCenter() );
1238  } );
1239 }
1240 
1241 void Qgs3DMapScene::on3DAxisSettingsChanged()
1242 {
1243  if ( !m3DAxis )
1244  {
1245  if ( QgsWindow3DEngine *engine = dynamic_cast<QgsWindow3DEngine *>( mEngine ) )
1246  {
1247  m3DAxis = new Qgs3DAxis( static_cast<Qt3DExtras::Qt3DWindow *>( engine->window() ),
1248  engine->root(),
1249  this,
1250  mCameraController,
1251  &mMap );
1252  }
1253  }
1254 }
1255 
qgssourcecache.h
Qgs3DMapSettings::backgroundColorChanged
void backgroundColorChanged()
Emitted when the background color has changed.
Qgs3DMapSettings::cameraMovementSpeedChanged
void cameraMovementSpeedChanged()
Emitted when the camera movement speed was changed.
Qgs3DSceneExporter::setScale
void setScale(float scale)
Sets the scale of the exported 3D model.
Definition: qgs3dsceneexporter.h:106
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:227
QgsMapLayer::request3DUpdate
void request3DUpdate()
Signal emitted when a layer requires an update in any 3D maps.
QgsRectangle::height
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
QgsPoint3DBillboardMaterial
Material of the billboard rendering for points in 3D map view.
Definition: qgspoint3dbillboardmaterial.h:36
Qgs3DMapSettings::crs
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used in the 3D scene.
Definition: qgs3dmapsettings.h:99
QgsShadowSettings::maximumShadowRenderingDistance
double maximumShadowRenderingDistance() const
Returns the maximum shadow rendering distance accounted for when rendering shadows Objects further aw...
Definition: qgsshadowsettings.h:60
qgstessellatedpolygongeometry.h
QgsPointXY::y
double y
Definition: qgspointxy.h:63
qgsmessageoutput.h
QgsShadowRenderingFrameGraph::setShadowBias
void setShadowBias(float shadowBias)
Sets the shadow bias value.
Definition: qgsshadowrenderingframegraph.cpp:580
QgsVectorLayer3DRenderer
3D renderer that renders all features of a vector layer with the same 3D symbol. The appearance is co...
Definition: qgsvectorlayer3drenderer.h:59
QgsCameraController::resetView
void resetView(float distance)
Move camera back to the initial position (looking down towards origin of world's coordinates)
Definition: qgscameracontroller.cpp:164
Qgs3DSceneExporter::save
void save(const QString &sceneName, const QString &sceneFolderPath)
Saves the scene to a .obj file.
Definition: qgs3dsceneexporter.cpp:655
Qgs3DMapSettings::lightSources
QList< QgsLightSource * > lightSources() const
Returns list of directional light sources defined in the scene.
Definition: qgs3dmapsettings.cpp:801
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:323
QgsRectangle::combineExtentWith
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:391
Qgs3DMapSettings::projectionTypeChanged
void projectionTypeChanged()
Emitted when the camera lens projection type changes.
QgsMapLayerType::MeshLayer
@ MeshLayer
Mesh layer. Added in QGIS 3.2.
Qgs3DMapSettings::worldToMapCoordinates
QgsVector3D worldToMapCoordinates(const QgsVector3D &worldCoords) const
Converts 3D world coordinates to map coordinates (applies offset and turns (x,y,z) into (x,...
Definition: qgs3dmapsettings.cpp:484
QgsMapLayerType::VectorLayer
@ VectorLayer
Vector layer.
Qgs3DMapSettings::maxTerrainGroundError
float maxTerrainGroundError() const
Returns maximum ground error of terrain tiles in world units.
Definition: qgs3dmapsettings.cpp:666
Qgs3DMapScene::fpsCountChanged
void fpsCountChanged(float fpsCount)
Emitted when the FPS count changes.
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:64
qgsaabb.h
Qgs3DMapScene::terrainPendingJobsCountChanged
void terrainPendingJobsCountChanged()
Emitted when the number of terrain's pending jobs changes.
Qgs3DMapSettings::terrainRenderingEnabled
bool terrainRenderingEnabled() const
Returns whether the 2D terrain surface will be rendered.
Definition: qgs3dmapsettings.h:578
QgsPointCloudLayer
Represents a map layer supporting display of point clouds.
Definition: qgspointcloudlayer.h:45
QgsAbstract3DRenderer
Base class for all renderers that may to participate in 3D view.
Definition: qgsabstract3drenderer.h:48
QgsVector3D
Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double precisi...
Definition: qgsvector3d.h:31
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:73
Qgs3DMapSettings::mapTileResolution
int mapTileResolution() const
Returns resolution (in pixels) of the texture of a terrain tile.
Definition: qgs3dmapsettings.cpp:630
QgsRectangle::center
QgsPointXY center() const SIP_HOLDGIL
Returns the center point of the rectangle.
Definition: qgsrectangle.h:251
QgsPointCloudLayer::subsetStringChanged
void subsetStringChanged()
Emitted when the layer's subset string has changed.
Qgs3DMapSettings::showCameraViewCenterChanged
void showCameraViewCenterChanged()
Emitted when the flag whether camera's view center is shown has changed.
qgs3dsceneexporter.h
QgsMapLayerType::AnnotationLayer
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
Qgs3DSceneExporter::setSmoothEdges
void setSmoothEdges(bool smoothEdges)
Sets whether the triangles will look smooth.
Definition: qgs3dsceneexporter.h:82
QgsMapLayerType
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgis.h:46
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
QgsCoordinateTransform::transformBoundingBox
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:560
Qgs3DMapSettings::eyeDomeLightingDistance
int eyeDomeLightingDistance() const
Returns the eye dome lighting distance value (contributes to the contrast of the image)
Definition: qgs3dmapsettings.h:410
QgsShadowRenderingFrameGraph::setupEyeDomeLighting
void setupEyeDomeLighting(bool enabled, double strength, int distance)
Sets eye dome lighting shading related settings.
Definition: qgsshadowrenderingframegraph.cpp:604
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:159
QgsMeshLayer3DRenderer::symbol
const QgsMesh3DSymbol * symbol() const
Returns 3D symbol associated with the renderer.
Definition: qgsmeshlayer3drenderer.cpp:68
QgsAbstract3DEngine::frameGraph
QgsShadowRenderingFrameGraph * frameGraph()
Returns the shadow rendering frame graph object used to render the scene.
Definition: qgsabstract3dengine.h:112
Qgs3DSceneExporter::setExportNormals
void setExportNormals(bool exportNormals)
Sets whether the normals will be exported.
Definition: qgs3dsceneexporter.h:87
qgschunknode_p.h
Qgs3DSceneExporter::parseTerrain
void parseTerrain(QgsTerrainEntity *terrain, const QString &layer)
Creates terrain export objects from the terrain entity.
Definition: qgs3dsceneexporter.cpp:251
QgsSkyboxSettings
Contains the configuration of a skybox entity.
Definition: qgsskyboxsettings.h:36
QgsRectangle::setMinimal
void setMinimal() SIP_HOLDGIL
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:172
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:480
Qgs3DMapSettings::mapTileResolutionChanged
void mapTileResolutionChanged()
Emitted when the map tile resoulution has changed.
qgsskyboxsettings.h
QgsMesh3DSymbol
3D symbol that draws mesh geometry as planar triangles.
Definition: qgsmesh3dsymbol.h:43
Qgs3DMapSettings::fpsCounterEnabledChanged
void fpsCounterEnabledChanged(bool fpsCounterEnabled)
Emitted when the FPS counter is enabled or disabled.
Qgs3DMapSettings::debugOverlayEnabledChanged
void debugOverlayEnabledChanged(bool debugOverlayEnabled)
Emitted when the debug overaly is enabled or disabled.
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.
Qgs3DUtils::worldToLayerExtent
static QgsRectangle worldToLayerExtent(const QgsAABB &bbox, const QgsCoordinateReferenceSystem &layerCrs, const QgsVector3D &mapOrigin, const QgsCoordinateReferenceSystem &mapCrs, const QgsCoordinateTransformContext &context)
Converts axis aligned bounding box in 3D world coordinates to extent in map layer CRS.
Definition: qgs3dutils.cpp:582
QgsAbstractVectorLayer3DRenderer
Base class for 3D renderers that are based on vector layers.
Definition: qgsabstractvectorlayer3drenderer.h:77
QgsAABB::zMax
float zMax
Definition: qgsaabb.h:86
Qgs3DMapSettings::debugShadowMapSize
double debugShadowMapSize() const
Returns the size of the shadow map preview.
Definition: qgs3dmapsettings.h:423
QgsAABB::yMin
float yMin
Definition: qgsaabb.h:82
qgspoint3dbillboardmaterial.h
Qgs3DMapSettings::skyboxSettingsChanged
void skyboxSettingsChanged()
Emitted when skybox settings are changed.
QgsShadowRenderingFrameGraph::setDebugOverlayEnabled
void setDebugOverlayEnabled(bool enabled)
Sets whether debug overlay is enabled.
Definition: qgsshadowrenderingframegraph.cpp:681
Qgs3DMapSettings::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
Definition: qgs3dmapsettings.cpp:494
Qgs3DMapSettings::isDebugOverlayEnabled
bool isDebugOverlayEnabled() const
Returns whether debug overlay is enabled.
Definition: qgs3dmapsettings.h:648
Qgs3DMapScene::Updating
@ Updating
The scene is still being loaded/updated.
Definition: qgs3dmapscene.h:112
Qgs3DMapSettings::renderersChanged
void renderersChanged()
Emitted when the list of map's extra renderers have been modified.
Qgs3DMapSettings::debugDepthMapCorner
Qt::Corner debugDepthMapCorner() const
Returns the corner where the shadow map preview is displayed.
Definition: qgs3dmapsettings.h:434
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsShadowRenderingFrameGraph
Container class that holds different objects related to shadow rendering.
Definition: qgsshadowrenderingframegraph.h:59
QgsLightSource
Base class for light sources in 3d scenes.
Definition: qgslightsource.h:46
Qgis::LightSourceType::Directional
@ Directional
Directional light source.
QgsMessageOutput::showMessage
virtual void showMessage(bool blocking=true)=0
display the message to the user and deletes itself
Qgs3DMapSettings::debugShadowMapSettingsChanged
void debugShadowMapSettingsChanged()
Emitted when shadow map debugging has changed.
Qgs3DUtils::rayFromScreenPoint
static QgsRay3D rayFromScreenPoint(const QPoint &point, const QSize &windowSize, Qt3DRender::QCamera *camera)
Convert from clicked point on the screen to a ray in world coordinates.
Definition: qgs3dutils.cpp:681
addQLayerComponentsToHierarchy
void addQLayerComponentsToHierarchy(Qt3DCore::QEntity *entity, const QVector< Qt3DRender::QLayer * > &layers)
Definition: qgs3dmapscene.cpp:440
QgsSkyboxEntity::DistinctTexturesSkybox
@ DistinctTexturesSkybox
Definition: qgsskyboxentity.h:52
QgsShadowRenderingFrameGraph::setupShadowMapDebugging
void setupShadowMapDebugging(bool enabled, Qt::Corner corner, double size)
Sets the shadow map debugging view port.
Definition: qgsshadowrenderingframegraph.cpp:614
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
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
Qgs3DMapSettings::projectionType
Qt3DRender::QCameraLens::ProjectionType projectionType() const
Returns the camera lens' projection type.
Definition: qgs3dmapsettings.h:471
Qgs3DMapExportSettings::exportTextures
bool exportTextures() const
Returns whether textures will be exported.
Definition: qgs3dmapexportsettings.h:63
qgs3dmapexportsettings.h
qgsmaplayertemporalproperties.h
Qgs3DMapSettings::debugDepthMapSettingsChanged
void debugDepthMapSettingsChanged()
Emitted when depth map debugging has changed.
Qgs3DMapScene::exportScene
void exportScene(const Qgs3DMapExportSettings &exportSettings)
Exports the scene according to the scene export settings.
Definition: qgs3dmapscene.cpp:1120
Qgs3DSceneExporter
Entity that handles the exporting of 3D scene.
Definition: qgs3dsceneexporter.h:55
qgsmeshlayer3drenderer.h
Qgs3DMapSettings::cameraMovementSpeed
double cameraMovementSpeed() const
Returns the camera movement speed.
Definition: qgs3dmapsettings.h:498
Qgs3DMapSettings::debugShadowMapCorner
Qt::Corner debugShadowMapCorner() const
Returns the corner where the shadow map preview is displayed.
Definition: qgs3dmapsettings.h:421
qgsFloatNear
bool qgsFloatNear(float a, float b, float epsilon=4 *FLT_EPSILON)
Compare two floats (but allow some difference)
Definition: qgis.h:2282
QgsTerrainGenerator
Base class for generators of terrain.
Definition: qgsterraingenerator.h:49
qgspointcloudlayer.h
QgsRay3D
A representation of a ray in 3D.
Definition: qgsray3d.h:30
QgsMapLayer::renderer3D
QgsAbstract3DRenderer * renderer3D() const
Returns 3D renderer associated with the layer.
Definition: qgsmaplayer.cpp:2109
Qgs3DMapScene::setViewFrom2DExtent
void setViewFrom2DExtent(const QgsRectangle &extent)
Resets camera view to show the extent extent (top view)
Definition: qgs3dmapscene.cpp:256
QgsTemporalProperty::isActive
bool isActive() const
Returns true if the temporal property is active.
Definition: qgstemporalproperty.cpp:36
QgsCoordinateTransform::setBallparkTransformsAreAppropriate
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
Definition: qgscoordinatetransform.cpp:939
Qgs3DMapExportSettings
Manages the various settings the user can choose from when exporting a 3D scene.
Definition: qgs3dmapexportsettings.h:30
QgsShadowRenderingFrameGraph::setupDepthMapDebugging
void setupDepthMapDebugging(bool enabled, Qt::Corner corner, double size)
Sets the depth map debugging view port.
Definition: qgsshadowrenderingframegraph.cpp:637
Qgs3DSceneExporter::setTerrainTextureResolution
void setTerrainTextureResolution(int resolution)
Sets the terrain texture resolution.
Definition: qgs3dsceneexporter.h:102
QgsVector3D::z
double z() const
Returns Z coordinate.
Definition: qgsvector3d.h:66
QgsCameraController::camera
Qt3DRender::QCamera camera
Definition: qgscameracontroller.h:64
QgsMapLayerType::GroupLayer
@ GroupLayer
Composite group layer. Added in QGIS 3.24.
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:78
QgsSkyboxSettings::cubeMapFacesPaths
QMap< QString, QString > cubeMapFacesPaths() const
Returns a map containing the path of each texture specified by the user.
Definition: qgsskyboxsettings.h:65
Qgs3DMapExportSettings::smoothEdges
bool smoothEdges() const
Returns whether triangles edges will look smooth.
Definition: qgs3dmapexportsettings.h:59
removeQLayerComponentsFromHierarchy
void removeQLayerComponentsFromHierarchy(Qt3DCore::QEntity *entity)
Definition: qgs3dmapscene.cpp:422
qgschunkedentity_p.h
QgsPoint3DSymbol::Model
@ Model
Definition: qgspoint3dsymbol.h:89
QgsSkyboxSettings::skyboxType
QgsSkyboxEntity::SkyboxType skyboxType() const
Returns the type of the skybox.
Definition: qgsskyboxsettings.h:52
QgsMeshLayer
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:98
qgsterraingenerator.h
Qgs3DMapScene::updateTemporal
void updateTemporal()
Updates the temporale entities.
Definition: qgs3dmapscene.cpp:748
QgsMapLayerType::RasterLayer
@ RasterLayer
Raster layer.
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:67
Qgs3DMapScene::worldSpaceError
float worldSpaceError(float epsilon, float distance)
Given screen error (in pixels) and distance from camera (in 3D world coordinates),...
Definition: qgs3dmapscene.cpp:369
Qgs3DMapSettings::backgroundColor
QColor backgroundColor() const
Returns background color of the 3D map view.
Definition: qgs3dmapsettings.cpp:513
_sceneState
QgsChunkedEntity::SceneState _sceneState(QgsCameraController *cameraController)
Definition: qgs3dmapscene.cpp:383
Qgs3DMapSettings::terrainVerticalScaleChanged
void terrainVerticalScaleChanged()
Emitted when the vertical scale of the terrain has changed.
qgspointcloudlayerchunkloader_p.h
Qgs3DMapSettings::showCameraRotationCenterChanged
void showCameraRotationCenterChanged()
Emitted when the flag whether camera's rotation center is shown has changed.
QgsMapLayer::temporalProperties
virtual QgsMapLayerTemporalProperties * temporalProperties()
Returns the layer's temporal properties.
Definition: qgsmaplayer.h:1502
QgsAABB::xMin
float xMin
Definition: qgsaabb.h:81
QgsCameraController::viewportChanged
void viewportChanged()
Emitted when viewport rectangle has been updated.
QgsAABB
Axis-aligned bounding box - in world coords.
Definition: qgsaabb.h:33
Qgs3DMapScene::unregisterPickHandler
void unregisterPickHandler(Qgs3DMapScenePickHandler *pickHandler)
Unregisters previously registered pick handler. Pick handler is not deleted. Also removes object pick...
Definition: qgs3dmapscene.cpp:338
qgsabstract3dengine.h
Qgs3DMapSettings::eyeDomeLightingDistanceChanged
void eyeDomeLightingDistanceChanged()
Emitted when the eye dome lighting distance has changed.
QgsMeshLayer3DRenderer
3D renderer that renders all mesh triangles of a mesh layer.
Definition: qgsmeshlayer3drenderer.h:59
QgsCameraController::viewport
QRect viewport
Definition: qgscameracontroller.h:65
Qgs3DAxis
Display 3D ortho axis in the main 3D view.
Definition: qgs3daxis.h:56
Qgs3DMapSettings
Definition of the world.
Definition: qgs3dmapsettings.h:57
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:105
QgsApplication::sourceCache
static QgsSourceCache * sourceCache()
Returns the application's source cache, used for caching embedded and remote source strings as local ...
Definition: qgsapplication.cpp:2370
Qgs3DMapExportSettings::sceneFolderPath
QString sceneFolderPath() const
Returns the scene folder path.
Definition: qgs3dmapexportsettings.h:55
Qgs3DMapScene::terrainEntityChanged
void terrainEntityChanged()
Emitted when the current terrain entity is replaced by a new one.
QgsRay3D::origin
QVector3D origin() const
Returns the origin of the ray.
Definition: qgsray3d.h:57
QgsCameraController::setCameraMovementSpeed
void setCameraMovementSpeed(double movementSpeed)
Sets the camera movement speed.
Definition: qgscameracontroller.cpp:83
QgsMapLayer::layerModified
void layerModified()
Emitted when modifications has been done on layer.
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
Qgs3DMapSettings::fieldOfView
float fieldOfView() const
Returns the camera lens' field of view.
Definition: qgs3dmapsettings.h:459
Qgs3DMapSettings::origin
QgsVector3D origin() const
Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
Definition: qgs3dmapsettings.h:89
Qgs3DMapSettings::fieldOfViewChanged
void fieldOfViewChanged()
Emitted when the camera lens field of view changes.
Qgs3DMapSettings::eyeDomeLightingEnabledChanged
void eyeDomeLightingEnabledChanged()
Emitted when the flag whether eye dome lighting is used has changed.
qgscameracontroller.h
QgsCameraController::setTerrainEntity
void setTerrainEntity(QgsTerrainEntity *te)
Connects to object picker attached to terrain entity.
Definition: qgscameracontroller.cpp:97
QgsAbstract3DEngine
Base class for 3D engine implementation. A 3D engine is responsible for setting up rendering with Qt3...
Definition: qgsabstract3dengine.h:60
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.
QgsSkyboxEntity::PanoramicSkybox
@ PanoramicSkybox
Definition: qgsskyboxentity.h:51
QgsAbstract3DEngine::camera
virtual Qt3DRender::QCamera * camera()=0
Returns pointer to the engine's camera entity.
QgsPointCloudLayer3DRenderer::setLayer
void setLayer(QgsPointCloudLayer *layer)
Sets point cloud layer associated with the renderer.
Definition: qgspointcloudlayer3drenderer.cpp:100
QgsRuleBased3DRenderer::RuleList
QList< QgsRuleBased3DRenderer::Rule * > RuleList
Definition: qgsrulebased3drenderer.h:65
Qgs3DMapSettings::shadowSettingsChanged
void shadowSettingsChanged()
Emitted when shadow rendering settings are changed.
QgsCameraController::cameraRotationCenterChanged
void cameraRotationCenterChanged(QVector3D position)
Emitted when the camera rotation center changes.
QgsMesh3DSymbol::clone
QgsMesh3DSymbol * clone() const override SIP_FACTORY
Returns a new instance of the symbol with the same settings.
Definition: qgsmesh3dsymbol.cpp:29
QgsTerrainGenerator::rootChunkError
virtual float rootChunkError(const Qgs3DMapSettings &map) const
Returns error of the root chunk in world coordinates.
Definition: qgsterraingenerator.cpp:35
Qgs3DMapSettings::terrainGenerator
QgsTerrainGenerator * terrainGenerator() const
Returns the terrain generator.
Definition: qgs3dmapsettings.h:277
qgsmeshlayer.h
Qgs3DMapScene::getLayerActiveChunkNodes
QVector< const QgsChunkNode * > getLayerActiveChunkNodes(QgsMapLayer *layer)
Returns the active chunk nodes of layer.
Definition: qgs3dmapscene.cpp:1169
qgsvectorlayer.h
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
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:50
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:310
QgsCameraController::setViewport
void setViewport(QRect viewport)
Sets viewport rectangle. Called internally from 3D canvas. Allows conversion of mouse coordinates.
Definition: qgscameracontroller.cpp:118
QgsPoint3DSymbol::shape
Shape shape() const
Returns 3D shape for points.
Definition: qgspoint3dsymbol.h:99
Qgs3DMapSettings::debugShadowMapEnabled
bool debugShadowMapEnabled() const
Returns whether the shadow map debugging is enabled.
Definition: qgs3dmapsettings.h:419
Qgs3DMapSettings::debugDepthMapEnabled
bool debugDepthMapEnabled() const
Returns whether the shadow map debugging is enabled.
Definition: qgs3dmapsettings.h:432
qgs3dmapsettings.h
Qgs3DMapExportSettings::scale
float scale() const
Returns the scale of the exported model.
Definition: qgs3dmapexportsettings.h:67
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
Qgs3DMapSettings::shadowSettings
QgsShadowSettings shadowSettings() const
Returns the current configuration of shadows.
Definition: qgs3dmapsettings.h:531
QgsShadowSettings::selectedDirectionalLight
int selectedDirectionalLight() const
Returns the selected direcctional light used to cast shadows.
Definition: qgsshadowsettings.h:52
qgsskyboxentity.h
Qgs3DMapSettings::eyeDomeLightingStrengthChanged
void eyeDomeLightingStrengthChanged()
Emitted when the eye dome lighting strength has changed.
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
Qgs3DMapScene::SceneState
SceneState
Enumeration of possible states of the 3D scene.
Definition: qgs3dmapscene.h:109
Qgs3DMapScene::Ready
@ Ready
The scene is fully loaded/updated.
Definition: qgs3dmapscene.h:111
Qgs3DMapScene::fpsCounterEnabledChanged
void fpsCounterEnabledChanged(bool fpsCounterEnabled)
Emitted when the FPS counter is activated or deactivated.
qgsrulebased3drenderer.h
Qgs3DMapScene::totalPendingJobsCount
int totalPendingJobsCount() const
Returns number of pending jobs for all chunked entities.
Definition: qgs3dmapscene.cpp:315
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
Qgs3DMapScene::viewZoomFull
void viewZoomFull()
Resets camera view to show the whole scene (top view)
Definition: qgs3dmapscene.cpp:247
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsRectangle::width
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
qgspoint3dsymbol.h
QgsMapLayer
Base class for all map layer types. This is the base class for all map layer types (vector,...
Definition: qgsmaplayer.h:72
Qgs3DMapSettings::layers
QList< QgsMapLayer * > layers() const
Returns the list of 3D map layers to be rendered in the scene.
Definition: qgs3dmapsettings.cpp:562
Qgs3DMapSettings::renderers
QList< QgsAbstract3DRenderer * > renderers() const
Returns list of extra 3D renderers.
Definition: qgs3dmapsettings.h:333
QgsPointXY::x
double x
Definition: qgspointxy.h:62
Qgs3DMapSettings::showCameraRotationCenter
bool showCameraRotationCenter() const
Returns whether to show camera's rotation center as a sphere (for debugging)
Definition: qgs3dmapsettings.h:366
QgsCameraController::setCameraNavigationMode
void setCameraNavigationMode(QgsCameraController::NavigationMode navigationMode)
Sets the navigation mode used by the camera controller.
Definition: qgscameracontroller.cpp:73
QgsAABB::yMax
float yMax
Definition: qgsaabb.h:85
Qgs3DMapScene::viewed2DExtentFrom3DChanged
void viewed2DExtentFrom3DChanged(QVector< QgsPointXY > extent)
Emitted when the viewed 2D extent seen by the 3D camera has changed.
QgsMapLayerType::VectorTileLayer
@ VectorTileLayer
Vector tile layer. Added in QGIS 3.14.
Qgs3DMapExportSettings::terrainTextureResolution
int terrainTextureResolution() const
Returns the terrain texture resolution.
Definition: qgs3dmapexportsettings.h:65
QgsShadowSettings
class containing the configuration of shadows rendering
Definition: qgsshadowsettings.h:34
qgs3dmapscenepickhandler.h
QgsMeshLayer3DRenderer::setLayer
void setLayer(QgsMeshLayer *layer)
Sets vector layer associated with the renderer.
Definition: qgsmeshlayer3drenderer.cpp:53
QgsShadowRenderingFrameGraph::transparentObjectLayer
Qt3DRender::QLayer * transparentObjectLayer()
Returns a layer object used to indicate that the object is transparent.
Definition: qgsshadowrenderingframegraph.h:90
Qgs3DMapExportSettings::sceneName
QString sceneName() const
Returns the scene name.
Definition: qgs3dmapexportsettings.h:53
QgsMapLayer::name
QString name
Definition: qgsmaplayer.h:76
qgsvectorlayer3drenderer.h
QgsPoint3DSymbol::shapeProperties
QVariantMap shapeProperties() const
Returns a key-value dictionary of point shape properties.
Definition: qgspoint3dsymbol.h:104
Qgs3DMapSettings::showTerrainBoundingBoxes
bool showTerrainBoundingBoxes() const
Returns whether to display bounding boxes of terrain tiles (for debugging)
Definition: qgs3dmapsettings.h:338
Qgs3DMapSettings::eyeDomeLightingStrength
double eyeDomeLightingStrength() const
Returns the eye dome lighting strength value.
Definition: qgs3dmapsettings.h:401
QgsRuleBased3DRenderer
Rule-based 3D renderer.
Definition: qgsrulebased3drenderer.h:61
Qgs3DMapSettings::eyeDomeLightingEnabled
bool eyeDomeLightingEnabled() const
Returns whether eye dome lighting is used.
Definition: qgs3dmapsettings.h:392
Qgs3DMapExportSettings::exportNormals
bool exportNormals() const
Returns whether normals will be exported.
Definition: qgs3dmapexportsettings.h:61
Qgs3DMapScene::engine
QgsAbstract3DEngine * engine()
Returns the abstract 3D engine.
Definition: qgs3dmapscene.h:158
Qgs3DMapSettings::isFpsCounterEnabled
bool isFpsCounterEnabled() const
Returns whether FPS counter label is enabled.
Definition: qgs3dmapsettings.h:564
QgsCameraController::distance
float distance() const
Returns distance of the camera from the point it is looking at.
Definition: qgscameracontroller.h:172
Qgs3DMapScene::totalPendingJobsCountChanged
void totalPendingJobsCountChanged()
Emitted when the total number of pending jobs changes.
Qgs3DMapSettings::mapToWorldCoordinates
QgsVector3D mapToWorldCoordinates(const QgsVector3D &mapCoords) const
Converts map coordinates to 3D world coordinates (applies offset and turns (x,y,z) into (x,...
Definition: qgs3dmapsettings.cpp:479
QgsPanoramicSkyboxEntity
A skybox constructed from a panoramic image.
Definition: qgsskyboxentity.h:78
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:260
Qgs3DMapSettings::cameraNavigationModeChanged
void cameraNavigationModeChanged()
Emitted when the camera navigation mode was changed.
QgsMeshLayer3DRenderer::setSymbol
void setSymbol(QgsMesh3DSymbol *symbol)
Sets 3D symbol associated with the renderer.
Definition: qgsmeshlayer3drenderer.cpp:63
QgsMessageOutput::MessageText
@ MessageText
Definition: qgsmessageoutput.h:48
qgspointcloudlayerelevationproperties.h
Qgs3DMapSettings::debugDepthMapSize
double debugDepthMapSize() const
Returns the size of the shadow map preview.
Definition: qgs3dmapsettings.h:436
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:354
QgsShadowRenderingFrameGraph::setupDirectionalLight
void setupDirectionalLight(const QgsDirectionalLightSettings &light, float maximumShadowRenderingDistance)
Sets shadow rendering to use a directional light.
Definition: qgsshadowrenderingframegraph.cpp:538
QgsCameraController
Object that controls camera movement based on user input.
Definition: qgscameracontroller.h:61
QgsAbstract3DEngine::renderSettings
virtual Qt3DRender::QRenderSettings * renderSettings()=0
Returns access to the engine's render settings (the frame graph can be accessed from here)
Qgs3DMapSettings::axisSettingsChanged
void axisSettingsChanged()
Emitted when 3d axis rendering settings are changed.
qgslogger.h
Qgs3DMapSettings::skyboxSettings
QgsSkyboxSettings skyboxSettings() const
Returns the current configuration of the skybox.
Definition: qgs3dmapsettings.h:525
QgsAABB::zMin
float zMin
Definition: qgsaabb.h:83
QgsAABB::xMax
float xMax
Definition: qgsaabb.h:84
qgs3daxis.h
QgsPointCloudLayer3DRenderer
3D renderer that renders all points from a point cloud layer
Definition: qgspointcloudlayer3drenderer.h:228
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
QgsCameraController::cameraChanged
void cameraChanged()
Emitted when camera has been updated.
QgsTerrainGenerator::rootChunkBbox
virtual QgsAABB rootChunkBbox(const Qgs3DMapSettings &map) const
Returns bounding box of the root chunk.
Definition: qgsterraingenerator.cpp:22
Qgs3DMapSettings::isSkyboxEnabled
bool isSkyboxEnabled() const
Returns whether the skybox is enabled.
Definition: qgs3dmapsettings.h:550
QgsVectorLayer::geometryType
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Definition: qgsvectorlayer.cpp:720
QgsMapLayerType::PointCloudLayer
@ PointCloudLayer
Point cloud layer. Added in QGIS 3.18.
QgsShadowRenderingFrameGraph::setShadowRenderingEnabled
void setShadowRenderingEnabled(bool enabled)
Sets whether the shadow rendering is enabled.
Definition: qgsshadowrenderingframegraph.cpp:570
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:179
QgsVector3D::x
double x() const
Returns X coordinate.
Definition: qgsvector3d.h:62
Qgs3DSceneExporter::setExportTextures
void setExportTextures(bool exportTextures)
Sets whether the textures will be exported.
Definition: qgs3dsceneexporter.h:92
Qgs3DMapSettings::lightSourcesChanged
void lightSourcesChanged()
Emitted when any of the light source settings in the map changes.
QgsMapLayer::renderer3DChanged
void renderer3DChanged()
Signal emitted when 3D renderer associated with the layer has changed.
QgsWindow3DEngine
On-screen 3D engine: it creates OpenGL window (QWindow) and displays rendered 3D scene there....
Definition: qgswindow3dengine.h:49
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:57
Qgs3DMapExportSettings::terrrainResolution
int terrrainResolution() const
Returns the terrain resolution.
Definition: qgs3dmapexportsettings.h:57
Qgs3DMapScene::viewFrustum2DExtent
QVector< QgsPointXY > viewFrustum2DExtent()
Calculates the 2D extent viewed by the 3D camera as the vertices of the viewed trapezoid.
Definition: qgs3dmapscene.cpp:279
QgsRay3D::direction
QVector3D direction() const
Returns the direction of the ray see setDirection()
Definition: qgsray3d.h:63
QgsMapLayerType::PluginLayer
@ PluginLayer
Plugin based layer.
Qgs3DMapScenePickHandler
Abstract base class for handlers that process pick events from a 3D map scene.
Definition: qgs3dmapscenepickhandler.h:36
Qgs3DMapScene::sceneExtent
QgsRectangle sceneExtent()
Returns the scene extent in the map's CRS.
Definition: qgs3dmapscene.cpp:1181
qgspointcloudlayer3drenderer.h
QgsCubeFacesSkyboxEntity
A skybox constructed from a 6 cube faces.
Definition: qgsskyboxentity.h:105
qgs3dmapscene.h
QgsPoint3DSymbol
3D symbol that draws point geometries as 3D objects using one of the predefined shapes.
Definition: qgspoint3dsymbol.h:38
QgsCameraController::setViewFromTop
void setViewFromTop(float worldX, float worldY, float distance, float yaw=0)
Sets camera to look down towards given point in world coordinate, in given distance from plane with z...
Definition: qgscameracontroller.cpp:169
Qgs3DMapSettings::cameraNavigationMode
QgsCameraController::NavigationMode cameraNavigationMode() const
Returns the navigation mode used by the camera.
Definition: qgs3dmapsettings.h:485
Qgs3DSceneExporter::setTerrainResolution
void setTerrainResolution(int resolution)
Sets the terrain resolution.
Definition: qgs3dsceneexporter.h:97
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.
Qgs3DMapScene::Qgs3DMapScene
Qgs3DMapScene(Qgs3DMapSettings &map, QgsAbstract3DEngine *engine)
Constructs a 3D scene based on map settings and Qt 3D renderer configuration.
Definition: qgs3dmapscene.cpp:88
QgsShadowRenderingFrameGraph::setShadowMapResolution
void setShadowMapResolution(int resolution)
Sets the resolution of the shadow map.
Definition: qgsshadowrenderingframegraph.cpp:586
QgsDirectionalLightSettings
Definition of a directional light in a 3D map scene.
Definition: qgsdirectionallightsettings.h:33
QgsMapLayer::type
QgsMapLayerType type
Definition: qgsmaplayer.h:80