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(
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(
QgsFeature &f,
const Qgs3DRenderContext &context )
105 LineData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
116 const int nSegments = 4;
119 const double mitreLimit = 0;
122 QgsAbstractGeometry *buffered = engine.buffer( mSymbol->width() / 2., nSegments, endCapStyle, joinStyle, mitreLimit );
129 processPolygon( polyBuffered, f.
id(), mSymbol->height(), mSymbol->extrusionHeight(), context, out );
137 processPolygon( polyBuffered, f.
id(), mSymbol->height(), mSymbol->extrusionHeight(), context, out );
143 void QgsBufferedLine3DSymbolHandler::processPolygon(
QgsPolygon *polyBuffered,
QgsFeatureId fid,
float height,
float extrusionHeight,
const Qgs3DRenderContext &context, LineData &out )
147 Q_ASSERT( out.tessellator->dataVerticesCount() % 3 == 0 );
148 uint startingTriangleIndex =
static_cast<uint
>( out.tessellator->dataVerticesCount() / 3 );
149 out.triangleIndexStartingIndices.append( startingTriangleIndex );
150 out.triangleIndexFids.append( fid );
151 out.tessellator->addPolygon( *polyBuffered, extrusionHeight );
155 void QgsBufferedLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
158 makeEntity( parent, context, outNormal,
false );
159 makeEntity( parent, context, outSelected,
true );
161 mZMin = std::min( outNormal.tessellator->zMinimum(), outSelected.tessellator->zMinimum() );
162 mZMax = std::max( outNormal.tessellator->zMaximum(), outSelected.tessellator->zMaximum() );
166 void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, LineData &out,
bool selected )
168 if ( out.tessellator->dataVerticesCount() == 0 )
174 Qt3DRender::QMaterial *mat = mSymbol->material()->toMaterial( QgsMaterialSettingsRenderingTechnique::Triangles, materialContext );
177 QByteArray data( (
const char * )out.tessellator->data().constData(), out.tessellator->data().count() *
sizeof(
float ) );
178 int nVerts = data.count() / out.tessellator->stride();
184 geometry->
setData( data, nVerts, out.triangleIndexFids, out.triangleIndexStartingIndices );
186 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
187 renderer->setGeometry( geometry );
190 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
191 entity->addComponent( renderer );
192 entity->addComponent( mat );
193 entity->setParent( parent );
196 entity->findChild<Qt3DRender::QGeometryRenderer *>()->setObjectName( QStringLiteral(
"main" ) );
206 class QgsSimpleLine3DSymbolHandler :
public QgsFeature3DHandler
211 , mSelectedIds( selectedIds )
215 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
216 void processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
217 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
221 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected );
222 Qt3DExtras::QPhongMaterial *material(
const QgsLine3DSymbol &symbol )
const;
225 std::unique_ptr< QgsLine3DSymbol > mSymbol;
230 QgsLineVertexData outNormal;
231 QgsLineVertexData outSelected;
236 bool QgsSimpleLine3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
238 Q_UNUSED( attributeNames )
240 outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
241 outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
246 void QgsSimpleLine3DSymbolHandler::processFeature(
QgsFeature &f,
const Qgs3DRenderContext &context )
252 QgsLineVertexData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
256 if (
const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
258 out.addLineString( *ls );
260 else if (
const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
262 for (
int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
265 out.addLineString( *ls );
270 void QgsSimpleLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
273 makeEntity( parent, context, outNormal,
false );
274 makeEntity( parent, context, outSelected,
true );
276 updateZRangeFromPositions( outNormal.vertices );
277 updateZRangeFromPositions( outSelected.vertices );
281 void QgsSimpleLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected )
283 if ( out.indexes.isEmpty() )
291 Qt3DRender::QMaterial *mat = mSymbol->material()->toMaterial( QgsMaterialSettingsRenderingTechnique::Lines, materialContext );
295 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
297 Qt3DRender::QGeometry *geom = out.createGeometry( entity );
299 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
300 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStrip );
301 renderer->setGeometry( geom );
302 renderer->setVertexCount( out.indexes.count() );
303 renderer->setPrimitiveRestartEnabled(
true );
304 renderer->setRestartIndexValue( 0 );
307 entity->addComponent( renderer );
308 entity->addComponent( mat );
309 entity->setParent( parent );
317 class QgsThickLine3DSymbolHandler :
public QgsFeature3DHandler
322 , mSelectedIds( selectedIds )
326 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
327 void processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
328 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
333 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected );
334 Qt3DExtras::QPhongMaterial *material(
const QgsLine3DSymbol &symbol )
const;
337 std::unique_ptr< QgsLine3DSymbol > mSymbol;
342 QgsLineVertexData outNormal;
343 QgsLineVertexData outSelected;
348 bool QgsThickLine3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
350 Q_UNUSED( attributeNames )
352 outNormal.withAdjacency =
true;
353 outSelected.withAdjacency =
true;
354 outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
355 outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
360 void QgsThickLine3DSymbolHandler::processFeature(
QgsFeature &f,
const Qgs3DRenderContext &context )
366 QgsLineVertexData &out = mSelectedIds.contains( f.
id() ) ? outSelected : outNormal;
370 if (
const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
372 out.addLineString( *ls );
374 else if (
const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
376 for (
int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
379 out.addLineString( *ls );
384 void QgsThickLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
387 makeEntity( parent, context, outNormal,
false );
388 makeEntity( parent, context, outSelected,
true );
390 updateZRangeFromPositions( outNormal.vertices );
391 updateZRangeFromPositions( outSelected.vertices );
395 void QgsThickLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, QgsLineVertexData &out,
bool selected )
397 if ( out.indexes.isEmpty() )
404 Qt3DRender::QMaterial *mat = mSymbol->material()->toMaterial( QgsMaterialSettingsRenderingTechnique::Lines, materialContext );
408 mat = defaultMaterial.
toMaterial( QgsMaterialSettingsRenderingTechnique::Lines, materialContext );
411 if ( QgsLineMaterial *lineMaterial =
dynamic_cast< QgsLineMaterial *
>( mat ) )
412 lineMaterial->setLineWidth( mSymbol->width() );
414 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
417 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
418 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
419 renderer->setGeometry( out.createGeometry( entity ) );
420 renderer->setVertexCount( out.indexes.count() );
421 renderer->setPrimitiveRestartEnabled(
true );
422 renderer->setRestartIndexValue( 0 );
425 entity->addComponent( renderer );
426 entity->addComponent( mat );
427 entity->setParent( parent );
434 namespace Qgs3DSymbolImpl
452 QgsFeature3DHandler *handler = handlerForLine3DSymbol( layer, &symbol );
453 Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );