QGIS API Documentation 3.34.0-Prizren (ffbdd678812)
Loading...
Searching...
No Matches
qgsline3dsymbol_p.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsline3dsymbol_p.cpp
3 --------------------------------------
4 Date : July 2017
5 Copyright : (C) 2017 by Martin Dobias
6 Email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsline3dsymbol_p.h"
17
18#include "qgsline3dsymbol.h"
19#include "qgslinematerial_p.h"
20#include "qgslinevertexdata_p.h"
22#include "qgstessellator.h"
23#include "qgs3dmapsettings.h"
24//#include "qgsterraingenerator.h"
25#include "qgs3dutils.h"
26
27#include "qgsvectorlayer.h"
28#include "qgsmultilinestring.h"
29#include "qgsmultipolygon.h"
30#include "qgsgeos.h"
32#include "qgspolygon.h"
34
35#include <Qt3DExtras/QPhongMaterial>
36#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
37#include <Qt3DRender/QAttribute>
38#include <Qt3DRender/QBuffer>
39
40typedef Qt3DRender::QAttribute Qt3DQAttribute;
41typedef Qt3DRender::QBuffer Qt3DQBuffer;
42typedef Qt3DRender::QGeometry Qt3DQGeometry;
43#else
44#include <Qt3DCore/QAttribute>
45#include <Qt3DCore/QBuffer>
46
47typedef Qt3DCore::QAttribute Qt3DQAttribute;
48typedef Qt3DCore::QBuffer Qt3DQBuffer;
49typedef Qt3DCore::QGeometry Qt3DQGeometry;
50#endif
51#include <Qt3DRender/QGeometryRenderer>
52
54
55// -----------
56
57
58class QgsBufferedLine3DSymbolHandler : public QgsFeature3DHandler
59{
60 public:
61 QgsBufferedLine3DSymbolHandler( const QgsLine3DSymbol *symbol, const QgsFeatureIds &selectedIds )
62 : mSymbol( static_cast< QgsLine3DSymbol *>( symbol->clone() ) )
63 , mSelectedIds( selectedIds ) {}
64
65 bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
66 void processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context ) override;
67 void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
68
69 private:
70
72 struct LineData
73 {
74 std::unique_ptr<QgsTessellator> tessellator;
75 QVector<QgsFeatureId> triangleIndexFids;
76 QVector<uint> triangleIndexStartingIndices;
77 };
78
79 void processPolygon( QgsPolygon *polyBuffered, QgsFeatureId fid, float height, float extrusionHeight, const Qgs3DRenderContext &context, LineData &out );
80
81 void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, LineData &out, bool selected );
82
83 // input specific for this class
84 std::unique_ptr< QgsLine3DSymbol > mSymbol;
85 // inputs - generic
86 QgsFeatureIds mSelectedIds;
87
88 // outputs
89 LineData outNormal;
90 LineData outSelected;
91};
92
93
94
95bool QgsBufferedLine3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
96{
97 Q_UNUSED( attributeNames )
98
99 const QgsPhongTexturedMaterialSettings *texturedMaterialSettings = dynamic_cast< const QgsPhongTexturedMaterialSettings * >( mSymbol->materialSettings() );
100
101 outNormal.tessellator.reset( new QgsTessellator( context.map().origin().x(), context.map().origin().y(), true,
102 false, false, false, texturedMaterialSettings ? texturedMaterialSettings->requiresTextureCoordinates() : false,
103 3,
104 texturedMaterialSettings ? texturedMaterialSettings->textureRotation() : 0 ) );
105 outSelected.tessellator.reset( new QgsTessellator( context.map().origin().x(), context.map().origin().y(), true,
106 false, false, false, texturedMaterialSettings ? texturedMaterialSettings->requiresTextureCoordinates() : false,
107 3,
108 texturedMaterialSettings ? texturedMaterialSettings->textureRotation() : 0 ) );
109
110 return true;
111}
112
113void QgsBufferedLine3DSymbolHandler::processFeature( const QgsFeature &f, const Qgs3DRenderContext &context )
114{
115 if ( f.geometry().isNull() )
116 return;
117
118 LineData &out = mSelectedIds.contains( f.id() ) ? outSelected : outNormal;
119
120 QgsGeometry geom = f.geometry();
122
123 // segmentize curved geometries if necessary
125 {
126 geom = QgsGeometry( g->segmentize() );
127 g = geom.constGet()->simplifiedTypeRef();
128 }
129
130 // TODO: configurable
131 const int nSegments = 4;
133 const Qgis::JoinStyle joinStyle = Qgis::JoinStyle::Round;
134 const double mitreLimit = 0;
135
136 const QgsGeos engine( g );
137
138 double width = mSymbol->width();
139 if ( qgsDoubleNear( width, 0 ) )
140 {
141 // a zero-width buffered line should be treated like a "wall" or "fence" -- we fake this by bumping the width to a very tiny amount,
142 // so that we get a very narrow polygon shape to work with...
143 width = 0.001;
144 }
145
146 QgsAbstractGeometry *buffered = engine.buffer( width / 2., nSegments, endCapStyle, joinStyle, mitreLimit ); // factory
147 if ( !buffered )
148 return;
149
151 {
152 QgsPolygon *polyBuffered = static_cast<QgsPolygon *>( buffered );
153 processPolygon( polyBuffered, f.id(), mSymbol->height(), mSymbol->extrusionHeight(), context, out );
154 }
155 else if ( QgsWkbTypes::flatType( buffered->wkbType() ) == Qgis::WkbType::MultiPolygon )
156 {
157 QgsMultiPolygon *mpolyBuffered = static_cast<QgsMultiPolygon *>( buffered );
158 for ( int i = 0; i < mpolyBuffered->numGeometries(); ++i )
159 {
160 QgsPolygon *polyBuffered = static_cast<QgsPolygon *>( mpolyBuffered->polygonN( i ) )->clone(); // need to clone individual geometry parts
161 processPolygon( polyBuffered, f.id(), mSymbol->height(), mSymbol->extrusionHeight(), context, out );
162 }
163 delete buffered;
164 }
165 mFeatureCount++;
166}
167
168void QgsBufferedLine3DSymbolHandler::processPolygon( QgsPolygon *polyBuffered, QgsFeatureId fid, float height, float extrusionHeight, const Qgs3DRenderContext &context, LineData &out )
169{
170 Qgs3DUtils::clampAltitudes( polyBuffered, mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), height, context.map() );
171
172 Q_ASSERT( out.tessellator->dataVerticesCount() % 3 == 0 );
173 const uint startingTriangleIndex = static_cast<uint>( out.tessellator->dataVerticesCount() / 3 );
174 out.triangleIndexStartingIndices.append( startingTriangleIndex );
175 out.triangleIndexFids.append( fid );
176 out.tessellator->addPolygon( *polyBuffered, extrusionHeight );
177 delete polyBuffered;
178}
179
180void QgsBufferedLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
181{
182 // create entity for selected and not selected
183 makeEntity( parent, context, outNormal, false );
184 makeEntity( parent, context, outSelected, true );
185
186 mZMin = std::min( outNormal.tessellator->zMinimum(), outSelected.tessellator->zMinimum() );
187 mZMax = std::max( outNormal.tessellator->zMaximum(), outSelected.tessellator->zMaximum() );
188}
189
190
191void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, LineData &out, bool selected )
192{
193 if ( out.tessellator->dataVerticesCount() == 0 )
194 return; // nothing to show - no need to create the entity
195
196 QgsMaterialContext materialContext;
197 materialContext.setIsSelected( selected );
198 materialContext.setSelectionColor( context.map().selectionColor() );
199 Qt3DRender::QMaterial *mat = mSymbol->materialSettings()->toMaterial( QgsMaterialSettingsRenderingTechnique::Triangles, materialContext );
200
201 // extract vertex buffer data from tessellator
202 const QByteArray data( ( const char * )out.tessellator->data().constData(), out.tessellator->data().count() * sizeof( float ) );
203 const int nVerts = data.count() / out.tessellator->stride();
204
205 const QgsPhongTexturedMaterialSettings *texturedMaterialSettings = dynamic_cast< const QgsPhongTexturedMaterialSettings * >( mSymbol->materialSettings() );
206
207 QgsTessellatedPolygonGeometry *geometry = new QgsTessellatedPolygonGeometry( true, false, false,
208 texturedMaterialSettings ? texturedMaterialSettings->requiresTextureCoordinates() : false );
209 geometry->setData( data, nVerts, out.triangleIndexFids, out.triangleIndexStartingIndices );
210
211 Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
212 renderer->setGeometry( geometry );
213
214 // make entity
215 Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
216 entity->addComponent( renderer );
217 entity->addComponent( mat );
218 entity->setParent( parent );
219
220 if ( !selected )
221 renderer->setProperty( Qgs3DTypes::PROP_NAME_3D_RENDERER_FLAG, Qgs3DTypes::Main3DRenderer ); // temporary measure to distinguish between "selected" and "main"
222
223 // cppcheck wrongly believes entity will leak
224 // cppcheck-suppress memleak
225}
226
227
228// --------------
229
230
231class QgsSimpleLine3DSymbolHandler : public QgsFeature3DHandler
232{
233 public:
234 QgsSimpleLine3DSymbolHandler( const QgsLine3DSymbol *symbol, const QgsFeatureIds &selectedIds )
235 : mSymbol( static_cast< QgsLine3DSymbol *>( symbol->clone() ) )
236 , mSelectedIds( selectedIds )
237 {
238 }
239
240 bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
241 void processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context ) override;
242 void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
243
244 private:
245
246 void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, QgsLineVertexData &out, bool selected );
247 Qt3DExtras::QPhongMaterial *material( const QgsLine3DSymbol &symbol ) const;
248
249 // input specific for this class
250 std::unique_ptr< QgsLine3DSymbol > mSymbol;
251 // inputs - generic
252 QgsFeatureIds mSelectedIds;
253
254 // outputs
255 QgsLineVertexData outNormal;
256 QgsLineVertexData outSelected;
257};
258
259
260
261bool QgsSimpleLine3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
262{
263 Q_UNUSED( attributeNames )
264
265 outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
266 outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
267
268 return true;
269}
270
271void QgsSimpleLine3DSymbolHandler::processFeature( const QgsFeature &f, const Qgs3DRenderContext &context )
272{
273 Q_UNUSED( context )
274 if ( f.geometry().isNull() )
275 return;
276
277 QgsLineVertexData &out = mSelectedIds.contains( f.id() ) ? outSelected : outNormal;
278
279 const QgsGeometry geom = f.geometry();
280 const QgsAbstractGeometry *g = geom.constGet();
281 if ( const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
282 {
283 out.addLineString( *ls );
284 }
285 else if ( const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
286 {
287 for ( int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
288 {
289 const QgsLineString *ls = mls->lineStringN( nGeom );
290 out.addLineString( *ls );
291 }
292 }
293 mFeatureCount++;
294}
295
296void QgsSimpleLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
297{
298 // create entity for selected and not selected
299 makeEntity( parent, context, outNormal, false );
300 makeEntity( parent, context, outSelected, true );
301
302 updateZRangeFromPositions( outNormal.vertices );
303 updateZRangeFromPositions( outSelected.vertices );
304}
305
306
307void QgsSimpleLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, QgsLineVertexData &out, bool selected )
308{
309 if ( out.indexes.isEmpty() )
310 return;
311
312 // material (only ambient color is used for the color)
313
314 QgsMaterialContext materialContext;
315 materialContext.setIsSelected( selected );
316 materialContext.setSelectionColor( context.map().selectionColor() );
317 Qt3DRender::QMaterial *mat = mSymbol->materialSettings()->toMaterial( QgsMaterialSettingsRenderingTechnique::Lines, materialContext );
318
319 // geometry renderer
320
321 Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
322
323 Qt3DQGeometry *geom = out.createGeometry( entity );
324
325 Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
326 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStrip );
327 renderer->setGeometry( geom );
328 renderer->setVertexCount( out.indexes.count() );
329 renderer->setPrimitiveRestartEnabled( true );
330 renderer->setRestartIndexValue( 0 );
331
332 // make entity
333 entity->addComponent( renderer );
334 entity->addComponent( mat );
335 entity->setParent( parent );
336}
337
338
339
340// --------------
341
342
343class QgsThickLine3DSymbolHandler : public QgsFeature3DHandler
344{
345 public:
346 QgsThickLine3DSymbolHandler( const QgsLine3DSymbol *symbol, const QgsFeatureIds &selectedIds )
347 : mSymbol( static_cast< QgsLine3DSymbol * >( symbol->clone() ) )
348 , mSelectedIds( selectedIds )
349 {
350 }
351
352 bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
353 void processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context ) override;
354 void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
355
356 private:
357
358
359 void makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, QgsLineVertexData &out, bool selected );
360 Qt3DExtras::QPhongMaterial *material( const QgsLine3DSymbol &symbol ) const;
361
362 // input specific for this class
363 std::unique_ptr< QgsLine3DSymbol > mSymbol;
364 // inputs - generic
365 QgsFeatureIds mSelectedIds;
366
367 // outputs
368 QgsLineVertexData outNormal;
369 QgsLineVertexData outSelected;
370};
371
372
373
374bool QgsThickLine3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
375{
376 Q_UNUSED( attributeNames )
377
378 outNormal.withAdjacency = true;
379 outSelected.withAdjacency = true;
380 outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
381 outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->height(), &context.map() );
382
383 return true;
384}
385
386void QgsThickLine3DSymbolHandler::processFeature( const QgsFeature &f, const Qgs3DRenderContext &context )
387{
388 Q_UNUSED( context )
389 if ( f.geometry().isNull() )
390 return;
391
392 QgsLineVertexData &out = mSelectedIds.contains( f.id() ) ? outSelected : outNormal;
393
394 QgsGeometry geom = f.geometry();
396
397 // segmentize curved geometries if necessary
399 {
400 geom = QgsGeometry( g->segmentize() );
401 g = geom.constGet()->simplifiedTypeRef();
402 }
403
404 if ( const QgsLineString *ls = qgsgeometry_cast<const QgsLineString *>( g ) )
405 {
406 out.addLineString( *ls );
407 }
408 else if ( const QgsMultiLineString *mls = qgsgeometry_cast<const QgsMultiLineString *>( g ) )
409 {
410 for ( int nGeom = 0; nGeom < mls->numGeometries(); ++nGeom )
411 {
412 const QgsLineString *ls = mls->lineStringN( nGeom );
413 out.addLineString( *ls );
414 }
415 }
416 mFeatureCount++;
417}
418
419void QgsThickLine3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context )
420{
421 // create entity for selected and not selected
422 makeEntity( parent, context, outNormal, false );
423 makeEntity( parent, context, outSelected, true );
424
425 updateZRangeFromPositions( outNormal.vertices );
426 updateZRangeFromPositions( outSelected.vertices );
427}
428
429
430void QgsThickLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context, QgsLineVertexData &out, bool selected )
431{
432 if ( out.indexes.isEmpty() )
433 return;
434
435 // material (only ambient color is used for the color)
436 QgsMaterialContext materialContext;
437 materialContext.setIsSelected( selected );
438 materialContext.setSelectionColor( context.map().selectionColor() );
439 Qt3DRender::QMaterial *mat = mSymbol->materialSettings()->toMaterial( QgsMaterialSettingsRenderingTechnique::Lines, materialContext );
440 if ( !mat )
441 {
442 const QgsSimpleLineMaterialSettings defaultMaterial;
443 mat = defaultMaterial.toMaterial( QgsMaterialSettingsRenderingTechnique::Lines, materialContext );
444 }
445
446 if ( QgsLineMaterial *lineMaterial = dynamic_cast< QgsLineMaterial * >( mat ) )
447 lineMaterial->setLineWidth( mSymbol->width() );
448
449 Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
450
451 // geometry renderer
452 Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
453 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::LineStripAdjacency );
454 renderer->setGeometry( out.createGeometry( entity ) );
455 renderer->setVertexCount( out.indexes.count() );
456 renderer->setPrimitiveRestartEnabled( true );
457 renderer->setRestartIndexValue( 0 );
458
459 // make entity
460 entity->addComponent( renderer );
461 entity->addComponent( mat );
462 entity->setParent( parent );
463}
464
465
466// --------------
467
468
469namespace Qgs3DSymbolImpl
470{
471
472 QgsFeature3DHandler *handlerForLine3DSymbol( QgsVectorLayer *layer, const QgsAbstract3DSymbol *symbol )
473 {
474 const QgsLine3DSymbol *lineSymbol = dynamic_cast< const QgsLine3DSymbol * >( symbol );
475 if ( !lineSymbol )
476 return nullptr;
477
478 if ( lineSymbol->renderAsSimpleLines() )
479 return new QgsThickLine3DSymbolHandler( lineSymbol, layer->selectedFeatureIds() );
480 //return new QgsSimpleLine3DSymbolHandler( symbol, layer->selectedFeatureIds() );
481 else
482 return new QgsBufferedLine3DSymbolHandler( lineSymbol, layer->selectedFeatureIds() );
483 }
484
485 Qt3DCore::QEntity *entityForLine3DSymbol( const Qgs3DMapSettings &map, QgsVectorLayer *layer, const QgsLine3DSymbol &symbol )
486 {
487 QgsFeature3DHandler *handler = handlerForLine3DSymbol( layer, &symbol );
488 Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );
489 delete handler;
490 return e;
491 }
492}
493
JoinStyle
Join styles for buffers.
Definition qgis.h:1599
@ Round
Use rounded joins.
EndCapStyle
End cap styles for buffers.
Definition qgis.h:1586
@ Round
Round cap.
@ Polygon
Polygon.
@ MultiPolygon
MultiPolygon.
@ Main3DRenderer
Renderer for normal entities.
Definition qgs3dtypes.h:49
static const char * PROP_NAME_3D_RENDERER_FLAG
Qt property name to hold the 3D geometry renderer flag.
Definition qgs3dtypes.h:44
static void clampAltitudes(QgsLineString *lineString, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, const QgsPoint &centroid, float height, const Qgs3DMapSettings &map)
Clamps altitude of vertices of a linestring according to the settings.
Abstract base class for all geometries.
virtual const QgsAbstractGeometry * simplifiedTypeRef() const
Returns a reference to the simplest lossless representation of this geometry, e.g.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:56
QgsFeatureId id
Definition qgsfeature.h:64
QgsGeometry geometry
Definition qgsfeature.h:67
int numGeometries() const
Returns the number of geometries within the collection.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Does vector analysis using the geos library and handles import, export, exception handling*.
Definition qgsgeos.h:99
bool renderAsSimpleLines() const
Returns whether the renderer will render data with simple lines (otherwise it uses buffer)
QgsAbstract3DSymbol * clone() const override SIP_FACTORY
Line string geometry type, with support for z-dimension and m-values.
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.
Multi line string geometry collection.
Multi polygon geometry collection.
QgsPolygon * polygonN(int index)
Returns the polygon with the specified index.
bool requiresTextureCoordinates() const
Returns true if the material requires texture coordinates to be generated during triangulation....
Polygon geometry type.
Definition qgspolygon.h:34
Qt3DRender::QMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const override
Creates a new QMaterial object representing the material settings.
void setData(const QByteArray &vertexBufferData, int vertexCount, const QVector< QgsFeatureId > &triangleIndexFids, const QVector< uint > &triangleIndexStartingIndices)
Initializes vertex buffer (and other members) from data that were already tessellated.
Class that takes care of tessellation of polygons into triangles.
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.
static bool isCurvedType(Qgis::WkbType type)
Returns true if the WKB type is a curved type or can contain curved geometries.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
@ Triangles
Triangle based rendering (default)
@ Lines
Line based rendering, requires line data.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:4332
Qt3DCore::QGeometry Qt3DQGeometry
Definition qgs3daxis.cpp:29
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer
Qt3DCore::QGeometry Qt3DQGeometry