QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgspoint3dsymbol_p.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspoint3dsymbol_p.cpp
3  --------------------------------------
4  Date : July 2017
5  Copyright : (C) 2017 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgspoint3dsymbol_p.h"
17 
18 #include <Qt3DRender/QAttribute>
19 #include <Qt3DRender/QBuffer>
20 #include <Qt3DRender/QEffect>
21 #include <Qt3DRender/QGraphicsApiFilter>
22 #include <Qt3DRender/QParameter>
23 #include <Qt3DRender/QTechnique>
24 
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>
34 
35 #include <Qt3DRender/QMesh>
36 
37 #if QT_VERSION >= 0x050900
38 #include <Qt3DExtras/QExtrudedTextGeometry>
39 #endif
40 
41 #include <QUrl>
42 #include <QVector3D>
43 
44 #include "qgspoint3dsymbol.h"
45 #include "qgs3dmapsettings.h"
46 
47 #include "qgsapplication.h"
48 #include "qgsvectorlayer.h"
49 #include "qgspoint.h"
50 #include "qgs3dutils.h"
51 #include "qgsbillboardgeometry.h"
53 #include "qgslogger.h"
54 #include "qgssourcecache.h"
55 #include "qgssymbol.h"
56 #include "qgssymbollayerutils.h"
57 #include "qgssymbollayer.h"
58 
60 
61 
62 //* INSTANCED RENDERING *//
63 
64 
65 class QgsInstancedPoint3DSymbolHandler : public QgsFeature3DHandler
66 {
67  public:
68  QgsInstancedPoint3DSymbolHandler( const QgsPoint3DSymbol *symbol, const QgsFeatureIds &selectedIds )
69  : mSymbol( static_cast< QgsPoint3DSymbol *>( symbol->clone() ) )
70  , mSelectedIds( selectedIds ) {}
71 
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;
75 
76  private:
77 
78  static Qt3DRender::QMaterial *material( const QgsPoint3DSymbol *symbol );
79  static Qt3DRender::QGeometryRenderer *renderer( const QgsPoint3DSymbol *symbol, const QVector<QVector3D> &positions );
80  static Qt3DRender::QGeometry *symbolGeometry( QgsPoint3DSymbol::Shape shape, const QVariantMap &shapeProperties );
81 
83  struct PointData
84  {
85  QVector<QVector3D> positions; // contains triplets of float x,y,z for each point
86  };
87 
88  void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected );
89 
90  // input specific for this class
91  std::unique_ptr< QgsPoint3DSymbol > mSymbol;
92  // inputs - generic
93  QgsFeatureIds mSelectedIds;
94 
95  // outputs
96  PointData outNormal;
97  PointData outSelected;
98 };
99 
100 
101 bool QgsInstancedPoint3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
102 {
103  Q_UNUSED( context )
104  Q_UNUSED( attributeNames )
105  return true;
106 }
107 
108 void QgsInstancedPoint3DSymbolHandler::processFeature( QgsFeature &feature, const Qgs3DRenderContext &context )
109 {
110  PointData &out = mSelectedIds.contains( feature.id() ) ? outSelected : outNormal;
111 
112  if ( feature.geometry().isNull() )
113  return;
114 
115  Qgs3DUtils::extractPointPositions( feature, context.map(), mSymbol->altitudeClamping(), out.positions );
116 }
117 
118 void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
119 {
120  makeEntity( parent, context, outNormal, false );
121  makeEntity( parent, context, outSelected, true );
122 
123  updateZRangeFromPositions( outNormal.positions );
124  updateZRangeFromPositions( outSelected.positions );
125 
126  // the elevation offset is applied in the vertex shader so let's account for it as well
127  float symbolHeight = mSymbol->transform().data()[13];
128  mZMin += symbolHeight;
129  mZMax += symbolHeight;
130 }
131 
132 void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected )
133 {
134  // build the default material
135  Qt3DRender::QMaterial *mat = material( mSymbol.get() );
136 
137  if ( selected )
138  {
139  // update the material with selection colors
140  for ( Qt3DRender::QParameter *param : mat->effect()->parameters() )
141  {
142  if ( param->name() == QLatin1String( "kd" ) ) // diffuse
143  param->setValue( context.map().selectionColor() );
144  else if ( param->name() == QLatin1String( "ka" ) ) // ambient
145  param->setValue( context.map().selectionColor().darker() );
146  }
147  }
148 
149  // build the entity
150  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
151  entity->addComponent( renderer( mSymbol.get(), out.positions ) );
152  entity->addComponent( mat );
153  entity->setParent( parent );
154 
155 // cppcheck wrongly believes entity will leak
156 // cppcheck-suppress memleak
157 }
158 
159 
160 
161 Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material( const QgsPoint3DSymbol *symbol )
162 {
163  Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey;
164  filterKey->setName( QStringLiteral( "renderingStyle" ) );
165  filterKey->setValue( "forward" );
166 
167  // the fragment shader implements a simplified version of phong shading that uses hardcoded light
168  // (instead of whatever light we have defined in the scene)
169  // TODO: use phong shading that respects lights from the scene
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" ) ) ) );
173 
174  Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass;
175  renderPass->setShaderProgram( shaderProgram );
176 
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 );
184 
185  QMatrix4x4 transformMatrix = symbol->transform();
186  QMatrix3x3 normalMatrix = transformMatrix.normalMatrix(); // transponed inverse of 3x3 sub-matrix
187 
188  // QMatrix3x3 is not supported for passing to shaders, so we pass QMatrix4x4
189  float *n = normalMatrix.data();
190  QMatrix4x4 normalMatrix4(
191  n[0], n[3], n[6], 0,
192  n[1], n[4], n[7], 0,
193  n[2], n[5], n[8], 0,
194  0, 0, 0, 0 );
195 
196  Qt3DRender::QParameter *paramInst = new Qt3DRender::QParameter;
197  paramInst->setName( QStringLiteral( "inst" ) );
198  paramInst->setValue( transformMatrix );
199 
200  Qt3DRender::QParameter *paramInstNormal = new Qt3DRender::QParameter;
201  paramInstNormal->setName( QStringLiteral( "instNormal" ) );
202  paramInstNormal->setValue( normalMatrix4 );
203 
204  Qt3DRender::QEffect *effect = new Qt3DRender::QEffect;
205  effect->addTechnique( technique );
206  effect->addParameter( paramInst );
207  effect->addParameter( paramInstNormal );
208 
209  symbol->material()->addParametersToEffect( effect );
210 
211  Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial;
212  material->setEffect( effect );
213 
214  return material;
215 }
216 
217 Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer( const QgsPoint3DSymbol *symbol, const QVector<QVector3D> &positions )
218 {
219  int count = positions.count();
220  int byteCount = positions.count() * sizeof( QVector3D );
221  QByteArray ba;
222  ba.resize( byteCount );
223  memcpy( ba.data(), positions.constData(), byteCount );
224 
225 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
226  Qt3DRender::QBuffer *instanceBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer );
227 #else
228  Qt3DRender::QBuffer *instanceBuffer = new Qt3DRender::QBuffer();
229 #endif
230  instanceBuffer->setData( ba );
231 
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 ) );
242 
243  Qt3DRender::QGeometry *geometry = symbolGeometry( symbol->shape(), symbol->shapeProperties() );
244  geometry->addAttribute( instanceDataAttribute );
245  geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
246 
247  Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
248  renderer->setGeometry( geometry );
249  renderer->setInstanceCount( count );
250 
251  return renderer;
252 }
253 
254 Qt3DRender::QGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( QgsPoint3DSymbol::Shape shape, const QVariantMap &shapeProperties )
255 {
256  switch ( shape )
257  {
259  {
260  float radius = shapeProperties[QStringLiteral( "radius" )].toFloat();
261  float length = shapeProperties[QStringLiteral( "length" )].toFloat();
262  Qt3DExtras::QCylinderGeometry *g = new Qt3DExtras::QCylinderGeometry;
263  //g->setRings(2); // how many vertices vertically
264  //g->setSlices(8); // how many vertices on circumference
265  g->setRadius( radius ? radius : 10 );
266  g->setLength( length ? length : 10 );
267  return g;
268  }
269 
271  {
272  float radius = shapeProperties[QStringLiteral( "radius" )].toFloat();
273  Qt3DExtras::QSphereGeometry *g = new Qt3DExtras::QSphereGeometry;
274  g->setRadius( radius ? radius : 10 );
275  return g;
276  }
277 
279  {
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 );
287  //g->setHasBottomEndcap(hasBottomEndcap);
288  //g->setHasTopEndcap(hasTopEndcap);
289  return g;
290  }
291 
293  {
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 );
299  return g;
300  }
301 
303  {
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 );
309  return g;
310  }
311 
313  {
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 );
318  return g;
319  }
320 
321 #if QT_VERSION >= 0x050900
323  {
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 );
328  g->setText( text );
329  return g;
330  }
331 #endif
332 
333  default:
334  Q_ASSERT( false );
335  return nullptr;
336  }
337 }
338 
339 //* 3D MODEL RENDERING *//
340 
341 
342 class QgsModelPoint3DSymbolHandler : public QgsFeature3DHandler
343 {
344  public:
345  QgsModelPoint3DSymbolHandler( const QgsPoint3DSymbol *symbol, const QgsFeatureIds &selectedIds )
346  : mSymbol( static_cast< QgsPoint3DSymbol * >( symbol->clone() ) )
347  , mSelectedIds( selectedIds ) {}
348 
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;
352 
353  private:
354 
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 );
358 
360  struct PointData
361  {
362  QVector<QVector3D> positions; // contains triplets of float x,y,z for each point
363  };
364 
365  void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected );
366 
367  // input specific for this class
368  std::unique_ptr< QgsPoint3DSymbol > mSymbol;
369  // inputs - generic
370  QgsFeatureIds mSelectedIds;
371 
372  // outputs
373  PointData outNormal;
374  PointData outSelected;
375 };
376 
377 bool QgsModelPoint3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
378 {
379  Q_UNUSED( context )
380  Q_UNUSED( attributeNames )
381  return true;
382 }
383 
384 void QgsModelPoint3DSymbolHandler::processFeature( QgsFeature &feature, const Qgs3DRenderContext &context )
385 {
386  PointData &out = mSelectedIds.contains( feature.id() ) ? outSelected : outNormal;
387 
388  if ( feature.geometry().isNull() )
389  return;
390 
391  Qgs3DUtils::extractPointPositions( feature, context.map(), mSymbol->altitudeClamping(), out.positions );
392 }
393 
394 void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
395 {
396  makeEntity( parent, context, outNormal, false );
397  makeEntity( parent, context, outSelected, true );
398 
399  updateZRangeFromPositions( outNormal.positions );
400  updateZRangeFromPositions( outSelected.positions );
401 
402  // the elevation offset is applied separately in QTransform added to sub-entities
403  float symbolHeight = mSymbol->transform().data()[13];
404  mZMin += symbolHeight;
405  mZMax += symbolHeight;
406 }
407 
408 void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected )
409 {
410  if ( selected )
411  {
412  addMeshEntities( context.map(), out.positions, mSymbol.get(), parent, true );
413  }
414  else
415  {
416  if ( mSymbol->shapeProperties()[QStringLiteral( "overwriteMaterial" )].toBool() )
417  {
418  addMeshEntities( context.map(), out.positions, mSymbol.get(), parent, false );
419  }
420  else
421  {
422  addSceneEntities( context.map(), out.positions, mSymbol.get(), parent );
423  }
424  }
425 }
426 
427 
428 
429 void QgsModelPoint3DSymbolHandler::addSceneEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
430 {
431  Q_UNUSED( map )
432  for ( const QVector3D &position : positions )
433  {
434  const QString source = QgsApplication::instance()->sourceCache()->localFilePath( symbol->shapeProperties()[QStringLiteral( "model" )].toString() );
435  // if the source is remote, the Qgs3DMapScene will take care of refreshing this 3D symbol when the source is fetched
436  if ( !source.isEmpty() )
437  {
438  // build the entity
439  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
440 
441  QUrl url = QUrl::fromLocalFile( source );
442  Qt3DRender::QSceneLoader *modelLoader = new Qt3DRender::QSceneLoader;
443  modelLoader->setSource( url );
444 
445  entity->addComponent( modelLoader );
446  entity->addComponent( transform( position, symbol ) );
447  entity->setParent( parent );
448 
449 // cppcheck wrongly believes entity will leak
450 // cppcheck-suppress memleak
451  }
452  }
453 }
454 
455 void QgsModelPoint3DSymbolHandler::addMeshEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, bool are_selected )
456 {
457  if ( positions.empty() )
458  return;
459 
460  // build the default material
461  QgsMaterialContext materialContext;
462  materialContext.setIsSelected( are_selected );
463  materialContext.setSelectionColor( map.selectionColor() );
464  Qt3DRender::QMaterial *mat = symbol->material()->toMaterial( QgsMaterialSettingsRenderingTechnique::Triangles, materialContext );
465 
466  // get nodes
467  for ( const QVector3D &position : positions )
468  {
469  const QString source = QgsApplication::instance()->sourceCache()->localFilePath( symbol->shapeProperties()[QStringLiteral( "model" )].toString() );
470  if ( !source.isEmpty() )
471  {
472  // build the entity
473  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
474 
475  QUrl url = QUrl::fromLocalFile( source );
476  Qt3DRender::QMesh *mesh = new Qt3DRender::QMesh;
477  mesh->setSource( url );
478 
479  entity->addComponent( mesh );
480  entity->addComponent( mat );
481  entity->addComponent( transform( position, symbol ) );
482  entity->setParent( parent );
483 
484 // cppcheck wrongly believes entity will leak
485 // cppcheck-suppress memleak
486  }
487  }
488 }
489 
490 Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position, const QgsPoint3DSymbol *symbol )
491 {
492  Qt3DCore::QTransform *tr = new Qt3DCore::QTransform;
493  tr->setMatrix( symbol->transform() );
494  tr->setTranslation( position + tr->translation() );
495  return tr;
496 }
497 
498 // --------------
499 
500 //* BILLBOARD RENDERING *//
501 
502 class QgsPoint3DBillboardSymbolHandler : public QgsFeature3DHandler
503 {
504  public:
505  QgsPoint3DBillboardSymbolHandler( const QgsPoint3DSymbol *symbol, const QgsFeatureIds &selectedIds )
506  : mSymbol( static_cast< QgsPoint3DSymbol * >( symbol->clone() ) )
507  , mSelectedIds( selectedIds ) {}
508 
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;
512 
513  private:
514 
516  struct PointData
517  {
518  QVector<QVector3D> positions; // contains triplets of float x,y,z for each point
519  };
520 
521  void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected );
522 
523  // input specific for this class
524  std::unique_ptr< QgsPoint3DSymbol > mSymbol;
525  // inputs - generic
526  QgsFeatureIds mSelectedIds;
527 
528  // outputs
529  PointData outNormal;
530  PointData outSelected;
531 };
532 
533 bool QgsPoint3DBillboardSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
534 {
535  Q_UNUSED( context )
536  Q_UNUSED( attributeNames )
537  return true;
538 }
539 
540 void QgsPoint3DBillboardSymbolHandler::processFeature( QgsFeature &feature, const Qgs3DRenderContext &context )
541 {
542  PointData &out = mSelectedIds.contains( feature.id() ) ? outSelected : outNormal;
543 
544  if ( feature.geometry().isNull() )
545  return;
546 
547  Qgs3DUtils::extractPointPositions( feature, context.map(), mSymbol->altitudeClamping(), out.positions );
548 }
549 
550 void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
551 {
552  makeEntity( parent, context, outNormal, false );
553  makeEntity( parent, context, outSelected, true );
554 
555  updateZRangeFromPositions( outNormal.positions );
556  updateZRangeFromPositions( outSelected.positions );
557 
558  // the elevation offset is applied externally through a QTransform of QEntity so let's account for it
559  float billboardHeight = mSymbol->transform().data()[13];
560  mZMin += billboardHeight;
561  mZMax += billboardHeight;
562 }
563 
564 void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected )
565 {
566  // Billboard Geometry
567  QgsBillboardGeometry *billboardGeometry = new QgsBillboardGeometry();
568  billboardGeometry->setPoints( out.positions );
569 
570  // Billboard Geometry Renderer
571  Qt3DRender::QGeometryRenderer *billboardGeometryRenderer = new Qt3DRender::QGeometryRenderer;
572  billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
573  billboardGeometryRenderer->setGeometry( billboardGeometry );
574  billboardGeometryRenderer->setVertexCount( billboardGeometry->count() );
575 
576  // Billboard Material
577  QgsPoint3DBillboardMaterial *billboardMaterial = new QgsPoint3DBillboardMaterial();
578  QgsMarkerSymbol *symbol = mSymbol->billboardSymbol();
579 
580  if ( symbol )
581  {
582  billboardMaterial->setTexture2DFromSymbol( symbol, context.map(), selected );
583  }
584  else
585  {
586  billboardMaterial->useDefaultSymbol( context.map(), selected );
587  }
588 
589  // Billboard Transform
590  Qt3DCore::QTransform *billboardTransform = new Qt3DCore::QTransform();
591  billboardTransform->setMatrix( mSymbol->billboardTransform() );
592 
593  // Build the entity
594  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
595 
596  entity->addComponent( billboardMaterial );
597  entity->addComponent( billboardTransform );
598  entity->addComponent( billboardGeometryRenderer );
599  entity->setParent( parent );
600 
601 // cppcheck wrongly believes entity will leak
602 // cppcheck-suppress memleak
603 }
604 
605 
606 namespace Qgs3DSymbolImpl
607 {
608 
609  QgsFeature3DHandler *handlerForPoint3DSymbol( QgsVectorLayer *layer, const QgsAbstract3DSymbol *symbol )
610  {
611  const QgsPoint3DSymbol *pointSymbol = dynamic_cast< const QgsPoint3DSymbol * >( symbol );
612  if ( !pointSymbol )
613  return nullptr;
614 
615  if ( pointSymbol->shape() == QgsPoint3DSymbol::Model )
616  return new QgsModelPoint3DSymbolHandler( pointSymbol, layer->selectedFeatureIds() );
617  // Add proper handler for billboard
618  else if ( pointSymbol->shape() == QgsPoint3DSymbol::Billboard )
619  return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->selectedFeatureIds() );
620  else
621  return new QgsInstancedPoint3DSymbolHandler( pointSymbol, layer->selectedFeatureIds() );
622  }
623 
624  Qt3DCore::QEntity *entityForPoint3DSymbol( const Qgs3DMapSettings &map, QgsVectorLayer *layer, const QgsPoint3DSymbol &symbol )
625  {
626  QgsFeature3DHandler *handler = handlerForPoint3DSymbol( layer, &symbol );
627  Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );
628  delete handler;
629  return e;
630  }
631 }
632 
qgssourcecache.h
QgsPoint3DBillboardMaterial
3 Material of the billboard rendering for points in 3D map view.
Definition: qgspoint3dbillboardmaterial.h:37
QgsFeature::id
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
QgsPoint3DSymbol::Cube
@ Cube
Definition: qgspoint3dsymbol.h:82
Qgs3DMapSettings::selectionColor
QColor selectionColor() const
Returns color used for selected features.
Definition: qgs3dmapsettings.cpp:425
QgsPoint3DBillboardMaterial::setTexture2DFromSymbol
void setTexture2DFromSymbol(QgsMarkerSymbol *markerSymbol, const Qgs3DMapSettings &map, bool selected=false)
Set markerSymbol for the texture with map and selected parameter for rendering.
Definition: qgspoint3dbillboardmaterial.cpp:122
QgsGeometry::isNull
Q_GADGET bool isNull
Definition: qgsgeometry.h:126
QgsPoint3DSymbol::Shape
Shape
3D shape types supported by the symbol
Definition: qgspoint3dsymbol.h:78
QgsSourceCache::localFilePath
QString localFilePath(const QString &path, bool blocking=false)
Returns a local file path reflecting the content of a specified source path.
Definition: qgssourcecache.cpp:64
qgssymbollayerutils.h
QgsMaterialContext::setSelectionColor
void setSelectionColor(const QColor &color)
Sets the color for representing materials in a selected state.
Definition: qgsabstractmaterialsettings.h:84
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:67
QgsPoint3DSymbol::Sphere
@ Sphere
Definition: qgspoint3dsymbol.h:80
QgsApplication::instance
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
Definition: qgsapplication.cpp:411
qgspoint.h
QgsPoint3DSymbol::material
QgsAbstractMaterialSettings * material() const
Returns material used for shading of the symbol.
Definition: qgspoint3dsymbol.cpp:166
qgspoint3dbillboardmaterial.h
qgsapplication.h
QgsMaterialContext
3 Context settings for a material.
Definition: qgsabstractmaterialsettings.h:55
QgsAbstract3DSymbol
3 Abstract base class for 3D symbols that are used by VectorLayer3DRenderer objects.
Definition: qgsabstract3dsymbol.h:46
QgsPoint3DSymbol::Cone
@ Cone
Definition: qgspoint3dsymbol.h:81
QgsBillboardGeometry::count
int count
Definition: qgsbillboardgeometry.h:38
qgs3dutils.h
QgsMarkerSymbol
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:931
QgsPoint3DSymbol::Model
@ Model
Definition: qgspoint3dsymbol.h:86
QgsVectorLayer::selectedFeatureIds
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
Definition: qgsvectorlayer.cpp:3441
qgssymbollayer.h
Qgs3DMapSettings
3 Definition of the world
Definition: qgs3dmapsettings.h:54
QgsApplication::sourceCache
static QgsSourceCache * sourceCache()
Returns the application's source cache, used for caching embedded and remote source strings as local ...
Definition: qgsapplication.cpp:2188
QgsPoint3DSymbol::Cylinder
@ Cylinder
Definition: qgspoint3dsymbol.h:79
QgsAbstractMaterialSettings::addParametersToEffect
virtual void addParametersToEffect(Qt3DRender::QEffect *effect) const =0
Adds parameters from the material to a destination effect.
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsPoint3DSymbol::Torus
@ Torus
Definition: qgspoint3dsymbol.h:83
qgsbillboardgeometry.h
qgsvectorlayer.h
QgsPoint3DSymbol::shape
Shape shape() const
Returns 3D shape for points.
Definition: qgspoint3dsymbol.h:96
QgsPoint3DSymbol::Plane
@ Plane
Definition: qgspoint3dsymbol.h:84
QgsBillboardGeometry
3 Geometry of the billboard rendering for points in 3D map view.
Definition: qgsbillboardgeometry.h:35
qgs3dmapsettings.h
QgsAbstractMaterialSettings::toMaterial
virtual Qt3DRender::QMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const =0
Creates a new QMaterial object representing the material settings.
QgsMaterialContext::setIsSelected
void setIsSelected(bool isSelected)
Sets whether the material should represent a selected state.
Definition: qgsabstractmaterialsettings.h:70
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
qgspoint3dsymbol.h
QgsPoint3DSymbol::ExtrudedText
@ ExtrudedText
Supported in Qt 5.9+.
Definition: qgspoint3dsymbol.h:85
QgsPoint3DSymbol::shapeProperties
QVariantMap shapeProperties() const
Returns a key-value dictionary of point shape properties.
Definition: qgspoint3dsymbol.h:101
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
Qgs3DUtils::extractPointPositions
static void extractPointPositions(QgsFeature &f, const Qgs3DMapSettings &map, Qgs3DTypes::AltitudeClamping altClamp, QVector< QVector3D > &positions)
Calculates (x,y,z) positions of (multi)point from the given feature.
Definition: qgs3dutils.cpp:346
QgsPoint3DSymbol::transform
QMatrix4x4 transform() const
Returns transform for individual objects represented by the symbol.
Definition: qgspoint3dsymbol.h:111
qgslogger.h
QgsPoint3DSymbol::Billboard
@ Billboard
Definition: qgspoint3dsymbol.h:87
qgssymbol.h
qgspoint3dsymbol_p.h
QgsPoint3DBillboardMaterial::useDefaultSymbol
void useDefaultSymbol(const Qgs3DMapSettings &map, bool selected=false)
Set default symbol for the texture with map and selected parameter for rendering.
Definition: qgspoint3dbillboardmaterial.cpp:115
QgsPoint3DSymbol::billboardSymbol
QgsMarkerSymbol * billboardSymbol() const
Returns a symbol for billboard.
Definition: qgspoint3dsymbol.h:106
QgsBillboardGeometry::setPoints
void setPoints(const QVector< QVector3D > &vertices)
Set the points for the billboard with vertices.
Definition: qgsbillboardgeometry.cpp:42
QgsPoint3DSymbol
3 3D symbol that draws point geometries as 3D objects using one of the predefined shapes.
Definition: qgspoint3dsymbol.h:39