35 #include <Qt3DExtras/QPhongMaterial> 
   36 #include <Qt3DRender/QAttribute> 
   37 #include <Qt3DRender/QBuffer> 
   38 #include <Qt3DRender/QGeometryRenderer> 
   45 class QgsBufferedLine3DSymbolHandler : 
public QgsFeature3DHandler
 
   50       , mSelectedIds( selectedIds ) {}
 
   52     bool prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) 
override;
 
   53     void processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context ) 
override;
 
   54     void finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context ) 
override;
 
   61       std::unique_ptr<QgsTessellator> tessellator;
 
   62       QVector<QgsFeatureId> triangleIndexFids;
 
   63       QVector<uint> triangleIndexStartingIndices;
 
   66     void processPolygon( 
QgsPolygon *polyBuffered, 
QgsFeatureId fid, 
float height, 
float extrusionHeight, 
const Qgs3DRenderContext &context, LineData &out );
 
   68     void makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, LineData &out, 
bool selected );
 
   71     std::unique_ptr< QgsLine3DSymbol > mSymbol;
 
   82 bool QgsBufferedLine3DSymbolHandler::prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
 
   84   Q_UNUSED( attributeNames )
 
   88   outNormal.tessellator.reset( 
new QgsTessellator( context.map().origin().x(), context.map().origin().y(), 
true,
 
   91                                texturedMaterialSettings ? texturedMaterialSettings->
textureRotation() : 0 ) );
 
   92   outSelected.tessellator.reset( 
new QgsTessellator( context.map().origin().x(), context.map().origin().y(), 
true,
 
   95                                  texturedMaterialSettings ? texturedMaterialSettings->
textureRotation() : 0 ) );
 
  100 void QgsBufferedLine3DSymbolHandler::processFeature( 
const QgsFeature &f, 
const Qgs3DRenderContext &context )
 
  105   LineData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
 
  118   const int nSegments = 4;
 
  121   const double mitreLimit = 0;
 
  125   double width = mSymbol->width();
 
  133   QgsAbstractGeometry *buffered = engine.buffer( width / 2., nSegments, endCapStyle, joinStyle, mitreLimit ); 
 
  140     processPolygon( polyBuffered, f.
id(), mSymbol->height(), mSymbol->extrusionHeight(), context, out );
 
  148       processPolygon( polyBuffered, f.
id(), mSymbol->height(), mSymbol->extrusionHeight(), context, out );
 
  155 void QgsBufferedLine3DSymbolHandler::processPolygon( 
QgsPolygon *polyBuffered, 
QgsFeatureId fid, 
float height, 
float extrusionHeight, 
const Qgs3DRenderContext &context, LineData &out )
 
  159   Q_ASSERT( out.tessellator->dataVerticesCount() % 3 == 0 );
 
  160   const uint startingTriangleIndex = 
static_cast<uint
>( out.tessellator->dataVerticesCount() / 3 );
 
  161   out.triangleIndexStartingIndices.append( startingTriangleIndex );
 
  162   out.triangleIndexFids.append( fid );
 
  163   out.tessellator->addPolygon( *polyBuffered, extrusionHeight );
 
  167 void QgsBufferedLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  170   makeEntity( parent, context, outNormal, 
false );
 
  171   makeEntity( parent, context, outSelected, 
true );
 
  173   mZMin = std::min( outNormal.tessellator->zMinimum(), outSelected.tessellator->zMinimum() );
 
  174   mZMax = std::max( outNormal.tessellator->zMaximum(), outSelected.tessellator->zMaximum() );
 
  178 void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, LineData &out, 
bool selected )
 
  180   if ( out.tessellator->dataVerticesCount() == 0 )
 
  189   const QByteArray data( ( 
const char * )out.tessellator->data().constData(), out.tessellator->data().count() * 
sizeof( 
float ) );
 
  190   const int nVerts = data.count() / out.tessellator->stride();
 
  196   geometry->
setData( data, nVerts, out.triangleIndexFids, out.triangleIndexStartingIndices );
 
  198   Qt3DRender::QGeometryRenderer *renderer = 
new Qt3DRender::QGeometryRenderer;
 
  199   renderer->setGeometry( geometry );
 
  202   Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  203   entity->addComponent( renderer );
 
  204   entity->addComponent( mat );
 
  205   entity->setParent( parent );
 
  208     entity->findChild<Qt3DRender::QGeometryRenderer *>()->setObjectName( QStringLiteral( 
"main" ) ); 
 
  218 class QgsSimpleLine3DSymbolHandler : 
public QgsFeature3DHandler
 
  223       , mSelectedIds( selectedIds )
 
  227     bool prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) 
override;
 
  228     void processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context ) 
override;
 
  229     void finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context ) 
override;
 
  233     void makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, QgsLineVertexData &out, 
bool selected );
 
  234     Qt3DExtras::QPhongMaterial *material( 
const QgsLine3DSymbol &symbol ) 
const;
 
  237     std::unique_ptr< QgsLine3DSymbol > mSymbol;
 
  242     QgsLineVertexData outNormal;  
 
  243     QgsLineVertexData outSelected;  
 
  248 bool QgsSimpleLine3DSymbolHandler::prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
 
  250   Q_UNUSED( attributeNames )
 
  252   outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
 
  253   outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
 
  258 void QgsSimpleLine3DSymbolHandler::processFeature( 
const QgsFeature &f, 
const Qgs3DRenderContext &context )
 
  264   QgsLineVertexData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
 
  268   if ( 
const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
 
  270     out.addLineString( *ls );
 
  272   else if ( 
const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
 
  274     for ( 
int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
 
  277       out.addLineString( *ls );
 
  283 void QgsSimpleLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  286   makeEntity( parent, context, outNormal, 
false );
 
  287   makeEntity( parent, context, outSelected, 
true );
 
  289   updateZRangeFromPositions( outNormal.vertices );
 
  290   updateZRangeFromPositions( outSelected.vertices );
 
  294 void QgsSimpleLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, QgsLineVertexData &out, 
bool selected )
 
  296   if ( out.indexes.isEmpty() )
 
  308   Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  310   Qt3DRender::QGeometry *geom = out.createGeometry( entity );
 
  312   Qt3DRender::QGeometryRenderer *renderer = 
new Qt3DRender::QGeometryRenderer;
 
  313   renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStrip );
 
  314   renderer->setGeometry( geom );
 
  315   renderer->setVertexCount( out.indexes.count() );
 
  316   renderer->setPrimitiveRestartEnabled( 
true );
 
  317   renderer->setRestartIndexValue( 0 );
 
  320   entity->addComponent( renderer );
 
  321   entity->addComponent( mat );
 
  322   entity->setParent( parent );
 
  330 class QgsThickLine3DSymbolHandler : 
public QgsFeature3DHandler
 
  335       , mSelectedIds( selectedIds )
 
  339     bool prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) 
override;
 
  340     void processFeature( 
const QgsFeature &feature, 
const Qgs3DRenderContext &context ) 
override;
 
  341     void finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context ) 
override;
 
  346     void makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, QgsLineVertexData &out, 
bool selected );
 
  347     Qt3DExtras::QPhongMaterial *material( 
const QgsLine3DSymbol &symbol ) 
const;
 
  350     std::unique_ptr< QgsLine3DSymbol > mSymbol;
 
  355     QgsLineVertexData outNormal;  
 
  356     QgsLineVertexData outSelected;  
 
  361 bool QgsThickLine3DSymbolHandler::prepare( 
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
 
  363   Q_UNUSED( attributeNames )
 
  365   outNormal.withAdjacency = 
true;
 
  366   outSelected.withAdjacency = 
true;
 
  367   outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
 
  368   outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
 
  373 void QgsThickLine3DSymbolHandler::processFeature( 
const QgsFeature &f, 
const Qgs3DRenderContext &context )
 
  379   QgsLineVertexData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
 
  391   if ( 
const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
 
  393     out.addLineString( *ls );
 
  395   else if ( 
const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
 
  397     for ( 
int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
 
  400       out.addLineString( *ls );
 
  406 void QgsThickLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context )
 
  409   makeEntity( parent, context, outNormal, 
false );
 
  410   makeEntity( parent, context, outSelected, 
true );
 
  412   updateZRangeFromPositions( outNormal.vertices );
 
  413   updateZRangeFromPositions( outSelected.vertices );
 
  417 void QgsThickLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, 
const Qgs3DRenderContext &context, QgsLineVertexData &out, 
bool selected )
 
  419   if ( out.indexes.isEmpty() )
 
  433   if ( QgsLineMaterial *lineMaterial = 
dynamic_cast< QgsLineMaterial * 
>( mat ) )
 
  434     lineMaterial->setLineWidth( mSymbol->width() );
 
  436   Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity;
 
  439   Qt3DRender::QGeometryRenderer *renderer = 
new Qt3DRender::QGeometryRenderer;
 
  440   renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
 
  441   renderer->setGeometry( out.createGeometry( entity ) );
 
  442   renderer->setVertexCount( out.indexes.count() );
 
  443   renderer->setPrimitiveRestartEnabled( 
true );
 
  444   renderer->setRestartIndexValue( 0 );
 
  447   entity->addComponent( renderer );
 
  448   entity->addComponent( mat );
 
  449   entity->setParent( parent );
 
  456 namespace Qgs3DSymbolImpl
 
  474     QgsFeature3DHandler *handler = handlerForLine3DSymbol( layer, &symbol );
 
  475     Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );