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>
73class QgsInstancedPoint3DSymbolHandler :
public QgsFeature3DHandler
78 , mSelectedIds( selectedIds ) {}
80 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
82 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
87 static Qt3DRender::QGeometryRenderer *renderer(
const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions );
93 QVector<QVector3D> positions;
96 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
99 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
105 PointData outSelected;
109bool QgsInstancedPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
112 Q_UNUSED( attributeNames )
118 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
127void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
129 makeEntity( parent, context, outNormal,
false );
130 makeEntity( parent, context, outSelected,
true );
132 updateZRangeFromPositions( outNormal.positions );
133 updateZRangeFromPositions( outSelected.positions );
136 const float symbolOffset = mSymbol->transform().data()[13];
140 switch ( mSymbol->shape() )
144 const float length = mSymbol->shapeProperty( QStringLiteral(
"length" ) ).toFloat();
145 mZMin -= length * 0.5f;
146 mZMax += length * 0.5f;
152 const float radius = mSymbol->shapeProperty( QStringLiteral(
"radius" ) ).toFloat();
160 const float length = mSymbol->shapeProperty( QStringLiteral(
"length" ) ).toFloat();
161 mZMin -= length * 0.5f;
162 mZMax += length * 0.5f;
168 const float size = mSymbol->shapeProperty( QStringLiteral(
"size" ) ).toFloat();
169 mZMin -= size * 0.5f;
170 mZMax += size * 0.5f;
176 const float radius = mSymbol->shapeProperty( QStringLiteral(
"radius" ) ).toFloat();
186 const float size = mSymbol->shapeProperty( QStringLiteral(
"size" ) ).toFloat();
187 mZMin -= size * 0.5f;
188 mZMax += size * 0.5f;
198 mZMin += symbolOffset;
199 mZMax += symbolOffset;
202void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
208 QgsMaterial *mat = material( mSymbol.get(), materialContext );
211 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
212 entity->addComponent( renderer( mSymbol.get(), out.positions ) );
213 entity->addComponent( mat );
214 entity->setParent( parent );
224 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
225 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
226 filterKey->setValue(
"forward" );
228 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram;
229 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/instanced.vert" ) ) ) );
230 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/phong.frag" ) ) ) );
232 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass;
233 renderPass->setShaderProgram( shaderProgram );
235 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
236 technique->addFilterKey( filterKey );
237 technique->addRenderPass( renderPass );
238 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
239 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
240 technique->graphicsApiFilter()->setMajorVersion( 3 );
241 technique->graphicsApiFilter()->setMinorVersion( 2 );
243 const QMatrix4x4 transformMatrix = symbol->
transform();
244 QMatrix3x3 normalMatrix = transformMatrix.normalMatrix();
247 float *n = normalMatrix.data();
248 const QMatrix4x4 normalMatrix4(
254 Qt3DRender::QParameter *paramInst =
new Qt3DRender::QParameter;
255 paramInst->setName( QStringLiteral(
"inst" ) );
256 paramInst->setValue( transformMatrix );
258 Qt3DRender::QParameter *paramInstNormal =
new Qt3DRender::QParameter;
259 paramInstNormal->setName( QStringLiteral(
"instNormal" ) );
260 paramInstNormal->setValue( normalMatrix4 );
262 Qt3DRender::QEffect *effect =
new Qt3DRender::QEffect;
263 effect->addTechnique( technique );
264 effect->addParameter( paramInst );
265 effect->addParameter( paramInstNormal );
270 material->setEffect( effect );
275Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer(
const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions )
277 const int count = positions.count();
278 const int byteCount = positions.count() *
sizeof( QVector3D );
280 ba.resize( byteCount );
281 memcpy( ba.data(), positions.constData(), byteCount );
284 instanceBuffer->setData( ba );
287 instanceDataAttribute->setName( QStringLiteral(
"pos" ) );
288 instanceDataAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
289 instanceDataAttribute->setVertexBaseType( Qt3DQAttribute::Float );
290 instanceDataAttribute->setVertexSize( 3 );
291 instanceDataAttribute->setByteOffset( 0 );
292 instanceDataAttribute->setDivisor( 1 );
293 instanceDataAttribute->setBuffer( instanceBuffer );
294 instanceDataAttribute->setCount( count );
295 instanceDataAttribute->setByteStride( 3 *
sizeof(
float ) );
298 geometry->addAttribute( instanceDataAttribute );
299 geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
301 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
302 renderer->setGeometry( geometry );
303 renderer->setInstanceCount( count );
310 switch ( symbol->
shape() )
314 const float radius = symbol->
shapeProperty( QStringLiteral(
"radius" ) ).toFloat();
315 const float length = symbol->
shapeProperty( QStringLiteral(
"length" ) ).toFloat();
316 Qt3DExtras::QCylinderGeometry *g =
new Qt3DExtras::QCylinderGeometry;
319 g->setRadius( radius );
320 g->setLength( length );
326 const float radius = symbol->
shapeProperty( QStringLiteral(
"radius" ) ).toFloat();
327 Qt3DExtras::QSphereGeometry *g =
new Qt3DExtras::QSphereGeometry;
328 g->setRadius( radius );
334 const float length = symbol->
shapeProperty( QStringLiteral(
"length" ) ).toFloat();
335 const float bottomRadius = symbol->
shapeProperty( QStringLiteral(
"bottomRadius" ) ).toFloat();
336 const float topRadius = symbol->
shapeProperty( QStringLiteral(
"topRadius" ) ).toFloat();
338 Qt3DExtras::QConeGeometry *g =
new Qt3DExtras::QConeGeometry;
339 g->setLength( length );
340 g->setBottomRadius( bottomRadius );
341 g->setTopRadius( topRadius );
349 const float size = symbol->
shapeProperty( QStringLiteral(
"size" ) ).toFloat();
350 Qt3DExtras::QCuboidGeometry *g =
new Qt3DExtras::QCuboidGeometry;
351 g->setXExtent( size );
352 g->setYExtent( size );
353 g->setZExtent( size );
359 const float radius = symbol->
shapeProperty( QStringLiteral(
"radius" ) ).toFloat();
360 const float minorRadius = symbol->
shapeProperty( QStringLiteral(
"minorRadius" ) ).toFloat();
361 Qt3DExtras::QTorusGeometry *g =
new Qt3DExtras::QTorusGeometry;
362 g->setRadius( radius );
363 g->setMinorRadius( minorRadius );
369 const float size = symbol->
shapeProperty( QStringLiteral(
"size" ) ).toFloat();
370 Qt3DExtras::QPlaneGeometry *g =
new Qt3DExtras::QPlaneGeometry;
372 g->setHeight( size );
378 const float depth = symbol->
shapeProperty( QStringLiteral(
"depth" ) ).toFloat();
379 const QString text = symbol->
shapeProperty( QStringLiteral(
"text" ) ).toString();
380 Qt3DExtras::QExtrudedTextGeometry *g =
new Qt3DExtras::QExtrudedTextGeometry;
381 g->setDepth( depth );
397class QgsModelPoint3DSymbolHandler :
public QgsFeature3DHandler
402 , mSelectedIds( selectedIds ) {}
404 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
406 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
411 static void addMeshEntities(
const Qgs3DRenderContext &context,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent,
bool are_selected );
412 static Qt3DCore::QTransform *transform( QVector3D position,
const QgsPoint3DSymbol *symbol );
417 QVector<QVector3D> positions;
420 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
423 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
429 PointData outSelected;
432bool QgsModelPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
435 Q_UNUSED( attributeNames )
441 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
450void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
452 makeEntity( parent, context, outNormal,
false );
453 makeEntity( parent, context, outSelected,
true );
455 updateZRangeFromPositions( outNormal.positions );
456 updateZRangeFromPositions( outSelected.positions );
459 const float symbolHeight = mSymbol->transform().data()[13];
460 mZMin += symbolHeight;
461 mZMax += symbolHeight;
464void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
468 addMeshEntities( context, out.positions, mSymbol.get(), parent,
true );
473 if ( mSymbol->shapeProperty( QStringLiteral(
"overwriteMaterial" ) ).toBool()
474 || ( mSymbol->materialSettings() && mSymbol->materialSettings()->type() != QLatin1String(
"null" ) ) )
476 addMeshEntities( context, out.positions, mSymbol.get(), parent,
false );
480 addSceneEntities( context, out.positions, mSymbol.get(), parent );
487void QgsModelPoint3DSymbolHandler::addSceneEntities(
const Qgs3DRenderContext &,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
489 for (
const QVector3D &position : positions )
493 if ( !source.isEmpty() )
496 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
498 const QUrl url = QUrl::fromLocalFile( source );
499 Qt3DRender::QSceneLoader *modelLoader =
new Qt3DRender::QSceneLoader;
500 modelLoader->setSource( url );
502 entity->addComponent( modelLoader );
503 entity->addComponent( transform( position, symbol ) );
504 entity->setParent( parent );
512void QgsModelPoint3DSymbolHandler::addMeshEntities(
const Qgs3DRenderContext &context,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent,
bool are_selected )
514 if ( positions.empty() )
524 for (
const QVector3D &position : positions )
527 if ( !source.isEmpty() )
530 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
532 const QUrl url = QUrl::fromLocalFile( source );
533 Qt3DRender::QMesh *mesh =
new Qt3DRender::QMesh;
534 mesh->setSource( url );
536 entity->addComponent( mesh );
537 entity->addComponent( mat );
538 entity->addComponent( transform( position, symbol ) );
539 entity->setParent( parent );
547Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position,
const QgsPoint3DSymbol *symbol )
549 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
551 tr->setTranslation( position + tr->translation() );
559class QgsPoint3DBillboardSymbolHandler :
public QgsFeature3DHandler
564 , mSelectedIds( selectedIds ) {}
566 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
568 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
575 QVector<QVector3D> positions;
578 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
581 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
587 PointData outSelected;
590bool QgsPoint3DBillboardSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
593 Q_UNUSED( attributeNames )
599 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
608void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
610 makeEntity( parent, context, outNormal,
false );
611 makeEntity( parent, context, outSelected,
true );
613 updateZRangeFromPositions( outNormal.positions );
614 updateZRangeFromPositions( outSelected.positions );
617 const float billboardHeight = mSymbol->transform().data()[13];
618 mZMin += billboardHeight;
619 mZMax += billboardHeight;
622void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
626 billboardGeometry->
setPoints( out.positions );
629 Qt3DRender::QGeometryRenderer *billboardGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
630 billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
631 billboardGeometryRenderer->setGeometry( billboardGeometry );
632 billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
648 Qt3DCore::QTransform *billboardTransform =
new Qt3DCore::QTransform();
649 billboardTransform->setMatrix( mSymbol->billboardTransform() );
652 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
654 entity->addComponent( billboardMaterial );
655 entity->addComponent( billboardTransform );
656 entity->addComponent( billboardGeometryRenderer );
657 entity->setParent( parent );
664namespace Qgs3DSymbolImpl
677 return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
679 return new QgsInstancedPoint3DSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
@ ExtrudedText
Extruded text.
QColor selectionColor() const
Returns color used for selected features.
static void extractPointPositions(const QgsFeature &f, const Qgs3DRenderContext &context, Qgis::AltitudeClamping altClamp, QVector< QVector3D > &positions)
Calculates (x,y,z) positions of (multi)point from the given feature.
virtual void addParametersToEffect(Qt3DRender::QEffect *effect, const QgsMaterialContext &materialContext) const =0
Adds parameters from the material to a destination effect.
virtual QgsMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const =0
Creates a new QgsMaterial object representing the material settings.
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 Qgs3DRenderContext &context, bool selected=false)
Set default symbol for the texture with context and selected parameter for rendering.
void setTexture2DFromSymbol(QgsMarkerSymbol *markerSymbol, const Qgs3DRenderContext &context, bool selected=false)
Set markerSymbol for the texture with context and selected parameter for rendering.
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.
Qgis::Point3DShape shape() const
Returns 3D shape for points.
QgsAbstract3DSymbol * clone() const override
Returns a new instance of the symbol with the same settings.
QVariant shapeProperty(const QString &property) const
Returns the value for a specific shape property.
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