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