22#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
23#include <Qt3DRender/QAttribute>
24#include <Qt3DRender/QBuffer>
28#include <Qt3DCore/QAttribute>
29#include <Qt3DCore/QBuffer>
39 , mWithNormals( _withNormals )
40 , mInvertNormals( _invertNormals )
41 , mAddBackFaces( _addBackFaces )
42 , mAddTextureCoords( _addTextureCoords )
46 const QgsTessellator tmpTess( 0, 0, mWithNormals,
false,
false,
false, mAddTextureCoords );
47 const int stride = tmpTess.
stride();
50 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
51 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
52 mPositionAttribute->setVertexSize( 3 );
53 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
54 mPositionAttribute->setBuffer( mVertexBuffer );
55 mPositionAttribute->setByteStride( stride );
56 mPositionAttribute->setByteOffset( 0 );
57 addAttribute( mPositionAttribute );
62 mNormalAttribute->setName( Qt3DQAttribute::defaultNormalAttributeName() );
63 mNormalAttribute->setVertexBaseType( Qt3DQAttribute::Float );
64 mNormalAttribute->setVertexSize( 3 );
65 mNormalAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
66 mNormalAttribute->setBuffer( mVertexBuffer );
67 mNormalAttribute->setByteStride( stride );
68 mNormalAttribute->setByteOffset( 3 *
sizeof(
float ) );
69 addAttribute( mNormalAttribute );
71 if ( mAddTextureCoords )
74 mTextureCoordsAttribute->setName( Qt3DQAttribute::defaultTextureCoordinateAttributeName() );
75 mTextureCoordsAttribute->setVertexBaseType( Qt3DQAttribute::Float );
76 mTextureCoordsAttribute->setVertexSize( 2 );
77 mTextureCoordsAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
78 mTextureCoordsAttribute->setBuffer( mVertexBuffer );
79 mTextureCoordsAttribute->setByteStride( stride );
80 mTextureCoordsAttribute->setByteOffset( mWithNormals ? 6 *
sizeof(
float ) : 3 *
sizeof( float ) );
81 addAttribute( mTextureCoordsAttribute );
87 Q_ASSERT( polygons.count() ==
featureIds.count() );
88 mTriangleIndexStartingIndices.reserve( polygons.count() );
89 mTriangleIndexFids.reserve( polygons.count() );
91 QgsTessellator tessellator( origin.
x(), origin.
y(), mWithNormals, mInvertNormals, mAddBackFaces,
false, mAddTextureCoords );
92 for (
int i = 0; i < polygons.count(); ++i )
95 const uint startingTriangleIndex =
static_cast<uint
>( tessellator.
dataVerticesCount() / 3 );
96 mTriangleIndexStartingIndices.append( startingTriangleIndex );
100 const float extr = extrusionHeightPerPolygon.
isEmpty() ? extrusionHeight : extrusionHeightPerPolygon.at( i );
103 if ( !tessellator.
error().isEmpty() )
108 qDeleteAll( polygons );
110 const QByteArray data( (
const char * )tessellator.
data().constData(), tessellator.
data().count() *
sizeof(
float ) );
111 const int nVerts = data.count() / tessellator.
stride();
113 mVertexBuffer->setData( data );
114 mPositionAttribute->setCount( nVerts );
115 if ( mNormalAttribute )
116 mNormalAttribute->setCount( nVerts );
117 if ( mAddTextureCoords )
118 mTextureCoordsAttribute->setCount( nVerts );
124 mTriangleIndexFids = triangleIndexFids;
126 mVertexBuffer->setData( vertexBufferData );
127 mPositionAttribute->setCount( vertexCount );
128 if ( mNormalAttribute )
129 mNormalAttribute->setCount( vertexCount );
130 if ( mTextureCoordsAttribute )
131 mTextureCoordsAttribute->setCount( vertexCount );
135static int binary_search( uint v,
const uint *data,
int count )
138 int idx1 = count - 1;
143 if ( v >= data[count - 1] )
146 while ( idx0 != idx1 )
148 const int idxPivot = ( idx0 + idx1 ) / 2;
149 const uint pivot = data[idxPivot];
152 if ( data[idxPivot + 1] > v )
166 const int i = binary_search( triangleIndex, mTriangleIndexStartingIndices.constData(), mTriangleIndexStartingIndices.count() );
167 return i != -1 ? mTriangleIndexFids[i] :
FID_NULL;
bool isEmpty() const override
Returns true if the geometry is empty.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
A class to represent a 2D point.
QVector< QgsFeatureId > featureIds() const
Returns included feature ids.
void setPolygons(const QList< QgsPolygon * > &polygons, const QList< QgsFeatureId > &featureIds, const QgsPointXY &origin, float extrusionHeight, const QList< float > &extrusionHeightPerPolygon=QList< float >())
Initializes vertex buffer from given polygons. Takes ownership of passed polygon geometries.
QgsFeatureId triangleIndexToFeatureId(uint triangleIndex) const
Returns ID of the feature to which given triangle index belongs (used for picking).
QgsTessellatedPolygonGeometry(bool _withNormals=true, bool invertNormals=false, bool addBackFaces=false, bool addTextureCoords=false, QNode *parent=nullptr)
Constructor.
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.
QVector< uint > triangleIndexStartingIndices() const
Returns triangle index for features. For a feature featureIds()[i], matching triangles start at trian...
Class that takes care of tessellation of polygons into triangles.
QVector< float > data() const
Returns array of triangle vertex data.
int stride() const
Returns size of one vertex entry in bytes.
void addPolygon(const QgsPolygon &polygon, float extrusionHeight)
Tessellates a triangle and adds its vertex entries to the output data array.
QString error() const
Returns a descriptive error string if the tessellation failed.
int dataVerticesCount() const
Returns the number of vertices stored in the output data array.
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer