QGIS/src/3d/qgsannotationlayerchunkloader_p.h
Nyall Dawson a01770e5cb
[feature] Support rendering annotation layer markers as 3d billboards
This commit adds a new option for showing annotation layers in 3d maps.

From the annotation layer properties, 3d tab, users can set the layer
to render as 3d billboards. When activated, all MARKERS from the layer
will be shown as floating billboard symbols above the 3d map. (lines,
polygons, and text items from the layer are ignored).

Users have control over the terrain clamping and offset for the
billboards, and whether or not "callout" lines should be shown (vertical
lines joining the billboard to the corresponding location on the
terrain surface)
2025-10-01 10:56:50 +10:00

147 lines
4.7 KiB
C++

/***************************************************************************
qgsannotationlayerchunkloader_p.h
--------------------------------------
Date : September 2025
Copyright : (C) 2025 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 QGSANNOTATIONLAYERCHUNKLOADER_P_H
#define QGSANNOTATIONLAYERCHUNKLOADER_P_H
///@cond PRIVATE
//
// W A R N I N G
// -------------
//
// This file is not part of the QGIS API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
#include "qgschunkloader.h"
#include "qgschunkedentity.h"
#include "qgs3drendercontext.h"
#include "qgsbillboardgeometry.h"
#include <QImage>
#define SIP_NO_FILE
class QgsAnnotationLayer;
class QgsAnnotationItem;
namespace Qt3DCore
{
class QTransform;
}
#include <QFutureWatcher>
/**
* \ingroup qgis_3d
* \brief This loader factory is responsible for creation of loaders of QgsAnnotationLayerChunkedEntity.
*
* \since QGIS 4.0
*/
class QgsAnnotationLayerChunkLoaderFactory : public QgsQuadtreeChunkLoaderFactory
{
Q_OBJECT
public:
//! Constructs the factory
QgsAnnotationLayerChunkLoaderFactory( const Qgs3DRenderContext &context, QgsAnnotationLayer *layer, int leafLevel, Qgis::AltitudeClamping clamping, double zOffset, bool showCallouts, const QColor &calloutLineColor, double calloutLineWidth, 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;
Qgs3DRenderContext mRenderContext;
QgsAnnotationLayer *mLayer = nullptr;
int mLeafLevel = 0;
Qgis::AltitudeClamping mClamping = Qgis::AltitudeClamping::Relative;
double mZOffset = 0;
bool mShowCallouts = false;
QColor mCalloutLineColor;
double mCalloutLineWidth = 2;
};
/**
* \ingroup qgis_3d
* \brief This loader class is responsible for async loading of data for QgsAnnotationLayerChunkedEntity
* and creation of final 3D entity from the data previously prepared in a worker thread.
*
* \since QGIS 4.0
*/
class QgsAnnotationLayerChunkLoader : public QgsChunkLoader
{
Q_OBJECT
public:
//! Constructs the loader
QgsAnnotationLayerChunkLoader( const QgsAnnotationLayerChunkLoaderFactory *factory, QgsChunkNode *node );
~QgsAnnotationLayerChunkLoader() override;
void start() override;
virtual void cancel() override;
virtual Qt3DCore::QEntity *createEntity( Qt3DCore::QEntity *parent ) override;
private:
const QgsAnnotationLayerChunkLoaderFactory *mFactory = nullptr;
Qgs3DRenderContext mRenderContext;
bool mCanceled = false;
QFutureWatcher<void> *mFutureWatcher = nullptr;
QString mLayerName;
QgsVector3D mChunkOrigin;
std::vector< std::unique_ptr< QgsAnnotationItem > > mItemsToRender;
QVector< QgsBillboardGeometry::BillboardAtlasData > mBillboardPositions;
QVector< QgsLineString > mCalloutLines;
QImage mBillboardAtlas;
double mZMin = std::numeric_limits< double >::max();
double mZMax = std::numeric_limits< double >::lowest();
};
/**
* \ingroup qgis_3d
* \brief 3D entity used for rendering of annotation layers.
*
* Internally it uses QgsAnnotationLayerChunkLoaderFactory and
* QgsAnnotationLayerChunkLoader to do the actual work
* of loading and creating 3D sub-entities for the layer.
*
* \since QGIS 4.0
*/
class QgsAnnotationLayerChunkedEntity : public QgsChunkedEntity
{
Q_OBJECT
public:
//! Constructs the entity.
explicit QgsAnnotationLayerChunkedEntity( Qgs3DMapSettings *map, QgsAnnotationLayer *layer, Qgis::AltitudeClamping clamping, double zOffset, bool showCallouts, const QColor &calloutLineColor, double calloutLineWidth, double zMin, double zMax );
~QgsAnnotationLayerChunkedEntity();
private slots:
void onTerrainElevationOffsetChanged();
private:
Qt3DCore::QTransform *mTransform = nullptr;
bool applyTerrainOffset() const;
friend class TestQgsChunkedEntity;
};
/// @endcond
#endif // QGSANNOTATIONLAYERCHUNKLOADER_P_H