Skip to content

Commit

Permalink
qgs3dmapscene: Compute max clip planes
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ptitjano committed Nov 4, 2024
1 parent a4105a3 commit 3f884a1
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 12 deletions.
6 changes: 3 additions & 3 deletions python/3d/auto_generated/qgs3dmapscene.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down
6 changes: 3 additions & 3 deletions python/PyQt6/3d/auto_generated/qgs3dmapscene.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down
9 changes: 6 additions & 3 deletions src/3d/qgs3dmapscene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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::getOpenGLMaxClipPlanes();

// Camera
float aspectRatio = ( float )viewportRect.width() / viewportRect.height();
mEngine->camera()->lens()->setPerspectiveProjection( mMap.fieldOfView(), aspectRatio, 10.f, 10000.0f );
Expand Down Expand Up @@ -1223,11 +1226,11 @@ void Qgs3DMapScene::handleClippingOnAllEntities() const

void Qgs3DMapScene::enableClipping( const QList<QVector4D> &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 %s clipping planes." ).arg( QString::number( mMaxClipPlanes ) ), 2 );
}
mClipPlanesEquations = clipPlaneEquations.mid( 0, 8 );
mClipPlanesEquations = clipPlaneEquations.mid( 0, mMaxClipPlanes );

// enable the clip planes on the framegraph
QgsFrameGraph *frameGraph = mEngine->frameGraph();
Expand Down
7 changes: 4 additions & 3 deletions src/3d/qgs3dmapscene.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -357,6 +357,7 @@ class _3D_EXPORT Qgs3DMapScene : public QObject
bool mSceneUpdatesEnabled = true;

QList<QVector4D> mClipPlanesEquations;
int mMaxClipPlanes;

};
#endif // QGS3DMAPSCENE_H
26 changes: 26 additions & 0 deletions src/3d/qgs3dutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
#include <QtMath>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DRender/QRenderSettings>
#include <QOffscreenSurface>
#include <QOpenGLContext>
#include <QOpenGLFunctions>


#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <Qt3DRender/QBuffer>
Expand Down Expand Up @@ -952,3 +956,25 @@ QByteArray Qgs3DUtils::removeDefinesFromShaderCode( const QByteArray &shaderCode

return newShaderCode;
}

int Qgs3DUtils::getOpenGLMaxClipPlanes()
{
int nrPlanes = 6;

QOffscreenSurface offscreen;
QOpenGLContext context;

offscreen.setFormat( QSurfaceFormat::defaultFormat() );
offscreen.create();
Q_ASSERT_X( offscreen.isValid(), Q_FUNC_INFO, "Unable to create offscreen surface to gather capabilities" );

context.setFormat( QSurfaceFormat::defaultFormat() );
if ( context.create() )
{
context.makeCurrent( &offscreen );
auto funcs = context.functions();
funcs->glGetIntegerv( GL_MAX_CLIP_PLANES, &nrPlanes );
}

return nrPlanes;
}
8 changes: 8 additions & 0 deletions src/3d/qgs3dutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,14 @@ class _3D_EXPORT Qgs3DUtils
* \since QGIS 3.40
*/
static QByteArray removeDefinesFromShaderCode( const QByteArray &shaderCode, const QStringList &defines );

/**
* 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 getOpenGLMaxClipPlanes();
};

#endif // QGS3DUTILS_H

0 comments on commit 3f884a1

Please sign in to comment.