18 #include <Qt3DRender/QCamera> 19 #include <Qt3DRender/QMesh> 20 #include <Qt3DRender/QPickingSettings> 21 #include <Qt3DRender/QRenderSettings> 22 #include <Qt3DRender/QSceneLoader> 23 #include <Qt3DExtras/QForwardRenderer> 24 #include <Qt3DExtras/QPhongMaterial> 25 #include <Qt3DExtras/QSkyboxEntity> 26 #include <Qt3DLogic/QFrameAction> 43 Qgs3DMapScene::Qgs3DMapScene(
const Qgs3DMapSettings &map, Qt3DExtras::QForwardRenderer *defaultFrameGraph, Qt3DRender::QRenderSettings *renderSettings, Qt3DRender::QCamera *camera,
const QRect &viewportRect, Qt3DCore::QNode *parent )
46 , mForwardRenderer( defaultFrameGraph )
50 onBackgroundColorChanged();
56 #if QT_VERSION >= 0x050900 58 renderSettings->pickingSettings()->setPickMethod( Qt3DRender::QPickingSettings::TrianglePicking );
62 float aspectRatio = ( float )viewportRect.width() / viewportRect.height();
63 camera->lens()->setPerspectiveProjection( 45.0
f, aspectRatio, 10.
f, 10000.0
f );
65 mFrameAction =
new Qt3DLogic::QFrameAction();
66 connect( mFrameAction, &Qt3DLogic::QFrameAction::triggered,
67 this, &Qgs3DMapScene::onFrameTriggered );
68 addComponent( mFrameAction );
89 Qt3DCore::QEntity *newEntity = renderer->
createEntity( map );
90 newEntity->setParent(
this );
96 Qt3DCore::QEntity *lightEntity =
new Qt3DCore::QEntity;
97 Qt3DCore::QTransform *lightTransform =
new Qt3DCore::QTransform;
98 lightTransform->setTranslation( QVector3D( 0, 1000, 0 ) );
101 Qt3DRender::QPointLight *light =
new Qt3DRender::QPointLight;
102 light->setConstantAttenuation( 0 );
105 lightEntity->addComponent( light );
106 lightEntity->addComponent( lightTransform );
107 lightEntity->setParent(
this );
111 ChunkedEntity *testChunkEntity =
new ChunkedEntity( AABB( -500, 0, -500, 500, 100, 500 ), 2.
f, 3.
f, 7,
new TestChunkLoaderFactory );
112 testChunkEntity->setEnabled(
false );
113 testChunkEntity->setParent(
this );
114 chunkEntities << testChunkEntity;
125 Qt3DCore::QEntity *loaderEntity =
new Qt3DCore::QEntity;
126 Qt3DRender::QSceneLoader *loader =
new Qt3DRender::QSceneLoader;
127 loader->setSource( QUrl(
"file:///home/martin/Downloads/LowPolyModels/tree.dae" ) );
128 loaderEntity->addComponent( loader );
129 loaderEntity->setParent(
this );
133 Qt3DCore::QEntity *meshEntity =
new Qt3DCore::QEntity;
134 Qt3DRender::QMesh *mesh =
new Qt3DRender::QMesh;
135 mesh->setSource( QUrl(
"file:///home/martin/Downloads/LowPolyModels/tree.obj" ) );
136 meshEntity->addComponent( mesh );
137 Qt3DExtras::QPhongMaterial *material =
new Qt3DExtras::QPhongMaterial;
138 material->setAmbient( Qt::red );
139 meshEntity->addComponent( material );
140 Qt3DCore::QTransform *meshTransform =
new Qt3DCore::QTransform;
141 meshTransform->setScale( 1 );
142 meshEntity->addComponent( meshTransform );
143 meshEntity->setParent(
this );
148 Qt3DExtras::QSkyboxEntity *skybox =
new Qt3DExtras::QSkyboxEntity;
151 skybox->setParent(
this );
156 defaultFrameGraph->setFrustumCullingEnabled(
false );
166 float side = qMax( extent.
width(), extent.
height() );
172 return mTerrain ? mTerrain->pendingJobsCount() : 0;
177 Qt3DRender::QCamera *camera = cameraController->
camera();
178 QgsChunkedEntity::SceneState state;
179 state.cameraFov = camera->fieldOfView();
180 state.cameraPos = camera->position();
181 QRect rect = cameraController->
viewport();
182 state.screenSizePx = qMax( rect.width(), rect.height() );
183 state.viewProjectionMatrix = camera->projectionMatrix() * camera->viewMatrix();
187 void Qgs3DMapScene::onCameraChanged()
189 Q_FOREACH ( QgsChunkedEntity *entity, mChunkEntities )
191 if ( entity->isEnabled() )
192 entity->update(
_sceneState( mCameraController ) );
210 QMatrix4x4 viewMatrix = camera->viewMatrix();
214 QList<QgsChunkNode *> activeNodes = mTerrain->activeNodes();
219 if ( activeNodes.isEmpty() )
220 activeNodes << mTerrain->rootNode();
222 Q_FOREACH ( QgsChunkNode *node, activeNodes )
227 for (
int i = 0; i < 8; ++i )
229 QVector4D p( ( ( i >> 0 ) & 1 ) ? bbox.
xMin : bbox.
xMax,
230 ( ( i >> 1 ) & 1 ) ? bbox.
yMin : bbox.
yMax,
231 ( ( i >> 2 ) & 1 ) ? bbox.
zMin : bbox.
zMax, 1 );
232 QVector4D pc = viewMatrix * p;
244 if ( fnear == 1e9 && ffar == 0 )
248 qDebug() <<
"oops... this should not happen! couldn't determine near/far plane. defaulting to 1...1e9";
254 camera->setFarPlane( ffar * 2 );
255 camera->setNearPlane( fnear / 2 );
258 qDebug() <<
"no terrain - not setting near/far plane";
263 void Qgs3DMapScene::onFrameTriggered(
float dt )
267 Q_FOREACH ( QgsChunkedEntity *entity, mChunkEntities )
269 if ( entity->isEnabled() && entity->needsUpdate() )
271 qDebug() <<
"need for update";
272 entity->update(
_sceneState( mCameraController ) );
277 void Qgs3DMapScene::createTerrain()
281 mChunkEntities.removeOne( mTerrain );
283 mTerrain->deleteLater();
287 if ( !mTerrainUpdateScheduled )
290 QTimer::singleShot( 0,
this, &Qgs3DMapScene::createTerrainDeferred );
291 mTerrainUpdateScheduled =
true;
295 void Qgs3DMapScene::createTerrainDeferred()
300 mTerrain =
new QgsTerrainEntity( maxZoomLevel, mMap );
302 mTerrain->setParent(
this );
305 mTerrain->setShowBoundingBoxes(
true );
309 mChunkEntities << mTerrain;
317 removeLayerEntity( layer );
320 addLayerEntity( layer );
323 mTerrainUpdateScheduled =
false;
330 void Qgs3DMapScene::onBackgroundColorChanged()
335 void Qgs3DMapScene::onLayerRenderer3DChanged()
341 removeLayerEntity( layer );
344 addLayerEntity( layer );
347 void Qgs3DMapScene::onLayersChanged()
349 QSet<QgsMapLayer *> layersBefore = QSet<QgsMapLayer *>::fromList( mLayerEntities.keys() );
350 QList<QgsMapLayer *> layersAdded;
353 if ( !layersBefore.contains( layer ) )
355 layersAdded << layer;
359 layersBefore.remove( layer );
366 removeLayerEntity( layer );
371 addLayerEntity( layer );
375 void Qgs3DMapScene::addLayerEntity(
QgsMapLayer *layer )
390 Qt3DCore::QEntity *newEntity = renderer->
createEntity( mMap );
393 newEntity->setParent(
this );
394 mLayerEntities.insert( layer, newEntity );
407 void Qgs3DMapScene::removeLayerEntity(
QgsMapLayer *layer )
409 Qt3DCore::QEntity *entity = mLayerEntities.take( layer );
411 entity->deleteLater();
void addTerrainPicker(Qt3DRender::QObjectPicker *picker)
Connects to object picker attached to terrain entity.
Qgs3DMapScene(const Qgs3DMapSettings &map, Qt3DExtras::QForwardRenderer *defaultFrameGraph, Qt3DRender::QRenderSettings *renderSettings, Qt3DRender::QCamera *camera, const QRect &viewportRect, Qt3DCore::QNode *parent=nullptr)
Constructs a 3D scene based on map settings and Qt 3D renderer configuration.
QList< QgsMapLayer * > layers() const
Returns the list of map layers to be rendered as a texture of the terrain.
void cameraChanged()
Emitted when camera has been updated.
3 Axis-aligned bounding box - in world coords.
A rectangle specified with double values.
Base class for all map layer types.
void maxTerrainGroundErrorChanged()
Emitted when the maximum terrain ground error has changed.
bool showTerrainBoundingBoxes() const
Returns whether to display bounding boxes of terrain tiles (for debugging)
void frameTriggered(float dt)
Called internally from 3D scene when a new frame is generated. Updates camera according to keyboard/m...
Base class for all renderers that may to participate in 3D view.
void layersChanged()
Emitted when the list of map layers for terrain texture has changed.
QString skyboxFileBase() const
Returns base part of filenames of skybox (see setSkybox())
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.
void terrainPendingJobsCountChanged()
Emitted when the number of terrain's pending jobs changes.
void resetView(float distance)
Move camera back to the initial position (looking down towards origin of world's coordinates) ...
void terrainVerticalScaleChanged()
Emitted when the vertical scale of the terrain has changed.
3 Definition of the world
QgsMapLayer::LayerType type() const
Returns the type of the layer.
float maxTerrainGroundError() const
Returns maximum ground error of terrain tiles in world units.
void viewportChanged()
Emitted when viewport rectangle has been updated.
virtual QString type() const =0
Returns unique identifier of the renderer class (used to identify subclass)
bool hasSkyboxEnabled() const
Returns whether skybox is enabled.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, const bool clearAndSelect)
This signal is emitted when selection was changed.
double width() const
Returns the width of the rectangle.
int mapTileResolution() const
Returns resolution (in pixels) of the texture of a terrain tile.
void terrainGeneratorChanged()
Emitted when the terrain generator has changed.
QColor backgroundColor() const
Returns background color of the 3D map view.
3 Object that controls camera movement based on user input
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...
void mapTileResolutionChanged()
Emitted when the map tile resoulution has changed.
Qt3DRender::QCamera camera
QgsAbstract3DRenderer * renderer3D() const
Returns 3D renderer associated with the layer.
3D renderer that renders all features of a vector layer with the same 3D symbol.
void setCamera(Qt3DRender::QCamera *camera)
Assigns camera that should be controlled by this class. Called internally from 3D scene...
void maxTerrainScreenErrorChanged()
Emitted when the maximum terrain screen error has changed.
void setViewport(const QRect &viewport)
Sets viewport rectangle. Called internally from 3D canvas. Allows conversion of mouse coordinates...
QList< QgsAbstract3DRenderer * > renderers() const
Returns list of extra 3D renderers.
void viewZoomFull()
Resets camera view to show the whole scene (top view)
int terrainPendingJobsCount() const
Returns number of pending jobs of the terrain entity.
virtual QgsRectangle extent() const =0
extent of the terrain in terrain's CRS
QString skyboxFileExtension() const
Returns extension part of filenames of skybox (see setSkybox())
void terrainEntityChanged()
Emitted when the current terrain entity is replaced by a new one.
void backgroundColorChanged()
Emitted when the background color has changed.
QgsChunkedEntity::SceneState _sceneState(QgsCameraController *cameraController)
Represents a vector layer which manages a vector based data sets.
QgsCameraController * cameraController()
Returns camera controller.
double height() const
Returns the height of the rectangle.
void renderer3DChanged()
Signal emitted when 3D renderer associated with the layer has changed.
QgsTerrainGenerator * terrainGenerator() const
Returns terrain generator. It takes care of producing terrain tiles from the input data...