Add some thread safety to Qgs3DMapSettings usage

Create a small, cheap to copy (non-qobject) class
Qgs3DMapSettingsSnapshot which is designed to store
just cheap properties of Qgs3DMapSettings. Then use this
object wherever possible to avoid accessing the (non-thread
safe) Qgs3DMapSettings object for retrieval of simple
map properties (eg crs, extent, ...)

Refs https://github.com/qgis/QGIS-Enhancement-Proposals/issues/301
This commit is contained in:
Nyall Dawson 2024-08-15 13:17:05 +10:00
parent a37fec4fc9
commit 5e33ee4a57
44 changed files with 421 additions and 90 deletions

View File

@ -16,6 +16,12 @@ class Qgs3DMapSettings : QObject, QgsTemporalRangeObject
{
%Docstring(signature="appended")
Definition of the world.
.. warning::
Qgs3DMapSettings are a QObject subclass, and accordingly are not
safe for access across different threads. See Qgs3DMapSettingsSnapshot instead
for a safe snapshot of settings from Qgs3DMapSettings.
%End
%TypeHeaderCode
@ -28,6 +34,7 @@ Definition of the world.
~Qgs3DMapSettings();
void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
%Docstring
Reads configuration from a DOM element previously written by :py:func:`~Qgs3DMapSettings.writeXml`

View File

@ -16,6 +16,12 @@ class Qgs3DMapSettings : QObject, QgsTemporalRangeObject
{
%Docstring(signature="appended")
Definition of the world.
.. warning::
Qgs3DMapSettings are a QObject subclass, and accordingly are not
safe for access across different threads. See Qgs3DMapSettingsSnapshot instead
for a safe snapshot of settings from Qgs3DMapSettings.
%End
%TypeHeaderCode
@ -28,6 +34,7 @@ Definition of the world.
~Qgs3DMapSettings();
void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
%Docstring
Reads configuration from a DOM element previously written by :py:func:`~Qgs3DMapSettings.writeXml`

View File

@ -13,6 +13,7 @@ set(QGIS_3D_SRCS
qgs3dmapexportsettings.cpp
qgs3dmapscene.cpp
qgs3dmapsettings.cpp
qgs3dmapsettingssnapshot.cpp
qgs3dmaptool.cpp
qgs3dmapcanvas.cpp
qgs3dsceneexporter.cpp
@ -120,6 +121,7 @@ set(QGIS_3D_HDRS
qgs3daxissettings.h
qgs3dmapscene.h
qgs3dmapsettings.h
qgs3dmapsettingssnapshot.h
qgs3dmaptool.h
qgs3dsceneexporter.h
qgs3dtypes.h

View File

@ -20,12 +20,12 @@
#include <Qt3DRender/QGeometryRenderer>
#include "qgsmeshlayer.h"
#include "qgs3dmapsettings.h"
#include "qgs3dmapsettingssnapshot.h"
#include "qgsmesh3dmaterial_p.h"
QgsMesh3DEntity::QgsMesh3DEntity( const Qgs3DMapSettings &map,
QgsMesh3DEntity::QgsMesh3DEntity( const Qgs3DMapSettingsSnapshot &map,
const QgsTriangularMesh &triangularMesh,
const QgsMesh3DSymbol *symbol )
: mMapSettings( map )
@ -34,7 +34,7 @@ QgsMesh3DEntity::QgsMesh3DEntity( const Qgs3DMapSettings &map,
{}
QgsMeshDataset3DEntity::QgsMeshDataset3DEntity(
const Qgs3DMapSettings &map,
const Qgs3DMapSettingsSnapshot &map,
const QgsTriangularMesh &triangularMesh,
QgsMeshLayer *meshLayer,
const QgsMesh3DSymbol *symbol )
@ -77,7 +77,7 @@ QgsMeshLayer *QgsMeshDataset3DEntity::layer() const
}
QgsMesh3DTerrainTileEntity::QgsMesh3DTerrainTileEntity(
const Qgs3DMapSettings &map,
const Qgs3DMapSettingsSnapshot &map,
const QgsTriangularMesh &triangularMesh,
const QgsMesh3DSymbol *symbol,
QgsChunkNodeId nodeId,

View File

@ -21,7 +21,7 @@
#include <Qt3DCore/QEntity>
#include "mesh/qgsmesh3dgeometry_p.h"
#include "qgs3dmapsettings.h"
#include "qgs3dmapsettingssnapshot.h"
#include "qgsmesh3dsymbol.h"
#include "qgsterraintileentity_p.h"
@ -52,13 +52,13 @@ class QgsMesh3DEntity
void build();
protected:
//! Constructor
QgsMesh3DEntity( const Qgs3DMapSettings &map,
QgsMesh3DEntity( const Qgs3DMapSettingsSnapshot &map,
const QgsTriangularMesh &triangularMesh,
const QgsMesh3DSymbol *symbol );
virtual ~QgsMesh3DEntity() = default;
Qgs3DMapSettings mMapSettings;
Qgs3DMapSettingsSnapshot mMapSettings;
QgsTriangularMesh mTriangularMesh;
std::unique_ptr< QgsMesh3DSymbol > mSymbol;
@ -74,7 +74,7 @@ class QgsMeshDataset3DEntity: public Qt3DCore::QEntity, public QgsMesh3DEntity
public:
//! Constructor
QgsMeshDataset3DEntity( const Qgs3DMapSettings &map,
QgsMeshDataset3DEntity( const Qgs3DMapSettingsSnapshot &map,
const QgsTriangularMesh &triangularMesh,
QgsMeshLayer *meshLayer,
const QgsMesh3DSymbol *symbol );
@ -94,7 +94,7 @@ class QgsMesh3DTerrainTileEntity: public QgsTerrainTileEntity, public QgsMesh3DE
Q_OBJECT
public:
QgsMesh3DTerrainTileEntity( const Qgs3DMapSettings &map,
QgsMesh3DTerrainTileEntity( const Qgs3DMapSettingsSnapshot &map,
const QgsTriangularMesh &triangularMesh,
const QgsMesh3DSymbol *symbol,
QgsChunkNodeId nodeId,

View File

@ -25,7 +25,7 @@
#include "qgsterrainentity_p.h"
#include "qgsterraintextureimage_p.h"
#include "qgsmeshlayerutils.h"
#include "qgs3dmapsettings.h"
QgsMeshTerrainTileLoader::QgsMeshTerrainTileLoader( QgsTerrainEntity *terrain, QgsChunkNode *node, const QgsTriangularMesh &triangularMesh, const QgsMesh3DSymbol *symbol )
: QgsTerrainTileLoader( terrain, node )
@ -37,7 +37,7 @@ QgsMeshTerrainTileLoader::QgsMeshTerrainTileLoader( QgsTerrainEntity *terrain, Q
Qt3DCore::QEntity *QgsMeshTerrainTileLoader::createEntity( Qt3DCore::QEntity *parent )
{
QgsMesh3DTerrainTileEntity *entity = new QgsMesh3DTerrainTileEntity( terrain()->map3D(), mTriangularMesh, mSymbol.get(), mNode->tileId(), parent );
QgsMesh3DTerrainTileEntity *entity = new QgsMesh3DTerrainTileEntity( terrain()->map3D().snapshot(), mTriangularMesh, mSymbol.get(), mNode->tileId(), parent );
entity->build();
createTexture( entity );
@ -145,7 +145,7 @@ void QgsMeshTerrainGenerator::readXml( const QDomElement &elem )
mSymbol->readXml( elem.firstChildElement( "symbol" ), rwc );
}
float QgsMeshTerrainGenerator::heightAt( double x, double y, const Qgs3DMapSettings & ) const
float QgsMeshTerrainGenerator::heightAt( double x, double y, const Qgs3DMapSettingsSnapshot & ) const
{
return QgsMeshLayerUtils::interpolateZForPoint( mTriangularMesh, x, y );
}

View File

@ -85,7 +85,7 @@ class _3D_EXPORT QgsMeshTerrainGenerator: public QgsTerrainGenerator
QgsRectangle rootChunkExtent() const override;
void writeXml( QDomElement &elem ) const override;
void readXml( const QDomElement &elem ) override;
float heightAt( double x, double y, const Qgs3DMapSettings & ) const override;
float heightAt( double x, double y, const Qgs3DMapSettingsSnapshot &map ) const override;
private slots:
void updateTriangularMesh();

View File

@ -21,9 +21,6 @@
#include "qgsmeshterraingenerator.h"
#include "qgsonlineterraingenerator.h"
#include "qgsprojectviewsettings.h"
#include "qgsvectorlayer3drenderer.h"
#include "qgsmeshlayer3drenderer.h"
#include "qgspointcloudlayer3drenderer.h"
#include "qgsprojectelevationproperties.h"
#include "qgsterrainprovider.h"
#include "qgslightsource.h"
@ -31,6 +28,8 @@
#include "qgsrasterlayer.h"
#include "qgspointlightsettings.h"
#include "qgsdirectionallightsettings.h"
#include "qgsthreadingutils.h"
#include "qgs3dmapsettingssnapshot.h"
#include <QDomDocument>
#include <QDomElement>
@ -118,6 +117,25 @@ Qgs3DMapSettings::~Qgs3DMapSettings()
qDeleteAll( mLightSources );
}
Qgs3DMapSettingsSnapshot Qgs3DMapSettings::snapshot() const
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
Qgs3DMapSettingsSnapshot res;
res.setCrs( mCrs );
res.setTransformContext( mTransformContext );
res.setOrigin( mOrigin );
res.setExtent( mExtent );
res.setTemporalRange( temporalRange() );
res.setSelectionColor( mSelectionColor );
res.setOutputDpi( mDpi );
res.setFieldOfView( mFieldOfView );
res.setTerrainRenderingEnabled( mTerrainRenderingEnabled );
res.setTerrainVerticalScale( mTerrainVerticalScale );
res.setTerrainGenerator( mTerrainGenerator.get() );
return res;
}
void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
{
QgsProjectDirtyBlocker blocker( QgsProject::instance() );

View File

@ -40,6 +40,7 @@ class QgsLightSource;
class QgsAbstract3DRenderer;
class QgsReadWriteContext;
class QgsProject;
class Qgs3DMapSettingsSnapshot;
class QDomElement;
@ -47,6 +48,9 @@ class QDomElement;
* \ingroup 3d
* \brief Definition of the world.
*
* \warning Qgs3DMapSettings are a QObject subclass, and accordingly are not
* safe for access across different threads. See Qgs3DMapSettingsSnapshot instead
* for a safe snapshot of settings from Qgs3DMapSettings.
*/
class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObject
{
@ -59,6 +63,13 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
Qgs3DMapSettings &operator=( Qgs3DMapSettings const & ) = delete;
/**
* Returns a snapshot of settings from this object in a thread-safe, cheap-to-copy structure.
*
* \since QGIS 3.40
*/
Qgs3DMapSettingsSnapshot snapshot() const SIP_SKIP;
//! Reads configuration from a DOM element previously written by writeXml()
void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
//! Writes configuration to a DOM element, to be used later with readXml()

View File

@ -0,0 +1,27 @@
/***************************************************************************
qgs3dmapsettingssnapshot.cpp
--------------------------------------
Date : August 2024
Copyright : (C) 2024 by Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgs3dmapsettingssnapshot.h"
#include "qgs3dutils.h"
QgsVector3D Qgs3DMapSettingsSnapshot::mapToWorldCoordinates( const QgsVector3D &mapCoords ) const
{
return Qgs3DUtils::mapToWorldCoordinates( mapCoords, mOrigin );
}
QgsVector3D Qgs3DMapSettingsSnapshot::worldToMapCoordinates( const QgsVector3D &worldCoords ) const
{
return Qgs3DUtils::worldToMapCoordinates( worldCoords, mOrigin );
}

View File

@ -0,0 +1,254 @@
/***************************************************************************
qgs3dmapsettingssnapshot.h
--------------------------------------
Date : August 2024
Copyright : (C) 2024 by Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGS3DMAPSETTINGSSNAPSHOT_H
#define QGS3DMAPSETTINGSSNAPSHOT_H
#include "qgis_3d.h"
#include "qgsvector3d.h"
#include "qgsrectangle.h"
#include "qgsrange.h"
#include "qgscoordinatereferencesystem.h"
#include "qgscoordinatetransformcontext.h"
#include <QColor>
class QgsTerrainGenerator;
#define SIP_NO_FILE
/**
* \ingroup 3d
* \brief A snapshot of properties from Qgs3DMapSettings, in a thread-safe, cheap-to-copy structure.
*
* \note Not available in Python bindings.
*
* \since QGIS 3.40
*/
class _3D_EXPORT Qgs3DMapSettingsSnapshot
{
public:
Qgs3DMapSettingsSnapshot() = default;
/**
* Sets the coordinate reference system used in the 3D scene
*
* \see crs()
*/
void setCrs( const QgsCoordinateReferenceSystem &crs ) { mCrs = crs; }
/**
* Returns the coordinate reference system used in the 3D scene.
*
* \see setCrs()
*/
QgsCoordinateReferenceSystem crs() const { return mCrs; }
/**
* Returns the coordinate transform context, which stores various
* information regarding which datum transforms should be used when transforming points
* from a source to destination coordinate reference system.
*
* \see setTransformContext()
*/
QgsCoordinateTransformContext transformContext() const { return mTransformContext; }
/**
* Sets the coordinate transform \a context, which stores various
* information regarding which datum transforms should be used when transforming points
* from a source to destination coordinate reference system.
*
* \see transformContext()
*/
void setTransformContext( const QgsCoordinateTransformContext &context ) { mTransformContext = context; }
/**
* Returns the 3D scene's 2D extent in the 3D scene's CRS
*
* \see crs()
* \see setExtent()
*/
QgsRectangle extent() const { return mExtent; }
/**
* Sets the 3D scene's 2D \a extent in the 3D scene's CRS, while also setting the scene's origin to the extent's center
* This needs to be called during initialization, as terrain will only be generated
* within this extent and layer 3D data will only be loaded within this extent too.
*
* \see extent()
* \see setOrigin()
* \see setCrs()
*/
void setExtent( const QgsRectangle &extent ) { mExtent = extent; }
/**
* Sets coordinates in map CRS at which our 3D world has origin (0,0,0)
*
* We move the 3D world origin to the center of the extent of our terrain: this is done
* to minimize the impact of numerical errors when operating with 32-bit floats.
* Unfortunately this is not enough when working with a large area (still results in jitter
* with scenes spanning hundreds of kilometers and zooming in a lot).
*
* Need to look into more advanced techniques like "relative to center" or "relative to eye"
* to improve the precision.
*
* \see origin()
*/
void setOrigin( const QgsVector3D &origin ) { mOrigin = origin; }
/**
* Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
*
* \see setOrigin()
*/
QgsVector3D origin() const { return mOrigin; }
/**
* Sets the temporal \a range for the map.
*
* \see temporalRange()
*/
void setTemporalRange( const QgsDateTimeRange &range ) { mTemporalRange = range; }
/**
* Returns the temporal range for the map.
*
* \see setTemporalRange()
*/
const QgsDateTimeRange &temporalRange() const { return mTemporalRange; }
/**
* Sets color used for selected features
*
* \see selectionColor()
*/
void setSelectionColor( const QColor &color ) { mSelectionColor = color; }
/**
* Returns color used for selected features
*
* \see setSelectionColor()
*/
QColor selectionColor() const { return mSelectionColor; }
/**
* Sets DPI used for conversion between real world units (e.g. mm) and pixels
*
* \see outputDpi()
*/
void setOutputDpi( const double dpi ) {mDpi = dpi;}
/**
* Returns DPI used for conversion between real world units (e.g. mm) and pixels
* Default value is 96
*
* \see setOutputDpi()
*/
double outputDpi() const { return mDpi; }
/**
* Returns the camera lens' field of view.
*
* \see setFieldOfView()
*/
float fieldOfView() const { return mFieldOfView; }
/**
* Sets the camera lens' field of view.
*
* \see fieldOfView()
*/
void setFieldOfView( const float fieldOfView ) { mFieldOfView = fieldOfView; }
/**
* Converts map coordinates to 3D world coordinates (applies offset and turns (x,y,z) into (x,-z,y)).
*
* \see worldToMapCoordinates()
*/
QgsVector3D mapToWorldCoordinates( const QgsVector3D &mapCoords ) const;
/**
* Converts 3D world coordinates to map coordinates (applies offset and turns (x,y,z) into (x,-z,y)).
*
* \see mapToWorldCoordinates()
*/
QgsVector3D worldToMapCoordinates( const QgsVector3D &worldCoords ) const;
/**
* Returns whether the 2D terrain surface will be rendered.
* \see setTerrainRenderingEnabled()
*/
bool terrainRenderingEnabled() const { return mTerrainRenderingEnabled; }
/**
* Sets whether the 2D terrain surface will be rendered in.
* \see terrainRenderingEnabled()
*/
void setTerrainRenderingEnabled( bool terrainRenderingEnabled ) { mTerrainRenderingEnabled = terrainRenderingEnabled; }
/**
* Sets the vertical scale (exaggeration) of terrain.
* (1 = true scale, > 1 = hills get more pronounced)
*
* \see terrainVerticalScale()
*/
void setTerrainVerticalScale( double zScale ) { mTerrainVerticalScale = zScale; }
/**
* Returns vertical scale (exaggeration) of terrain
* \see setTerrainVerticalScale()
*/
double terrainVerticalScale() const { return mTerrainVerticalScale; }
/**
* Sets terrain generator.
*
* Ownership is NOT transferred, and belongs to the Qgs3DMapSettings.
*
* \see terrainGenerator()
*/
void setTerrainGenerator( QgsTerrainGenerator *gen ) { mTerrainGenerator = gen; }
/**
* Returns the terrain generator.
*
* \see setTerrainGenerator()
*/
QgsTerrainGenerator *terrainGenerator() const { return mTerrainGenerator; }
private:
QgsCoordinateReferenceSystem mCrs; //!< Destination coordinate system of the world
//! Coordinate transform context
QgsCoordinateTransformContext mTransformContext;
//! Offset in map CRS coordinates at which our 3D world has origin (0,0,0)
QgsVector3D mOrigin;
QgsRectangle mExtent; //!< 2d extent used to limit the 3d view
QgsDateTimeRange mTemporalRange;
QColor mSelectionColor; //!< Color to be used for selected map features
double mDpi = 96; //!< Dot per inch value for the screen / painter
float mFieldOfView = 45.0f; //!< Camera lens field of view value
bool mTerrainRenderingEnabled = true;
double mTerrainVerticalScale = 1; //!< Multiplier of terrain heights to make the terrain shape more pronounced
// not owned, currently a pointer to the Qgs3DMapSettings terrain generator.
// TODO -- fix during implementation of https://github.com/qgis/QGIS-Enhancement-Proposals/issues/301
QgsTerrainGenerator *mTerrainGenerator = nullptr; //!< Implementation of the terrain generation
};
#endif // QGS3DMAPSETTINGSSNAPSHOT_H

View File

@ -351,7 +351,7 @@ Qgs3DTypes::CullingMode Qgs3DUtils::cullingModeFromString( const QString &str )
return Qgs3DTypes::NoCulling;
}
float Qgs3DUtils::clampAltitude( const QgsPoint &p, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, float offset, const QgsPoint &centroid, const Qgs3DMapSettings &map )
float Qgs3DUtils::clampAltitude( const QgsPoint &p, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, float offset, const QgsPoint &centroid, const Qgs3DMapSettingsSnapshot &map )
{
float terrainZ = 0;
switch ( altClamp )
@ -387,7 +387,7 @@ float Qgs3DUtils::clampAltitude( const QgsPoint &p, Qgis::AltitudeClamping altCl
return z;
}
void Qgs3DUtils::clampAltitudes( QgsLineString *lineString, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, const QgsPoint &centroid, float offset, const Qgs3DMapSettings &map )
void Qgs3DUtils::clampAltitudes( QgsLineString *lineString, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, const QgsPoint &centroid, float offset, const Qgs3DMapSettingsSnapshot &map )
{
for ( int i = 0; i < lineString->nCoordinates(); ++i )
{
@ -437,7 +437,7 @@ void Qgs3DUtils::clampAltitudes( QgsLineString *lineString, Qgis::AltitudeClampi
}
bool Qgs3DUtils::clampAltitudes( QgsPolygon *polygon, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, float offset, const Qgs3DMapSettings &map )
bool Qgs3DUtils::clampAltitudes( QgsPolygon *polygon, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, float offset, const Qgs3DMapSettingsSnapshot &map )
{
if ( !polygon->is3D() )
polygon->addZValue( 0 );
@ -493,7 +493,7 @@ QMatrix4x4 Qgs3DUtils::stringToMatrix4x4( const QString &str )
return m;
}
void Qgs3DUtils::extractPointPositions( const QgsFeature &f, const Qgs3DMapSettings &map, Qgis::AltitudeClamping altClamp, QVector<QVector3D> &positions )
void Qgs3DUtils::extractPointPositions( const QgsFeature &f, const Qgs3DMapSettingsSnapshot &map, Qgis::AltitudeClamping altClamp, QVector<QVector3D> &positions )
{
const QgsAbstractGeometry *g = f.geometry().constGet();
for ( auto it = g->vertices_begin(); it != g->vertices_end(); ++it )

View File

@ -130,11 +130,11 @@ class _3D_EXPORT Qgs3DUtils
static Qgs3DTypes::CullingMode cullingModeFromString( const QString &str );
//! Clamps altitude of a vertex according to the settings, returns Z value
static float clampAltitude( const QgsPoint &p, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, float offset, const QgsPoint &centroid, const Qgs3DMapSettings &map );
static float clampAltitude( const QgsPoint &p, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, float offset, const QgsPoint &centroid, const Qgs3DMapSettingsSnapshot &map );
//! Clamps altitude of vertices of a linestring according to the settings
static void clampAltitudes( QgsLineString *lineString, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, const QgsPoint &centroid, float offset, const Qgs3DMapSettings &map );
static void clampAltitudes( QgsLineString *lineString, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, const QgsPoint &centroid, float offset, const Qgs3DMapSettingsSnapshot &map );
//! Clamps altitude of vertices of a polygon according to the settings
static bool clampAltitudes( QgsPolygon *polygon, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, float offset, const Qgs3DMapSettings &map );
static bool clampAltitudes( QgsPolygon *polygon, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, float offset, const Qgs3DMapSettingsSnapshot &map );
//! Converts a 4x4 transform matrix to a string
static QString matrix4x4toString( const QMatrix4x4 &m );
@ -142,7 +142,7 @@ class _3D_EXPORT Qgs3DUtils
static QMatrix4x4 stringToMatrix4x4( const QString &str );
//! Calculates (x,y,z) positions of (multi)point from the given feature
static void extractPointPositions( const QgsFeature &f, const Qgs3DMapSettings &map, Qgis::AltitudeClamping altClamp, QVector<QVector3D> &positions );
static void extractPointPositions( const QgsFeature &f, const Qgs3DMapSettingsSnapshot &map, Qgis::AltitudeClamping altClamp, QVector<QVector3D> &positions );
/**
* Returns TRUE if bbox is completely outside the current viewing volume.

View File

@ -33,8 +33,7 @@ class QgsFeature;
#include "qgsexpressioncontext.h"
class Qgs3DMapSettings;
#include "qgs3dmapsettingssnapshot.h"
#define SIP_NO_FILE
@ -48,9 +47,9 @@ class Qgs3DMapSettings;
class Qgs3DRenderContext
{
public:
Qgs3DRenderContext( const Qgs3DMapSettings &map ) : mMap( map ) {}
Qgs3DRenderContext( const Qgs3DMapSettingsSnapshot &map ) : mMap( map ) {}
const Qgs3DMapSettings &map() const { return mMap; }
const Qgs3DMapSettingsSnapshot &map() const { return mMap; }
/**
* Sets the expression context. This context is used for all expression evaluation
@ -75,7 +74,7 @@ class Qgs3DRenderContext
const QgsExpressionContext &expressionContext() const { return mExpressionContext; } SIP_SKIP
private:
const Qgs3DMapSettings &mMap;
Qgs3DMapSettingsSnapshot mMap;
//! Expression context
QgsExpressionContext mExpressionContext;

View File

@ -21,6 +21,7 @@
#include "qgsmeshlayer.h"
#include "qgsxmlutils.h"
#include "qgsmesh3dentity_p.h"
#include "qgs3dmapsettings.h"
QgsMeshLayer3DRendererMetadata::QgsMeshLayer3DRendererMetadata()
: Qgs3DRendererAbstractMetadata( QStringLiteral( "mesh" ) )
@ -91,7 +92,7 @@ Qt3DCore::QEntity *QgsMeshLayer3DRenderer::createEntity( const Qgs3DMapSettings
const QgsCoordinateTransform coordTrans( meshLayer->crs(), map.crs(), map.transformContext() );
meshLayer->updateTriangularMesh( coordTrans );
const QgsTriangularMesh triangularMesh = *meshLayer->triangularMeshByLodIndex( mSymbol->levelOfDetailIndex() );
QgsMeshDataset3DEntity *meshEntity = new QgsMeshDataset3DEntity( map, triangularMesh, meshLayer, mSymbol.get() );
QgsMeshDataset3DEntity *meshEntity = new QgsMeshDataset3DEntity( map.snapshot(), triangularMesh, meshLayer, mSymbol.get() );
meshEntity->build();
entity = meshEntity;

View File

@ -26,7 +26,7 @@
#include "qgspointcloud3dsymbol.h"
#include "qgspointcloudlayerelevationproperties.h"
QgsPointCloud3DRenderContext::QgsPointCloud3DRenderContext( const Qgs3DMapSettings &map, const QgsCoordinateTransform &coordinateTransform, std::unique_ptr<QgsPointCloud3DSymbol> symbol, double zValueScale, double zValueFixedOffset )
QgsPointCloud3DRenderContext::QgsPointCloud3DRenderContext( const Qgs3DMapSettingsSnapshot &map, const QgsCoordinateTransform &coordinateTransform, std::unique_ptr<QgsPointCloud3DSymbol> symbol, double zValueScale, double zValueFixedOffset )
: Qgs3DRenderContext( map )
, mSymbol( std::move( symbol ) )
, mZValueScale( zValueScale )
@ -161,13 +161,13 @@ Qt3DCore::QEntity *QgsPointCloudLayer3DRenderer::createEntity( const Qgs3DMapSet
Qt3DCore::QEntity *entity = nullptr;
if ( pcl->dataProvider()->index() )
{
entity = new QgsPointCloudLayerChunkedEntity( pcl->dataProvider()->index(), map, coordinateTransform, dynamic_cast<QgsPointCloud3DSymbol *>( mSymbol->clone() ), maximumScreenError(), showBoundingBoxes(),
entity = new QgsPointCloudLayerChunkedEntity( pcl->dataProvider()->index(), map.snapshot(), coordinateTransform, dynamic_cast<QgsPointCloud3DSymbol *>( mSymbol->clone() ), maximumScreenError(), showBoundingBoxes(),
static_cast< const QgsPointCloudLayerElevationProperties * >( pcl->elevationProperties() )->zScale(),
static_cast< const QgsPointCloudLayerElevationProperties * >( pcl->elevationProperties() )->zOffset(), mPointBudget );
}
else if ( !pcl->dataProvider()->subIndexes().isEmpty() )
{
entity = new QgsVirtualPointCloudEntity( pcl, map, coordinateTransform, dynamic_cast<QgsPointCloud3DSymbol *>( mSymbol->clone() ), maximumScreenError(), showBoundingBoxes(),
entity = new QgsVirtualPointCloudEntity( pcl, map.snapshot(), coordinateTransform, dynamic_cast<QgsPointCloud3DSymbol *>( mSymbol->clone() ), maximumScreenError(), showBoundingBoxes(),
static_cast< const QgsPointCloudLayerElevationProperties * >( pcl->elevationProperties() )->zScale(),
static_cast< const QgsPointCloudLayerElevationProperties * >( pcl->elevationProperties() )->zOffset(), mPointBudget );
}

View File

@ -52,7 +52,7 @@ class _3D_NO_EXPORT QgsPointCloud3DRenderContext : public Qgs3DRenderContext
* The \a zValueFixedOffset argument specifies any constant offset value which must be added to z values
* taken from the point cloud index.
*/
QgsPointCloud3DRenderContext( const Qgs3DMapSettings &map, const QgsCoordinateTransform &coordinateTransform, std::unique_ptr< QgsPointCloud3DSymbol > symbol,
QgsPointCloud3DRenderContext( const Qgs3DMapSettingsSnapshot &map, const QgsCoordinateTransform &coordinateTransform, std::unique_ptr< QgsPointCloud3DSymbol > symbol,
double zValueScale, double zValueFixedOffset );
QgsPointCloud3DRenderContext( const QgsPointCloud3DRenderContext &rh ) = delete;

View File

@ -131,7 +131,7 @@ Qt3DCore::QEntity *QgsPointCloudLayerChunkLoader::createEntity( Qt3DCore::QEntit
///////////////
QgsPointCloudLayerChunkLoaderFactory::QgsPointCloudLayerChunkLoaderFactory( const Qgs3DMapSettings &map, const QgsCoordinateTransform &coordinateTransform, QgsPointCloudIndex *pc, QgsPointCloud3DSymbol *symbol,
QgsPointCloudLayerChunkLoaderFactory::QgsPointCloudLayerChunkLoaderFactory( const Qgs3DMapSettingsSnapshot &map, const QgsCoordinateTransform &coordinateTransform, QgsPointCloudIndex *pc, QgsPointCloud3DSymbol *symbol,
double zValueScale, double zValueOffset, int pointBudget )
: mMap( map )
, mCoordinateTransform( coordinateTransform )
@ -170,7 +170,7 @@ int QgsPointCloudLayerChunkLoaderFactory::primitivesCount( QgsChunkNode *node )
return mPointCloudIndex->nodePointCount( n );
}
QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset, QgsVector3D scale, const Qgs3DMapSettings &map, const QgsCoordinateTransform &coordinateTransform, double zValueOffset );
QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset, QgsVector3D scale, const Qgs3DMapSettingsSnapshot &map, const QgsCoordinateTransform &coordinateTransform, double zValueOffset );
QgsChunkNode *QgsPointCloudLayerChunkLoaderFactory::createRootNode() const
{
@ -220,7 +220,7 @@ QVector<QgsChunkNode *> QgsPointCloudLayerChunkLoaderFactory::createChildren( Qg
///////////////
QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset, QgsVector3D scale, const Qgs3DMapSettings &map, const QgsCoordinateTransform &coordinateTransform, double zValueOffset )
QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset, QgsVector3D scale, const Qgs3DMapSettingsSnapshot &map, const QgsCoordinateTransform &coordinateTransform, double zValueOffset )
{
QgsVector3D extentMin3D( nodeBounds.xMin() * scale.x() + offset.x(), nodeBounds.yMin() * scale.y() + offset.y(), nodeBounds.zMin() * scale.z() + offset.z() + zValueOffset );
QgsVector3D extentMax3D( nodeBounds.xMax() * scale.x() + offset.x(), nodeBounds.yMax() * scale.y() + offset.y(), nodeBounds.zMax() * scale.z() + offset.z() + zValueOffset );
@ -243,7 +243,7 @@ QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset
}
QgsPointCloudLayerChunkedEntity::QgsPointCloudLayerChunkedEntity( QgsPointCloudIndex *pc, const Qgs3DMapSettings &map,
QgsPointCloudLayerChunkedEntity::QgsPointCloudLayerChunkedEntity( QgsPointCloudIndex *pc, const Qgs3DMapSettingsSnapshot &map,
const QgsCoordinateTransform &coordinateTransform, QgsPointCloud3DSymbol *symbol,
float maximumScreenSpaceError, bool showBoundingBoxes,
double zValueScale, double zValueOffset,

View File

@ -66,7 +66,7 @@ class QgsPointCloudLayerChunkLoaderFactory : public QgsChunkLoaderFactory
* Constructs the factory
* The factory takes ownership over the passed \a symbol
*/
QgsPointCloudLayerChunkLoaderFactory( const Qgs3DMapSettings &map, const QgsCoordinateTransform &coordinateTransform, QgsPointCloudIndex *pc, QgsPointCloud3DSymbol *symbol,
QgsPointCloudLayerChunkLoaderFactory( const Qgs3DMapSettingsSnapshot &map, const QgsCoordinateTransform &coordinateTransform, QgsPointCloudIndex *pc, QgsPointCloud3DSymbol *symbol,
double zValueScale, double zValueOffset, int pointBudget );
//! Creates loader for the given chunk node. Ownership of the returned is passed to the caller.
@ -74,7 +74,7 @@ class QgsPointCloudLayerChunkLoaderFactory : public QgsChunkLoaderFactory
virtual QgsChunkNode *createRootNode() const override;
virtual QVector<QgsChunkNode *> createChildren( QgsChunkNode *node ) const override;
virtual int primitivesCount( QgsChunkNode *node ) const override;
const Qgs3DMapSettings &mMap;
Qgs3DMapSettingsSnapshot mMap;
QgsCoordinateTransform mCoordinateTransform;
QgsPointCloudIndex *mPointCloudIndex;
std::unique_ptr< QgsPointCloud3DSymbol > mSymbol;
@ -133,7 +133,7 @@ class QgsPointCloudLayerChunkedEntity : public QgsChunkedEntity
{
Q_OBJECT
public:
explicit QgsPointCloudLayerChunkedEntity( QgsPointCloudIndex *pc, const Qgs3DMapSettings &map, const QgsCoordinateTransform &coordinateTransform, QgsPointCloud3DSymbol *symbol, float maxScreenError, bool showBoundingBoxes,
explicit QgsPointCloudLayerChunkedEntity( QgsPointCloudIndex *pc, const Qgs3DMapSettingsSnapshot &map, const QgsCoordinateTransform &coordinateTransform, QgsPointCloud3DSymbol *symbol, float maxScreenError, bool showBoundingBoxes,
double zValueScale, double zValueOffset, int pointBudget );
QVector<QgsRayCastingUtils::RayHit> rayIntersection( const QgsRayCastingUtils::Ray3D &ray, const QgsRayCastingUtils::RayCastContext &context ) const override;

View File

@ -167,7 +167,7 @@ void QgsRubberBand3D::updateGeometry()
{
QgsLineVertexData lineData;
lineData.withAdjacency = true;
lineData.init( Qgis::AltitudeClamping::Absolute, Qgis::AltitudeBinding::Vertex, 0, mMapSettings );
lineData.init( Qgis::AltitudeClamping::Absolute, Qgis::AltitudeBinding::Vertex, 0, mMapSettings->snapshot() );
lineData.addLineString( mLineString );
mPositionAttribute->buffer()->setData( lineData.createVertexBuffer() );
@ -189,7 +189,7 @@ void QgsRubberBand3D::updateMarkerMaterial()
{
delete mMarkerMaterial;
mMarkerMaterial = new QgsPoint3DBillboardMaterial();
mMarkerMaterial->setTexture2DFromSymbol( mMarkerSymbol, *mMapSettings );
mMarkerMaterial->setTexture2DFromSymbol( mMarkerSymbol, mMapSettings->snapshot() );
mMarkerEntity->addComponent( mMarkerMaterial );
//TODO: QgsAbstract3DEngine::sizeChanged should have const QSize &size param

View File

@ -49,7 +49,7 @@ QgsRuleBasedChunkLoader::QgsRuleBasedChunkLoader( const QgsRuleBasedChunkLoaderF
}
QgsVectorLayer *layer = mFactory->mLayer;
const Qgs3DMapSettings &map = mFactory->mMap;
const Qgs3DMapSettingsSnapshot &map = mFactory->mMap;
QgsExpressionContext exprContext( Qgs3DUtils::globalProjectLayerExpressionContext( layer ) );
exprContext.setFields( layer->fields() );
@ -165,7 +165,7 @@ Qt3DCore::QEntity *QgsRuleBasedChunkLoader::createEntity( Qt3DCore::QEntity *par
///////////////
QgsRuleBasedChunkLoaderFactory::QgsRuleBasedChunkLoaderFactory( const Qgs3DMapSettings &map, QgsVectorLayer *vl, QgsRuleBased3DRenderer::Rule *rootRule, int leafLevel, double zMin, double zMax )
QgsRuleBasedChunkLoaderFactory::QgsRuleBasedChunkLoaderFactory( const Qgs3DMapSettingsSnapshot &map, QgsVectorLayer *vl, QgsRuleBased3DRenderer::Rule *rootRule, int leafLevel, double zMin, double zMax )
: mMap( map )
, mLayer( vl )
, mRootRule( rootRule->clone() )
@ -187,7 +187,7 @@ QgsChunkLoader *QgsRuleBasedChunkLoaderFactory::createChunkLoader( QgsChunkNode
QgsRuleBasedChunkedEntity::QgsRuleBasedChunkedEntity( QgsVectorLayer *vl, double zMin, double zMax, const QgsVectorLayer3DTilingSettings &tilingSettings, QgsRuleBased3DRenderer::Rule *rootRule, const Qgs3DMapSettings &map )
: QgsChunkedEntity( -1, // max. allowed screen error (negative tau means that we need to go until leaves are reached)
new QgsRuleBasedChunkLoaderFactory( map, vl, rootRule, tilingSettings.zoomLevelsCount() - 1, zMin, zMax ), true )
new QgsRuleBasedChunkLoaderFactory( map.snapshot(), vl, rootRule, tilingSettings.zoomLevelsCount() - 1, zMin, zMax ), true )
{
mTransform = new Qt3DCore::QTransform;
if ( applyTerrainOffset() )

View File

@ -59,13 +59,13 @@ class QgsRuleBasedChunkLoaderFactory : public QgsQuadtreeChunkLoaderFactory
public:
//! Constructs the factory (vl and rootRule must not be null)
QgsRuleBasedChunkLoaderFactory( const Qgs3DMapSettings &map, QgsVectorLayer *vl, QgsRuleBased3DRenderer::Rule *rootRule, int leafLevel, double zMin, double zMax );
QgsRuleBasedChunkLoaderFactory( const Qgs3DMapSettingsSnapshot &map, QgsVectorLayer *vl, QgsRuleBased3DRenderer::Rule *rootRule, int leafLevel, double zMin, double zMax );
~QgsRuleBasedChunkLoaderFactory() override;
//! Creates loader for the given chunk node. Ownership of the returned is passed to the caller.
virtual QgsChunkLoader *createChunkLoader( QgsChunkNode *node ) const override;
const Qgs3DMapSettings &mMap;
Qgs3DMapSettingsSnapshot mMap;
QgsVectorLayer *mLayer;
std::unique_ptr<QgsRuleBased3DRenderer::Rule> mRootRule;
int mLeafLevel;

View File

@ -136,7 +136,7 @@ Qt3DCore::QEntity *QgsTiledSceneChunkLoader::createEntity( Qt3DCore::QEntity *pa
///
QgsTiledSceneChunkLoaderFactory::QgsTiledSceneChunkLoaderFactory( const Qgs3DMapSettings &map, const QgsTiledSceneIndex &index, double zValueScale, double zValueOffset )
QgsTiledSceneChunkLoaderFactory::QgsTiledSceneChunkLoaderFactory( const Qgs3DMapSettingsSnapshot &map, const QgsTiledSceneIndex &index, double zValueScale, double zValueOffset )
: mMap( map )
, mIndex( index )
, mZValueScale( zValueScale )
@ -318,7 +318,7 @@ void QgsTiledSceneChunkLoaderFactory::prepareChildren( QgsChunkNode *node )
///
QgsTiledSceneLayerChunkedEntity::QgsTiledSceneLayerChunkedEntity( const Qgs3DMapSettings &map, const QgsTiledSceneIndex &index, double maximumScreenError, bool showBoundingBoxes, double zValueScale, double zValueOffset )
QgsTiledSceneLayerChunkedEntity::QgsTiledSceneLayerChunkedEntity( const Qgs3DMapSettingsSnapshot &map, const QgsTiledSceneIndex &index, double maximumScreenError, bool showBoundingBoxes, double zValueScale, double zValueOffset )
: QgsChunkedEntity( maximumScreenError, new QgsTiledSceneChunkLoaderFactory( map, index, zValueScale, zValueOffset ), true )
, mIndex( index )
{

View File

@ -33,6 +33,7 @@
#include "qgschunknode_p.h"
#include "qgstiledsceneindex.h"
#include "qgstiledscenetile.h"
#include "qgs3dmapsettingssnapshot.h"
#include <QFutureWatcher>
@ -79,7 +80,7 @@ class QgsTiledSceneChunkLoaderFactory : public QgsChunkLoaderFactory
{
Q_OBJECT
public:
QgsTiledSceneChunkLoaderFactory( const Qgs3DMapSettings &map, const QgsTiledSceneIndex &index,
QgsTiledSceneChunkLoaderFactory( const Qgs3DMapSettingsSnapshot &map, const QgsTiledSceneIndex &index,
double zValueScale, double zValueOffset );
virtual QgsChunkLoader *createChunkLoader( QgsChunkNode *node ) const override;
@ -92,7 +93,7 @@ class QgsTiledSceneChunkLoaderFactory : public QgsChunkLoaderFactory
QgsChunkNode *nodeForTile( const QgsTiledSceneTile &t, const QgsChunkNodeId &nodeId, QgsChunkNode *parent ) const;
void fetchHierarchyForNode( long long nodeId, QgsChunkNode *origNode );
const Qgs3DMapSettings &mMap;
Qgs3DMapSettingsSnapshot mMap;
QString mRelativePathBase;
mutable QgsTiledSceneIndex mIndex;
double mZValueScale = 1.0;
@ -117,7 +118,7 @@ class QgsTiledSceneLayerChunkedEntity : public QgsChunkedEntity
{
Q_OBJECT
public:
explicit QgsTiledSceneLayerChunkedEntity( const Qgs3DMapSettings &map, const QgsTiledSceneIndex &index, double maximumScreenError, bool showBoundingBoxes,
explicit QgsTiledSceneLayerChunkedEntity( const Qgs3DMapSettingsSnapshot &map, const QgsTiledSceneIndex &index, double maximumScreenError, bool showBoundingBoxes,
double zValueScale, double zValueOffset );
~QgsTiledSceneLayerChunkedEntity();

View File

@ -66,7 +66,7 @@ Qt3DCore::QEntity *QgsTiledSceneLayer3DRenderer::createEntity( const Qgs3DMapSet
QgsTiledSceneIndex index = tsl->dataProvider()->index();
return new QgsTiledSceneLayerChunkedEntity( map, index,
return new QgsTiledSceneLayerChunkedEntity( map.snapshot(), index,
maximumScreenError(),
showBoundingBoxes(),
qgis::down_cast< const QgsTiledSceneLayerElevationProperties * >( tsl->elevationProperties() )->zScale(),

View File

@ -50,7 +50,7 @@ QgsVectorLayerChunkLoader::QgsVectorLayerChunkLoader( const QgsVectorLayerChunkL
QgsVectorLayer *layer = mFactory->mLayer;
mLayerName = mFactory->mLayer->name();
const Qgs3DMapSettings &map = mFactory->mMap;
const Qgs3DMapSettingsSnapshot &map = mFactory->mMap;
QgsFeature3DHandler *handler = QgsApplication::symbol3DRegistry()->createHandlerForSymbol( layer, mFactory->mSymbol.get() );
if ( !handler )
@ -160,7 +160,7 @@ Qt3DCore::QEntity *QgsVectorLayerChunkLoader::createEntity( Qt3DCore::QEntity *p
///////////////
QgsVectorLayerChunkLoaderFactory::QgsVectorLayerChunkLoaderFactory( const Qgs3DMapSettings &map, QgsVectorLayer *vl, QgsAbstract3DSymbol *symbol, int leafLevel, double zMin, double zMax )
QgsVectorLayerChunkLoaderFactory::QgsVectorLayerChunkLoaderFactory( const Qgs3DMapSettingsSnapshot &map, QgsVectorLayer *vl, QgsAbstract3DSymbol *symbol, int leafLevel, double zMin, double zMax )
: mMap( map )
, mLayer( vl )
, mSymbol( symbol->clone() )
@ -188,7 +188,7 @@ QgsChunkLoader *QgsVectorLayerChunkLoaderFactory::createChunkLoader( QgsChunkNod
QgsVectorLayerChunkedEntity::QgsVectorLayerChunkedEntity( QgsVectorLayer *vl, double zMin, double zMax, const QgsVectorLayer3DTilingSettings &tilingSettings, QgsAbstract3DSymbol *symbol, const Qgs3DMapSettings &map )
: QgsChunkedEntity( -1, // max. allowed screen error (negative tau means that we need to go until leaves are reached)
new QgsVectorLayerChunkLoaderFactory( map, vl, symbol, tilingSettings.zoomLevelsCount() - 1, zMin, zMax ), true )
new QgsVectorLayerChunkLoaderFactory( map.snapshot(), vl, symbol, tilingSettings.zoomLevelsCount() - 1, zMin, zMax ), true )
{
mTransform = new Qt3DCore::QTransform;
if ( applyTerrainOffset() )

View File

@ -61,12 +61,12 @@ class QgsVectorLayerChunkLoaderFactory : public QgsQuadtreeChunkLoaderFactory
public:
//! Constructs the factory
QgsVectorLayerChunkLoaderFactory( const Qgs3DMapSettings &map, QgsVectorLayer *vl, QgsAbstract3DSymbol *symbol, int leafLevel, double zMin, double zMax );
QgsVectorLayerChunkLoaderFactory( const Qgs3DMapSettingsSnapshot &map, QgsVectorLayer *vl, QgsAbstract3DSymbol *symbol, int leafLevel, double zMin, double zMax );
//! Creates loader for the given chunk node. Ownership of the returned is passed to the caller.
virtual QgsChunkLoader *createChunkLoader( QgsChunkNode *node ) const override;
const Qgs3DMapSettings &mMap;
Qgs3DMapSettingsSnapshot mMap;
QgsVectorLayer *mLayer;
std::unique_ptr<QgsAbstract3DSymbol> mSymbol;
int mLeafLevel;

View File

@ -23,7 +23,7 @@
QgsVirtualPointCloudEntity::QgsVirtualPointCloudEntity( QgsPointCloudLayer *layer,
const Qgs3DMapSettings &map,
const Qgs3DMapSettingsSnapshot &map,
const QgsCoordinateTransform &coordinateTransform,
QgsPointCloud3DSymbol *symbol,
float maximumScreenSpaceError,

View File

@ -31,6 +31,7 @@
#include "qgscoordinatetransform.h"
#include "qgschunkedentity_p.h"
#include "qgs3dmapsceneentity_p.h"
#include "qgs3dmapsettingssnapshot.h"
class QgsAABB;
class QgsChunkBoundsEntity;
@ -56,7 +57,7 @@ class QgsVirtualPointCloudEntity : public Qgs3DMapSceneEntity
Q_OBJECT
public:
//! Constructs
QgsVirtualPointCloudEntity( QgsPointCloudLayer *layer, const Qgs3DMapSettings &map, const QgsCoordinateTransform &coordinateTransform, QgsPointCloud3DSymbol *symbol, float maxScreenError, bool showBoundingBoxes,
QgsVirtualPointCloudEntity( QgsPointCloudLayer *layer, const Qgs3DMapSettingsSnapshot &map, const QgsCoordinateTransform &coordinateTransform, QgsPointCloud3DSymbol *symbol, float maxScreenError, bool showBoundingBoxes,
double zValueScale, double zValueOffset, int pointBudget );
//! This is called when the camera moves. It's responsible for loading new indexes and decides if subindex will be rendered as bbox or chunked entity.
@ -95,7 +96,7 @@ class QgsVirtualPointCloudEntity : public Qgs3DMapSceneEntity
QMap<int, QgsChunkedEntity *> mChunkedEntitiesMap;
QgsChunkBoundsEntity *mBboxesEntity = nullptr;
QList<QgsAABB> mBboxes;
const Qgs3DMapSettings &mMap;
Qgs3DMapSettingsSnapshot mMap;
QgsCoordinateTransform mCoordinateTransform;
QgsPointCloudIndex *mPointCloudIndex;
std::unique_ptr< QgsPointCloud3DSymbol > mSymbol;

View File

@ -272,8 +272,8 @@ bool QgsThickLine3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QS
outNormal.withAdjacency = true;
outSelected.withAdjacency = true;
outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), &context.map() );
outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), &context.map() );
outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), context.map() );
outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), context.map() );
QSet<QString> attrs = mSymbol->dataDefinedProperties().referencedFields( context.expressionContext() );
attributeNames.unite( attrs );

View File

@ -46,7 +46,7 @@ QgsLineVertexData::QgsLineVertexData()
vertices << QVector3D();
}
void QgsLineVertexData::init( Qgis::AltitudeClamping clamping, Qgis::AltitudeBinding binding, float height, const Qgs3DMapSettings *map )
void QgsLineVertexData::init( Qgis::AltitudeClamping clamping, Qgis::AltitudeBinding binding, float height, const Qgs3DMapSettingsSnapshot &map )
{
altClamping = clamping;
altBinding = binding;
@ -133,9 +133,9 @@ void QgsLineVertexData::addLineString( const QgsLineString &lineString, float ex
for ( int i = 0; i < lineString.vertexCount(); ++i )
{
QgsPoint p = lineString.pointN( i );
float z = Qgs3DUtils::clampAltitude( p, altClamping, altBinding, baseHeight + extraHeightOffset, centroid, *mapSettings );
float z = Qgs3DUtils::clampAltitude( p, altClamping, altBinding, baseHeight + extraHeightOffset, centroid, mapSettings );
vertices << QVector3D( p.x() - mapSettings->origin().x(), z, -( p.y() - mapSettings->origin().y() ) );
vertices << QVector3D( p.x() - mapSettings.origin().x(), z, -( p.y() - mapSettings.origin().y() ) );
indexes << vertices.count() - 1;
}
@ -160,15 +160,15 @@ void QgsLineVertexData::addVerticalLines( const QgsLineString &lineString, float
for ( int i = 0; i < lineString.vertexCount(); ++i )
{
QgsPoint p = lineString.pointN( i );
float z = Qgs3DUtils::clampAltitude( p, altClamping, altBinding, baseHeight + extraHeightOffset, centroid, *mapSettings );
float z = Qgs3DUtils::clampAltitude( p, altClamping, altBinding, baseHeight + extraHeightOffset, centroid, mapSettings );
float z2 = z + verticalLength;
if ( withAdjacency )
indexes << vertices.count(); // add the following vertex (for adjacency)
vertices << QVector3D( p.x() - mapSettings->origin().x(), z, -( p.y() - mapSettings->origin().y() ) );
vertices << QVector3D( p.x() - mapSettings.origin().x(), z, -( p.y() - mapSettings.origin().y() ) );
indexes << vertices.count() - 1;
vertices << QVector3D( p.x() - mapSettings->origin().x(), z2, -( p.y() - mapSettings->origin().y() ) );
vertices << QVector3D( p.x() - mapSettings.origin().x(), z2, -( p.y() - mapSettings.origin().y() ) );
indexes << vertices.count() - 1;
if ( withAdjacency )

View File

@ -33,6 +33,7 @@
#define SIP_NO_FILE
#include "qgis.h"
#include "qgs3dmapsettingssnapshot.h"
namespace Qt3DCore
@ -51,7 +52,6 @@ namespace Qt3DRender
#endif
class QgsLineString;
class Qgs3DMapSettings;
/**
@ -79,11 +79,11 @@ struct QgsLineVertexData
Qgis::AltitudeClamping altClamping = Qgis::AltitudeClamping::Relative;
Qgis::AltitudeBinding altBinding = Qgis::AltitudeBinding::Vertex;
float baseHeight = 0;
const Qgs3DMapSettings *mapSettings = nullptr;
Qgs3DMapSettingsSnapshot mapSettings;
QgsLineVertexData();
void init( Qgis::AltitudeClamping clamping, Qgis::AltitudeBinding binding, float height, const Qgs3DMapSettings *map );
void init( Qgis::AltitudeClamping clamping, Qgis::AltitudeBinding binding, float height, const Qgs3DMapSettingsSnapshot &map );
QByteArray createVertexBuffer();
QByteArray createIndexBuffer();

View File

@ -28,6 +28,7 @@
#include "qgssymbollayerutils.h"
#include "qgs3dmapsettings.h"
#include "qgsmarkersymbol.h"
#include "qgs3dmapsettingssnapshot.h"
QgsPoint3DBillboardMaterial::QgsPoint3DBillboardMaterial()
: mSize( new Qt3DRender::QParameter( "BB_SIZE", QSizeF( 100, 100 ), this ) )
@ -113,14 +114,14 @@ void QgsPoint3DBillboardMaterial::setTexture2DFromImage( QImage image, double si
setSize( QSizeF( size + size, size + size ) );
}
void QgsPoint3DBillboardMaterial::useDefaultSymbol( const Qgs3DMapSettings &map, bool selected )
void QgsPoint3DBillboardMaterial::useDefaultSymbol( const Qgs3DMapSettingsSnapshot &map, bool selected )
{
// Default texture
const std::unique_ptr< QgsMarkerSymbol> defaultSymbol( static_cast<QgsMarkerSymbol *>( QgsSymbol::defaultSymbol( Qgis::GeometryType::Point ) ) );
setTexture2DFromSymbol( defaultSymbol.get(), map, selected );
}
void QgsPoint3DBillboardMaterial::setTexture2DFromSymbol( QgsMarkerSymbol *markerSymbol, const Qgs3DMapSettings &map, bool selected )
void QgsPoint3DBillboardMaterial::setTexture2DFromSymbol( QgsMarkerSymbol *markerSymbol, const Qgs3DMapSettingsSnapshot &map, bool selected )
{
QgsRenderContext context;
context.setSelectionColor( map.selectionColor() );

View File

@ -53,10 +53,10 @@ class QgsPoint3DBillboardMaterial : public Qt3DRender::QMaterial
QSizeF windowSize() const;
//! Set default symbol for the texture with \a map and \a selected parameter for rendering.
void useDefaultSymbol( const Qgs3DMapSettings &map, bool selected = false );
void useDefaultSymbol( const Qgs3DMapSettingsSnapshot &map, bool selected = false );
//! Set \a markerSymbol for the texture with \a map and \a selected parameter for rendering.
void setTexture2DFromSymbol( QgsMarkerSymbol *markerSymbol, const Qgs3DMapSettings &map, bool selected = false );
void setTexture2DFromSymbol( QgsMarkerSymbol *markerSymbol, const Qgs3DMapSettingsSnapshot &map, bool selected = false );
private:
//! Set the texture2D of the billboard from \a image with \a size.

View File

@ -409,8 +409,8 @@ class QgsModelPoint3DSymbolHandler : public QgsFeature3DHandler
private:
static void addSceneEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent );
static void addMeshEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, bool are_selected );
static void addSceneEntities( const Qgs3DMapSettingsSnapshot &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent );
static void addMeshEntities( const Qgs3DMapSettingsSnapshot &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, bool are_selected );
static Qt3DCore::QTransform *transform( QVector3D position, const QgsPoint3DSymbol *symbol );
//! temporary data we will pass to the tessellator
@ -486,7 +486,7 @@ void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const
void QgsModelPoint3DSymbolHandler::addSceneEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
void QgsModelPoint3DSymbolHandler::addSceneEntities( const Qgs3DMapSettingsSnapshot &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
{
Q_UNUSED( map )
for ( const QVector3D &position : positions )
@ -512,7 +512,7 @@ void QgsModelPoint3DSymbolHandler::addSceneEntities( const Qgs3DMapSettings &map
}
}
void QgsModelPoint3DSymbolHandler::addMeshEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, bool are_selected )
void QgsModelPoint3DSymbolHandler::addMeshEntities( const Qgs3DMapSettingsSnapshot &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, bool are_selected )
{
if ( positions.empty() )
return;

View File

@ -40,7 +40,7 @@ namespace Qgs3DSymbolImpl
QgsFeature3DHandler *handlerForPoint3DSymbol( QgsVectorLayer *layer, const QgsAbstract3DSymbol *symbol );
//! convenience function to create a complete entity from QgsPolygon3DSymbol (will run getFeatures() on the layer)
Qt3DCore::QEntity *entityForPoint3DSymbol( const Qgs3DMapSettings &map, QgsVectorLayer *layer, const QgsPoint3DSymbol &symbol );
Qt3DCore::QEntity *entityForPoint3DSymbol( const Qgs3DMapSettingsSnapshot &map, QgsVectorLayer *layer, const QgsPoint3DSymbol &symbol );
}
/// @endcond

View File

@ -90,7 +90,7 @@ class QgsPolygon3DSymbolHandler : public QgsFeature3DHandler
bool QgsPolygon3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
{
outEdges.withAdjacency = true;
outEdges.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), 0, &context.map() );
outEdges.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), 0, context.map() );
const QgsPhongTexturedMaterialSettings *texturedMaterialSettings = dynamic_cast< const QgsPhongTexturedMaterialSettings * >( mSymbol->materialSettings() );

View File

@ -67,7 +67,7 @@ QgsRectangle QgsDemTerrainGenerator::rootChunkExtent() const
return mTerrainTilingScheme.tileToExtent( 0, 0, 0 );
}
float QgsDemTerrainGenerator::heightAt( double x, double y, const Qgs3DMapSettings &map ) const
float QgsDemTerrainGenerator::heightAt( double x, double y, const Qgs3DMapSettingsSnapshot &map ) const
{
Q_UNUSED( map )
if ( mHeightMapGenerator )

View File

@ -70,7 +70,7 @@ class _3D_EXPORT QgsDemTerrainGenerator : public QgsTerrainGenerator
Type type() const override;
QgsRectangle rootChunkExtent() const override;
void setExtent( const QgsRectangle &extent ) override;
float heightAt( double x, double y, const Qgs3DMapSettings &map ) const override;
float heightAt( double x, double y, const Qgs3DMapSettingsSnapshot &map ) const override;
void writeXml( QDomElement &elem ) const override;
void readXml( const QDomElement &elem ) override;
void resolveReferences( const QgsProject &project ) override;

View File

@ -49,7 +49,7 @@ QgsRectangle QgsOnlineTerrainGenerator::rootChunkExtent() const
return mTerrainTilingScheme.tileToExtent( 0, 0, 0 );
}
float QgsOnlineTerrainGenerator::heightAt( double x, double y, const Qgs3DMapSettings &map ) const
float QgsOnlineTerrainGenerator::heightAt( double x, double y, const Qgs3DMapSettingsSnapshot &map ) const
{
Q_UNUSED( map )
if ( mHeightMapGenerator )

View File

@ -63,7 +63,7 @@ class _3D_EXPORT QgsOnlineTerrainGenerator : public QgsTerrainGenerator
Type type() const override;
QgsRectangle rootChunkExtent() const override;
void setExtent( const QgsRectangle &extent ) override;
float heightAt( double x, double y, const Qgs3DMapSettings &map ) const override;
float heightAt( double x, double y, const Qgs3DMapSettingsSnapshot &map ) const override;
void writeXml( QDomElement &elem ) const override;
void readXml( const QDomElement &elem ) override;
//void resolveReferences( const QgsProject &project ) override;

View File

@ -44,7 +44,7 @@ void QgsTerrainGenerator::rootChunkHeightRange( float &hMin, float &hMax ) const
hMax = 400;
}
float QgsTerrainGenerator::heightAt( double x, double y, const Qgs3DMapSettings &map ) const
float QgsTerrainGenerator::heightAt( double x, double y, const Qgs3DMapSettingsSnapshot &map ) const
{
Q_UNUSED( x )
Q_UNUSED( y )

View File

@ -23,6 +23,7 @@
class QgsAABB;
class Qgs3DMapSettings;
class Qgs3DMapSettingsSnapshot;
class QgsRectangle;
class QgsTerrainEntity;
@ -87,7 +88,7 @@ class _3D_EXPORT QgsTerrainGenerator : public QgsQuadtreeChunkLoaderFactory
virtual void rootChunkHeightRange( float &hMin, float &hMax ) const;
//! Returns height at (x,y) in terrain's CRS
virtual float heightAt( double x, double y, const Qgs3DMapSettings &map ) const;
virtual float heightAt( double x, double y, const Qgs3DMapSettingsSnapshot &map ) const;
//! Write terrain generator's configuration to XML
virtual void writeXml( QDomElement &elem ) const = 0;

View File

@ -30,6 +30,7 @@
#include "qgsoffscreen3dengine.h"
#include "qgspointlightsettings.h"
#include "qgsproject.h"
#include "qgs3dmapsettingssnapshot.h"
class TestQgsMesh3DRendering : public QgsTest
@ -121,7 +122,7 @@ void TestQgsMesh3DRendering::testMeshTerrain()
meshTerrain->setLayer( mLayerMeshTerrain );
map->setTerrainGenerator( meshTerrain );
QCOMPARE( meshTerrain->heightAt( 750, 2500, *map ), 500.0 );
QCOMPARE( meshTerrain->heightAt( 750, 2500, map->snapshot() ), 500.0 );
QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );