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;
117 void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
119 makeEntity( parent, context, outNormal,
false );
120 makeEntity( parent, context, outSelected,
true );
122 updateZRangeFromPositions( outNormal.positions );
123 updateZRangeFromPositions( outSelected.positions );
126 const float symbolHeight = mSymbol->transform().data()[13];
127 mZMin += symbolHeight;
128 mZMax += symbolHeight;
131 void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
134 Qt3DRender::QMaterial *mat = material( mSymbol.get() );
139 for ( Qt3DRender::QParameter *param : mat->effect()->parameters() )
141 if ( param->name() == QLatin1String(
"kd" ) )
142 param->setValue( context.map().selectionColor() );
143 else if ( param->name() == QLatin1String(
"ka" ) )
144 param->setValue( context.map().selectionColor().darker() );
149 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
150 entity->addComponent( renderer( mSymbol.get(), out.positions ) );
151 entity->addComponent( mat );
152 entity->setParent( parent );
160 Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material(
const QgsPoint3DSymbol *symbol )
162 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
163 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
164 filterKey->setValue(
"forward" );
169 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram;
170 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/instanced.vert" ) ) ) );
171 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/instanced.frag" ) ) ) );
173 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass;
174 renderPass->setShaderProgram( shaderProgram );
176 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
177 technique->addFilterKey( filterKey );
178 technique->addRenderPass( renderPass );
179 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
180 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
181 technique->graphicsApiFilter()->setMajorVersion( 3 );
182 technique->graphicsApiFilter()->setMinorVersion( 2 );
184 const QMatrix4x4 transformMatrix = symbol->
transform();
185 QMatrix3x3 normalMatrix = transformMatrix.normalMatrix();
188 float *n = normalMatrix.data();
189 const QMatrix4x4 normalMatrix4(
195 Qt3DRender::QParameter *paramInst =
new Qt3DRender::QParameter;
196 paramInst->setName( QStringLiteral(
"inst" ) );
197 paramInst->setValue( transformMatrix );
199 Qt3DRender::QParameter *paramInstNormal =
new Qt3DRender::QParameter;
200 paramInstNormal->setName( QStringLiteral(
"instNormal" ) );
201 paramInstNormal->setValue( normalMatrix4 );
203 Qt3DRender::QEffect *effect =
new Qt3DRender::QEffect;
204 effect->addTechnique( technique );
205 effect->addParameter( paramInst );
206 effect->addParameter( paramInstNormal );
210 Qt3DRender::QMaterial *material =
new Qt3DRender::QMaterial;
211 material->setEffect( effect );
216 Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer(
const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions )
218 const int count = positions.count();
219 const int byteCount = positions.count() *
sizeof( QVector3D );
221 ba.resize( byteCount );
222 memcpy( ba.data(), positions.constData(), byteCount );
224 Qt3DRender::QBuffer *instanceBuffer =
new Qt3DRender::QBuffer();
225 instanceBuffer->setData( ba );
227 Qt3DRender::QAttribute *instanceDataAttribute =
new Qt3DRender::QAttribute;
228 instanceDataAttribute->setName( QStringLiteral(
"pos" ) );
229 instanceDataAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
230 instanceDataAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
231 instanceDataAttribute->setVertexSize( 3 );
232 instanceDataAttribute->setByteOffset( 0 );
233 instanceDataAttribute->setDivisor( 1 );
234 instanceDataAttribute->setBuffer( instanceBuffer );
235 instanceDataAttribute->setCount( count );
236 instanceDataAttribute->setByteStride( 3 *
sizeof(
float ) );
239 geometry->addAttribute( instanceDataAttribute );
240 geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
242 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
243 renderer->setGeometry( geometry );
244 renderer->setInstanceCount( count );
249 Qt3DRender::QGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry(
QgsPoint3DSymbol::Shape shape,
const QVariantMap &shapeProperties )
255 const float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
256 const float length = shapeProperties[QStringLiteral(
"length" )].toFloat();
257 Qt3DExtras::QCylinderGeometry *g =
new Qt3DExtras::QCylinderGeometry;
260 g->setRadius( radius ? radius : 10 );
261 g->setLength( length ? length : 10 );
267 const float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
268 Qt3DExtras::QSphereGeometry *g =
new Qt3DExtras::QSphereGeometry;
269 g->setRadius( radius ? radius : 10 );
275 const float length = shapeProperties[QStringLiteral(
"length" )].toFloat();
276 const float bottomRadius = shapeProperties[QStringLiteral(
"bottomRadius" )].toFloat();
277 const float topRadius = shapeProperties[QStringLiteral(
"topRadius" )].toFloat();
278 Qt3DExtras::QConeGeometry *g =
new Qt3DExtras::QConeGeometry;
279 g->setLength( length ? length : 10 );
280 g->setBottomRadius( bottomRadius );
281 g->setTopRadius( topRadius );
289 const float size = shapeProperties[QStringLiteral(
"size" )].toFloat();
290 Qt3DExtras::QCuboidGeometry *g =
new Qt3DExtras::QCuboidGeometry;
291 g->setXExtent( size ? size : 10 );
292 g->setYExtent( size ? size : 10 );
293 g->setZExtent( size ? size : 10 );
299 const float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
300 const float minorRadius = shapeProperties[QStringLiteral(
"minorRadius" )].toFloat();
301 Qt3DExtras::QTorusGeometry *g =
new Qt3DExtras::QTorusGeometry;
302 g->setRadius( radius ? radius : 10 );
303 g->setMinorRadius( minorRadius ? minorRadius : 5 );
309 const float size = shapeProperties[QStringLiteral(
"size" )].toFloat();
310 Qt3DExtras::QPlaneGeometry *g =
new Qt3DExtras::QPlaneGeometry;
311 g->setWidth( size ? size : 10 );
312 g->setHeight( size ? size : 10 );
318 const float depth = shapeProperties[QStringLiteral(
"depth" )].toFloat();
319 const QString text = shapeProperties[QStringLiteral(
"text" )].toString();
320 Qt3DExtras::QExtrudedTextGeometry *g =
new Qt3DExtras::QExtrudedTextGeometry;
321 g->setDepth( depth ? depth : 1 );
335 class QgsModelPoint3DSymbolHandler :
public QgsFeature3DHandler
340 , mSelectedIds( selectedIds ) {}
342 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
343 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
344 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
348 static void addSceneEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent );
349 static void addMeshEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent,
bool are_selected );
350 static Qt3DCore::QTransform *transform( QVector3D position,
const QgsPoint3DSymbol *symbol );
355 QVector<QVector3D> positions;
358 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
361 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
367 PointData outSelected;
370 bool QgsModelPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
373 Q_UNUSED( attributeNames )
377 void QgsModelPoint3DSymbolHandler::processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
379 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
388 void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
390 makeEntity( parent, context, outNormal,
false );
391 makeEntity( parent, context, outSelected,
true );
393 updateZRangeFromPositions( outNormal.positions );
394 updateZRangeFromPositions( outSelected.positions );
397 const float symbolHeight = mSymbol->transform().data()[13];
398 mZMin += symbolHeight;
399 mZMax += symbolHeight;
402 void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
406 addMeshEntities( context.map(), out.positions, mSymbol.get(), parent,
true );
411 if ( mSymbol->shapeProperties()[QStringLiteral(
"overwriteMaterial" )].toBool()
412 || ( mSymbol->material() && mSymbol->material()->type() != QLatin1String(
"null" ) ) )
414 addMeshEntities( context.map(), out.positions, mSymbol.get(), parent,
false );
418 addSceneEntities( context.map(), out.positions, mSymbol.get(), parent );
425 void QgsModelPoint3DSymbolHandler::addSceneEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
428 for (
const QVector3D &position : positions )
432 if ( !source.isEmpty() )
435 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
437 const QUrl url = QUrl::fromLocalFile( source );
438 Qt3DRender::QSceneLoader *modelLoader =
new Qt3DRender::QSceneLoader;
439 modelLoader->setSource( url );
441 entity->addComponent( modelLoader );
442 entity->addComponent( transform( position, symbol ) );
443 entity->setParent( parent );
451 void QgsModelPoint3DSymbolHandler::addMeshEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent,
bool are_selected )
453 if ( positions.empty() )
463 for (
const QVector3D &position : positions )
466 if ( !source.isEmpty() )
469 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
471 const QUrl url = QUrl::fromLocalFile( source );
472 Qt3DRender::QMesh *mesh =
new Qt3DRender::QMesh;
473 mesh->setSource( url );
475 entity->addComponent( mesh );
476 entity->addComponent( mat );
477 entity->addComponent( transform( position, symbol ) );
478 entity->setParent( parent );
486 Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position,
const QgsPoint3DSymbol *symbol )
488 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
490 tr->setTranslation( position + tr->translation() );
498 class QgsPoint3DBillboardSymbolHandler :
public QgsFeature3DHandler
503 , mSelectedIds( selectedIds ) {}
505 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
506 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
507 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
514 QVector<QVector3D> positions;
517 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
520 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
526 PointData outSelected;
529 bool QgsPoint3DBillboardSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
532 Q_UNUSED( attributeNames )
536 void QgsPoint3DBillboardSymbolHandler::processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
538 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
547 void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
549 makeEntity( parent, context, outNormal,
false );
550 makeEntity( parent, context, outSelected,
true );
552 updateZRangeFromPositions( outNormal.positions );
553 updateZRangeFromPositions( outSelected.positions );
556 const float billboardHeight = mSymbol->transform().data()[13];
557 mZMin += billboardHeight;
558 mZMax += billboardHeight;
561 void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
565 billboardGeometry->
setPoints( out.positions );
568 Qt3DRender::QGeometryRenderer *billboardGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
569 billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
570 billboardGeometryRenderer->setGeometry( billboardGeometry );
571 billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
587 Qt3DCore::QTransform *billboardTransform =
new Qt3DCore::QTransform();
588 billboardTransform->setMatrix( mSymbol->billboardTransform() );
591 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
593 entity->addComponent( billboardMaterial );
594 entity->addComponent( billboardTransform );
595 entity->addComponent( billboardGeometryRenderer );
596 entity->setParent( parent );
603 namespace Qgs3DSymbolImpl
616 return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
618 return new QgsInstancedPoint3DSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
623 QgsFeature3DHandler *handler = handlerForPoint3DSymbol( layer, &symbol );
624 Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );