QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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 "qgsvectorlayer.h"
48 #include "qgspoint.h"
49 #include "qgs3dutils.h"
50 #include "qgsbillboardgeometry.h"
52 #include "qgslogger.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( symbol ), mSelectedIds( selectedIds ) {}
68 
69  bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
70  void processFeature( QgsFeature &feature, const Qgs3DRenderContext &context ) override;
71  void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
72 
73  private:
74 
75  static Qt3DRender::QMaterial *material( const QgsPoint3DSymbol &symbol );
76  static Qt3DRender::QGeometryRenderer *renderer( const QgsPoint3DSymbol &symbol, const QVector<QVector3D> &positions );
77  static Qt3DRender::QGeometry *symbolGeometry( QgsPoint3DSymbol::Shape shape, const QVariantMap &shapeProperties );
78 
80  struct PointData
81  {
82  QVector<QVector3D> positions; // contains triplets of float x,y,z for each point
83  };
84 
85  void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected );
86 
87  // input specific for this class
88  const QgsPoint3DSymbol &mSymbol;
89  // inputs - generic
90  QgsFeatureIds mSelectedIds;
91 
92  // outputs
93  PointData outNormal;
94  PointData outSelected;
95 };
96 
97 
98 bool QgsInstancedPoint3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
99 {
100  Q_UNUSED( context )
101  Q_UNUSED( attributeNames )
102  return true;
103 }
104 
105 void QgsInstancedPoint3DSymbolHandler::processFeature( QgsFeature &feature, const Qgs3DRenderContext &context )
106 {
107  PointData &out = mSelectedIds.contains( feature.id() ) ? outSelected : outNormal;
108 
109  if ( feature.geometry().isNull() )
110  return;
111 
112  Qgs3DUtils::extractPointPositions( feature, context.map(), mSymbol.altitudeClamping(), out.positions );
113 }
114 
115 void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
116 {
117  makeEntity( parent, context, outNormal, false );
118  makeEntity( parent, context, outSelected, true );
119 
120  updateZRangeFromPositions( outNormal.positions );
121  updateZRangeFromPositions( outSelected.positions );
122 
123  // the elevation offset is applied in the vertex shader so let's account for it as well
124  float symbolHeight = mSymbol.transform().data()[13];
125  mZMin += symbolHeight;
126  mZMax += symbolHeight;
127 }
128 
129 void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected )
130 {
131  // build the default material
132  Qt3DRender::QMaterial *mat = material( mSymbol );
133 
134  if ( selected )
135  {
136  // update the material with selection colors
137  for ( Qt3DRender::QParameter *param : mat->effect()->parameters() )
138  {
139  if ( param->name() == QLatin1String( "kd" ) ) // diffuse
140  param->setValue( context.map().selectionColor() );
141  else if ( param->name() == QLatin1String( "ka" ) ) // ambient
142  param->setValue( context.map().selectionColor().darker() );
143  }
144  }
145 
146  // build the entity
147  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
148  entity->addComponent( renderer( mSymbol, out.positions ) );
149  entity->addComponent( mat );
150  entity->setParent( parent );
151 
152 // cppcheck wrongly believes entity will leak
153 // cppcheck-suppress memleak
154 }
155 
156 
157 
158 Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material( const QgsPoint3DSymbol &symbol )
159 {
160  Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey;
161  filterKey->setName( QStringLiteral( "renderingStyle" ) );
162  filterKey->setValue( "forward" );
163 
164  // the fragment shader implements a simplified version of phong shading that uses hardcoded light
165  // (instead of whatever light we have defined in the scene)
166  // TODO: use phong shading that respects lights from the scene
167  Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram;
168  shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/instanced.vert" ) ) ) );
169  shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/instanced.frag" ) ) ) );
170 
171  Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass;
172  renderPass->setShaderProgram( shaderProgram );
173 
174  Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
175  technique->addFilterKey( filterKey );
176  technique->addRenderPass( renderPass );
177  technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
178  technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
179  technique->graphicsApiFilter()->setMajorVersion( 3 );
180  technique->graphicsApiFilter()->setMinorVersion( 2 );
181 
182  Qt3DRender::QParameter *ambientParameter = new Qt3DRender::QParameter( QStringLiteral( "ka" ), QColor::fromRgbF( 0.05f, 0.05f, 0.05f, 1.0f ) );
183  Qt3DRender::QParameter *diffuseParameter = new Qt3DRender::QParameter( QStringLiteral( "kd" ), QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) );
184  Qt3DRender::QParameter *specularParameter = new Qt3DRender::QParameter( QStringLiteral( "ks" ), QColor::fromRgbF( 0.01f, 0.01f, 0.01f, 1.0f ) );
185  Qt3DRender::QParameter *shininessParameter = new Qt3DRender::QParameter( QStringLiteral( "shininess" ), 150.0f );
186 
187  diffuseParameter->setValue( symbol.material().diffuse() );
188  ambientParameter->setValue( symbol.material().ambient() );
189  specularParameter->setValue( symbol.material().specular() );
190  shininessParameter->setValue( symbol.material().shininess() );
191 
192  QMatrix4x4 transformMatrix = symbol.transform();
193  QMatrix3x3 normalMatrix = transformMatrix.normalMatrix(); // transponed inverse of 3x3 sub-matrix
194 
195  // QMatrix3x3 is not supported for passing to shaders, so we pass QMatrix4x4
196  float *n = normalMatrix.data();
197  QMatrix4x4 normalMatrix4(
198  n[0], n[3], n[6], 0,
199  n[1], n[4], n[7], 0,
200  n[2], n[5], n[8], 0,
201  0, 0, 0, 0 );
202 
203  Qt3DRender::QParameter *paramInst = new Qt3DRender::QParameter;
204  paramInst->setName( QStringLiteral( "inst" ) );
205  paramInst->setValue( transformMatrix );
206 
207  Qt3DRender::QParameter *paramInstNormal = new Qt3DRender::QParameter;
208  paramInstNormal->setName( QStringLiteral( "instNormal" ) );
209  paramInstNormal->setValue( normalMatrix4 );
210 
211  Qt3DRender::QEffect *effect = new Qt3DRender::QEffect;
212  effect->addTechnique( technique );
213  effect->addParameter( paramInst );
214  effect->addParameter( paramInstNormal );
215 
216  effect->addParameter( ambientParameter );
217  effect->addParameter( diffuseParameter );
218  effect->addParameter( specularParameter );
219  effect->addParameter( shininessParameter );
220 
221  Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial;
222  material->setEffect( effect );
223 
224  return material;
225 }
226 
227 Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer( const QgsPoint3DSymbol &symbol, const QVector<QVector3D> &positions )
228 {
229  int count = positions.count();
230  int byteCount = positions.count() * sizeof( QVector3D );
231  QByteArray ba;
232  ba.resize( byteCount );
233  memcpy( ba.data(), positions.constData(), byteCount );
234 
235 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
236  Qt3DRender::QBuffer *instanceBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer );
237 #else
238  Qt3DRender::QBuffer *instanceBuffer = new Qt3DRender::QBuffer();
239 #endif
240  instanceBuffer->setData( ba );
241 
242  Qt3DRender::QAttribute *instanceDataAttribute = new Qt3DRender::QAttribute;
243  instanceDataAttribute->setName( QStringLiteral( "pos" ) );
244  instanceDataAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
245  instanceDataAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
246  instanceDataAttribute->setVertexSize( 3 );
247  instanceDataAttribute->setDivisor( 1 );
248  instanceDataAttribute->setBuffer( instanceBuffer );
249  instanceDataAttribute->setCount( count );
250  instanceDataAttribute->setByteStride( 3 * sizeof( float ) );
251 
252  Qt3DRender::QGeometry *geometry = symbolGeometry( symbol.shape(), symbol.shapeProperties() );
253  geometry->addAttribute( instanceDataAttribute );
254  geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
255 
256  Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
257  renderer->setGeometry( geometry );
258  renderer->setInstanceCount( count );
259 
260  return renderer;
261 }
262 
263 Qt3DRender::QGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( QgsPoint3DSymbol::Shape shape, const QVariantMap &shapeProperties )
264 {
265  switch ( shape )
266  {
268  {
269  float radius = shapeProperties[QStringLiteral( "radius" )].toFloat();
270  float length = shapeProperties[QStringLiteral( "length" )].toFloat();
271  Qt3DExtras::QCylinderGeometry *g = new Qt3DExtras::QCylinderGeometry;
272  //g->setRings(2); // how many vertices vertically
273  //g->setSlices(8); // how many vertices on circumference
274  g->setRadius( radius ? radius : 10 );
275  g->setLength( length ? length : 10 );
276  return g;
277  }
278 
280  {
281  float radius = shapeProperties[QStringLiteral( "radius" )].toFloat();
282  Qt3DExtras::QSphereGeometry *g = new Qt3DExtras::QSphereGeometry;
283  g->setRadius( radius ? radius : 10 );
284  return g;
285  }
286 
288  {
289  float length = shapeProperties[QStringLiteral( "length" )].toFloat();
290  float bottomRadius = shapeProperties[QStringLiteral( "bottomRadius" )].toFloat();
291  float topRadius = shapeProperties[QStringLiteral( "topRadius" )].toFloat();
292  Qt3DExtras::QConeGeometry *g = new Qt3DExtras::QConeGeometry;
293  g->setLength( length ? length : 10 );
294  g->setBottomRadius( bottomRadius );
295  g->setTopRadius( topRadius );
296  //g->setHasBottomEndcap(hasBottomEndcap);
297  //g->setHasTopEndcap(hasTopEndcap);
298  return g;
299  }
300 
302  {
303  float size = shapeProperties[QStringLiteral( "size" )].toFloat();
304  Qt3DExtras::QCuboidGeometry *g = new Qt3DExtras::QCuboidGeometry;
305  g->setXExtent( size ? size : 10 );
306  g->setYExtent( size ? size : 10 );
307  g->setZExtent( size ? size : 10 );
308  return g;
309  }
310 
312  {
313  float radius = shapeProperties[QStringLiteral( "radius" )].toFloat();
314  float minorRadius = shapeProperties[QStringLiteral( "minorRadius" )].toFloat();
315  Qt3DExtras::QTorusGeometry *g = new Qt3DExtras::QTorusGeometry;
316  g->setRadius( radius ? radius : 10 );
317  g->setMinorRadius( minorRadius ? minorRadius : 5 );
318  return g;
319  }
320 
322  {
323  float size = shapeProperties[QStringLiteral( "size" )].toFloat();
324  Qt3DExtras::QPlaneGeometry *g = new Qt3DExtras::QPlaneGeometry;
325  g->setWidth( size ? size : 10 );
326  g->setHeight( size ? size : 10 );
327  return g;
328  }
329 
330 #if QT_VERSION >= 0x050900
332  {
333  float depth = shapeProperties[QStringLiteral( "depth" )].toFloat();
334  QString text = shapeProperties[QStringLiteral( "text" )].toString();
335  Qt3DExtras::QExtrudedTextGeometry *g = new Qt3DExtras::QExtrudedTextGeometry;
336  g->setDepth( depth ? depth : 1 );
337  g->setText( text );
338  return g;
339  }
340 #endif
341 
342  default:
343  Q_ASSERT( false );
344  return nullptr;
345  }
346 }
347 
348 //* 3D MODEL RENDERING *//
349 
350 
351 class QgsModelPoint3DSymbolHandler : public QgsFeature3DHandler
352 {
353  public:
354  QgsModelPoint3DSymbolHandler( const QgsPoint3DSymbol &symbol, const QgsFeatureIds &selectedIds )
355  : mSymbol( symbol ), mSelectedIds( selectedIds ) {}
356 
357  bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
358  void processFeature( QgsFeature &feature, const Qgs3DRenderContext &context ) override;
359  void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
360 
361  private:
362 
363  static void addSceneEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol &symbol, Qt3DCore::QEntity *parent );
364  static void addMeshEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol &symbol, Qt3DCore::QEntity *parent, bool are_selected );
365  static Qt3DCore::QTransform *transform( QVector3D position, const QgsPoint3DSymbol &symbol );
366 
368  struct PointData
369  {
370  QVector<QVector3D> positions; // contains triplets of float x,y,z for each point
371  };
372 
373  void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected );
374 
375  // input specific for this class
376  const QgsPoint3DSymbol &mSymbol;
377  // inputs - generic
378  QgsFeatureIds mSelectedIds;
379 
380  // outputs
381  PointData outNormal;
382  PointData outSelected;
383 };
384 
385 bool QgsModelPoint3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
386 {
387  Q_UNUSED( context )
388  Q_UNUSED( attributeNames )
389  return true;
390 }
391 
392 void QgsModelPoint3DSymbolHandler::processFeature( QgsFeature &feature, const Qgs3DRenderContext &context )
393 {
394  PointData &out = mSelectedIds.contains( feature.id() ) ? outSelected : outNormal;
395 
396  if ( feature.geometry().isNull() )
397  return;
398 
399  Qgs3DUtils::extractPointPositions( feature, context.map(), mSymbol.altitudeClamping(), out.positions );
400 }
401 
402 void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
403 {
404  makeEntity( parent, context, outNormal, false );
405  makeEntity( parent, context, outSelected, true );
406 
407  updateZRangeFromPositions( outNormal.positions );
408  updateZRangeFromPositions( outSelected.positions );
409 
410  // the elevation offset is applied separately in QTransform added to sub-entities
411  float symbolHeight = mSymbol.transform().data()[13];
412  mZMin += symbolHeight;
413  mZMax += symbolHeight;
414 }
415 
416 void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected )
417 {
418  if ( selected )
419  {
420  addMeshEntities( context.map(), out.positions, mSymbol, parent, true );
421  }
422  else
423  {
424  if ( mSymbol.shapeProperties()[QStringLiteral( "overwriteMaterial" )].toBool() )
425  {
426  addMeshEntities( context.map(), out.positions, mSymbol, parent, false );
427  }
428  else
429  {
430  addSceneEntities( context.map(), out.positions, mSymbol, parent );
431  }
432  }
433 }
434 
435 
436 
437 void QgsModelPoint3DSymbolHandler::addSceneEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol &symbol, Qt3DCore::QEntity *parent )
438 {
439  Q_UNUSED( map )
440  for ( const QVector3D &position : positions )
441  {
442  // build the entity
443  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
444 
445  QUrl url = QUrl::fromLocalFile( symbol.shapeProperties()[QStringLiteral( "model" )].toString() );
446  Qt3DRender::QSceneLoader *modelLoader = new Qt3DRender::QSceneLoader;
447  modelLoader->setSource( url );
448 
449  entity->addComponent( modelLoader );
450  entity->addComponent( transform( position, symbol ) );
451  entity->setParent( parent );
452 
453 // cppcheck wrongly believes entity will leak
454 // cppcheck-suppress memleak
455  }
456 }
457 
458 void QgsModelPoint3DSymbolHandler::addMeshEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol &symbol, Qt3DCore::QEntity *parent, bool are_selected )
459 {
460  // build the default material
461  Qt3DExtras::QPhongMaterial *mat = Qgs3DUtils::phongMaterial( symbol.material() );
462 
463  if ( are_selected )
464  {
465  mat->setDiffuse( map.selectionColor() );
466  mat->setAmbient( map.selectionColor().darker() );
467  }
468 
469  // get nodes
470  for ( const QVector3D &position : positions )
471  {
472  // build the entity
473  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
474 
475  QUrl url = QUrl::fromLocalFile( symbol.shapeProperties()[QStringLiteral( "model" )].toString() );
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 Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position, const QgsPoint3DSymbol &symbol )
490 {
491  Qt3DCore::QTransform *tr = new Qt3DCore::QTransform;
492  tr->setMatrix( symbol.transform() );
493  tr->setTranslation( position + tr->translation() );
494  return tr;
495 }
496 
497 // --------------
498 
499 //* BILLBOARD RENDERING *//
500 
501 class QgsPoint3DBillboardSymbolHandler : public QgsFeature3DHandler
502 {
503  public:
504  QgsPoint3DBillboardSymbolHandler( const QgsPoint3DSymbol &symbol, const QgsFeatureIds &selectedIds )
505  : mSymbol( symbol ), mSelectedIds( selectedIds ) {}
506 
507  bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
508  void processFeature( QgsFeature &feature, const Qgs3DRenderContext &context ) override;
509  void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
510 
511  private:
512 
514  struct PointData
515  {
516  QVector<QVector3D> positions; // contains triplets of float x,y,z for each point
517  };
518 
519  void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected );
520 
521  // input specific for this class
522  const QgsPoint3DSymbol &mSymbol;
523  // inputs - generic
524  QgsFeatureIds mSelectedIds;
525 
526  // outputs
527  PointData outNormal;
528  PointData outSelected;
529 };
530 
531 bool QgsPoint3DBillboardSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
532 {
533  Q_UNUSED( context )
534  Q_UNUSED( attributeNames )
535  return true;
536 }
537 
538 void QgsPoint3DBillboardSymbolHandler::processFeature( QgsFeature &feature, const Qgs3DRenderContext &context )
539 {
540  PointData &out = mSelectedIds.contains( feature.id() ) ? outSelected : outNormal;
541 
542  if ( feature.geometry().isNull() )
543  return;
544 
545  Qgs3DUtils::extractPointPositions( feature, context.map(), mSymbol.altitudeClamping(), out.positions );
546 }
547 
548 void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
549 {
550  makeEntity( parent, context, outNormal, false );
551  makeEntity( parent, context, outSelected, true );
552 
553  updateZRangeFromPositions( outNormal.positions );
554  updateZRangeFromPositions( outSelected.positions );
555 
556  // the elevation offset is applied externally through a QTransform of QEntity so let's account for it
557  float billboardHeight = mSymbol.transform().data()[13];
558  mZMin += billboardHeight;
559  mZMax += billboardHeight;
560 }
561 
562 void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected )
563 {
564  // Billboard Geometry
565  QgsBillboardGeometry *billboardGeometry = new QgsBillboardGeometry();
566  billboardGeometry->setPoints( out.positions );
567 
568  // Billboard Geometry Renderer
569  Qt3DRender::QGeometryRenderer *billboardGeometryRenderer = new Qt3DRender::QGeometryRenderer;
570  billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
571  billboardGeometryRenderer->setGeometry( billboardGeometry );
572  billboardGeometryRenderer->setVertexCount( billboardGeometry->count() );
573 
574  // Billboard Material
575  QgsPoint3DBillboardMaterial *billboardMaterial = new QgsPoint3DBillboardMaterial();
576  QgsMarkerSymbol *symbol = mSymbol.billboardSymbol();
577 
578  if ( symbol )
579  {
580  billboardMaterial->setTexture2DFromSymbol( symbol, context.map(), selected );
581  }
582  else
583  {
584  billboardMaterial->useDefaultSymbol( context.map(), selected );
585  }
586 
587  // Billboard Transform
588  Qt3DCore::QTransform *billboardTransform = new Qt3DCore::QTransform();
589  billboardTransform->setMatrix( mSymbol.billboardTransform() );
590 
591  // Build the entity
592  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
593 
594  entity->addComponent( billboardMaterial );
595  entity->addComponent( billboardTransform );
596  entity->addComponent( billboardGeometryRenderer );
597  entity->setParent( parent );
598 
599 // cppcheck wrongly believes entity will leak
600 // cppcheck-suppress memleak
601 }
602 
603 
604 namespace Qgs3DSymbolImpl
605 {
606 
607  QgsFeature3DHandler *handlerForPoint3DSymbol( QgsVectorLayer *layer, const QgsPoint3DSymbol &symbol )
608  {
609  if ( symbol.shape() == QgsPoint3DSymbol::Model )
610  return new QgsModelPoint3DSymbolHandler( symbol, layer->selectedFeatureIds() );
611  // Add proper handler for billboard
612  else if ( symbol.shape() == QgsPoint3DSymbol::Billboard )
613  return new QgsPoint3DBillboardSymbolHandler( symbol, layer->selectedFeatureIds() );
614  else
615  return new QgsInstancedPoint3DSymbolHandler( symbol, layer->selectedFeatureIds() );
616  }
617 
618  Qt3DCore::QEntity *entityForPoint3DSymbol( const Qgs3DMapSettings &map, QgsVectorLayer *layer, const QgsPoint3DSymbol &symbol )
619  {
620  QgsFeature3DHandler *handler = handlerForPoint3DSymbol( layer, symbol );
621  Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );
622  delete handler;
623  return e;
624  }
625 }
626 
QgsPoint3DSymbol::material
QgsPhongMaterialSettings material() const
Returns material used for shading of the symbol.
Definition: qgspoint3dsymbol.h:71
QgsPhongMaterialSettings::ambient
QColor ambient() const
Returns ambient color component.
Definition: qgsphongmaterialsettings.h:46
QgsPoint3DBillboardMaterial
Definition: qgspoint3dbillboardmaterial.h:36
QgsPhongMaterialSettings::diffuse
QColor diffuse() const
Returns diffuse color component.
Definition: qgsphongmaterialsettings.h:48
QgsPhongMaterialSettings::specular
QColor specular() const
Returns specular color component.
Definition: qgsphongmaterialsettings.h:50
QgsPoint3DSymbol::Cube
@ Cube
Definition: qgspoint3dsymbol.h:81
Qgs3DMapSettings::selectionColor
QColor selectionColor() const
Returns color used for selected features.
Definition: qgs3dmapsettings.cpp:362
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
QgsPoint3DSymbol::Shape
Shape
3D shape types supported by the symbol
Definition: qgspoint3dsymbol.h:76
qgssymbollayerutils.h
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsPoint3DSymbol::Sphere
@ Sphere
Definition: qgspoint3dsymbol.h:79
qgspoint.h
qgspoint3dbillboardmaterial.h
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsPoint3DSymbol::Cone
@ Cone
Definition: qgspoint3dsymbol.h:80
QgsBillboardGeometry::count
int count
Definition: qgsbillboardgeometry.h:38
qgs3dutils.h
QgsMarkerSymbol
Definition: qgssymbol.h:917
QgsPoint3DSymbol::Model
@ Model
Definition: qgspoint3dsymbol.h:85
QgsVectorLayer::selectedFeatureIds
const Q_INVOKABLE QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
Definition: qgsvectorlayer.cpp:3433
qgssymbollayer.h
Qgs3DMapSettings
Definition: qgs3dmapsettings.h:51
QgsGeometry::isNull
bool isNull
Definition: qgsgeometry.h:125
QgsPoint3DSymbol::Cylinder
@ Cylinder
Definition: qgspoint3dsymbol.h:78
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:34
QgsPoint3DSymbol::Torus
@ Torus
Definition: qgspoint3dsymbol.h:82
qgsbillboardgeometry.h
qgsvectorlayer.h
QgsPoint3DSymbol::shape
Shape shape() const
Returns 3D shape for points.
Definition: qgspoint3dsymbol.h:95
QgsPoint3DSymbol::Plane
@ Plane
Definition: qgspoint3dsymbol.h:83
QgsBillboardGeometry
Definition: qgsbillboardgeometry.h:34
qgs3dmapsettings.h
QgsVectorLayer
Definition: qgsvectorlayer.h:385
Qgs3DUtils::phongMaterial
static Qt3DExtras::QPhongMaterial * phongMaterial(const QgsPhongMaterialSettings &settings)
Returns phong material object based on the material settings.
Definition: qgs3dutils.cpp:575
qgspoint3dsymbol.h
QgsPoint3DSymbol::ExtrudedText
@ ExtrudedText
Supported in Qt 5.9+.
Definition: qgspoint3dsymbol.h:84
QgsPoint3DSymbol::shapeProperties
QVariantMap shapeProperties() const
Returns a key-value dictionary of point shape properties.
Definition: qgspoint3dsymbol.h:100
QgsPhongMaterialSettings::shininess
float shininess() const
Returns shininess of the surface.
Definition: qgsphongmaterialsettings.h:52
QgsFeature
Definition: qgsfeature.h:55
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:110
qgslogger.h
QgsPoint3DSymbol::Billboard
@ Billboard
Definition: qgspoint3dsymbol.h:86
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:105
QgsBillboardGeometry::setPoints
void setPoints(const QVector< QVector3D > &vertices)
Set the points for the billboard with vertices.
Definition: qgsbillboardgeometry.cpp:40
QgsPoint3DSymbol
Definition: qgspoint3dsymbol.h:37