18 #include <Qt3DRender/QAttribute>
19 #include <Qt3DRender/QBuffer>
20 #include <Qt3DRender/QEffect>
21 #include <Qt3DRender/QGraphicsApiFilter>
22 #include <Qt3DRender/QParameter>
23 #include <Qt3DRender/QTechnique>
25 #include <Qt3DExtras/QCylinderGeometry>
26 #include <Qt3DExtras/QConeGeometry>
27 #include <Qt3DExtras/QCuboidGeometry>
28 #include <Qt3DExtras/QPlaneGeometry>
29 #include <Qt3DExtras/QSphereGeometry>
30 #include <Qt3DExtras/QTorusGeometry>
31 #include <Qt3DExtras/QPhongMaterial>
32 #include <Qt3DRender/QSceneLoader>
33 #include <Qt3DRender/QPaintedTextureImage>
35 #include <Qt3DRender/QMesh>
37 #include <Qt3DExtras/QExtrudedTextGeometry>
63 class QgsInstancedPoint3DSymbolHandler :
public QgsFeature3DHandler
68 , mSelectedIds( selectedIds ) {}
70 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
71 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
72 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
77 static Qt3DRender::QGeometryRenderer *renderer(
const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions );
78 static Qt3DRender::QGeometry *symbolGeometry(
QgsPoint3DSymbol::Shape shape,
const QVariantMap &shapeProperties );
83 QVector<QVector3D> positions;
86 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
89 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
95 PointData outSelected;
99 bool QgsInstancedPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
102 Q_UNUSED( attributeNames )
106 void QgsInstancedPoint3DSymbolHandler::processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
108 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
116 void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
118 makeEntity( parent, context, outNormal,
false );
119 makeEntity( parent, context, outSelected,
true );
121 updateZRangeFromPositions( outNormal.positions );
122 updateZRangeFromPositions( outSelected.positions );
125 float symbolHeight = mSymbol->transform().data()[13];
126 mZMin += symbolHeight;
127 mZMax += symbolHeight;
130 void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
133 Qt3DRender::QMaterial *mat = material( mSymbol.get() );
138 for ( Qt3DRender::QParameter *param : mat->effect()->parameters() )
140 if ( param->name() == QLatin1String(
"kd" ) )
141 param->setValue( context.map().selectionColor() );
142 else if ( param->name() == QLatin1String(
"ka" ) )
143 param->setValue( context.map().selectionColor().darker() );
148 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
149 entity->addComponent( renderer( mSymbol.get(), out.positions ) );
150 entity->addComponent( mat );
151 entity->setParent( parent );
159 Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material(
const QgsPoint3DSymbol *symbol )
161 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
162 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
163 filterKey->setValue(
"forward" );
168 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram;
169 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/instanced.vert" ) ) ) );
170 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/instanced.frag" ) ) ) );
172 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass;
173 renderPass->setShaderProgram( shaderProgram );
175 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
176 technique->addFilterKey( filterKey );
177 technique->addRenderPass( renderPass );
178 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
179 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
180 technique->graphicsApiFilter()->setMajorVersion( 3 );
181 technique->graphicsApiFilter()->setMinorVersion( 2 );
183 QMatrix4x4 transformMatrix = symbol->
transform();
184 QMatrix3x3 normalMatrix = transformMatrix.normalMatrix();
187 float *n = normalMatrix.data();
188 QMatrix4x4 normalMatrix4(
194 Qt3DRender::QParameter *paramInst =
new Qt3DRender::QParameter;
195 paramInst->setName( QStringLiteral(
"inst" ) );
196 paramInst->setValue( transformMatrix );
198 Qt3DRender::QParameter *paramInstNormal =
new Qt3DRender::QParameter;
199 paramInstNormal->setName( QStringLiteral(
"instNormal" ) );
200 paramInstNormal->setValue( normalMatrix4 );
202 Qt3DRender::QEffect *effect =
new Qt3DRender::QEffect;
203 effect->addTechnique( technique );
204 effect->addParameter( paramInst );
205 effect->addParameter( paramInstNormal );
209 Qt3DRender::QMaterial *material =
new Qt3DRender::QMaterial;
210 material->setEffect( effect );
215 Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer(
const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions )
217 int count = positions.count();
218 int byteCount = positions.count() *
sizeof( QVector3D );
220 ba.resize( byteCount );
221 memcpy( ba.data(), positions.constData(), byteCount );
223 Qt3DRender::QBuffer *instanceBuffer =
new Qt3DRender::QBuffer();
224 instanceBuffer->setData( ba );
226 Qt3DRender::QAttribute *instanceDataAttribute =
new Qt3DRender::QAttribute;
227 instanceDataAttribute->setName( QStringLiteral(
"pos" ) );
228 instanceDataAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
229 instanceDataAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
230 instanceDataAttribute->setVertexSize( 3 );
231 instanceDataAttribute->setByteOffset( 0 );
232 instanceDataAttribute->setDivisor( 1 );
233 instanceDataAttribute->setBuffer( instanceBuffer );
234 instanceDataAttribute->setCount( count );
235 instanceDataAttribute->setByteStride( 3 *
sizeof(
float ) );
238 geometry->addAttribute( instanceDataAttribute );
239 geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
241 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
242 renderer->setGeometry( geometry );
243 renderer->setInstanceCount( count );
248 Qt3DRender::QGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry(
QgsPoint3DSymbol::Shape shape,
const QVariantMap &shapeProperties )
254 float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
255 float length = shapeProperties[QStringLiteral(
"length" )].toFloat();
256 Qt3DExtras::QCylinderGeometry *g =
new Qt3DExtras::QCylinderGeometry;
259 g->setRadius( radius ? radius : 10 );
260 g->setLength( length ? length : 10 );
266 float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
267 Qt3DExtras::QSphereGeometry *g =
new Qt3DExtras::QSphereGeometry;
268 g->setRadius( radius ? radius : 10 );
274 float length = shapeProperties[QStringLiteral(
"length" )].toFloat();
275 float bottomRadius = shapeProperties[QStringLiteral(
"bottomRadius" )].toFloat();
276 float topRadius = shapeProperties[QStringLiteral(
"topRadius" )].toFloat();
277 Qt3DExtras::QConeGeometry *g =
new Qt3DExtras::QConeGeometry;
278 g->setLength( length ? length : 10 );
279 g->setBottomRadius( bottomRadius );
280 g->setTopRadius( topRadius );
288 float size = shapeProperties[QStringLiteral(
"size" )].toFloat();
289 Qt3DExtras::QCuboidGeometry *g =
new Qt3DExtras::QCuboidGeometry;
290 g->setXExtent( size ? size : 10 );
291 g->setYExtent( size ? size : 10 );
292 g->setZExtent( size ? size : 10 );
298 float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
299 float minorRadius = shapeProperties[QStringLiteral(
"minorRadius" )].toFloat();
300 Qt3DExtras::QTorusGeometry *g =
new Qt3DExtras::QTorusGeometry;
301 g->setRadius( radius ? radius : 10 );
302 g->setMinorRadius( minorRadius ? minorRadius : 5 );
308 float size = shapeProperties[QStringLiteral(
"size" )].toFloat();
309 Qt3DExtras::QPlaneGeometry *g =
new Qt3DExtras::QPlaneGeometry;
310 g->setWidth( size ? size : 10 );
311 g->setHeight( size ? size : 10 );
317 float depth = shapeProperties[QStringLiteral(
"depth" )].toFloat();
318 QString text = shapeProperties[QStringLiteral(
"text" )].toString();
319 Qt3DExtras::QExtrudedTextGeometry *g =
new Qt3DExtras::QExtrudedTextGeometry;
320 g->setDepth( depth ? depth : 1 );
334 class QgsModelPoint3DSymbolHandler :
public QgsFeature3DHandler
339 , mSelectedIds( selectedIds ) {}
341 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
342 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
343 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
347 static void addSceneEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent );
348 static void addMeshEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent,
bool are_selected );
349 static Qt3DCore::QTransform *transform( QVector3D position,
const QgsPoint3DSymbol *symbol );
354 QVector<QVector3D> positions;
357 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
360 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
366 PointData outSelected;
369 bool QgsModelPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
372 Q_UNUSED( attributeNames )
376 void QgsModelPoint3DSymbolHandler::processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
378 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
386 void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
388 makeEntity( parent, context, outNormal,
false );
389 makeEntity( parent, context, outSelected,
true );
391 updateZRangeFromPositions( outNormal.positions );
392 updateZRangeFromPositions( outSelected.positions );
395 float symbolHeight = mSymbol->transform().data()[13];
396 mZMin += symbolHeight;
397 mZMax += symbolHeight;
400 void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
404 addMeshEntities( context.map(), out.positions, mSymbol.get(), parent,
true );
409 if ( mSymbol->shapeProperties()[QStringLiteral(
"overwriteMaterial" )].toBool()
410 || ( mSymbol->material() && mSymbol->material()->type() != QLatin1String(
"null" ) ) )
412 addMeshEntities( context.map(), out.positions, mSymbol.get(), parent,
false );
416 addSceneEntities( context.map(), out.positions, mSymbol.get(), parent );
423 void QgsModelPoint3DSymbolHandler::addSceneEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
426 for (
const QVector3D &position : positions )
430 if ( !source.isEmpty() )
433 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
435 QUrl url = QUrl::fromLocalFile( source );
436 Qt3DRender::QSceneLoader *modelLoader =
new Qt3DRender::QSceneLoader;
437 modelLoader->setSource( url );
439 entity->addComponent( modelLoader );
440 entity->addComponent( transform( position, symbol ) );
441 entity->setParent( parent );
449 void QgsModelPoint3DSymbolHandler::addMeshEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent,
bool are_selected )
451 if ( positions.empty() )
461 for (
const QVector3D &position : positions )
464 if ( !source.isEmpty() )
467 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
469 QUrl url = QUrl::fromLocalFile( source );
470 Qt3DRender::QMesh *mesh =
new Qt3DRender::QMesh;
471 mesh->setSource( url );
473 entity->addComponent( mesh );
474 entity->addComponent( mat );
475 entity->addComponent( transform( position, symbol ) );
476 entity->setParent( parent );
484 Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position,
const QgsPoint3DSymbol *symbol )
486 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
488 tr->setTranslation( position + tr->translation() );
496 class QgsPoint3DBillboardSymbolHandler :
public QgsFeature3DHandler
501 , mSelectedIds( selectedIds ) {}
503 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
504 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
505 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
512 QVector<QVector3D> positions;
515 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
518 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
524 PointData outSelected;
527 bool QgsPoint3DBillboardSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
530 Q_UNUSED( attributeNames )
534 void QgsPoint3DBillboardSymbolHandler::processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
536 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
544 void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
546 makeEntity( parent, context, outNormal,
false );
547 makeEntity( parent, context, outSelected,
true );
549 updateZRangeFromPositions( outNormal.positions );
550 updateZRangeFromPositions( outSelected.positions );
553 float billboardHeight = mSymbol->transform().data()[13];
554 mZMin += billboardHeight;
555 mZMax += billboardHeight;
558 void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
562 billboardGeometry->
setPoints( out.positions );
565 Qt3DRender::QGeometryRenderer *billboardGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
566 billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
567 billboardGeometryRenderer->setGeometry( billboardGeometry );
568 billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
584 Qt3DCore::QTransform *billboardTransform =
new Qt3DCore::QTransform();
585 billboardTransform->setMatrix( mSymbol->billboardTransform() );
588 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
590 entity->addComponent( billboardMaterial );
591 entity->addComponent( billboardTransform );
592 entity->addComponent( billboardGeometryRenderer );
593 entity->setParent( parent );
600 namespace Qgs3DSymbolImpl
613 return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
615 return new QgsInstancedPoint3DSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
620 QgsFeature3DHandler *handler = handlerForPoint3DSymbol( layer, &symbol );
621 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, Qgs3DTypes::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 QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
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 * material() const
Returns material 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.
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)
QSet< QgsFeatureId > QgsFeatureIds