From 79a5011f8648aedb3526c2c8a8cff80c37eaea1f Mon Sep 17 00:00:00 2001 From: Jean Felder Date: Sun, 27 Oct 2024 09:37:57 +0100 Subject: [PATCH] qgs3dmapscene: Compute max clip planes The number of available clip planes depends on the OpenGL implementation. This change Introduces a new function in Qgs3DUtils function called `Qgs3DUtils::getOpenGLMaxClipPlanes` to compute this number (`GL_MAX_CLIP_PLANES`) and use it in the 3D scene. See: https://registry.khronos.org/OpenGL-Refpages/gl2.1/xhtml/glClipPlane.xml --- python/3d/auto_generated/qgs3dmapscene.sip.in | 6 +++--- .../3d/auto_generated/qgs3dmapscene.sip.in | 6 +++--- src/3d/qgs3dmapscene.cpp | 9 ++++++--- src/3d/qgs3dmapscene.h | 7 ++++--- src/3d/qgs3dutils.cpp | 19 +++++++++++++++++++ src/3d/qgs3dutils.h | 10 ++++++++++ 6 files changed, 45 insertions(+), 12 deletions(-) diff --git a/python/3d/auto_generated/qgs3dmapscene.sip.in b/python/3d/auto_generated/qgs3dmapscene.sip.in index 410b442120b6..c8538b35198a 100644 --- a/python/3d/auto_generated/qgs3dmapscene.sip.in +++ b/python/3d/auto_generated/qgs3dmapscene.sip.in @@ -160,9 +160,9 @@ In mathematical terms, a 3d plane can be defined with the equation ``ax+by+cz+d= The normal is ``(a, b, c)`` with ``|a, b, c| = 1`` The distance is ``-d``. -By default, OpenGL supports up to 8 additional clipping planes. If ``clipPlaneEquations`` -contains more than 8 planes, only the first 8 ones will be used. -If ``clipPlaneEquations`` is empty, the clipping is disabled. +The number of available clip planes depends on the OpenGL implementation. It should at least handle +6 additional clip planes. When the map scene is created, this number is retrieved. +If ``clipPlaneEquations`` contains more than this maximum, only the first ones will be kept. .. seealso:: :py:func:`disableClipping` diff --git a/python/PyQt6/3d/auto_generated/qgs3dmapscene.sip.in b/python/PyQt6/3d/auto_generated/qgs3dmapscene.sip.in index c3209dc6d09b..a760f92bba9c 100644 --- a/python/PyQt6/3d/auto_generated/qgs3dmapscene.sip.in +++ b/python/PyQt6/3d/auto_generated/qgs3dmapscene.sip.in @@ -160,9 +160,9 @@ In mathematical terms, a 3d plane can be defined with the equation ``ax+by+cz+d= The normal is ``(a, b, c)`` with ``|a, b, c| = 1`` The distance is ``-d``. -By default, OpenGL supports up to 8 additional clipping planes. If ``clipPlaneEquations`` -contains more than 8 planes, only the first 8 ones will be used. -If ``clipPlaneEquations`` is empty, the clipping is disabled. +The number of available clip planes depends on the OpenGL implementation. It should at least handle +6 additional clip planes. When the map scene is created, this number is retrieved. +If ``clipPlaneEquations`` contains more than this maximum, only the first ones will be kept. .. seealso:: :py:func:`disableClipping` diff --git a/src/3d/qgs3dmapscene.cpp b/src/3d/qgs3dmapscene.cpp index 046ab22000a4..2c3fa926b884 100644 --- a/src/3d/qgs3dmapscene.cpp +++ b/src/3d/qgs3dmapscene.cpp @@ -99,6 +99,9 @@ Qgs3DMapScene::Qgs3DMapScene( Qgs3DMapSettings &map, QgsAbstract3DEngine *engine QRect viewportRect( QPoint( 0, 0 ), mEngine->size() ); + // Get the maximum of clip planes available + mMaxClipPlanes = Qgs3DUtils::openGlMaxClipPlanes( mEngine->surface() ); + // Camera float aspectRatio = ( float )viewportRect.width() / viewportRect.height(); mEngine->camera()->lens()->setPerspectiveProjection( mMap.fieldOfView(), aspectRatio, 10.f, 10000.0f ); @@ -1223,11 +1226,11 @@ void Qgs3DMapScene::handleClippingOnAllEntities() const void Qgs3DMapScene::enableClipping( const QList &clipPlaneEquations ) { - if ( clipPlaneEquations.size() > 8 ) + if ( clipPlaneEquations.size() > mMaxClipPlanes ) { - QgsDebugMsgLevel( QStringLiteral( "Qgs3DMapScene::enableClipping: it is not possible to use more than 8 clipping planes." ), 2 ); + QgsDebugMsgLevel( QStringLiteral( "Qgs3DMapScene::enableClipping: it is not possible to use more than %1 clipping planes." ).arg( mMaxClipPlanes ), 2 ); } - mClipPlanesEquations = clipPlaneEquations.mid( 0, 8 ); + mClipPlanesEquations = clipPlaneEquations.mid( 0, mMaxClipPlanes ); // enable the clip planes on the framegraph QgsFrameGraph *frameGraph = mEngine->frameGraph(); diff --git a/src/3d/qgs3dmapscene.h b/src/3d/qgs3dmapscene.h index 3a880f59d87c..be1b77f17baa 100644 --- a/src/3d/qgs3dmapscene.h +++ b/src/3d/qgs3dmapscene.h @@ -227,9 +227,9 @@ class _3D_EXPORT Qgs3DMapScene : public QObject * The normal is ``(a, b, c)`` with ``|a, b, c| = 1`` * The distance is ``-d``. * - * By default, OpenGL supports up to 8 additional clipping planes. If \a clipPlaneEquations - * contains more than 8 planes, only the first 8 ones will be used. - * If \a clipPlaneEquations is empty, the clipping is disabled. + * The number of available clip planes depends on the OpenGL implementation. It should at least handle + * 6 additional clip planes. When the map scene is created, this number is retrieved. + * If \a clipPlaneEquations contains more than this maximum, only the first ones will be kept. * * \see disableClipping() * \since QGIS 3.40 @@ -357,6 +357,7 @@ class _3D_EXPORT Qgs3DMapScene : public QObject bool mSceneUpdatesEnabled = true; QList mClipPlanesEquations; + int mMaxClipPlanes = 6; }; #endif // QGS3DMAPSCENE_H diff --git a/src/3d/qgs3dutils.cpp b/src/3d/qgs3dutils.cpp index 7a642fd5a9be..1d5eb151f531 100644 --- a/src/3d/qgs3dutils.cpp +++ b/src/3d/qgs3dutils.cpp @@ -42,6 +42,9 @@ #include #include #include +#include +#include + #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) #include @@ -974,3 +977,19 @@ void Qgs3DUtils::decomposeTransformMatrix( const QMatrix4x4 &matrix, QVector3D & rotation = QQuaternion::fromRotationMatrix( rot3x3 ); translation = QVector3D( md[12], md[13], md[14] ); } + +int Qgs3DUtils::openGlMaxClipPlanes( QSurface *surface ) +{ + int numPlanes = 6; + + QOpenGLContext context; + context.setFormat( QSurfaceFormat::defaultFormat() ); + if ( context.create() ) + { + context.makeCurrent( surface ); + QOpenGLFunctions *funcs = context.functions(); + funcs->glGetIntegerv( GL_MAX_CLIP_PLANES, &numPlanes ); + } + + return numPlanes; +} diff --git a/src/3d/qgs3dutils.h b/src/3d/qgs3dutils.h index ac90fba81fe1..a5bcb89130f0 100644 --- a/src/3d/qgs3dutils.h +++ b/src/3d/qgs3dutils.h @@ -31,6 +31,8 @@ namespace Qt3DExtras class QPhongMaterial; } +class QSurface; + #include "qgs3dmapsettings.h" #include "qgs3danimationsettings.h" #include "qgs3dtypes.h" @@ -340,6 +342,14 @@ class _3D_EXPORT Qgs3DUtils * \since QGIS 3.42 */ static void decomposeTransformMatrix( const QMatrix4x4 &matrix, QVector3D &translation, QQuaternion &rotation, QVector3D &scale ); + + /** + * Gets the maximum number of clip planes that can be used. + * This value depends on the OpenGL implementation. It should be at least 6. + * + * \since QGIS 3.42 + */ + static int openGlMaxClipPlanes( QSurface *surface ); }; #endif // QGS3DUTILS_H