From 813ce01de2d153d43bc0623a04adde8b7d923959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ko=C5=88a=C5=99=C3=ADk?= Date: Thu, 13 Feb 2025 10:34:18 +0100 Subject: [PATCH 1/2] Decouple 3D scene update from near/far planes --- src/3d/qgs3dmapscene.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/3d/qgs3dmapscene.cpp b/src/3d/qgs3dmapscene.cpp index baa60913ef0c..c5af5d132fee 100644 --- a/src/3d/qgs3dmapscene.cpp +++ b/src/3d/qgs3dmapscene.cpp @@ -310,15 +310,7 @@ void Qgs3DMapScene::onCameraChanged() } updateScene( true ); - bool changedCameraPlanes = updateCameraNearFarPlanes(); - - if ( changedCameraPlanes ) - { - // repeat update of entities - because we have updated camera's near/far planes, - // the active nodes may have changed as well - updateScene( true ); - updateCameraNearFarPlanes(); - } + updateCameraNearFarPlanes(); onShadowSettingsChanged(); @@ -342,6 +334,14 @@ void Qgs3DMapScene::updateScene( bool forceUpdate ) sceneContext.cameraPos = camera->position(); const QSize size = mEngine->size(); sceneContext.screenSizePx = std::max( size.width(), size.height() ); // TODO: is this correct? + + // Make our own projection matrix so that frustum culling done by the + // entities isn't dependent on the current near/far planes, which would then + // require multiple steps to stabilize. + QMatrix4x4 projMatrix; + projMatrix.setToIdentity(); + // Just use some high values for the far plane so we don't have to custom-make the matrix. + projMatrix.perspective( camera->fieldOfView(), camera->aspectRatio(), 1, 10'000'000 ); sceneContext.viewProjectionMatrix = camera->projectionMatrix() * camera->viewMatrix(); From a50d2b974decc71873e344e6be74d3b67c8ebbfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ko=C5=88a=C5=99=C3=ADk?= Date: Thu, 20 Feb 2025 00:11:03 +0100 Subject: [PATCH 2/2] Speed up QgsVirtualPointCloudEntity::handleSceneUpdate Done by adding frustum culling early in the loop, results in a ~10x speedup in one project. --- src/3d/qgsvirtualpointcloudentity_p.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/3d/qgsvirtualpointcloudentity_p.cpp b/src/3d/qgsvirtualpointcloudentity_p.cpp index f2afd4b24e48..852ffcb05a55 100644 --- a/src/3d/qgsvirtualpointcloudentity_p.cpp +++ b/src/3d/qgsvirtualpointcloudentity_p.cpp @@ -130,9 +130,18 @@ void QgsVirtualPointCloudEntity::handleSceneUpdate( const SceneContext &sceneCon const QVector subIndexes = provider()->subIndexes(); for ( int i = 0; i < subIndexes.size(); ++i ) { + // If the chunked entity needs an update, do it even if it's occluded, + // since otherwise we'd return needsUpdate() == true until it comes into + // view again. + bool needsUpdate = mChunkedEntitiesMap.contains( i ) && mChunkedEntitiesMap[i]->needsUpdate(); + const QgsBox3D &box3D = mBboxes.at( i ); - if ( box3D.isEmpty() ) + if ( !needsUpdate && box3D.isEmpty() ) + continue; + + QgsAABB aabb = QgsAABB::fromBox3D( box3D, mBboxesEntity->vertexDataOrigin() ); + if ( !needsUpdate && Qgs3DUtils::isCullable( aabb, sceneContext.viewProjectionMatrix ) ) continue; // magic number 256 is the common span value for a COPC root node