18 #include <Qt3DRender/QAttribute> 
   19 #include <Qt3DRender/QBuffer> 
   20 #include <Qt3DRender/QEffect> 
   21 #include <Qt3DRender/QGraphicsApiFilter> 
   22 #include <Qt3DRender/QParameter> 
   23 #include <Qt3DRender/QTechnique> 
   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> 
   35 #include <Qt3DRender/QMesh> 
   37 #include <Qt3DExtras/QExtrudedTextGeometry> 
   63 class QgsInstancedPoint3DSymbolHandler : 
public QgsFeature3DHandler
 
   68       , mSelectedIds( selectedIds ) {}
 
   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;
 
   77     static Qt3DRender::QGeometryRenderer *renderer( 
const QgsPoint3DSymbol *symbol, 
const QVector<QVector3D> &positions );
 
   78     static Qt3DRender::QGeometry *symbolGeometry( 
QgsPoint3DSymbol::Shape shape, 
const QVariantMap &shapeProperties );
 
   83       QVector<QVector3D> positions;  
 
   86     void makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected );
 
   89     std::unique_ptr< QgsPoint3DSymbol > mSymbol;
 
   95     PointData outSelected;  
 
   99 bool QgsInstancedPoint3DSymbolHandler::prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
 
  102   Q_UNUSED( attributeNames )
 
  106 void QgsInstancedPoint3DSymbolHandler::processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context )
 
  108   PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
 
  116 void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  118   makeEntity( parent, context, outNormal, 
false );
 
  119   makeEntity( parent, context, outSelected, 
true );
 
  121   updateZRangeFromPositions( outNormal.positions );
 
  122   updateZRangeFromPositions( outSelected.positions );
 
  125   float symbolHeight = mSymbol->transform().data()[13];
 
  126   mZMin += symbolHeight;
 
  127   mZMax += symbolHeight;
 
  130 void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected )
 
  133   Qt3DRender::QMaterial *mat = material( mSymbol.get() );
 
  138     for ( Qt3DRender::QParameter *param : mat->effect()->parameters() )
 
  140       if ( param->name() == QLatin1String( 
"kd" ) ) 
 
  141         param->setValue( context.map().selectionColor() );
 
  142       else if ( param->name() == QLatin1String( 
"ka" ) ) 
 
  143         param->setValue( context.map().selectionColor().darker() );
 
  148   Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  149   entity->addComponent( renderer( mSymbol.get(), out.positions ) );
 
  150   entity->addComponent( mat );
 
  151   entity->setParent( parent );
 
  159 Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material( 
const QgsPoint3DSymbol *symbol )
 
  161   Qt3DRender::QFilterKey *filterKey = 
new Qt3DRender::QFilterKey;
 
  162   filterKey->setName( QStringLiteral( 
"renderingStyle" ) );
 
  163   filterKey->setValue( 
"forward" );
 
  168   Qt3DRender::QShaderProgram *shaderProgram = 
new Qt3DRender::QShaderProgram;
 
  169   shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( 
"qrc:/shaders/instanced.vert" ) ) ) );
 
  170   shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( 
"qrc:/shaders/instanced.frag" ) ) ) );
 
  172   Qt3DRender::QRenderPass *renderPass = 
new Qt3DRender::QRenderPass;
 
  173   renderPass->setShaderProgram( shaderProgram );
 
  175   Qt3DRender::QTechnique *technique = 
new Qt3DRender::QTechnique;
 
  176   technique->addFilterKey( filterKey );
 
  177   technique->addRenderPass( renderPass );
 
  178   technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
 
  179   technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
 
  180   technique->graphicsApiFilter()->setMajorVersion( 3 );
 
  181   technique->graphicsApiFilter()->setMinorVersion( 2 );
 
  183   QMatrix4x4 transformMatrix = symbol->
transform();
 
  184   QMatrix3x3 normalMatrix = transformMatrix.normalMatrix();  
 
  187   float *n = normalMatrix.data();
 
  188   QMatrix4x4 normalMatrix4(
 
  194   Qt3DRender::QParameter *paramInst = 
new Qt3DRender::QParameter;
 
  195   paramInst->setName( QStringLiteral( 
"inst" ) );
 
  196   paramInst->setValue( transformMatrix );
 
  198   Qt3DRender::QParameter *paramInstNormal = 
new Qt3DRender::QParameter;
 
  199   paramInstNormal->setName( QStringLiteral( 
"instNormal" ) );
 
  200   paramInstNormal->setValue( normalMatrix4 );
 
  202   Qt3DRender::QEffect *effect = 
new Qt3DRender::QEffect;
 
  203   effect->addTechnique( technique );
 
  204   effect->addParameter( paramInst );
 
  205   effect->addParameter( paramInstNormal );
 
  209   Qt3DRender::QMaterial *material = 
new Qt3DRender::QMaterial;
 
  210   material->setEffect( effect );
 
  215 Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer( 
const QgsPoint3DSymbol *symbol, 
const QVector<QVector3D> &positions )
 
  217   int count = positions.count();
 
  218   int byteCount = positions.count() * 
sizeof( QVector3D );
 
  220   ba.resize( byteCount );
 
  221   memcpy( ba.data(), positions.constData(), byteCount );
 
  223   Qt3DRender::QBuffer *instanceBuffer = 
new Qt3DRender::QBuffer();
 
  224   instanceBuffer->setData( ba );
 
  226   Qt3DRender::QAttribute *instanceDataAttribute = 
new Qt3DRender::QAttribute;
 
  227   instanceDataAttribute->setName( QStringLiteral( 
"pos" ) );
 
  228   instanceDataAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
 
  229   instanceDataAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
 
  230   instanceDataAttribute->setVertexSize( 3 );
 
  231   instanceDataAttribute->setByteOffset( 0 );
 
  232   instanceDataAttribute->setDivisor( 1 );
 
  233   instanceDataAttribute->setBuffer( instanceBuffer );
 
  234   instanceDataAttribute->setCount( count );
 
  235   instanceDataAttribute->setByteStride( 3 * 
sizeof( 
float ) );
 
  238   geometry->addAttribute( instanceDataAttribute );
 
  239   geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
 
  241   Qt3DRender::QGeometryRenderer *renderer = 
new Qt3DRender::QGeometryRenderer;
 
  242   renderer->setGeometry( geometry );
 
  243   renderer->setInstanceCount( count );
 
  248 Qt3DRender::QGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( 
QgsPoint3DSymbol::Shape shape, 
const QVariantMap &shapeProperties )
 
  254       float radius = shapeProperties[QStringLiteral( 
"radius" )].toFloat();
 
  255       float length = shapeProperties[QStringLiteral( 
"length" )].toFloat();
 
  256       Qt3DExtras::QCylinderGeometry *g = 
new Qt3DExtras::QCylinderGeometry;
 
  259       g->setRadius( radius ? radius : 10 );
 
  260       g->setLength( length ? length : 10 );
 
  266       float radius = shapeProperties[QStringLiteral( 
"radius" )].toFloat();
 
  267       Qt3DExtras::QSphereGeometry *g = 
new Qt3DExtras::QSphereGeometry;
 
  268       g->setRadius( radius ? radius : 10 );
 
  274       float length = shapeProperties[QStringLiteral( 
"length" )].toFloat();
 
  275       float bottomRadius = shapeProperties[QStringLiteral( 
"bottomRadius" )].toFloat();
 
  276       float topRadius = shapeProperties[QStringLiteral( 
"topRadius" )].toFloat();
 
  277       Qt3DExtras::QConeGeometry *g = 
new Qt3DExtras::QConeGeometry;
 
  278       g->setLength( length ? length : 10 );
 
  279       g->setBottomRadius( bottomRadius );
 
  280       g->setTopRadius( topRadius );
 
  288       float size = shapeProperties[QStringLiteral( 
"size" )].toFloat();
 
  289       Qt3DExtras::QCuboidGeometry *g = 
new Qt3DExtras::QCuboidGeometry;
 
  290       g->setXExtent( size ? size : 10 );
 
  291       g->setYExtent( size ? size : 10 );
 
  292       g->setZExtent( size ? size : 10 );
 
  298       float radius = shapeProperties[QStringLiteral( 
"radius" )].toFloat();
 
  299       float minorRadius = shapeProperties[QStringLiteral( 
"minorRadius" )].toFloat();
 
  300       Qt3DExtras::QTorusGeometry *g = 
new Qt3DExtras::QTorusGeometry;
 
  301       g->setRadius( radius ? radius : 10 );
 
  302       g->setMinorRadius( minorRadius ? minorRadius : 5 );
 
  308       float size = shapeProperties[QStringLiteral( 
"size" )].toFloat();
 
  309       Qt3DExtras::QPlaneGeometry *g = 
new Qt3DExtras::QPlaneGeometry;
 
  310       g->setWidth( size ? size : 10 );
 
  311       g->setHeight( size ? size : 10 );
 
  317       float depth = shapeProperties[QStringLiteral( 
"depth" )].toFloat();
 
  318       QString text = shapeProperties[QStringLiteral( 
"text" )].toString();
 
  319       Qt3DExtras::QExtrudedTextGeometry *g = 
new Qt3DExtras::QExtrudedTextGeometry;
 
  320       g->setDepth( depth ? depth : 1 );
 
  334 class QgsModelPoint3DSymbolHandler : 
public QgsFeature3DHandler
 
  339       , mSelectedIds( selectedIds ) {}
 
  341     bool prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) 
override;
 
  342     void processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context ) 
override;
 
  343     void finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context ) 
override;
 
  347     static void addSceneEntities( 
const Qgs3DMapSettings &map, 
const QVector<QVector3D> &positions, 
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent );
 
  348     static void addMeshEntities( 
const Qgs3DMapSettings &map, 
const QVector<QVector3D> &positions, 
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, 
bool are_selected );
 
  349     static Qt3DCore::QTransform *transform( QVector3D position, 
const QgsPoint3DSymbol *symbol );
 
  354       QVector<QVector3D> positions;  
 
  357     void makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected );
 
  360     std::unique_ptr< QgsPoint3DSymbol > mSymbol;
 
  366     PointData outSelected;  
 
  369 bool QgsModelPoint3DSymbolHandler::prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
 
  372   Q_UNUSED( attributeNames )
 
  376 void QgsModelPoint3DSymbolHandler::processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context )
 
  378   PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
 
  386 void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  388   makeEntity( parent, context, outNormal, 
false );
 
  389   makeEntity( parent, context, outSelected, 
true );
 
  391   updateZRangeFromPositions( outNormal.positions );
 
  392   updateZRangeFromPositions( outSelected.positions );
 
  395   float symbolHeight = mSymbol->transform().data()[13];
 
  396   mZMin += symbolHeight;
 
  397   mZMax += symbolHeight;
 
  400 void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected )
 
  404     addMeshEntities( context.map(), out.positions, mSymbol.get(), parent, 
true );
 
  409     if ( mSymbol->shapeProperties()[QStringLiteral( 
"overwriteMaterial" )].toBool()
 
  410          || ( mSymbol->material() && mSymbol->material()->type() != QLatin1String( 
"null" ) ) )
 
  412       addMeshEntities( context.map(), out.positions, mSymbol.get(), parent, 
false );
 
  416       addSceneEntities( context.map(), out.positions, mSymbol.get(), parent );
 
  423 void QgsModelPoint3DSymbolHandler::addSceneEntities( 
const Qgs3DMapSettings &map, 
const QVector<QVector3D> &positions, 
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
 
  426   for ( 
const QVector3D &position : positions )
 
  430     if ( !source.isEmpty() )
 
  433       Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  435       QUrl url = QUrl::fromLocalFile( source );
 
  436       Qt3DRender::QSceneLoader *modelLoader = 
new Qt3DRender::QSceneLoader;
 
  437       modelLoader->setSource( url );
 
  439       entity->addComponent( modelLoader );
 
  440       entity->addComponent( transform( position, symbol ) );
 
  441       entity->setParent( parent );
 
  449 void QgsModelPoint3DSymbolHandler::addMeshEntities( 
const Qgs3DMapSettings &map, 
const QVector<QVector3D> &positions, 
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, 
bool are_selected )
 
  451   if ( positions.empty() )
 
  461   for ( 
const QVector3D &position : positions )
 
  464     if ( !source.isEmpty() )
 
  467       Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  469       QUrl url = QUrl::fromLocalFile( source );
 
  470       Qt3DRender::QMesh *mesh = 
new Qt3DRender::QMesh;
 
  471       mesh->setSource( url );
 
  473       entity->addComponent( mesh );
 
  474       entity->addComponent( mat );
 
  475       entity->addComponent( transform( position, symbol ) );
 
  476       entity->setParent( parent );
 
  484 Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position, 
const QgsPoint3DSymbol *symbol )
 
  486   Qt3DCore::QTransform *tr = 
new Qt3DCore::QTransform;
 
  488   tr->setTranslation( position + tr->translation() );
 
  496 class QgsPoint3DBillboardSymbolHandler : 
public QgsFeature3DHandler
 
  501       , mSelectedIds( selectedIds ) {}
 
  503     bool prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) 
override;
 
  504     void processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context ) 
override;
 
  505     void finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context ) 
override;
 
  512       QVector<QVector3D> positions;  
 
  515     void makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected );
 
  518     std::unique_ptr< QgsPoint3DSymbol > mSymbol;
 
  524     PointData outSelected;  
 
  527 bool QgsPoint3DBillboardSymbolHandler::prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
 
  530   Q_UNUSED( attributeNames )
 
  534 void QgsPoint3DBillboardSymbolHandler::processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context )
 
  536   PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
 
  544 void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  546   makeEntity( parent, context, outNormal, 
false );
 
  547   makeEntity( parent, context, outSelected, 
true );
 
  549   updateZRangeFromPositions( outNormal.positions );
 
  550   updateZRangeFromPositions( outSelected.positions );
 
  553   float billboardHeight = mSymbol->transform().data()[13];
 
  554   mZMin += billboardHeight;
 
  555   mZMax += billboardHeight;
 
  558 void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected )
 
  562   billboardGeometry->
setPoints( out.positions );
 
  565   Qt3DRender::QGeometryRenderer *billboardGeometryRenderer = 
new Qt3DRender::QGeometryRenderer;
 
  566   billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
 
  567   billboardGeometryRenderer->setGeometry( billboardGeometry );
 
  568   billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
 
  584   Qt3DCore::QTransform *billboardTransform = 
new Qt3DCore::QTransform();
 
  585   billboardTransform->setMatrix( mSymbol->billboardTransform() );
 
  588   Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  590   entity->addComponent( billboardMaterial );
 
  591   entity->addComponent( billboardTransform );
 
  592   entity->addComponent( billboardGeometryRenderer );
 
  593   entity->setParent( parent );
 
  600 namespace Qgs3DSymbolImpl
 
  613       return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
 
  615       return new QgsInstancedPoint3DSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
 
  620     QgsFeature3DHandler *handler = handlerForPoint3DSymbol( layer, &symbol );
 
  621     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, Qgs3DTypes::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 QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
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 * material() const
Returns material 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.
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)
QSet< QgsFeatureId > QgsFeatureIds