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 ) {}
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;
108 PointData outSelected;
112bool QgsInstancedPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsVector3D &chunkOrigin )
115 Q_UNUSED( attributeNames )
117 mChunkOrigin = chunkOrigin;
124 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
133void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
135 makeEntity( parent, context, outNormal,
false );
136 makeEntity( parent, context, outSelected,
true );
138 updateZRangeFromPositions( outNormal.positions );
139 updateZRangeFromPositions( outSelected.positions );
142 const float symbolOffset = mSymbol->transform().data()[14];
146 switch ( mSymbol->shape() )
150 const float length = mSymbol->shapeProperty( QStringLiteral(
"length" ) ).toFloat();
151 mZMin -= length * 0.5f;
152 mZMax += length * 0.5f;
158 const float radius = mSymbol->shapeProperty( QStringLiteral(
"radius" ) ).toFloat();
166 const float length = mSymbol->shapeProperty( QStringLiteral(
"length" ) ).toFloat();
167 mZMin -= length * 0.5f;
168 mZMax += length * 0.5f;
174 const float size = mSymbol->shapeProperty( QStringLiteral(
"size" ) ).toFloat();
175 mZMin -= size * 0.5f;
176 mZMax += size * 0.5f;
182 const float radius = mSymbol->shapeProperty( QStringLiteral(
"radius" ) ).toFloat();
192 const float size = mSymbol->shapeProperty( QStringLiteral(
"size" ) ).toFloat();
193 mZMin -= size * 0.5f;
194 mZMax += size * 0.5f;
204 mZMin += symbolOffset;
205 mZMax += symbolOffset;
208void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
214 QgsMaterial *mat = material( mSymbol.get(), materialContext );
217 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
218 QVector3D nodeTranslation = ( mChunkOrigin - context.
origin() ).toVector3D();
219 tr->setTranslation( nodeTranslation );
222 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
223 entity->addComponent( renderer( mSymbol.get(), out.positions ) );
224 entity->addComponent( mat );
225 entity->addComponent( tr );
226 entity->setParent( parent );
236 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
237 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
238 filterKey->setValue(
"forward" );
240 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram;
241 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/instanced.vert" ) ) ) );
242 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/phong.frag" ) ) ) );
244 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass;
245 renderPass->setShaderProgram( shaderProgram );
247 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
248 technique->addFilterKey( filterKey );
249 technique->addRenderPass( renderPass );
250 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
251 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
252 technique->graphicsApiFilter()->setMajorVersion( 3 );
253 technique->graphicsApiFilter()->setMinorVersion( 2 );
255 const QMatrix4x4 transformMatrix = symbol->
transform();
256 QMatrix3x3 normalMatrix = transformMatrix.normalMatrix();
259 float *n = normalMatrix.data();
260 const QMatrix4x4 normalMatrix4(
266 Qt3DRender::QParameter *paramInst =
new Qt3DRender::QParameter;
267 paramInst->setName( QStringLiteral(
"inst" ) );
268 paramInst->setValue( transformMatrix );
270 Qt3DRender::QParameter *paramInstNormal =
new Qt3DRender::QParameter;
271 paramInstNormal->setName( QStringLiteral(
"instNormal" ) );
272 paramInstNormal->setValue( normalMatrix4 );
274 Qt3DRender::QEffect *effect =
new Qt3DRender::QEffect;
275 effect->addTechnique( technique );
276 effect->addParameter( paramInst );
277 effect->addParameter( paramInstNormal );
282 material->setEffect( effect );
287Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer(
const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions )
289 const int count = positions.count();
290 const int byteCount = positions.count() *
sizeof( QVector3D );
292 ba.resize( byteCount );
293 memcpy( ba.data(), positions.constData(), byteCount );
296 instanceBuffer->setData( ba );
299 instanceDataAttribute->setName( QStringLiteral(
"pos" ) );
300 instanceDataAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
301 instanceDataAttribute->setVertexBaseType( Qt3DQAttribute::Float );
302 instanceDataAttribute->setVertexSize( 3 );
303 instanceDataAttribute->setByteOffset( 0 );
304 instanceDataAttribute->setDivisor( 1 );
305 instanceDataAttribute->setBuffer( instanceBuffer );
306 instanceDataAttribute->setCount( count );
307 instanceDataAttribute->setByteStride( 3 *
sizeof(
float ) );
310 geometry->addAttribute( instanceDataAttribute );
311 geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
313 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
314 renderer->setGeometry( geometry );
315 renderer->setInstanceCount( count );
322 switch ( symbol->
shape() )
326 const float radius = symbol->
shapeProperty( QStringLiteral(
"radius" ) ).toFloat();
327 const float length = symbol->
shapeProperty( QStringLiteral(
"length" ) ).toFloat();
328 Qt3DExtras::QCylinderGeometry *g =
new Qt3DExtras::QCylinderGeometry;
331 g->setRadius( radius );
332 g->setLength( length );
338 const float radius = symbol->
shapeProperty( QStringLiteral(
"radius" ) ).toFloat();
339 Qt3DExtras::QSphereGeometry *g =
new Qt3DExtras::QSphereGeometry;
340 g->setRadius( radius );
346 const float length = symbol->
shapeProperty( QStringLiteral(
"length" ) ).toFloat();
347 const float bottomRadius = symbol->
shapeProperty( QStringLiteral(
"bottomRadius" ) ).toFloat();
348 const float topRadius = symbol->
shapeProperty( QStringLiteral(
"topRadius" ) ).toFloat();
350 Qt3DExtras::QConeGeometry *g =
new Qt3DExtras::QConeGeometry;
351 g->setLength( length );
352 g->setBottomRadius( bottomRadius );
353 g->setTopRadius( topRadius );
361 const float size = symbol->
shapeProperty( QStringLiteral(
"size" ) ).toFloat();
362 Qt3DExtras::QCuboidGeometry *g =
new Qt3DExtras::QCuboidGeometry;
363 g->setXExtent( size );
364 g->setYExtent( size );
365 g->setZExtent( size );
371 const float radius = symbol->
shapeProperty( QStringLiteral(
"radius" ) ).toFloat();
372 const float minorRadius = symbol->
shapeProperty( QStringLiteral(
"minorRadius" ) ).toFloat();
373 Qt3DExtras::QTorusGeometry *g =
new Qt3DExtras::QTorusGeometry;
374 g->setRadius( radius );
375 g->setMinorRadius( minorRadius );
381 const float size = symbol->
shapeProperty( QStringLiteral(
"size" ) ).toFloat();
382 Qt3DExtras::QPlaneGeometry *g =
new Qt3DExtras::QPlaneGeometry;
384 g->setHeight( size );
390 const float depth = symbol->
shapeProperty( QStringLiteral(
"depth" ) ).toFloat();
391 const QString text = symbol->
shapeProperty( QStringLiteral(
"text" ) ).toString();
392 Qt3DExtras::QExtrudedTextGeometry *g =
new Qt3DExtras::QExtrudedTextGeometry;
393 g->setDepth( depth );
409class QgsModelPoint3DSymbolHandler :
public QgsFeature3DHandler
414 , mSelectedIds( selectedIds ) {}
418 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
429 QVector<QVector3D> positions;
432 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
435 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
444 PointData outSelected;
447bool QgsModelPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsVector3D &chunkOrigin )
450 Q_UNUSED( attributeNames )
452 mChunkOrigin = chunkOrigin;
459 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
468void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
470 makeEntity( parent, context, outNormal,
false );
471 makeEntity( parent, context, outSelected,
true );
473 updateZRangeFromPositions( outNormal.positions );
474 updateZRangeFromPositions( outSelected.positions );
477 const float symbolHeight = mSymbol->transform().data()[14];
478 mZMin += symbolHeight;
479 mZMax += symbolHeight;
482void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
486 addMeshEntities( context, out.positions, mChunkOrigin, mSymbol.get(), parent,
true );
491 if ( mSymbol->shapeProperty( QStringLiteral(
"overwriteMaterial" ) ).toBool()
492 || ( mSymbol->materialSettings() && mSymbol->materialSettings()->type() != QLatin1String(
"null" ) ) )
494 addMeshEntities( context, out.positions, mChunkOrigin, mSymbol.get(), parent,
false );
498 addSceneEntities( context, out.positions, mChunkOrigin, mSymbol.get(), parent );
507 for (
const QVector3D &position : positions )
511 if ( !source.isEmpty() )
514 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
516 const QUrl url = QUrl::fromLocalFile( source );
517 Qt3DRender::QSceneLoader *modelLoader =
new Qt3DRender::QSceneLoader;
518 modelLoader->setSource( url );
520 entity->addComponent( modelLoader );
521 entity->addComponent( transform( position, symbol, chunkOrigin, context.
origin() ) );
522 entity->setParent( parent );
530void QgsModelPoint3DSymbolHandler::addMeshEntities(
const Qgs3DRenderContext &context,
const QVector<QVector3D> &positions,
const QgsVector3D &chunkOrigin,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent,
bool are_selected )
532 if ( positions.empty() )
542 for (
const QVector3D &position : positions )
545 if ( !source.isEmpty() )
548 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
550 const QUrl url = QUrl::fromLocalFile( source );
551 Qt3DRender::QMesh *mesh =
new Qt3DRender::QMesh;
552 mesh->setSource( url );
554 entity->addComponent( mesh );
555 entity->addComponent( mat );
556 entity->addComponent( transform( position, symbol, chunkOrigin, context.
origin() ) );
557 entity->setParent( parent );
568 QVector3D nodeTranslation = ( chunkOrigin - contextOrigin ).toVector3D();
569 QMatrix4x4 translation;
570 translation.translate( nodeTranslation + position );
572 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
573 tr->setMatrix( translation * symbol->
transform() );
581class QgsPoint3DBillboardSymbolHandler :
public QgsFeature3DHandler
586 , mSelectedIds( selectedIds ) {}
590 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
597 QVector<QVector3D> positions;
600 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
603 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
612 PointData outSelected;
615bool QgsPoint3DBillboardSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsVector3D &chunkOrigin )
618 Q_UNUSED( attributeNames )
620 mChunkOrigin = chunkOrigin;
627 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
636void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
638 makeEntity( parent, context, outNormal,
false );
639 makeEntity( parent, context, outSelected,
true );
641 updateZRangeFromPositions( outNormal.positions );
642 updateZRangeFromPositions( outSelected.positions );
645 const float billboardHeight = mSymbol->billboardHeight();
646 mZMin += billboardHeight;
647 mZMax += billboardHeight;
650void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
654 billboardGeometry->
setPoints( out.positions );
657 Qt3DRender::QGeometryRenderer *billboardGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
658 billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
659 billboardGeometryRenderer->setGeometry( billboardGeometry );
660 billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
676 Qt3DCore::QTransform *billboardTransform =
new Qt3DCore::QTransform();
677 QVector3D billboardHeightTranslation( 0, 0, mSymbol->billboardHeight() );
679 QVector3D nodeTranslation = ( mChunkOrigin - context.
origin() ).toVector3D();
680 billboardTransform->setTranslation( billboardHeightTranslation + nodeTranslation );
683 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
685 entity->addComponent( billboardMaterial );
686 entity->addComponent( billboardTransform );
687 entity->addComponent( billboardGeometryRenderer );
688 entity->setParent( parent );
695namespace Qgs3DSymbolImpl
708 return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
710 return new QgsInstancedPoint3DSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
@ ExtrudedText
Extruded text.
QColor selectionColor() const
Returns color used for selected features.
QgsVector3D origin() const
Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
static void extractPointPositions(const QgsFeature &f, const Qgs3DRenderContext &context, const QgsVector3D &chunkOrigin, 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.
Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double precisi...
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