QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
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 
153 
154 
155 Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material( const QgsPoint3DSymbol &symbol )
156 {
157  Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey;
158  filterKey->setName( QStringLiteral( "renderingStyle" ) );
159  filterKey->setValue( "forward" );
160 
161  // the fragment shader implements a simplified version of phong shading that uses hardcoded light
162  // (instead of whatever light we have defined in the scene)
163  // TODO: use phong shading that respects lights from the scene
164  Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram;
165  shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/instanced.vert" ) ) ) );
166  shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/instanced.frag" ) ) ) );
167 
168  Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass;
169  renderPass->setShaderProgram( shaderProgram );
170 
171  Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
172  technique->addFilterKey( filterKey );
173  technique->addRenderPass( renderPass );
174  technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
175  technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
176  technique->graphicsApiFilter()->setMajorVersion( 3 );
177  technique->graphicsApiFilter()->setMinorVersion( 2 );
178 
179  Qt3DRender::QParameter *ambientParameter = new Qt3DRender::QParameter( QStringLiteral( "ka" ), QColor::fromRgbF( 0.05f, 0.05f, 0.05f, 1.0f ) );
180  Qt3DRender::QParameter *diffuseParameter = new Qt3DRender::QParameter( QStringLiteral( "kd" ), QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) );
181  Qt3DRender::QParameter *specularParameter = new Qt3DRender::QParameter( QStringLiteral( "ks" ), QColor::fromRgbF( 0.01f, 0.01f, 0.01f, 1.0f ) );
182  Qt3DRender::QParameter *shininessParameter = new Qt3DRender::QParameter( QStringLiteral( "shininess" ), 150.0f );
183 
184  diffuseParameter->setValue( symbol.material().diffuse() );
185  ambientParameter->setValue( symbol.material().ambient() );
186  specularParameter->setValue( symbol.material().specular() );
187  shininessParameter->setValue( symbol.material().shininess() );
188 
189  QMatrix4x4 transformMatrix = symbol.transform();
190  QMatrix3x3 normalMatrix = transformMatrix.normalMatrix(); // transponed inverse of 3x3 sub-matrix
191 
192  // QMatrix3x3 is not supported for passing to shaders, so we pass QMatrix4x4
193  float *n = normalMatrix.data();
194  QMatrix4x4 normalMatrix4(
195  n[0], n[3], n[6], 0,
196  n[1], n[4], n[7], 0,
197  n[2], n[5], n[8], 0,
198  0, 0, 0, 0 );
199 
200  Qt3DRender::QParameter *paramInst = new Qt3DRender::QParameter;
201  paramInst->setName( QStringLiteral( "inst" ) );
202  paramInst->setValue( transformMatrix );
203 
204  Qt3DRender::QParameter *paramInstNormal = new Qt3DRender::QParameter;
205  paramInstNormal->setName( QStringLiteral( "instNormal" ) );
206  paramInstNormal->setValue( normalMatrix4 );
207 
208  Qt3DRender::QEffect *effect = new Qt3DRender::QEffect;
209  effect->addTechnique( technique );
210  effect->addParameter( paramInst );
211  effect->addParameter( paramInstNormal );
212 
213  effect->addParameter( ambientParameter );
214  effect->addParameter( diffuseParameter );
215  effect->addParameter( specularParameter );
216  effect->addParameter( shininessParameter );
217 
218  Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial;
219  material->setEffect( effect );
220 
221  return material;
222 }
223 
224 Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer( const QgsPoint3DSymbol &symbol, const QVector<QVector3D> &positions )
225 {
226  int count = positions.count();
227  int byteCount = positions.count() * sizeof( QVector3D );
228  QByteArray ba;
229  ba.resize( byteCount );
230  memcpy( ba.data(), positions.constData(), byteCount );
231 
232 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
233  Qt3DRender::QBuffer *instanceBuffer = new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer );
234 #else
235  Qt3DRender::QBuffer *instanceBuffer = new Qt3DRender::QBuffer();
236 #endif
237  instanceBuffer->setData( ba );
238 
239  Qt3DRender::QAttribute *instanceDataAttribute = new Qt3DRender::QAttribute;
240  instanceDataAttribute->setName( QStringLiteral( "pos" ) );
241  instanceDataAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
242  instanceDataAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
243  instanceDataAttribute->setVertexSize( 3 );
244  instanceDataAttribute->setDivisor( 1 );
245  instanceDataAttribute->setBuffer( instanceBuffer );
246  instanceDataAttribute->setCount( count );
247  instanceDataAttribute->setByteStride( 3 * sizeof( float ) );
248 
249  Qt3DRender::QGeometry *geometry = symbolGeometry( symbol.shape(), symbol.shapeProperties() );
250  geometry->addAttribute( instanceDataAttribute );
251  geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
252 
253  Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
254  renderer->setGeometry( geometry );
255  renderer->setInstanceCount( count );
256 
257  return renderer;
258 }
259 
260 Qt3DRender::QGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( QgsPoint3DSymbol::Shape shape, const QVariantMap &shapeProperties )
261 {
262  switch ( shape )
263  {
265  {
266  float radius = shapeProperties[QStringLiteral( "radius" )].toFloat();
267  float length = shapeProperties[QStringLiteral( "length" )].toFloat();
268  Qt3DExtras::QCylinderGeometry *g = new Qt3DExtras::QCylinderGeometry;
269  //g->setRings(2); // how many vertices vertically
270  //g->setSlices(8); // how many vertices on circumference
271  g->setRadius( radius ? radius : 10 );
272  g->setLength( length ? length : 10 );
273  return g;
274  }
275 
277  {
278  float radius = shapeProperties[QStringLiteral( "radius" )].toFloat();
279  Qt3DExtras::QSphereGeometry *g = new Qt3DExtras::QSphereGeometry;
280  g->setRadius( radius ? radius : 10 );
281  return g;
282  }
283 
285  {
286  float length = shapeProperties[QStringLiteral( "length" )].toFloat();
287  float bottomRadius = shapeProperties[QStringLiteral( "bottomRadius" )].toFloat();
288  float topRadius = shapeProperties[QStringLiteral( "topRadius" )].toFloat();
289  Qt3DExtras::QConeGeometry *g = new Qt3DExtras::QConeGeometry;
290  g->setLength( length ? length : 10 );
291  g->setBottomRadius( bottomRadius );
292  g->setTopRadius( topRadius );
293  //g->setHasBottomEndcap(hasBottomEndcap);
294  //g->setHasTopEndcap(hasTopEndcap);
295  return g;
296  }
297 
299  {
300  float size = shapeProperties[QStringLiteral( "size" )].toFloat();
301  Qt3DExtras::QCuboidGeometry *g = new Qt3DExtras::QCuboidGeometry;
302  g->setXExtent( size ? size : 10 );
303  g->setYExtent( size ? size : 10 );
304  g->setZExtent( size ? size : 10 );
305  return g;
306  }
307 
309  {
310  float radius = shapeProperties[QStringLiteral( "radius" )].toFloat();
311  float minorRadius = shapeProperties[QStringLiteral( "minorRadius" )].toFloat();
312  Qt3DExtras::QTorusGeometry *g = new Qt3DExtras::QTorusGeometry;
313  g->setRadius( radius ? radius : 10 );
314  g->setMinorRadius( minorRadius ? minorRadius : 5 );
315  return g;
316  }
317 
319  {
320  float size = shapeProperties[QStringLiteral( "size" )].toFloat();
321  Qt3DExtras::QPlaneGeometry *g = new Qt3DExtras::QPlaneGeometry;
322  g->setWidth( size ? size : 10 );
323  g->setHeight( size ? size : 10 );
324  return g;
325  }
326 
327 #if QT_VERSION >= 0x050900
329  {
330  float depth = shapeProperties[QStringLiteral( "depth" )].toFloat();
331  QString text = shapeProperties[QStringLiteral( "text" )].toString();
332  Qt3DExtras::QExtrudedTextGeometry *g = new Qt3DExtras::QExtrudedTextGeometry;
333  g->setDepth( depth ? depth : 1 );
334  g->setText( text );
335  return g;
336  }
337 #endif
338 
339  default:
340  Q_ASSERT( false );
341  return nullptr;
342  }
343 }
344 
345 //* 3D MODEL RENDERING *//
346 
347 
348 class QgsModelPoint3DSymbolHandler : public QgsFeature3DHandler
349 {
350  public:
351  QgsModelPoint3DSymbolHandler( const QgsPoint3DSymbol &symbol, const QgsFeatureIds &selectedIds )
352  : mSymbol( symbol ), mSelectedIds( selectedIds ) {}
353 
354  bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
355  void processFeature( QgsFeature &feature, const Qgs3DRenderContext &context ) override;
356  void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
357 
358  private:
359 
360  static void addSceneEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol &symbol, Qt3DCore::QEntity *parent );
361  static void addMeshEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol &symbol, Qt3DCore::QEntity *parent, bool are_selected );
362  static Qt3DCore::QTransform *transform( QVector3D position, const QgsPoint3DSymbol &symbol );
363 
365  struct PointData
366  {
367  QVector<QVector3D> positions; // contains triplets of float x,y,z for each point
368  };
369 
370  void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected );
371 
372  // input specific for this class
373  const QgsPoint3DSymbol &mSymbol;
374  // inputs - generic
375  QgsFeatureIds mSelectedIds;
376 
377  // outputs
378  PointData outNormal;
379  PointData outSelected;
380 };
381 
382 bool QgsModelPoint3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
383 {
384  Q_UNUSED( context )
385  Q_UNUSED( attributeNames )
386  return true;
387 }
388 
389 void QgsModelPoint3DSymbolHandler::processFeature( QgsFeature &feature, const Qgs3DRenderContext &context )
390 {
391  PointData &out = mSelectedIds.contains( feature.id() ) ? outSelected : outNormal;
392 
393  if ( feature.geometry().isNull() )
394  return;
395 
396  Qgs3DUtils::extractPointPositions( feature, context.map(), mSymbol.altitudeClamping(), out.positions );
397 }
398 
399 void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
400 {
401  makeEntity( parent, context, outNormal, false );
402  makeEntity( parent, context, outSelected, true );
403 
404  updateZRangeFromPositions( outNormal.positions );
405  updateZRangeFromPositions( outSelected.positions );
406 
407  // the elevation offset is applied separately in QTransform added to sub-entities
408  float symbolHeight = mSymbol.transform().data()[13];
409  mZMin += symbolHeight;
410  mZMax += symbolHeight;
411 }
412 
413 void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected )
414 {
415  if ( selected )
416  {
417  addMeshEntities( context.map(), out.positions, mSymbol, parent, true );
418  }
419  else
420  {
421  if ( mSymbol.shapeProperties()[QStringLiteral( "overwriteMaterial" )].toBool() )
422  {
423  addMeshEntities( context.map(), out.positions, mSymbol, parent, false );
424  }
425  else
426  {
427  addSceneEntities( context.map(), out.positions, mSymbol, parent );
428  }
429  }
430 }
431 
432 
433 
434 void QgsModelPoint3DSymbolHandler::addSceneEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol &symbol, Qt3DCore::QEntity *parent )
435 {
436  Q_UNUSED( map )
437  for ( const QVector3D &position : positions )
438  {
439  // build the entity
440  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
441 
442  QUrl url = QUrl::fromLocalFile( symbol.shapeProperties()[QStringLiteral( "model" )].toString() );
443  Qt3DRender::QSceneLoader *modelLoader = new Qt3DRender::QSceneLoader;
444  modelLoader->setSource( url );
445 
446  entity->addComponent( modelLoader );
447  entity->addComponent( transform( position, symbol ) );
448  entity->setParent( parent );
449  }
450 }
451 
452 void QgsModelPoint3DSymbolHandler::addMeshEntities( const Qgs3DMapSettings &map, const QVector<QVector3D> &positions, const QgsPoint3DSymbol &symbol, Qt3DCore::QEntity *parent, bool are_selected )
453 {
454  // build the default material
455  Qt3DExtras::QPhongMaterial *mat = Qgs3DUtils::phongMaterial( symbol.material() );
456 
457  if ( are_selected )
458  {
459  mat->setDiffuse( map.selectionColor() );
460  mat->setAmbient( map.selectionColor().darker() );
461  }
462 
463  // get nodes
464  for ( const QVector3D &position : positions )
465  {
466  // build the entity
467  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
468 
469  QUrl url = QUrl::fromLocalFile( symbol.shapeProperties()[QStringLiteral( "model" )].toString() );
470  Qt3DRender::QMesh *mesh = new Qt3DRender::QMesh;
471  mesh->setSource( url );
472 
473  entity->addComponent( mesh );
474  entity->addComponent( mat );
475  entity->addComponent( transform( position, symbol ) );
476  entity->setParent( parent );
477  }
478 }
479 
480 Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position, const QgsPoint3DSymbol &symbol )
481 {
482  Qt3DCore::QTransform *tr = new Qt3DCore::QTransform;
483  tr->setMatrix( symbol.transform() );
484  tr->setTranslation( position + tr->translation() );
485  return tr;
486 }
487 
488 // --------------
489 
490 //* BILLBOARD RENDERING *//
491 
492 class QgsPoint3DBillboardSymbolHandler : public QgsFeature3DHandler
493 {
494  public:
495  QgsPoint3DBillboardSymbolHandler( const QgsPoint3DSymbol &symbol, const QgsFeatureIds &selectedIds )
496  : mSymbol( symbol ), mSelectedIds( selectedIds ) {}
497 
498  bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
499  void processFeature( QgsFeature &feature, const Qgs3DRenderContext &context ) override;
500  void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
501 
502  private:
503 
505  struct PointData
506  {
507  QVector<QVector3D> positions; // contains triplets of float x,y,z for each point
508  };
509 
510  void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected );
511 
512  // input specific for this class
513  const QgsPoint3DSymbol &mSymbol;
514  // inputs - generic
515  QgsFeatureIds mSelectedIds;
516 
517  // outputs
518  PointData outNormal;
519  PointData outSelected;
520 };
521 
522 bool QgsPoint3DBillboardSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
523 {
524  Q_UNUSED( context )
525  Q_UNUSED( attributeNames )
526  return true;
527 }
528 
529 void QgsPoint3DBillboardSymbolHandler::processFeature( QgsFeature &feature, const Qgs3DRenderContext &context )
530 {
531  PointData &out = mSelectedIds.contains( feature.id() ) ? outSelected : outNormal;
532 
533  if ( feature.geometry().isNull() )
534  return;
535 
536  Qgs3DUtils::extractPointPositions( feature, context.map(), mSymbol.altitudeClamping(), out.positions );
537 }
538 
539 void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
540 {
541  makeEntity( parent, context, outNormal, false );
542  makeEntity( parent, context, outSelected, true );
543 
544  updateZRangeFromPositions( outNormal.positions );
545  updateZRangeFromPositions( outSelected.positions );
546 
547  // the elevation offset is applied externally through a QTransform of QEntity so let's account for it
548  float billboardHeight = mSymbol.transform().data()[13];
549  mZMin += billboardHeight;
550  mZMax += billboardHeight;
551 }
552 
553 void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, PointData &out, bool selected )
554 {
555  // Billboard Geometry
556  QgsBillboardGeometry *billboardGeometry = new QgsBillboardGeometry();
557  billboardGeometry->setPoints( out.positions );
558 
559  // Billboard Geometry Renderer
560  Qt3DRender::QGeometryRenderer *billboardGeometryRenderer = new Qt3DRender::QGeometryRenderer;
561  billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
562  billboardGeometryRenderer->setGeometry( billboardGeometry );
563  billboardGeometryRenderer->setVertexCount( billboardGeometry->count() );
564 
565  // Billboard Material
566  QgsPoint3DBillboardMaterial *billboardMaterial = new QgsPoint3DBillboardMaterial();
567  QgsMarkerSymbol *symbol = mSymbol.billboardSymbol();
568 
569  if ( symbol )
570  {
571  billboardMaterial->setTexture2DFromSymbol( symbol, context.map(), selected );
572  }
573  else
574  {
575  billboardMaterial->useDefaultSymbol( context.map(), selected );
576  }
577 
578  // Billboard Transform
579  Qt3DCore::QTransform *billboardTransform = new Qt3DCore::QTransform();
580  billboardTransform->setMatrix( mSymbol.billboardTransform() );
581 
582  // Build the entity
583  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
584 
585  entity->addComponent( billboardMaterial );
586  entity->addComponent( billboardTransform );
587  entity->addComponent( billboardGeometryRenderer );
588  entity->setParent( parent );
589 }
590 
591 
592 namespace Qgs3DSymbolImpl
593 {
594 
595  QgsFeature3DHandler *handlerForPoint3DSymbol( QgsVectorLayer *layer, const QgsPoint3DSymbol &symbol )
596  {
597  if ( symbol.shape() == QgsPoint3DSymbol::Model )
598  return new QgsModelPoint3DSymbolHandler( symbol, layer->selectedFeatureIds() );
599  // Add proper handler for billboard
600  else if ( symbol.shape() == QgsPoint3DSymbol::Billboard )
601  return new QgsPoint3DBillboardSymbolHandler( symbol, layer->selectedFeatureIds() );
602  else
603  return new QgsInstancedPoint3DSymbolHandler( symbol, layer->selectedFeatureIds() );
604  }
605 
606  Qt3DCore::QEntity *entityForPoint3DSymbol( const Qgs3DMapSettings &map, QgsVectorLayer *layer, const QgsPoint3DSymbol &symbol )
607  {
608  QgsFeature3DHandler *handler = handlerForPoint3DSymbol( layer, symbol );
609  Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );
610  delete handler;
611  return e;
612  }
613 }
614 
3 Material of the billboard rendering for points in 3D map view.
QgsFeatureId id
Definition: qgsfeature.h:64
float shininess() const
Returns shininess of the surface.
void useDefaultSymbol(const Qgs3DMapSettings &map, bool selected=false)
Set default symbol for the texture with map and selected parameter for rendering. ...
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:34
QColor selectionColor() const
Returns color used for selected features.
QColor specular() const
Returns specular color component.
static Qt3DExtras::QPhongMaterial * phongMaterial(const QgsPhongMaterialSettings &settings)
Returns phong material object based on the material settings.
Definition: qgs3dutils.cpp:575
Shape shape() const
Returns 3D shape for points.
3 Geometry of the billboard rendering for points in 3D map view.
QVariantMap shapeProperties() const
Returns a key-value dictionary of point shape properties.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
Supported in Qt 5.9+.
3 Definition of the world
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:895
QMatrix4x4 transform() const
Returns transform for individual objects represented by the symbol.
void setTexture2DFromSymbol(QgsMarkerSymbol *markerSymbol, const Qgs3DMapSettings &map, bool selected=false)
Set markerSymbol for the texture with map and selected parameter for rendering.
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
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
3 3D symbol that draws point geometries as 3D objects using one of the predefined shapes...
QgsPhongMaterialSettings material() const
Returns material used for shading of the symbol.
QgsMarkerSymbol * billboardSymbol() const
Returns a symbol for billboard.
Shape
3D shape types supported by the symbol
void setPoints(const QVector< QVector3D > &vertices)
Set the points for the billboard with vertices.
QColor ambient() const
Returns ambient color component.
QColor diffuse() const
Returns diffuse color component.
QgsGeometry geometry
Definition: qgsfeature.h:67
Represents a vector layer which manages a vector based data sets.