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