18#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
   19#include <Qt3DRender/QAttribute> 
   20#include <Qt3DRender/QBuffer> 
   21#include <Qt3DRender/QGeometry> 
   22#include <Qt3DCore/QTransform> 
   28#include <Qt3DCore/QAttribute> 
   29#include <Qt3DCore/QBuffer> 
   30#include <Qt3DCore/QGeometry> 
   37#include <Qt3DRender/QEffect> 
   38#include <Qt3DRender/QGraphicsApiFilter> 
   39#include <Qt3DRender/QParameter> 
   40#include <Qt3DRender/QTechnique> 
   42#include <Qt3DExtras/QCylinderGeometry> 
   43#include <Qt3DExtras/QConeGeometry> 
   44#include <Qt3DExtras/QCuboidGeometry> 
   45#include <Qt3DExtras/QPlaneGeometry> 
   46#include <Qt3DExtras/QSphereGeometry> 
   47#include <Qt3DExtras/QTorusGeometry> 
   48#include <Qt3DExtras/QPhongMaterial> 
   49#include <Qt3DRender/QSceneLoader> 
   50#include <Qt3DRender/QPaintedTextureImage> 
   52#include <Qt3DRender/QMesh> 
   54#include <Qt3DExtras/QExtrudedTextGeometry> 
   75class QgsInstancedPoint3DSymbolHandler : 
public QgsFeature3DHandler
 
   80      , mSelectedIds( selectedIds ) {}
 
   82    bool prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) 
override;
 
   83    void processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context ) 
override;
 
   84    void finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context ) 
override;
 
   89    static Qt3DRender::QGeometryRenderer *renderer( 
const QgsPoint3DSymbol *symbol, 
const QVector<QVector3D> &positions );
 
   95      QVector<QVector3D> positions;  
 
   98    void makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected );
 
  101    std::unique_ptr< QgsPoint3DSymbol > mSymbol;
 
  107    PointData outSelected;  
 
  111bool QgsInstancedPoint3DSymbolHandler::prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
 
  114  Q_UNUSED( attributeNames )
 
  118void QgsInstancedPoint3DSymbolHandler::processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context )
 
  120  PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
 
  129void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  131  makeEntity( parent, context, outNormal, 
false );
 
  132  makeEntity( parent, context, outSelected, 
true );
 
  134  updateZRangeFromPositions( outNormal.positions );
 
  135  updateZRangeFromPositions( outSelected.positions );
 
  138  const float symbolHeight = mSymbol->transform().data()[13];
 
  139  mZMin += symbolHeight;
 
  140  mZMax += symbolHeight;
 
  143void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected )
 
  146  Qt3DRender::QMaterial *mat = material( mSymbol.get() );
 
  151    for ( Qt3DRender::QParameter *param : mat->effect()->parameters() )
 
  153      if ( param->name() == QLatin1String( 
"kd" ) ) 
 
  154        param->setValue( context.map().selectionColor() );
 
  155      else if ( param->name() == QLatin1String( 
"ka" ) ) 
 
  156        param->setValue( context.map().selectionColor().darker() );
 
  161  Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  162  entity->addComponent( renderer( mSymbol.get(), out.positions ) );
 
  163  entity->addComponent( mat );
 
  164  entity->setParent( parent );
 
  172Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material( 
const QgsPoint3DSymbol *symbol )
 
  174  Qt3DRender::QFilterKey *filterKey = 
new Qt3DRender::QFilterKey;
 
  175  filterKey->setName( QStringLiteral( 
"renderingStyle" ) );
 
  176  filterKey->setValue( 
"forward" );
 
  181  Qt3DRender::QShaderProgram *shaderProgram = 
new Qt3DRender::QShaderProgram;
 
  182  shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( 
"qrc:/shaders/instanced.vert" ) ) ) );
 
  183  shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( 
"qrc:/shaders/instanced.frag" ) ) ) );
 
  185  Qt3DRender::QRenderPass *renderPass = 
new Qt3DRender::QRenderPass;
 
  186  renderPass->setShaderProgram( shaderProgram );
 
  188  Qt3DRender::QTechnique *technique = 
new Qt3DRender::QTechnique;
 
  189  technique->addFilterKey( filterKey );
 
  190  technique->addRenderPass( renderPass );
 
  191  technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
 
  192  technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
 
  193  technique->graphicsApiFilter()->setMajorVersion( 3 );
 
  194  technique->graphicsApiFilter()->setMinorVersion( 2 );
 
  196  const QMatrix4x4 transformMatrix = symbol->
transform();
 
  197  QMatrix3x3 normalMatrix = transformMatrix.normalMatrix();  
 
  200  float *n = normalMatrix.data();
 
  201  const QMatrix4x4 normalMatrix4(
 
  207  Qt3DRender::QParameter *paramInst = 
new Qt3DRender::QParameter;
 
  208  paramInst->setName( QStringLiteral( 
"inst" ) );
 
  209  paramInst->setValue( transformMatrix );
 
  211  Qt3DRender::QParameter *paramInstNormal = 
new Qt3DRender::QParameter;
 
  212  paramInstNormal->setName( QStringLiteral( 
"instNormal" ) );
 
  213  paramInstNormal->setValue( normalMatrix4 );
 
  215  Qt3DRender::QEffect *effect = 
new Qt3DRender::QEffect;
 
  216  effect->addTechnique( technique );
 
  217  effect->addParameter( paramInst );
 
  218  effect->addParameter( paramInstNormal );
 
  222  Qt3DRender::QMaterial *material = 
new Qt3DRender::QMaterial;
 
  223  material->setEffect( effect );
 
  228Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer( 
const QgsPoint3DSymbol *symbol, 
const QVector<QVector3D> &positions )
 
  230  const int count = positions.count();
 
  231  const int byteCount = positions.count() * 
sizeof( QVector3D );
 
  233  ba.resize( byteCount );
 
  234  memcpy( ba.data(), positions.constData(), byteCount );
 
  237  instanceBuffer->setData( ba );
 
  240  instanceDataAttribute->setName( QStringLiteral( 
"pos" ) );
 
  241  instanceDataAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
 
  242  instanceDataAttribute->setVertexBaseType( Qt3DQAttribute::Float );
 
  243  instanceDataAttribute->setVertexSize( 3 );
 
  244  instanceDataAttribute->setByteOffset( 0 );
 
  245  instanceDataAttribute->setDivisor( 1 );
 
  246  instanceDataAttribute->setBuffer( instanceBuffer );
 
  247  instanceDataAttribute->setCount( count );
 
  248  instanceDataAttribute->setByteStride( 3 * 
sizeof( 
float ) );
 
  251  geometry->addAttribute( instanceDataAttribute );
 
  252  geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
 
  254  Qt3DRender::QGeometryRenderer *renderer = 
new Qt3DRender::QGeometryRenderer;
 
  255  renderer->setGeometry( geometry );
 
  256  renderer->setInstanceCount( count );
 
  267      const float radius = shapeProperties[QStringLiteral( 
"radius" )].toFloat();
 
  268      const float length = shapeProperties[QStringLiteral( 
"length" )].toFloat();
 
  269      Qt3DExtras::QCylinderGeometry *g = 
new Qt3DExtras::QCylinderGeometry;
 
  272      g->setRadius( radius ? radius : 10 );
 
  273      g->setLength( length ? length : 10 );
 
  279      const float radius = shapeProperties[QStringLiteral( 
"radius" )].toFloat();
 
  280      Qt3DExtras::QSphereGeometry *g = 
new Qt3DExtras::QSphereGeometry;
 
  281      g->setRadius( radius ? radius : 10 );
 
  287      const float length = shapeProperties[QStringLiteral( 
"length" )].toFloat();
 
  288      const float bottomRadius = shapeProperties[QStringLiteral( 
"bottomRadius" )].toFloat();
 
  289      const float topRadius = shapeProperties[QStringLiteral( 
"topRadius" )].toFloat();
 
  290      Qt3DExtras::QConeGeometry *g = 
new Qt3DExtras::QConeGeometry;
 
  291      g->setLength( length ? length : 10 );
 
  292      g->setBottomRadius( bottomRadius );
 
  293      g->setTopRadius( topRadius );
 
  301      const float size = shapeProperties[QStringLiteral( 
"size" )].toFloat();
 
  302      Qt3DExtras::QCuboidGeometry *g = 
new Qt3DExtras::QCuboidGeometry;
 
  303      g->setXExtent( size ? size : 10 );
 
  304      g->setYExtent( size ? size : 10 );
 
  305      g->setZExtent( size ? size : 10 );
 
  311      const float radius = shapeProperties[QStringLiteral( 
"radius" )].toFloat();
 
  312      const float minorRadius = shapeProperties[QStringLiteral( 
"minorRadius" )].toFloat();
 
  313      Qt3DExtras::QTorusGeometry *g = 
new Qt3DExtras::QTorusGeometry;
 
  314      g->setRadius( radius ? radius : 10 );
 
  315      g->setMinorRadius( minorRadius ? minorRadius : 5 );
 
  321      const float size = shapeProperties[QStringLiteral( 
"size" )].toFloat();
 
  322      Qt3DExtras::QPlaneGeometry *g = 
new Qt3DExtras::QPlaneGeometry;
 
  323      g->setWidth( size ? size : 10 );
 
  324      g->setHeight( size ? size : 10 );
 
  330      const float depth = shapeProperties[QStringLiteral( 
"depth" )].toFloat();
 
  331      const QString text = shapeProperties[QStringLiteral( 
"text" )].toString();
 
  332      Qt3DExtras::QExtrudedTextGeometry *g = 
new Qt3DExtras::QExtrudedTextGeometry;
 
  333      g->setDepth( depth ? depth : 1 );
 
  347class QgsModelPoint3DSymbolHandler : 
public QgsFeature3DHandler
 
  352      , mSelectedIds( selectedIds ) {}
 
  354    bool prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) 
override;
 
  355    void processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context ) 
override;
 
  356    void finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context ) 
override;
 
  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 );
 
  367      QVector<QVector3D> positions;  
 
  370    void makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected );
 
  373    std::unique_ptr< QgsPoint3DSymbol > mSymbol;
 
  379    PointData outSelected;  
 
  382bool QgsModelPoint3DSymbolHandler::prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
 
  385  Q_UNUSED( attributeNames )
 
  389void QgsModelPoint3DSymbolHandler::processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context )
 
  391  PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
 
  400void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  402  makeEntity( parent, context, outNormal, 
false );
 
  403  makeEntity( parent, context, outSelected, 
true );
 
  405  updateZRangeFromPositions( outNormal.positions );
 
  406  updateZRangeFromPositions( outSelected.positions );
 
  409  const float symbolHeight = mSymbol->transform().data()[13];
 
  410  mZMin += symbolHeight;
 
  411  mZMax += symbolHeight;
 
  414void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected )
 
  418    addMeshEntities( context.map(), out.positions, mSymbol.get(), parent, 
true );
 
  423    if ( mSymbol->shapeProperties()[QStringLiteral( 
"overwriteMaterial" )].toBool()
 
  424         || ( mSymbol->materialSettings() && mSymbol->materialSettings()->type() != QLatin1String( 
"null" ) ) )
 
  426      addMeshEntities( context.map(), out.positions, mSymbol.get(), parent, 
false );
 
  430      addSceneEntities( context.map(), out.positions, mSymbol.get(), parent );
 
  437void QgsModelPoint3DSymbolHandler::addSceneEntities( 
const Qgs3DMapSettings &map, 
const QVector<QVector3D> &positions, 
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
 
  440  for ( 
const QVector3D &position : positions )
 
  444    if ( !source.isEmpty() )
 
  447      Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  449      const QUrl url = QUrl::fromLocalFile( source );
 
  450      Qt3DRender::QSceneLoader *modelLoader = 
new Qt3DRender::QSceneLoader;
 
  451      modelLoader->setSource( url );
 
  453      entity->addComponent( modelLoader );
 
  454      entity->addComponent( transform( position, symbol ) );
 
  455      entity->setParent( parent );
 
  463void QgsModelPoint3DSymbolHandler::addMeshEntities( 
const Qgs3DMapSettings &map, 
const QVector<QVector3D> &positions, 
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, 
bool are_selected )
 
  465  if ( positions.empty() )
 
  475  for ( 
const QVector3D &position : positions )
 
  478    if ( !source.isEmpty() )
 
  481      Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  483      const QUrl url = QUrl::fromLocalFile( source );
 
  484      Qt3DRender::QMesh *mesh = 
new Qt3DRender::QMesh;
 
  485      mesh->setSource( url );
 
  487      entity->addComponent( mesh );
 
  488      entity->addComponent( mat );
 
  489      entity->addComponent( transform( position, symbol ) );
 
  490      entity->setParent( parent );
 
  498Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position, 
const QgsPoint3DSymbol *symbol )
 
  500  Qt3DCore::QTransform *tr = 
new Qt3DCore::QTransform;
 
  502  tr->setTranslation( position + tr->translation() );
 
  510class QgsPoint3DBillboardSymbolHandler : 
public QgsFeature3DHandler
 
  515      , mSelectedIds( selectedIds ) {}
 
  517    bool prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) 
override;
 
  518    void processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context ) 
override;
 
  519    void finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context ) 
override;
 
  526      QVector<QVector3D> positions;  
 
  529    void makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected );
 
  532    std::unique_ptr< QgsPoint3DSymbol > mSymbol;
 
  538    PointData outSelected;  
 
  541bool QgsPoint3DBillboardSymbolHandler::prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
 
  544  Q_UNUSED( attributeNames )
 
  548void QgsPoint3DBillboardSymbolHandler::processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context )
 
  550  PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
 
  559void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  561  makeEntity( parent, context, outNormal, 
false );
 
  562  makeEntity( parent, context, outSelected, 
true );
 
  564  updateZRangeFromPositions( outNormal.positions );
 
  565  updateZRangeFromPositions( outSelected.positions );
 
  568  const float billboardHeight = mSymbol->transform().data()[13];
 
  569  mZMin += billboardHeight;
 
  570  mZMax += billboardHeight;
 
  573void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected )
 
  577  billboardGeometry->
setPoints( out.positions );
 
  580  Qt3DRender::QGeometryRenderer *billboardGeometryRenderer = 
new Qt3DRender::QGeometryRenderer;
 
  581  billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
 
  582  billboardGeometryRenderer->setGeometry( billboardGeometry );
 
  583  billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
 
  599  Qt3DCore::QTransform *billboardTransform = 
new Qt3DCore::QTransform();
 
  600  billboardTransform->setMatrix( mSymbol->billboardTransform() );
 
  603  Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  605  entity->addComponent( billboardMaterial );
 
  606  entity->addComponent( billboardTransform );
 
  607  entity->addComponent( billboardGeometryRenderer );
 
  608  entity->setParent( parent );
 
  615namespace Qgs3DSymbolImpl
 
  628      return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
 
  630      return new QgsInstancedPoint3DSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
 
  635    QgsFeature3DHandler *handler = handlerForPoint3DSymbol( layer, &symbol );
 
  636    Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );
 
QColor selectionColor() const
Returns color used for selected features.
 
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.
 
virtual Qt3DRender::QMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const =0
Creates a new QMaterial object representing the material settings.
 
virtual void addParametersToEffect(Qt3DRender::QEffect *effect) const =0
Adds parameters from the material to a destination effect.
 
static QgsSourceCache * sourceCache()
Returns the application's source cache, used for caching embedded and remote source strings as local ...
 
void setPoints(const QVector< QVector3D > &vertices)
Set the points for the billboard with vertices.
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
A marker symbol type, for rendering Point and MultiPoint geometries.
 
void setIsSelected(bool isSelected)
Sets whether the material should represent a selected state.
 
void setSelectionColor(const QColor &color)
Sets the color for representing materials in a selected state.
 
void useDefaultSymbol(const Qgs3DMapSettings &map, bool selected=false)
Set default symbol for the texture with map and selected parameter for rendering.
 
void setTexture2DFromSymbol(QgsMarkerSymbol *markerSymbol, const Qgs3DMapSettings &map, bool selected=false)
Set markerSymbol for the texture with map and selected parameter for rendering.
 
Shape
3D shape types supported by the symbol
 
@ ExtrudedText
Supported in Qt 5.9+.
 
QgsAbstractMaterialSettings * materialSettings() const
Returns material settings used for shading of the symbol.
 
QMatrix4x4 transform() const
Returns transform for individual objects represented by the symbol.
 
QgsMarkerSymbol * billboardSymbol() const
Returns a symbol for billboard.
 
QgsAbstract3DSymbol * clone() const override SIP_FACTORY
 
Shape shape() const
Returns 3D shape for points.
 
QVariantMap shapeProperties() const
Returns a key-value dictionary of point shape properties.
 
QString localFilePath(const QString &path, bool blocking=false)
Returns a local file path reflecting the content of a specified source path.
 
Represents a vector layer which manages a vector based data sets.
 
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
 
@ Triangles
Triangle based rendering (default)
 
Qt3DCore::QAttribute Qt3DQAttribute
 
Qt3DCore::QBuffer Qt3DQBuffer
 
Qt3DCore::QGeometry Qt3DQGeometry
 
QSet< QgsFeatureId > QgsFeatureIds
 
Qt3DCore::QAttribute Qt3DQAttribute
 
Qt3DCore::QBuffer Qt3DQBuffer
 
Qt3DCore::QGeometry Qt3DQGeometry