18#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
19#include <Qt3DRender/QAttribute>
20#include <Qt3DRender/QBuffer>
21#include <Qt3DRender/QGeometry>
22#include <Qt3DCore/QTransform>
28#include <Qt3DCore/QAttribute>
29#include <Qt3DCore/QBuffer>
30#include <Qt3DCore/QGeometry>
37#include <Qt3DRender/QEffect>
38#include <Qt3DRender/QGraphicsApiFilter>
39#include <Qt3DRender/QParameter>
40#include <Qt3DRender/QTechnique>
42#include <Qt3DExtras/QCylinderGeometry>
43#include <Qt3DExtras/QConeGeometry>
44#include <Qt3DExtras/QCuboidGeometry>
45#include <Qt3DExtras/QPlaneGeometry>
46#include <Qt3DExtras/QSphereGeometry>
47#include <Qt3DExtras/QTorusGeometry>
48#include <Qt3DExtras/QPhongMaterial>
49#include <Qt3DRender/QSceneLoader>
50#include <Qt3DRender/QPaintedTextureImage>
52#include <Qt3DRender/QMesh>
54#include <Qt3DExtras/QExtrudedTextGeometry>
75class QgsInstancedPoint3DSymbolHandler :
public QgsFeature3DHandler
80 , mSelectedIds( selectedIds ) {}
82 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
83 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
84 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
89 static Qt3DRender::QGeometryRenderer *renderer(
const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions );
95 QVector<QVector3D> positions;
98 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
101 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
107 PointData outSelected;
111bool QgsInstancedPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
114 Q_UNUSED( attributeNames )
118void QgsInstancedPoint3DSymbolHandler::processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
120 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
129void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
131 makeEntity( parent, context, outNormal,
false );
132 makeEntity( parent, context, outSelected,
true );
134 updateZRangeFromPositions( outNormal.positions );
135 updateZRangeFromPositions( outSelected.positions );
138 const float symbolOffset = mSymbol->transform().data()[13];
142 switch ( mSymbol->shape() )
146 const float length = mSymbol->shapeProperties().value( QStringLiteral(
"length" ), 10 ).toFloat();
147 mZMin -= length * 0.5f;
148 mZMax += length * 0.5f;
154 const float radius = mSymbol->shapeProperties().value( QStringLiteral(
"radius" ), 10 ).toFloat();
162 const float length = mSymbol->shapeProperties().value( QStringLiteral(
"length" ), 10 ).toFloat();
163 mZMin -= length * 0.5f;
164 mZMax += length * 0.5f;
170 const float size = mSymbol->shapeProperties().value( QStringLiteral(
"size" ) ).toFloat();
171 mZMin -= size * 0.5f;
172 mZMax += size * 0.5f;
178 const float radius = mSymbol->shapeProperties().value( QStringLiteral(
"radius" ), 10 ).toFloat();
191 mZMin += symbolOffset;
192 mZMax += symbolOffset;
195void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
198 Qt3DRender::QMaterial *mat = material( mSymbol.get() );
203 for ( Qt3DRender::QParameter *param : mat->effect()->parameters() )
205 if ( param->name() == QLatin1String(
"kd" ) )
206 param->setValue( context.map().selectionColor() );
207 else if ( param->name() == QLatin1String(
"ka" ) )
208 param->setValue( context.map().selectionColor().darker() );
213 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
214 entity->addComponent( renderer( mSymbol.get(), out.positions ) );
215 entity->addComponent( mat );
216 entity->setParent( parent );
224Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material(
const QgsPoint3DSymbol *symbol )
226 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
227 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
228 filterKey->setValue(
"forward" );
233 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram;
234 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/instanced.vert" ) ) ) );
235 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/instanced.frag" ) ) ) );
237 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass;
238 renderPass->setShaderProgram( shaderProgram );
240 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
241 technique->addFilterKey( filterKey );
242 technique->addRenderPass( renderPass );
243 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
244 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
245 technique->graphicsApiFilter()->setMajorVersion( 3 );
246 technique->graphicsApiFilter()->setMinorVersion( 2 );
248 const QMatrix4x4 transformMatrix = symbol->
transform();
249 QMatrix3x3 normalMatrix = transformMatrix.normalMatrix();
252 float *n = normalMatrix.data();
253 const QMatrix4x4 normalMatrix4(
259 Qt3DRender::QParameter *paramInst =
new Qt3DRender::QParameter;
260 paramInst->setName( QStringLiteral(
"inst" ) );
261 paramInst->setValue( transformMatrix );
263 Qt3DRender::QParameter *paramInstNormal =
new Qt3DRender::QParameter;
264 paramInstNormal->setName( QStringLiteral(
"instNormal" ) );
265 paramInstNormal->setValue( normalMatrix4 );
267 Qt3DRender::QEffect *effect =
new Qt3DRender::QEffect;
268 effect->addTechnique( technique );
269 effect->addParameter( paramInst );
270 effect->addParameter( paramInstNormal );
274 Qt3DRender::QMaterial *material =
new Qt3DRender::QMaterial;
275 material->setEffect( effect );
280Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer(
const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions )
282 const int count = positions.count();
283 const int byteCount = positions.count() *
sizeof( QVector3D );
285 ba.resize( byteCount );
286 memcpy( ba.data(), positions.constData(), byteCount );
289 instanceBuffer->setData( ba );
292 instanceDataAttribute->setName( QStringLiteral(
"pos" ) );
293 instanceDataAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
294 instanceDataAttribute->setVertexBaseType( Qt3DQAttribute::Float );
295 instanceDataAttribute->setVertexSize( 3 );
296 instanceDataAttribute->setByteOffset( 0 );
297 instanceDataAttribute->setDivisor( 1 );
298 instanceDataAttribute->setBuffer( instanceBuffer );
299 instanceDataAttribute->setCount( count );
300 instanceDataAttribute->setByteStride( 3 *
sizeof(
float ) );
303 geometry->addAttribute( instanceDataAttribute );
304 geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
306 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
307 renderer->setGeometry( geometry );
308 renderer->setInstanceCount( count );
319 const float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
320 const float length = shapeProperties[QStringLiteral(
"length" )].toFloat();
321 Qt3DExtras::QCylinderGeometry *g =
new Qt3DExtras::QCylinderGeometry;
324 g->setRadius( radius ? radius : 10 );
325 g->setLength( length ? length : 10 );
331 const float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
332 Qt3DExtras::QSphereGeometry *g =
new Qt3DExtras::QSphereGeometry;
333 g->setRadius( radius ? radius : 10 );
339 const float length = shapeProperties[QStringLiteral(
"length" )].toFloat();
340 const float bottomRadius = shapeProperties[QStringLiteral(
"bottomRadius" )].toFloat();
341 const float topRadius = shapeProperties[QStringLiteral(
"topRadius" )].toFloat();
342 Qt3DExtras::QConeGeometry *g =
new Qt3DExtras::QConeGeometry;
343 g->setLength( length ? length : 10 );
344 g->setBottomRadius( bottomRadius );
345 g->setTopRadius( topRadius );
353 const float size = shapeProperties[QStringLiteral(
"size" )].toFloat();
354 Qt3DExtras::QCuboidGeometry *g =
new Qt3DExtras::QCuboidGeometry;
355 g->setXExtent( size ? size : 10 );
356 g->setYExtent( size ? size : 10 );
357 g->setZExtent( size ? size : 10 );
363 const float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
364 const float minorRadius = shapeProperties[QStringLiteral(
"minorRadius" )].toFloat();
365 Qt3DExtras::QTorusGeometry *g =
new Qt3DExtras::QTorusGeometry;
366 g->setRadius( radius ? radius : 10 );
367 g->setMinorRadius( minorRadius ? minorRadius : 5 );
373 const float size = shapeProperties[QStringLiteral(
"size" )].toFloat();
374 Qt3DExtras::QPlaneGeometry *g =
new Qt3DExtras::QPlaneGeometry;
375 g->setWidth( size ? size : 10 );
376 g->setHeight( size ? size : 10 );
382 const float depth = shapeProperties[QStringLiteral(
"depth" )].toFloat();
383 const QString text = shapeProperties[QStringLiteral(
"text" )].toString();
384 Qt3DExtras::QExtrudedTextGeometry *g =
new Qt3DExtras::QExtrudedTextGeometry;
385 g->setDepth( depth ? depth : 1 );
399class QgsModelPoint3DSymbolHandler :
public QgsFeature3DHandler
404 , mSelectedIds( selectedIds ) {}
406 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
407 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
408 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
412 static void addSceneEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent );
413 static void addMeshEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent,
bool are_selected );
414 static Qt3DCore::QTransform *transform( QVector3D position,
const QgsPoint3DSymbol *symbol );
419 QVector<QVector3D> positions;
422 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
425 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
431 PointData outSelected;
434bool QgsModelPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
437 Q_UNUSED( attributeNames )
441void QgsModelPoint3DSymbolHandler::processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
443 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
452void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
454 makeEntity( parent, context, outNormal,
false );
455 makeEntity( parent, context, outSelected,
true );
457 updateZRangeFromPositions( outNormal.positions );
458 updateZRangeFromPositions( outSelected.positions );
461 const float symbolHeight = mSymbol->transform().data()[13];
462 mZMin += symbolHeight;
463 mZMax += symbolHeight;
466void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
470 addMeshEntities( context.map(), out.positions, mSymbol.get(), parent,
true );
475 if ( mSymbol->shapeProperties()[QStringLiteral(
"overwriteMaterial" )].toBool()
476 || ( mSymbol->materialSettings() && mSymbol->materialSettings()->type() != QLatin1String(
"null" ) ) )
478 addMeshEntities( context.map(), out.positions, mSymbol.get(), parent,
false );
482 addSceneEntities( context.map(), out.positions, mSymbol.get(), parent );
489void QgsModelPoint3DSymbolHandler::addSceneEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
492 for (
const QVector3D &position : positions )
496 if ( !source.isEmpty() )
499 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
501 const QUrl url = QUrl::fromLocalFile( source );
502 Qt3DRender::QSceneLoader *modelLoader =
new Qt3DRender::QSceneLoader;
503 modelLoader->setSource( url );
505 entity->addComponent( modelLoader );
506 entity->addComponent( transform( position, symbol ) );
507 entity->setParent( parent );
515void QgsModelPoint3DSymbolHandler::addMeshEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent,
bool are_selected )
517 if ( positions.empty() )
527 for (
const QVector3D &position : positions )
530 if ( !source.isEmpty() )
533 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
535 const QUrl url = QUrl::fromLocalFile( source );
536 Qt3DRender::QMesh *mesh =
new Qt3DRender::QMesh;
537 mesh->setSource( url );
539 entity->addComponent( mesh );
540 entity->addComponent( mat );
541 entity->addComponent( transform( position, symbol ) );
542 entity->setParent( parent );
550Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position,
const QgsPoint3DSymbol *symbol )
552 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
554 tr->setTranslation( position + tr->translation() );
562class QgsPoint3DBillboardSymbolHandler :
public QgsFeature3DHandler
567 , mSelectedIds( selectedIds ) {}
569 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
570 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
571 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
578 QVector<QVector3D> positions;
581 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
584 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
590 PointData outSelected;
593bool QgsPoint3DBillboardSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
596 Q_UNUSED( attributeNames )
600void QgsPoint3DBillboardSymbolHandler::processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
602 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
611void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
613 makeEntity( parent, context, outNormal,
false );
614 makeEntity( parent, context, outSelected,
true );
616 updateZRangeFromPositions( outNormal.positions );
617 updateZRangeFromPositions( outSelected.positions );
620 const float billboardHeight = mSymbol->transform().data()[13];
621 mZMin += billboardHeight;
622 mZMax += billboardHeight;
625void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
629 billboardGeometry->
setPoints( out.positions );
632 Qt3DRender::QGeometryRenderer *billboardGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
633 billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
634 billboardGeometryRenderer->setGeometry( billboardGeometry );
635 billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
651 Qt3DCore::QTransform *billboardTransform =
new Qt3DCore::QTransform();
652 billboardTransform->setMatrix( mSymbol->billboardTransform() );
655 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
657 entity->addComponent( billboardMaterial );
658 entity->addComponent( billboardTransform );
659 entity->addComponent( billboardGeometryRenderer );
660 entity->setParent( parent );
667namespace Qgs3DSymbolImpl
680 return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
682 return new QgsInstancedPoint3DSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
687 QgsFeature3DHandler *handler = handlerForPoint3DSymbol( layer, &symbol );
688 Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );
QColor selectionColor() const
Returns color used for selected features.
static void extractPointPositions(const QgsFeature &f, const Qgs3DMapSettings &map, Qgis::AltitudeClamping altClamp, QVector< QVector3D > &positions)
Calculates (x,y,z) positions of (multi)point from the given feature.
virtual Qt3DRender::QMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const =0
Creates a new QMaterial object representing the material settings.
virtual void addParametersToEffect(Qt3DRender::QEffect *effect) const =0
Adds parameters from the material to a destination effect.
static QgsSourceCache * sourceCache()
Returns the application's source cache, used for caching embedded and remote source strings as local ...
void setPoints(const QVector< QVector3D > &vertices)
Set the points for the billboard with vertices.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
A marker symbol type, for rendering Point and MultiPoint geometries.
void setIsSelected(bool isSelected)
Sets whether the material should represent a selected state.
void setSelectionColor(const QColor &color)
Sets the color for representing materials in a selected state.
void useDefaultSymbol(const Qgs3DMapSettings &map, bool selected=false)
Set default symbol for the texture with map and selected parameter for rendering.
void setTexture2DFromSymbol(QgsMarkerSymbol *markerSymbol, const Qgs3DMapSettings &map, bool selected=false)
Set markerSymbol for the texture with map and selected parameter for rendering.
Shape
3D shape types supported by the symbol
@ ExtrudedText
Supported in Qt 5.9+.
QgsAbstractMaterialSettings * materialSettings() const
Returns material settings used for shading of the symbol.
QMatrix4x4 transform() const
Returns transform for individual objects represented by the symbol.
QgsMarkerSymbol * billboardSymbol() const
Returns a symbol for billboard.
QgsAbstract3DSymbol * clone() const override SIP_FACTORY
Shape shape() const
Returns 3D shape for points.
QVariantMap shapeProperties() const
Returns a key-value dictionary of point shape properties.
QString localFilePath(const QString &path, bool blocking=false)
Returns a local file path reflecting the content of a specified source path.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
@ Triangles
Triangle based rendering (default)
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer
Qt3DCore::QGeometry Qt3DQGeometry
QSet< QgsFeatureId > QgsFeatureIds
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer
Qt3DCore::QGeometry Qt3DQGeometry