31 #include <Qt3DCore/QTransform> 
   32 #include <Qt3DRender/QGeometryRenderer> 
   33 #include <Qt3DRender/QObjectPicker> 
   39 class TerrainMapUpdateJobFactory : 
public QgsChunkQueueJobFactory
 
   42     TerrainMapUpdateJobFactory( QgsTerrainTextureGenerator *textureGenerator )
 
   43       : mTextureGenerator( textureGenerator )
 
   47     QgsChunkQueueJob *createJob( QgsChunkNode *chunk )
 override 
   49       return new TerrainMapUpdateJob( mTextureGenerator, chunk );
 
   53     QgsTerrainTextureGenerator *mTextureGenerator = 
nullptr;
 
   60 QgsTerrainEntity::QgsTerrainEntity( 
const Qgs3DMapSettings &map, Qt3DCore::QNode *parent )
 
   61   : QgsChunkedEntity( map.maxTerrainScreenError(), map.terrainGenerator(), false, std::numeric_limits<int>::max(), parent )
 
   75   connectToLayersRepaintRequest();
 
   79   mTextureGenerator = 
new QgsTerrainTextureGenerator( map );
 
   81   mUpdateJobFactory.reset( 
new TerrainMapUpdateJobFactory( mTextureGenerator ) );
 
   83   mTerrainPicker = 
new Qt3DRender::QObjectPicker;
 
   86   addComponent( mTerrainPicker );
 
   88   mTerrainTransform = 
new Qt3DCore::QTransform;
 
   89   mTerrainTransform->setScale( 1.0f );
 
   91   addComponent( mTerrainTransform );
 
   94 QgsTerrainEntity::~QgsTerrainEntity()
 
   99   delete mTextureGenerator;
 
  100   delete mTerrainToMapTransform;
 
  103 bool QgsTerrainEntity::rayIntersection( 
const QgsRayCastingUtils::Ray3D &ray, QVector3D &intersectionPoint )
 
  113   QList<QgsChunkNode *> lst = activeNodes();
 
  114   for ( QgsChunkNode *n : lst )
 
  116     if ( n->entity() && ( minDist < 0 || n->bbox().distanceFromPoint( ray.origin() ) < minDist ) && QgsRayCastingUtils::rayBoxIntersection( ray, n->bbox() ) )
 
  118       Qt3DRender::QGeometryRenderer *rend = n->entity()->findChild<Qt3DRender::QGeometryRenderer *>();
 
  119       Qt3DRender::QGeometry *geom = rend->geometry();
 
  120       DemTerrainTileGeometry *demGeom = 
static_cast<DemTerrainTileGeometry *
>( geom );
 
  121       Qt3DCore::QTransform *tr = n->entity()->findChild<Qt3DCore::QTransform *>();
 
  122       QVector3D nodeIntPoint;
 
  123       if ( demGeom->rayIntersection( ray, tr->matrix(), nodeIntPoint ) )
 
  125         float dist = ( ray.origin() - intersectionPoint ).length();
 
  126         if ( minDist < 0 || dist < minDist )
 
  129           intersectionPoint = nodeIntPoint;
 
  138 void QgsTerrainEntity::onShowBoundingBoxesChanged()
 
  140   setShowBoundingBoxes( mMap.showTerrainBoundingBoxes() );
 
  144 void QgsTerrainEntity::invalidateMapImages()
 
  146   QgsEventTracing::addEvent( QgsEventTracing::Instant, QStringLiteral( 
"3D" ), QStringLiteral( 
"Invalidate textures" ) );
 
  150   updateNodes( mActiveNodes, mUpdateJobFactory.get() );
 
  154   QList<QgsChunkNode *> inactiveNodes;
 
  155   const QList<QgsChunkNode *> descendants = mRootNode->descendants();
 
  156   for ( QgsChunkNode *node : descendants )
 
  158     if ( !node->entity() )
 
  160     if ( mActiveNodes.contains( node ) )
 
  162     inactiveNodes << node;
 
  165   updateNodes( inactiveNodes, mUpdateJobFactory.get() );
 
  167   setNeedsUpdate( 
true );
 
  170 void QgsTerrainEntity::onLayersChanged()
 
  172   connectToLayersRepaintRequest();
 
  173   invalidateMapImages();
 
  176 void QgsTerrainEntity::connectToLayersRepaintRequest()
 
  178   for ( 
QgsMapLayer *layer : std::as_const( mLayers ) )
 
  183   mLayers = mMap.terrainLayers();
 
  185   for ( 
QgsMapLayer *layer : std::as_const( mLayers ) )
 
  191 void QgsTerrainEntity::onTerrainElevationOffsetChanged( 
float newOffset )
 
  193   mTerrainTransform->setTranslation( QVector3D( 0.0f, newOffset, 0.0f ) );
 
  196 float QgsTerrainEntity::terrainElevationOffset()
 const 
  198   return mMap.terrainElevationOffset();
 
  205 TerrainMapUpdateJob::TerrainMapUpdateJob( QgsTerrainTextureGenerator *textureGenerator, QgsChunkNode *node )
 
  206   : QgsChunkQueueJob( node )
 
  207   , mTextureGenerator( textureGenerator )
 
  209   QgsTerrainTileEntity *entity = qobject_cast<QgsTerrainTileEntity *>( node->entity() );
 
  210   connect( textureGenerator, &QgsTerrainTextureGenerator::tileReady, 
this, &TerrainMapUpdateJob::onTileReady );
 
  211   mJobId = textureGenerator->render( entity->textureImage()->imageExtent(), node->tileId(), entity->textureImage()->imageDebugText() );
 
  214 void TerrainMapUpdateJob::cancel()
 
  217     mTextureGenerator->cancelJob( mJobId );
 
  221 void TerrainMapUpdateJob::onTileReady( 
int jobId, 
const QImage &image )
 
  223   if ( mJobId == jobId )
 
  225     QgsTerrainTileEntity *entity = qobject_cast<QgsTerrainTileEntity *>( mNode->entity() );
 
  226     entity->textureImage()->setImage( image );
 
QgsTerrainGenerator * terrainGenerator() const
Returns terrain generator. It takes care of producing terrain tiles from the input data.
void backgroundColorChanged()
Emitted when the background color has changed.
void showTerrainBoundingBoxesChanged()
Emitted when the flag whether terrain's bounding boxes are shown has changed.
void terrainLayersChanged()
Emitted when the list of map layers for terrain texture has changed.
void terrainMapThemeChanged()
Emitted when terrain's map theme has changed.
float terrainElevationOffset() const
Returns the elevation offset of the terrain (used to move the terrain up or down)
void showLabelsChanged()
Emitted when the flag whether labels are displayed on terrain tiles has changed.
void terrainElevationOffsetChanged(float newElevation)
Emitted when the terrain elevation offset is changed.
void showTerrainTilesInfoChanged()
Emitted when the flag whether terrain's tile info is shown has changed.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used in the 3D scene.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
Base class for all map layer types.
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
@ Dem
Terrain is built from raster layer with digital elevation model.
QgsCoordinateReferenceSystem crs() const
Returns CRS of the terrain.
void setTerrain(QgsTerrainEntity *t)
Sets terrain entity for the generator (does not transfer ownership)
bool isValid() const
Returns whether the terrain generator is valid.