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 #if QT_VERSION >= 0x050900
38 #include <Qt3DExtras/QExtrudedTextGeometry>
65 class QgsInstancedPoint3DSymbolHandler :
public QgsFeature3DHandler
70 , mSelectedIds( selectedIds ) {}
72 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
73 void processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
74 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
79 static Qt3DRender::QGeometryRenderer *renderer(
const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions );
80 static Qt3DRender::QGeometry *symbolGeometry(
QgsPoint3DSymbol::Shape shape,
const QVariantMap &shapeProperties );
85 QVector<QVector3D> positions;
88 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
91 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
97 PointData outSelected;
101 bool QgsInstancedPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
104 Q_UNUSED( attributeNames )
108 void QgsInstancedPoint3DSymbolHandler::processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
110 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
118 void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
120 makeEntity( parent, context, outNormal,
false );
121 makeEntity( parent, context, outSelected,
true );
123 updateZRangeFromPositions( outNormal.positions );
124 updateZRangeFromPositions( outSelected.positions );
127 float symbolHeight = mSymbol->transform().data()[13];
128 mZMin += symbolHeight;
129 mZMax += symbolHeight;
132 void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
135 Qt3DRender::QMaterial *mat = material( mSymbol.get() );
140 for ( Qt3DRender::QParameter *param : mat->effect()->parameters() )
142 if ( param->name() == QLatin1String(
"kd" ) )
143 param->setValue( context.map().selectionColor() );
144 else if ( param->name() == QLatin1String(
"ka" ) )
145 param->setValue( context.map().selectionColor().darker() );
150 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
151 entity->addComponent( renderer( mSymbol.get(), out.positions ) );
152 entity->addComponent( mat );
153 entity->setParent( parent );
161 Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material(
const QgsPoint3DSymbol *symbol )
163 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
164 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
165 filterKey->setValue(
"forward" );
170 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram;
171 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/instanced.vert" ) ) ) );
172 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/instanced.frag" ) ) ) );
174 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass;
175 renderPass->setShaderProgram( shaderProgram );
177 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
178 technique->addFilterKey( filterKey );
179 technique->addRenderPass( renderPass );
180 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
181 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
182 technique->graphicsApiFilter()->setMajorVersion( 3 );
183 technique->graphicsApiFilter()->setMinorVersion( 2 );
185 QMatrix4x4 transformMatrix = symbol->
transform();
186 QMatrix3x3 normalMatrix = transformMatrix.normalMatrix();
189 float *n = normalMatrix.data();
190 QMatrix4x4 normalMatrix4(
196 Qt3DRender::QParameter *paramInst =
new Qt3DRender::QParameter;
197 paramInst->setName( QStringLiteral(
"inst" ) );
198 paramInst->setValue( transformMatrix );
200 Qt3DRender::QParameter *paramInstNormal =
new Qt3DRender::QParameter;
201 paramInstNormal->setName( QStringLiteral(
"instNormal" ) );
202 paramInstNormal->setValue( normalMatrix4 );
204 Qt3DRender::QEffect *effect =
new Qt3DRender::QEffect;
205 effect->addTechnique( technique );
206 effect->addParameter( paramInst );
207 effect->addParameter( paramInstNormal );
211 Qt3DRender::QMaterial *material =
new Qt3DRender::QMaterial;
212 material->setEffect( effect );
217 Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer(
const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions )
219 int count = positions.count();
220 int byteCount = positions.count() *
sizeof( QVector3D );
222 ba.resize( byteCount );
223 memcpy( ba.data(), positions.constData(), byteCount );
225 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
226 Qt3DRender::QBuffer *instanceBuffer =
new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer );
228 Qt3DRender::QBuffer *instanceBuffer =
new Qt3DRender::QBuffer();
230 instanceBuffer->setData( ba );
232 Qt3DRender::QAttribute *instanceDataAttribute =
new Qt3DRender::QAttribute;
233 instanceDataAttribute->setName( QStringLiteral(
"pos" ) );
234 instanceDataAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
235 instanceDataAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
236 instanceDataAttribute->setVertexSize( 3 );
237 instanceDataAttribute->setByteOffset( 0 );
238 instanceDataAttribute->setDivisor( 1 );
239 instanceDataAttribute->setBuffer( instanceBuffer );
240 instanceDataAttribute->setCount( count );
241 instanceDataAttribute->setByteStride( 3 *
sizeof(
float ) );
244 geometry->addAttribute( instanceDataAttribute );
245 geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
247 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
248 renderer->setGeometry( geometry );
249 renderer->setInstanceCount( count );
254 Qt3DRender::QGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry(
QgsPoint3DSymbol::Shape shape,
const QVariantMap &shapeProperties )
260 float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
261 float length = shapeProperties[QStringLiteral(
"length" )].toFloat();
262 Qt3DExtras::QCylinderGeometry *g =
new Qt3DExtras::QCylinderGeometry;
265 g->setRadius( radius ? radius : 10 );
266 g->setLength( length ? length : 10 );
272 float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
273 Qt3DExtras::QSphereGeometry *g =
new Qt3DExtras::QSphereGeometry;
274 g->setRadius( radius ? radius : 10 );
280 float length = shapeProperties[QStringLiteral(
"length" )].toFloat();
281 float bottomRadius = shapeProperties[QStringLiteral(
"bottomRadius" )].toFloat();
282 float topRadius = shapeProperties[QStringLiteral(
"topRadius" )].toFloat();
283 Qt3DExtras::QConeGeometry *g =
new Qt3DExtras::QConeGeometry;
284 g->setLength( length ? length : 10 );
285 g->setBottomRadius( bottomRadius );
286 g->setTopRadius( topRadius );
294 float size = shapeProperties[QStringLiteral(
"size" )].toFloat();
295 Qt3DExtras::QCuboidGeometry *g =
new Qt3DExtras::QCuboidGeometry;
296 g->setXExtent( size ? size : 10 );
297 g->setYExtent( size ? size : 10 );
298 g->setZExtent( size ? size : 10 );
304 float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
305 float minorRadius = shapeProperties[QStringLiteral(
"minorRadius" )].toFloat();
306 Qt3DExtras::QTorusGeometry *g =
new Qt3DExtras::QTorusGeometry;
307 g->setRadius( radius ? radius : 10 );
308 g->setMinorRadius( minorRadius ? minorRadius : 5 );
314 float size = shapeProperties[QStringLiteral(
"size" )].toFloat();
315 Qt3DExtras::QPlaneGeometry *g =
new Qt3DExtras::QPlaneGeometry;
316 g->setWidth( size ? size : 10 );
317 g->setHeight( size ? size : 10 );
321 #if QT_VERSION >= 0x050900
324 float depth = shapeProperties[QStringLiteral(
"depth" )].toFloat();
325 QString text = shapeProperties[QStringLiteral(
"text" )].toString();
326 Qt3DExtras::QExtrudedTextGeometry *g =
new Qt3DExtras::QExtrudedTextGeometry;
327 g->setDepth( depth ? depth : 1 );
342 class QgsModelPoint3DSymbolHandler :
public QgsFeature3DHandler
347 , mSelectedIds( selectedIds ) {}
349 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
350 void processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
351 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
355 static void addSceneEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent );
356 static void addMeshEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent,
bool are_selected );
357 static Qt3DCore::QTransform *transform( QVector3D position,
const QgsPoint3DSymbol *symbol );
362 QVector<QVector3D> positions;
365 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
368 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
374 PointData outSelected;
377 bool QgsModelPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
380 Q_UNUSED( attributeNames )
384 void QgsModelPoint3DSymbolHandler::processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
386 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
394 void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
396 makeEntity( parent, context, outNormal,
false );
397 makeEntity( parent, context, outSelected,
true );
399 updateZRangeFromPositions( outNormal.positions );
400 updateZRangeFromPositions( outSelected.positions );
403 float symbolHeight = mSymbol->transform().data()[13];
404 mZMin += symbolHeight;
405 mZMax += symbolHeight;
408 void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
412 addMeshEntities( context.map(), out.positions, mSymbol.get(), parent,
true );
416 if ( mSymbol->shapeProperties()[QStringLiteral(
"overwriteMaterial" )].toBool() )
418 addMeshEntities( context.map(), out.positions, mSymbol.get(), parent,
false );
422 addSceneEntities( context.map(), out.positions, mSymbol.get(), parent );
429 void QgsModelPoint3DSymbolHandler::addSceneEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
432 for (
const QVector3D &position : positions )
436 if ( !source.isEmpty() )
439 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
441 QUrl url = QUrl::fromLocalFile( source );
442 Qt3DRender::QSceneLoader *modelLoader =
new Qt3DRender::QSceneLoader;
443 modelLoader->setSource( url );
445 entity->addComponent( modelLoader );
446 entity->addComponent( transform( position, symbol ) );
447 entity->setParent( parent );
455 void QgsModelPoint3DSymbolHandler::addMeshEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent,
bool are_selected )
457 if ( positions.empty() )
464 Qt3DRender::QMaterial *mat = symbol->
material()->
toMaterial( QgsMaterialSettingsRenderingTechnique::Triangles, materialContext );
467 for (
const QVector3D &position : positions )
470 if ( !source.isEmpty() )
473 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
475 QUrl url = QUrl::fromLocalFile( source );
476 Qt3DRender::QMesh *mesh =
new Qt3DRender::QMesh;
477 mesh->setSource( url );
479 entity->addComponent( mesh );
480 entity->addComponent( mat );
481 entity->addComponent( transform( position, symbol ) );
482 entity->setParent( parent );
490 Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position,
const QgsPoint3DSymbol *symbol )
492 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
494 tr->setTranslation( position + tr->translation() );
502 class QgsPoint3DBillboardSymbolHandler :
public QgsFeature3DHandler
507 , mSelectedIds( selectedIds ) {}
509 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
510 void processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
511 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
518 QVector<QVector3D> positions;
521 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
524 std::unique_ptr< QgsPoint3DSymbol > mSymbol;
530 PointData outSelected;
533 bool QgsPoint3DBillboardSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
536 Q_UNUSED( attributeNames )
540 void QgsPoint3DBillboardSymbolHandler::processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
542 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
550 void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
552 makeEntity( parent, context, outNormal,
false );
553 makeEntity( parent, context, outSelected,
true );
555 updateZRangeFromPositions( outNormal.positions );
556 updateZRangeFromPositions( outSelected.positions );
559 float billboardHeight = mSymbol->transform().data()[13];
560 mZMin += billboardHeight;
561 mZMax += billboardHeight;
564 void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
568 billboardGeometry->
setPoints( out.positions );
571 Qt3DRender::QGeometryRenderer *billboardGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
572 billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
573 billboardGeometryRenderer->setGeometry( billboardGeometry );
574 billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
590 Qt3DCore::QTransform *billboardTransform =
new Qt3DCore::QTransform();
591 billboardTransform->setMatrix( mSymbol->billboardTransform() );
594 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
596 entity->addComponent( billboardMaterial );
597 entity->addComponent( billboardTransform );
598 entity->addComponent( billboardGeometryRenderer );
599 entity->setParent( parent );
606 namespace Qgs3DSymbolImpl
619 return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
621 return new QgsInstancedPoint3DSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
626 QgsFeature3DHandler *handler = handlerForPoint3DSymbol( layer, &symbol );
627 Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );