QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
qgsbillboardgeometry.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsbillboardgeometry.cpp
3 --------------------------------------
4 Date : Jul 2019
5 Copyright : (C) 2019 by Ismail Sunni
6 Email : imajimatika 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 <QVector3D>
17
18#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
19#include <Qt3DRender/QAttribute>
20#include <Qt3DRender/QBuffer>
21
22typedef Qt3DRender::QAttribute Qt3DQAttribute;
23typedef Qt3DRender::QBuffer Qt3DQBuffer;
24#else
25#include <Qt3DCore/QAttribute>
26#include <Qt3DCore/QBuffer>
27
28typedef Qt3DCore::QAttribute Qt3DQAttribute;
29typedef Qt3DCore::QBuffer Qt3DQBuffer;
30#endif
31
33#include "moc_qgsbillboardgeometry.cpp"
34
36 : QGeometry( parent )
37 , mVertexBuffer( new Qt3DQBuffer( this ) )
38{
39 setMode( Mode::PositionOnly );
40}
41
42void QgsBillboardGeometry::setMode( Mode mode )
43{
44 uint stride = 0;
45 switch ( mode )
46 {
47 case Mode::PositionOnly:
48 stride = 3 * sizeof( float );
49 break;
50 case Mode::PositionAndTextureData:
51 stride = ( 3 + 2 + 2 ) * sizeof( float );
52 break;
53 case Mode::PositionAndTextureDataWithPixelOffsets:
54 stride = ( 3 + 2 + 2 ) * sizeof( float ) + 2 * sizeof( int );
55 break;
56 }
57
58 if ( mPositionAttribute && mPositionAttribute->byteStride() == stride )
59 {
60 // already in the target mode
61 return;
62 }
63 else if ( mPositionAttribute )
64 {
65 removeAttribute( mPositionAttribute );
66 delete mPositionAttribute;
67 mPositionAttribute = nullptr;
68 }
69
70 mPositionAttribute = new Qt3DQAttribute( this );
71 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
72 mPositionAttribute->setBuffer( mVertexBuffer );
73 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
74 mPositionAttribute->setVertexSize( 3 );
75 mPositionAttribute->setByteOffset( 0 );
76 mPositionAttribute->setByteStride( stride );
77 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
78 addAttribute( mPositionAttribute );
79
80 switch ( mode )
81 {
82 case Mode::PositionOnly:
83 {
84 if ( mAtlasOffsetAttribute )
85 {
86 removeAttribute( mAtlasOffsetAttribute );
87 delete mAtlasOffsetAttribute;
88 mAtlasOffsetAttribute = nullptr;
89 }
90 if ( mAtlasSizeAttribute )
91 {
92 removeAttribute( mAtlasSizeAttribute );
93 delete mAtlasSizeAttribute;
94 mAtlasSizeAttribute = nullptr;
95 }
96 if ( mAtlasPixelOffsetAttribute )
97 {
98 removeAttribute( mAtlasPixelOffsetAttribute );
99 delete mAtlasPixelOffsetAttribute;
100 mAtlasPixelOffsetAttribute = nullptr;
101 }
102 break;
103 }
104
105 case Mode::PositionAndTextureData:
106 {
107 if ( mAtlasPixelOffsetAttribute )
108 {
109 removeAttribute( mAtlasPixelOffsetAttribute );
110 delete mAtlasPixelOffsetAttribute;
111 mAtlasPixelOffsetAttribute = nullptr;
112 }
113
114 mAtlasOffsetAttribute = new Qt3DQAttribute( this );
115 mAtlasOffsetAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
116 mAtlasOffsetAttribute->setBuffer( mVertexBuffer );
117 mAtlasOffsetAttribute->setVertexBaseType( Qt3DQAttribute::Float );
118 mAtlasOffsetAttribute->setVertexSize( 2 );
119 mAtlasOffsetAttribute->setByteOffset( 3 * sizeof( float ) );
120 mAtlasOffsetAttribute->setByteStride( stride );
121 mAtlasOffsetAttribute->setName( QStringLiteral( "atlasOffset" ) );
122 addAttribute( mAtlasOffsetAttribute );
123
124 mAtlasSizeAttribute = new Qt3DQAttribute( this );
125 mAtlasSizeAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
126 mAtlasSizeAttribute->setBuffer( mVertexBuffer );
127 mAtlasSizeAttribute->setVertexBaseType( Qt3DQAttribute::Float );
128 mAtlasSizeAttribute->setVertexSize( 2 );
129 mAtlasSizeAttribute->setByteOffset( ( 3 + 2 ) * sizeof( float ) );
130 mAtlasSizeAttribute->setByteStride( stride );
131 mAtlasSizeAttribute->setName( QStringLiteral( "atlasSize" ) );
132 addAttribute( mAtlasSizeAttribute );
133 break;
134 }
135
136 case Mode::PositionAndTextureDataWithPixelOffsets:
137 {
138 mAtlasOffsetAttribute = new Qt3DQAttribute( this );
139 mAtlasOffsetAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
140 mAtlasOffsetAttribute->setBuffer( mVertexBuffer );
141 mAtlasOffsetAttribute->setVertexBaseType( Qt3DQAttribute::Float );
142 mAtlasOffsetAttribute->setVertexSize( 2 );
143 mAtlasOffsetAttribute->setByteOffset( 3 * sizeof( float ) );
144 mAtlasOffsetAttribute->setByteStride( stride );
145 mAtlasOffsetAttribute->setName( QStringLiteral( "atlasOffset" ) );
146 addAttribute( mAtlasOffsetAttribute );
147
148 mAtlasSizeAttribute = new Qt3DQAttribute( this );
149 mAtlasSizeAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
150 mAtlasSizeAttribute->setBuffer( mVertexBuffer );
151 mAtlasSizeAttribute->setVertexBaseType( Qt3DQAttribute::Float );
152 mAtlasSizeAttribute->setVertexSize( 2 );
153 mAtlasSizeAttribute->setByteOffset( ( 3 + 2 ) * sizeof( float ) );
154 mAtlasSizeAttribute->setByteStride( stride );
155 mAtlasSizeAttribute->setName( QStringLiteral( "atlasSize" ) );
156 addAttribute( mAtlasSizeAttribute );
157
158 mAtlasPixelOffsetAttribute = new Qt3DQAttribute( this );
159 mAtlasPixelOffsetAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
160 mAtlasPixelOffsetAttribute->setBuffer( mVertexBuffer );
161 mAtlasPixelOffsetAttribute->setVertexBaseType( Qt3DQAttribute::Int );
162 mAtlasPixelOffsetAttribute->setVertexSize( 2 );
163 mAtlasPixelOffsetAttribute->setByteOffset( ( 3 + 2 + 2 ) * sizeof( float ) );
164 mAtlasPixelOffsetAttribute->setByteStride( stride );
165 mAtlasPixelOffsetAttribute->setName( QStringLiteral( "pixelOffset" ) );
166 addAttribute( mAtlasPixelOffsetAttribute );
167 break;
168 }
169 }
170}
171
172void QgsBillboardGeometry::setPositions( const QVector<QVector3D> &vertices )
173{
174 setMode( Mode::PositionOnly );
175
176 QByteArray vertexBufferData;
177 vertexBufferData.resize( vertices.size() * 3 * sizeof( float ) );
178 float *rawVertexArray = reinterpret_cast<float *>( vertexBufferData.data() );
179 int idx = 0;
180 for ( const auto &v : vertices )
181 {
182 rawVertexArray[idx++] = v.x();
183 rawVertexArray[idx++] = v.y();
184 rawVertexArray[idx++] = v.z();
185 }
186
187 mVertexCount = vertices.count();
188 mVertexBuffer->setData( vertexBufferData );
189
190 emit countChanged( mVertexCount );
191}
192
194#pragma pack( push, 1 )
195struct BillboardVertex
196{
197 float position[3];
198 float textureAtlasOffset[2];
199 float textureAtlasSize[2];
200};
201
202struct BillboardVertexWithPixelOffset : BillboardVertex
203{
204 int pixelOffset[2];
205};
206#pragma pack( pop )
207
208template<typename VertexType>
209QByteArray createVertexBuffer( const QVector<QgsBillboardGeometry::BillboardAtlasData> &billboards )
210{
211 QByteArray buffer;
212 buffer.resize( billboards.size() * sizeof( VertexType ) );
213 auto *vertexData = reinterpret_cast<VertexType *>( buffer.data() );
214
215 int idx = 0;
216 for ( const QgsBillboardGeometry::BillboardAtlasData &billboard : billboards )
217 {
218 VertexType &vertex = vertexData[idx++];
219
220 vertex.position[0] = billboard.position.x();
221 vertex.position[1] = billboard.position.y();
222 vertex.position[2] = billboard.position.z();
223
224 vertex.textureAtlasOffset[0] = billboard.textureAtlasOffset.x();
225 vertex.textureAtlasOffset[1] = billboard.textureAtlasOffset.y();
226
227 vertex.textureAtlasSize[0] = billboard.textureAtlasSize.x();
228 vertex.textureAtlasSize[1] = billboard.textureAtlasSize.y();
229
230 if constexpr ( std::is_same_v<VertexType, BillboardVertexWithPixelOffset> )
231 {
232 vertex.pixelOffset[0] = billboard.pixelOffset.x();
233 vertex.pixelOffset[1] = billboard.pixelOffset.y();
234 }
235 }
236 return buffer;
237}
239
240void QgsBillboardGeometry::setBillboardData( const QVector<BillboardAtlasData> &billboards, bool includePixelOffsets )
241{
242 if ( includePixelOffsets )
243 setMode( Mode::PositionAndTextureDataWithPixelOffsets );
244 else
245 setMode( Mode::PositionAndTextureData );
246
247
248 QByteArray vertexBufferData;
249 if ( includePixelOffsets )
250 {
251 vertexBufferData = createVertexBuffer<BillboardVertexWithPixelOffset>( billboards );
252 }
253 else
254 {
255 vertexBufferData = createVertexBuffer<BillboardVertex>( billboards );
256 }
257
258 mVertexCount = billboards.count();
259 mVertexBuffer->setData( vertexBufferData );
260
261 emit countChanged( mVertexCount );
262}
263
265{
266 return mVertexCount;
267}
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.
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer
Contains the billboard positions and texture information.