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 19, 2024
1 parent a34442d commit a5312f9
Show file tree
Hide file tree
Showing 6 changed files with 46 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::openGlMaxClipPlanes( mEngine->surface() );

// 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 %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();
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 = 6;

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


#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <Qt3DRender/QBuffer>
Expand Down Expand Up @@ -974,3 +977,20 @@ 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;
}
10 changes: 10 additions & 0 deletions src/3d/qgs3dutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ namespace Qt3DExtras
class QPhongMaterial;
}

class QSurface;

#include "qgs3dmapsettings.h"
#include "qgs3danimationsettings.h"
#include "qgs3dtypes.h"
Expand Down Expand Up @@ -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

0 comments on commit a5312f9

Please sign in to comment.