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 Q_FOREACH ( QgsChunkNode *node, mRootNode->descendants() )
157 if ( !node->entity() )
159 if ( mActiveNodes.contains( node ) )
161 inactiveNodes << node;
164 updateNodes( inactiveNodes, mUpdateJobFactory.get() );
166 setNeedsUpdate(
true );
169 void QgsTerrainEntity::onLayersChanged()
171 connectToLayersRepaintRequest();
172 invalidateMapImages();
175 void QgsTerrainEntity::connectToLayersRepaintRequest()
182 mLayers = mMap.terrainLayers();
190 void QgsTerrainEntity::onTerrainElevationOffsetChanged(
float newOffset )
192 mTerrainTransform->setTranslation( QVector3D( 0.0f, newOffset, 0.0f ) );
195 float QgsTerrainEntity::terrainElevationOffset()
const
197 return mMap.terrainElevationOffset();
204 TerrainMapUpdateJob::TerrainMapUpdateJob( QgsTerrainTextureGenerator *textureGenerator, QgsChunkNode *node )
205 : QgsChunkQueueJob( node )
206 , mTextureGenerator( textureGenerator )
208 QgsTerrainTileEntity *entity = qobject_cast<QgsTerrainTileEntity *>( node->entity() );
209 connect( textureGenerator, &QgsTerrainTextureGenerator::tileReady,
this, &TerrainMapUpdateJob::onTileReady );
210 mJobId = textureGenerator->render( entity->textureImage()->imageExtent(), node->tileId(), entity->textureImage()->imageDebugText() );
213 void TerrainMapUpdateJob::cancel()
216 mTextureGenerator->cancelJob( mJobId );
220 void TerrainMapUpdateJob::onTileReady(
int jobId,
const QImage &image )
222 if ( mJobId == jobId )
224 QgsTerrainTileEntity *entity = qobject_cast<QgsTerrainTileEntity *>( mNode->entity() );
225 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.