25 #include <Qt3DCore/QTransform> 
   26 #include <Qt3DRender/QMaterial> 
   27 #include <Qt3DExtras/QPhongMaterial> 
   29 #include <Qt3DExtras/QDiffuseMapMaterial> 
   30 #include <Qt3DRender/QAbstractTextureImage> 
   31 #include <Qt3DRender/QTexture> 
   33 #include <Qt3DRender/QEffect> 
   34 #include <Qt3DRender/QTechnique> 
   35 #include <Qt3DRender/QCullFace> 
   36 #include <Qt3DRender/QGeometryRenderer> 
   50 class QgsPolygon3DSymbolHandler : 
public QgsFeature3DHandler
 
   55       , mSelectedIds( selectedIds ) {}
 
   57     bool prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) 
override;
 
   58     void processFeature( 
const QgsFeature &f, 
const Qgs3DRenderContext &context ) 
override;
 
   59     void finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context ) 
override;
 
   66       std::unique_ptr<QgsTessellator> tessellator;
 
   67       QVector<QgsFeatureId> triangleIndexFids;
 
   68       QVector<uint> triangleIndexStartingIndices;
 
   69       QByteArray materialDataDefined;
 
   72     void processPolygon( 
QgsPolygon *polyClone, 
QgsFeatureId fid, 
float height, 
float extrusionHeight, 
const Qgs3DRenderContext &context, PolygonData &out );
 
   73     void processMaterialDatadefined( uint verticesCount, 
const QgsExpressionContext &context, PolygonData &out );
 
   74     void makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PolygonData &out, 
bool selected );
 
   75     Qt3DRender::QMaterial *material( 
const QgsPolygon3DSymbol *symbol, 
bool isSelected, 
const Qgs3DRenderContext &context ) 
const;
 
   78     std::unique_ptr< QgsPolygon3DSymbol > mSymbol;
 
   83     PolygonData outNormal;  
 
   84     PolygonData outSelected;  
 
   86     QgsLineVertexData outEdges;  
 
   90 bool QgsPolygon3DSymbolHandler::prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
 
   92   outEdges.withAdjacency = 
true;
 
   93   outEdges.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), 0, &context.map() );
 
   97   outNormal.tessellator.reset( 
new QgsTessellator( context.map().origin().x(), context.map().origin().y(), 
true, mSymbol->invertNormals(), mSymbol->addBackFaces(), 
false,
 
   99                                mSymbol->renderedFacade(),
 
  100                                texturedMaterialSettings ? texturedMaterialSettings->
textureRotation() : 0 ) );
 
  101   outSelected.tessellator.reset( 
new QgsTessellator( context.map().origin().x(), context.map().origin().y(), 
true, mSymbol->invertNormals(),
 
  102                                  mSymbol->addBackFaces(), 
false,
 
  104                                  mSymbol->renderedFacade(),
 
  105                                  texturedMaterialSettings ? texturedMaterialSettings->
textureRotation() : 0 ) );
 
  108   attributeNames.unite( attrs );
 
  109   attrs = mSymbol->material()->dataDefinedProperties().referencedFields( context.expressionContext() );
 
  110   attributeNames.unite( attrs );
 
  114 void QgsPolygon3DSymbolHandler::processPolygon( 
QgsPolygon *polyClone, 
QgsFeatureId fid, 
float height, 
float extrusionHeight, 
const Qgs3DRenderContext &context, PolygonData &out )
 
  116   const uint oldVerticesCount = out.tessellator->dataVerticesCount();
 
  117   if ( mSymbol->edgesEnabled() )
 
  124     if ( extrusionHeight )
 
  128       outEdges.addLineString( *exterior, extrusionHeight + height );
 
  129       outEdges.addVerticalLines( *exterior, extrusionHeight, height );
 
  133         outEdges.addLineString( *interior, extrusionHeight + height );
 
  134         outEdges.addVerticalLines( *interior, extrusionHeight, height );
 
  141   Q_ASSERT( out.tessellator->dataVerticesCount() % 3 == 0 );
 
  142   const uint startingTriangleIndex = 
static_cast<uint
>( out.tessellator->dataVerticesCount() / 3 );
 
  143   out.triangleIndexStartingIndices.append( startingTriangleIndex );
 
  144   out.triangleIndexFids.append( fid );
 
  145   out.tessellator->addPolygon( *polyClone, extrusionHeight );
 
  148   if ( mSymbol->material()->dataDefinedProperties().hasActiveProperties() )
 
  149     processMaterialDatadefined( out.tessellator->dataVerticesCount() - oldVerticesCount, context.expressionContext(), out );
 
  152 void QgsPolygon3DSymbolHandler::processMaterialDatadefined( uint verticesCount, 
const QgsExpressionContext &context, QgsPolygon3DSymbolHandler::PolygonData &out )
 
  154   const QByteArray bytes = mSymbol->material()->dataDefinedVertexColorsAsByte( context );
 
  155   out.materialDataDefined.append( bytes.repeated( verticesCount ) );
 
  158 void QgsPolygon3DSymbolHandler::processFeature( 
const QgsFeature &f, 
const Qgs3DRenderContext &context )
 
  163   PolygonData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
 
  179   float height = mSymbol->height();
 
  180   float extrusionHeight = mSymbol->extrusionHeight();
 
  183   if ( hasDDExtrusion )
 
  186   if ( 
const QgsPolygon *poly = qgsgeometry_cast< const QgsPolygon *>( g ) )
 
  189     processPolygon( polyClone, f.
id(), height, extrusionHeight, context, out );
 
  191   else if ( 
const QgsMultiPolygon *mpoly = qgsgeometry_cast< const QgsMultiPolygon *>( g ) )
 
  193     for ( 
int i = 0; i < mpoly->numGeometries(); ++i )
 
  196       processPolygon( polyClone, f.
id(), height, extrusionHeight, context, out );
 
  201     for ( 
int i = 0; i < gc->numGeometries(); ++i )
 
  207         processPolygon( polyClone, f.
id(), height, extrusionHeight, context, out );
 
  212     qWarning() << 
"not a polygon";
 
  217 void QgsPolygon3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  220   makeEntity( parent, context, outNormal, 
false );
 
  221   makeEntity( parent, context, outSelected, 
true );
 
  223   mZMin = std::min( outNormal.tessellator->zMinimum(), outSelected.tessellator->zMinimum() );
 
  224   mZMax = std::max( outNormal.tessellator->zMaximum(), outSelected.tessellator->zMaximum() );
 
  227   if ( mSymbol->edgesEnabled() && !outEdges.indexes.isEmpty() )
 
  229     QgsLineMaterial *mat = 
new QgsLineMaterial;
 
  230     mat->setLineColor( mSymbol->edgeColor() );
 
  231     mat->setLineWidth( mSymbol->edgeWidth() );
 
  233     Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  236     Qt3DRender::QGeometryRenderer *renderer = 
new Qt3DRender::QGeometryRenderer;
 
  237     renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
 
  238     renderer->setGeometry( outEdges.createGeometry( entity ) );
 
  239     renderer->setVertexCount( outEdges.indexes.count() );
 
  240     renderer->setPrimitiveRestartEnabled( 
true );
 
  241     renderer->setRestartIndexValue( 0 );
 
  244     entity->addComponent( renderer );
 
  245     entity->addComponent( mat );
 
  246     entity->setParent( parent );
 
  251 void QgsPolygon3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, PolygonData &out, 
bool selected )
 
  253   if ( out.tessellator->dataVerticesCount() == 0 )
 
  256   Qt3DRender::QMaterial *mat = material( mSymbol.get(), selected, context );
 
  259   const QByteArray data( ( 
const char * )out.tessellator->data().constData(), out.tessellator->data().count() * 
sizeof( 
float ) );
 
  260   const int nVerts = data.count() / out.tessellator->stride();
 
  266   geometry->
setData( data, nVerts, out.triangleIndexFids, out.triangleIndexStartingIndices );
 
  267   if ( mSymbol->material()->dataDefinedProperties().hasActiveProperties() )
 
  268     mSymbol->material()->applyDataDefinedToGeometry( geometry, nVerts, out.materialDataDefined );
 
  270   Qt3DRender::QGeometryRenderer *renderer = 
new Qt3DRender::QGeometryRenderer;
 
  271   renderer->setGeometry( geometry );
 
  274   Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  275   entity->addComponent( renderer );
 
  276   entity->addComponent( mat );
 
  277   entity->setParent( parent );
 
  280     entity->findChild<Qt3DRender::QGeometryRenderer *>()->setObjectName( QStringLiteral( 
"main" ) ); 
 
  295   return Qt3DRender::QCullFace::NoCulling;
 
  301   const auto techniques = material->effect()->techniques();
 
  302   for ( 
auto tit = techniques.constBegin(); tit != techniques.constEnd(); ++tit )
 
  304     auto renderPasses = ( *tit )->renderPasses();
 
  305     for ( 
auto rpit = renderPasses.begin(); rpit != renderPasses.end(); ++rpit )
 
  307       Qt3DRender::QCullFace *cullFace = 
new Qt3DRender::QCullFace;
 
  308       cullFace->setMode( _qt3DcullingMode( cullingMode ) );
 
  309       ( *rpit )->addRenderState( cullFace );
 
  314 Qt3DRender::QMaterial *QgsPolygon3DSymbolHandler::material( 
const QgsPolygon3DSymbol *symbol, 
bool isSelected, 
const Qgs3DRenderContext &context )
 const 
  320   const bool dataDefined = mSymbol->material()->dataDefinedProperties().hasActiveProperties();
 
  324   applyCullingMode( symbol->
cullingMode(), material );
 
  332 namespace Qgs3DSymbolImpl
 
  339     if ( !polygonSymbol )
 
  347     QgsFeature3DHandler *handler = handlerForPolygon3DSymbol( layer, &symbol );
 
  348     Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );