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;
 
  117 void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  119   makeEntity( parent, context, outNormal, 
false );
 
  120   makeEntity( parent, context, outSelected, 
true );
 
  122   updateZRangeFromPositions( outNormal.positions );
 
  123   updateZRangeFromPositions( outSelected.positions );
 
  126   const float symbolHeight = mSymbol->transform().data()[13];
 
  127   mZMin += symbolHeight;
 
  128   mZMax += symbolHeight;
 
  131 void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected )
 
  134   Qt3DRender::QMaterial *mat = material( mSymbol.get() );
 
  139     for ( Qt3DRender::QParameter *param : mat->effect()->parameters() )
 
  141       if ( param->name() == QLatin1String( 
"kd" ) ) 
 
  142         param->setValue( context.map().selectionColor() );
 
  143       else if ( param->name() == QLatin1String( 
"ka" ) ) 
 
  144         param->setValue( context.map().selectionColor().darker() );
 
  149   Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  150   entity->addComponent( renderer( mSymbol.get(), out.positions ) );
 
  151   entity->addComponent( mat );
 
  152   entity->setParent( parent );
 
  160 Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material( 
const QgsPoint3DSymbol *symbol )
 
  162   Qt3DRender::QFilterKey *filterKey = 
new Qt3DRender::QFilterKey;
 
  163   filterKey->setName( QStringLiteral( 
"renderingStyle" ) );
 
  164   filterKey->setValue( 
"forward" );
 
  169   Qt3DRender::QShaderProgram *shaderProgram = 
new Qt3DRender::QShaderProgram;
 
  170   shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( 
"qrc:/shaders/instanced.vert" ) ) ) );
 
  171   shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( 
"qrc:/shaders/instanced.frag" ) ) ) );
 
  173   Qt3DRender::QRenderPass *renderPass = 
new Qt3DRender::QRenderPass;
 
  174   renderPass->setShaderProgram( shaderProgram );
 
  176   Qt3DRender::QTechnique *technique = 
new Qt3DRender::QTechnique;
 
  177   technique->addFilterKey( filterKey );
 
  178   technique->addRenderPass( renderPass );
 
  179   technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
 
  180   technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
 
  181   technique->graphicsApiFilter()->setMajorVersion( 3 );
 
  182   technique->graphicsApiFilter()->setMinorVersion( 2 );
 
  184   const QMatrix4x4 transformMatrix = symbol->
transform();
 
  185   QMatrix3x3 normalMatrix = transformMatrix.normalMatrix();  
 
  188   float *n = normalMatrix.data();
 
  189   const QMatrix4x4 normalMatrix4(
 
  195   Qt3DRender::QParameter *paramInst = 
new Qt3DRender::QParameter;
 
  196   paramInst->setName( QStringLiteral( 
"inst" ) );
 
  197   paramInst->setValue( transformMatrix );
 
  199   Qt3DRender::QParameter *paramInstNormal = 
new Qt3DRender::QParameter;
 
  200   paramInstNormal->setName( QStringLiteral( 
"instNormal" ) );
 
  201   paramInstNormal->setValue( normalMatrix4 );
 
  203   Qt3DRender::QEffect *effect = 
new Qt3DRender::QEffect;
 
  204   effect->addTechnique( technique );
 
  205   effect->addParameter( paramInst );
 
  206   effect->addParameter( paramInstNormal );
 
  210   Qt3DRender::QMaterial *material = 
new Qt3DRender::QMaterial;
 
  211   material->setEffect( effect );
 
  216 Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer( 
const QgsPoint3DSymbol *symbol, 
const QVector<QVector3D> &positions )
 
  218   const int count = positions.count();
 
  219   const int byteCount = positions.count() * 
sizeof( QVector3D );
 
  221   ba.resize( byteCount );
 
  222   memcpy( ba.data(), positions.constData(), byteCount );
 
  224   Qt3DRender::QBuffer *instanceBuffer = 
new Qt3DRender::QBuffer();
 
  225   instanceBuffer->setData( ba );
 
  227   Qt3DRender::QAttribute *instanceDataAttribute = 
new Qt3DRender::QAttribute;
 
  228   instanceDataAttribute->setName( QStringLiteral( 
"pos" ) );
 
  229   instanceDataAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
 
  230   instanceDataAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
 
  231   instanceDataAttribute->setVertexSize( 3 );
 
  232   instanceDataAttribute->setByteOffset( 0 );
 
  233   instanceDataAttribute->setDivisor( 1 );
 
  234   instanceDataAttribute->setBuffer( instanceBuffer );
 
  235   instanceDataAttribute->setCount( count );
 
  236   instanceDataAttribute->setByteStride( 3 * 
sizeof( 
float ) );
 
  239   geometry->addAttribute( instanceDataAttribute );
 
  240   geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
 
  242   Qt3DRender::QGeometryRenderer *renderer = 
new Qt3DRender::QGeometryRenderer;
 
  243   renderer->setGeometry( geometry );
 
  244   renderer->setInstanceCount( count );
 
  249 Qt3DRender::QGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry( 
QgsPoint3DSymbol::Shape shape, 
const QVariantMap &shapeProperties )
 
  255       const float radius = shapeProperties[QStringLiteral( 
"radius" )].toFloat();
 
  256       const float length = shapeProperties[QStringLiteral( 
"length" )].toFloat();
 
  257       Qt3DExtras::QCylinderGeometry *g = 
new Qt3DExtras::QCylinderGeometry;
 
  260       g->setRadius( radius ? radius : 10 );
 
  261       g->setLength( length ? length : 10 );
 
  267       const float radius = shapeProperties[QStringLiteral( 
"radius" )].toFloat();
 
  268       Qt3DExtras::QSphereGeometry *g = 
new Qt3DExtras::QSphereGeometry;
 
  269       g->setRadius( radius ? radius : 10 );
 
  275       const float length = shapeProperties[QStringLiteral( 
"length" )].toFloat();
 
  276       const float bottomRadius = shapeProperties[QStringLiteral( 
"bottomRadius" )].toFloat();
 
  277       const float topRadius = shapeProperties[QStringLiteral( 
"topRadius" )].toFloat();
 
  278       Qt3DExtras::QConeGeometry *g = 
new Qt3DExtras::QConeGeometry;
 
  279       g->setLength( length ? length : 10 );
 
  280       g->setBottomRadius( bottomRadius );
 
  281       g->setTopRadius( topRadius );
 
  289       const float size = shapeProperties[QStringLiteral( 
"size" )].toFloat();
 
  290       Qt3DExtras::QCuboidGeometry *g = 
new Qt3DExtras::QCuboidGeometry;
 
  291       g->setXExtent( size ? size : 10 );
 
  292       g->setYExtent( size ? size : 10 );
 
  293       g->setZExtent( size ? size : 10 );
 
  299       const float radius = shapeProperties[QStringLiteral( 
"radius" )].toFloat();
 
  300       const float minorRadius = shapeProperties[QStringLiteral( 
"minorRadius" )].toFloat();
 
  301       Qt3DExtras::QTorusGeometry *g = 
new Qt3DExtras::QTorusGeometry;
 
  302       g->setRadius( radius ? radius : 10 );
 
  303       g->setMinorRadius( minorRadius ? minorRadius : 5 );
 
  309       const float size = shapeProperties[QStringLiteral( 
"size" )].toFloat();
 
  310       Qt3DExtras::QPlaneGeometry *g = 
new Qt3DExtras::QPlaneGeometry;
 
  311       g->setWidth( size ? size : 10 );
 
  312       g->setHeight( size ? size : 10 );
 
  318       const float depth = shapeProperties[QStringLiteral( 
"depth" )].toFloat();
 
  319       const QString text = shapeProperties[QStringLiteral( 
"text" )].toString();
 
  320       Qt3DExtras::QExtrudedTextGeometry *g = 
new Qt3DExtras::QExtrudedTextGeometry;
 
  321       g->setDepth( depth ? depth : 1 );
 
  335 class QgsModelPoint3DSymbolHandler : 
public QgsFeature3DHandler
 
  340       , mSelectedIds( selectedIds ) {}
 
  342     bool prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) 
override;
 
  343     void processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context ) 
override;
 
  344     void finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context ) 
override;
 
  348     static void addSceneEntities( 
const Qgs3DMapSettings &map, 
const QVector<QVector3D> &positions, 
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent );
 
  349     static void addMeshEntities( 
const Qgs3DMapSettings &map, 
const QVector<QVector3D> &positions, 
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, 
bool are_selected );
 
  350     static Qt3DCore::QTransform *transform( QVector3D position, 
const QgsPoint3DSymbol *symbol );
 
  355       QVector<QVector3D> positions;  
 
  358     void makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected );
 
  361     std::unique_ptr< QgsPoint3DSymbol > mSymbol;
 
  367     PointData outSelected;  
 
  370 bool QgsModelPoint3DSymbolHandler::prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
 
  373   Q_UNUSED( attributeNames )
 
  377 void QgsModelPoint3DSymbolHandler::processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context )
 
  379   PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
 
  388 void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  390   makeEntity( parent, context, outNormal, 
false );
 
  391   makeEntity( parent, context, outSelected, 
true );
 
  393   updateZRangeFromPositions( outNormal.positions );
 
  394   updateZRangeFromPositions( outSelected.positions );
 
  397   const float symbolHeight = mSymbol->transform().data()[13];
 
  398   mZMin += symbolHeight;
 
  399   mZMax += symbolHeight;
 
  402 void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected )
 
  406     addMeshEntities( context.map(), out.positions, mSymbol.get(), parent, 
true );
 
  411     if ( mSymbol->shapeProperties()[QStringLiteral( 
"overwriteMaterial" )].toBool()
 
  412          || ( mSymbol->material() && mSymbol->material()->type() != QLatin1String( 
"null" ) ) )
 
  414       addMeshEntities( context.map(), out.positions, mSymbol.get(), parent, 
false );
 
  418       addSceneEntities( context.map(), out.positions, mSymbol.get(), parent );
 
  425 void QgsModelPoint3DSymbolHandler::addSceneEntities( 
const Qgs3DMapSettings &map, 
const QVector<QVector3D> &positions, 
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
 
  428   for ( 
const QVector3D &position : positions )
 
  432     if ( !source.isEmpty() )
 
  435       Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  437       const QUrl url = QUrl::fromLocalFile( source );
 
  438       Qt3DRender::QSceneLoader *modelLoader = 
new Qt3DRender::QSceneLoader;
 
  439       modelLoader->setSource( url );
 
  441       entity->addComponent( modelLoader );
 
  442       entity->addComponent( transform( position, symbol ) );
 
  443       entity->setParent( parent );
 
  451 void QgsModelPoint3DSymbolHandler::addMeshEntities( 
const Qgs3DMapSettings &map, 
const QVector<QVector3D> &positions, 
const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, 
bool are_selected )
 
  453   if ( positions.empty() )
 
  463   for ( 
const QVector3D &position : positions )
 
  466     if ( !source.isEmpty() )
 
  469       Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  471       const QUrl url = QUrl::fromLocalFile( source );
 
  472       Qt3DRender::QMesh *mesh = 
new Qt3DRender::QMesh;
 
  473       mesh->setSource( url );
 
  475       entity->addComponent( mesh );
 
  476       entity->addComponent( mat );
 
  477       entity->addComponent( transform( position, symbol ) );
 
  478       entity->setParent( parent );
 
  486 Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position, 
const QgsPoint3DSymbol *symbol )
 
  488   Qt3DCore::QTransform *tr = 
new Qt3DCore::QTransform;
 
  490   tr->setTranslation( position + tr->translation() );
 
  498 class QgsPoint3DBillboardSymbolHandler : 
public QgsFeature3DHandler
 
  503       , mSelectedIds( selectedIds ) {}
 
  505     bool prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) 
override;
 
  506     void processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context ) 
override;
 
  507     void finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context ) 
override;
 
  514       QVector<QVector3D> positions;  
 
  517     void makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected );
 
  520     std::unique_ptr< QgsPoint3DSymbol > mSymbol;
 
  526     PointData outSelected;  
 
  529 bool QgsPoint3DBillboardSymbolHandler::prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
 
  532   Q_UNUSED( attributeNames )
 
  536 void QgsPoint3DBillboardSymbolHandler::processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context )
 
  538   PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
 
  547 void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  549   makeEntity( parent, context, outNormal, 
false );
 
  550   makeEntity( parent, context, outSelected, 
true );
 
  552   updateZRangeFromPositions( outNormal.positions );
 
  553   updateZRangeFromPositions( outSelected.positions );
 
  556   const float billboardHeight = mSymbol->transform().data()[13];
 
  557   mZMin += billboardHeight;
 
  558   mZMax += billboardHeight;
 
  561 void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PointData &out, 
bool selected )
 
  565   billboardGeometry->
setPoints( out.positions );
 
  568   Qt3DRender::QGeometryRenderer *billboardGeometryRenderer = 
new Qt3DRender::QGeometryRenderer;
 
  569   billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
 
  570   billboardGeometryRenderer->setGeometry( billboardGeometry );
 
  571   billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
 
  587   Qt3DCore::QTransform *billboardTransform = 
new Qt3DCore::QTransform();
 
  588   billboardTransform->setMatrix( mSymbol->billboardTransform() );
 
  591   Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  593   entity->addComponent( billboardMaterial );
 
  594   entity->addComponent( billboardTransform );
 
  595   entity->addComponent( billboardGeometryRenderer );
 
  596   entity->setParent( parent );
 
  603 namespace Qgs3DSymbolImpl
 
  616       return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
 
  618       return new QgsInstancedPoint3DSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
 
  623     QgsFeature3DHandler *handler = handlerForPoint3DSymbol( layer, &symbol );
 
  624     Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );