20#include <Qt3DCore/QAttribute>
21#include <Qt3DCore/QBuffer>
23#include "moc_qgsbillboardgeometry.cpp"
25using namespace Qt::StringLiterals;
29 , mVertexBuffer( new
Qt3DCore::QBuffer( this ) )
31 static constexpr float quadVertices[] = { -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f };
32 Qt3DCore::QBuffer *quadVertexBuffer =
new Qt3DCore::QBuffer(
this );
33 quadVertexBuffer->setData( QByteArray(
reinterpret_cast<const char *
>( quadVertices ),
sizeof( quadVertices ) ) );
35 Qt3DCore::QAttribute *quadVertexAttribute =
new Qt3DCore::QAttribute(
this );
36 quadVertexAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
37 quadVertexAttribute->setBuffer( quadVertexBuffer );
38 quadVertexAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
39 quadVertexAttribute->setVertexSize( 2 );
40 quadVertexAttribute->setByteOffset( 0 );
41 quadVertexAttribute->setByteStride( 2 *
sizeof(
float ) );
42 quadVertexAttribute->setCount( 4 );
43 quadVertexAttribute->setName( u
"vertexPosition"_s );
44 addAttribute( quadVertexAttribute );
46 setAttributes( Attribute::Position );
49void QgsBillboardGeometry::setAttributes( QgsBillboardGeometry::Attributes attributes )
52 Q_ASSERT( attributes.testFlag( Attribute::Position ) );
54 if ( mAttributes == attributes )
57 mAttributes = attributes;
60 uint stride = 3 *
sizeof( float );
61 if ( attributes.testFlag( Attribute::Size ) )
63 stride += 2 *
sizeof( float );
65 if ( attributes.testFlag( Attribute::TextureData ) )
67 stride += ( 2 + 2 ) *
sizeof(
float );
69 if ( attributes.testFlag( Attribute::PixelOffsets ) )
71 stride += 2 *
sizeof( int );
74 if ( mPositionAttribute )
76 removeAttribute( mPositionAttribute );
77 delete mPositionAttribute;
78 mPositionAttribute =
nullptr;
82 mPositionAttribute =
new Qt3DCore::QAttribute(
this );
83 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
84 mPositionAttribute->setBuffer( mVertexBuffer );
85 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
86 mPositionAttribute->setVertexSize( 3 );
87 mPositionAttribute->setByteOffset( offset );
88 mPositionAttribute->setByteStride( stride );
89 mPositionAttribute->setDivisor( 1 );
90 mPositionAttribute->setName(
"instancePosition" );
91 addAttribute( mPositionAttribute );
92 setBoundingVolumePositionAttribute( mPositionAttribute );
93 offset += 3 *
sizeof( float );
95 if ( attributes.testFlag( Attribute::Size ) )
97 mSizeAttribute =
new Qt3DCore::QAttribute(
this );
98 mSizeAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
99 mSizeAttribute->setBuffer( mVertexBuffer );
100 mSizeAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
101 mSizeAttribute->setVertexSize( 2 );
102 mSizeAttribute->setByteOffset( offset );
103 mSizeAttribute->setByteStride( stride );
104 mSizeAttribute->setDivisor( 1 );
105 mSizeAttribute->setName( u
"instanceSize"_s );
106 addAttribute( mSizeAttribute );
107 offset += 2 *
sizeof( float );
111 removeAttribute( mSizeAttribute );
112 delete mSizeAttribute;
113 mSizeAttribute =
nullptr;
116 if ( attributes.testFlag( Attribute::TextureData ) )
118 mAtlasOffsetAttribute =
new Qt3DCore::QAttribute(
this );
119 mAtlasOffsetAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
120 mAtlasOffsetAttribute->setBuffer( mVertexBuffer );
121 mAtlasOffsetAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
122 mAtlasOffsetAttribute->setVertexSize( 2 );
123 mAtlasOffsetAttribute->setByteOffset( offset );
124 mAtlasOffsetAttribute->setByteStride( stride );
125 mAtlasOffsetAttribute->setDivisor( 1 );
126 mAtlasOffsetAttribute->setName( u
"atlasOffset"_s );
127 addAttribute( mAtlasOffsetAttribute );
128 offset += 2 *
sizeof( float );
130 mAtlasSizeAttribute =
new Qt3DCore::QAttribute(
this );
131 mAtlasSizeAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
132 mAtlasSizeAttribute->setBuffer( mVertexBuffer );
133 mAtlasSizeAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
134 mAtlasSizeAttribute->setVertexSize( 2 );
135 mAtlasSizeAttribute->setByteOffset( offset );
136 mAtlasSizeAttribute->setByteStride( stride );
137 mAtlasSizeAttribute->setDivisor( 1 );
138 mAtlasSizeAttribute->setName( u
"atlasSize"_s );
139 addAttribute( mAtlasSizeAttribute );
140 offset += 2 *
sizeof( float );
144 if ( mAtlasOffsetAttribute )
146 removeAttribute( mAtlasOffsetAttribute );
147 delete mAtlasOffsetAttribute;
148 mAtlasOffsetAttribute =
nullptr;
150 if ( mAtlasSizeAttribute )
152 removeAttribute( mAtlasSizeAttribute );
153 delete mAtlasSizeAttribute;
154 mAtlasSizeAttribute =
nullptr;
158 if ( attributes.testFlag( Attribute::PixelOffsets ) )
160 mAtlasPixelOffsetAttribute =
new Qt3DCore::QAttribute(
this );
161 mAtlasPixelOffsetAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
162 mAtlasPixelOffsetAttribute->setBuffer( mVertexBuffer );
163 mAtlasPixelOffsetAttribute->setVertexBaseType( Qt3DCore::QAttribute::Int );
164 mAtlasPixelOffsetAttribute->setVertexSize( 2 );
165 mAtlasPixelOffsetAttribute->setByteOffset( offset );
166 mAtlasPixelOffsetAttribute->setByteStride( stride );
167 mAtlasPixelOffsetAttribute->setDivisor( 1 );
168 mAtlasPixelOffsetAttribute->setName( u
"pixelOffset"_s );
169 addAttribute( mAtlasPixelOffsetAttribute );
170 offset += 2 *
sizeof( int );
174 removeAttribute( mAtlasPixelOffsetAttribute );
175 delete mAtlasPixelOffsetAttribute;
176 mAtlasPixelOffsetAttribute =
nullptr;
182 setAttributes( Attribute::Position );
184 QByteArray vertexBufferData;
185 vertexBufferData.resize( vertices.size() * 3 *
sizeof(
float ) );
186 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
188 for (
const auto &v : vertices )
190 rawVertexArray[idx++] = v.x();
191 rawVertexArray[idx++] = v.y();
192 rawVertexArray[idx++] = v.z();
195 mVertexCount = vertices.count();
196 mVertexBuffer->setData( vertexBufferData );
197 mPositionAttribute->setCount( mVertexCount );
204 Attributes attributes = Attribute::Position;
205 attributes.setFlag( Attribute::Size );
206 setAttributes( attributes );
208 const qsizetype size = std::min( positions.size(), sizes.size() );
209 QByteArray vertexBufferData;
210 vertexBufferData.resize( size * ( 3 + 2 ) *
sizeof(
float ) );
211 float *rawArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
213 for ( qsizetype i = 0; i < size; ++i )
215 rawArray[idx++] = positions[i].x();
216 rawArray[idx++] = positions[i].y();
217 rawArray[idx++] = positions[i].z();
219 rawArray[idx++] = sizes[i].width();
220 rawArray[idx++] = sizes[i].height();
224 mVertexBuffer->setData( vertexBufferData );
225 mPositionAttribute->setCount( mVertexCount );
226 mSizeAttribute->setCount( mVertexCount );
232#pragma pack( push, 1 )
233struct BillboardVertex
236 float textureAtlasOffset[2];
237 float textureAtlasSize[2];
240struct BillboardVertexWithPixelOffset : BillboardVertex
246template<
typename VertexType> QByteArray createVertexBuffer(
const QVector<QgsBillboardGeometry::BillboardAtlasData> &billboards )
249 buffer.resize( billboards.size() *
sizeof( VertexType ) );
250 auto *vertexData =
reinterpret_cast<VertexType *
>( buffer.data() );
255 VertexType &vertex = vertexData[idx++];
257 vertex.position[0] = billboard.position.x();
258 vertex.position[1] = billboard.position.y();
259 vertex.position[2] = billboard.position.z();
261 vertex.textureAtlasOffset[0] = billboard.textureAtlasOffset.x();
262 vertex.textureAtlasOffset[1] = billboard.textureAtlasOffset.y();
264 vertex.textureAtlasSize[0] = billboard.textureAtlasSize.x();
265 vertex.textureAtlasSize[1] = billboard.textureAtlasSize.y();
267 if constexpr ( std::is_same_v<VertexType, BillboardVertexWithPixelOffset> )
269 vertex.pixelOffset[0] = billboard.pixelOffset.x();
270 vertex.pixelOffset[1] = billboard.pixelOffset.y();
279 Attributes attributes = Attribute::Position;
280 attributes.setFlag( Attribute::TextureData,
true );
281 attributes.setFlag( Attribute::PixelOffsets, includePixelOffsets );
282 setAttributes( attributes );
284 QByteArray vertexBufferData;
285 if ( includePixelOffsets )
287 vertexBufferData = createVertexBuffer<BillboardVertexWithPixelOffset>( billboards );
291 vertexBufferData = createVertexBuffer<BillboardVertex>( billboards );
294 mVertexCount = billboards.count();
295 mVertexBuffer->setData( vertexBufferData );
296 mPositionAttribute->setCount( mVertexCount );
void countChanged(int count)
Signal when the number of points changed.
void setBillboardData(const QVector< QgsBillboardGeometry::BillboardAtlasData > &billboards, bool includePixelOffsets=false)
Set the position and texture data for the billboard.
void setPositions(const QVector< QVector3D > &vertices)
Sets the vertex positions for the billboards.
QgsBillboardGeometry(Qt3DCore::QNode *parent=nullptr)
Constructor of QgsBillboardGeometry.
void setPositionsAndSizes(const QVector< QVector3D > &positions, const QVector< QSizeF > &sizes)
Sets per-instance positions and sizes for billboards sharing a single texture.
Contains the billboard positions and texture information.