25#include <Qt3DCore/QAttribute>
26#include <Qt3DCore/QBuffer>
27#include <Qt3DCore/QEntity>
28#include <Qt3DCore/QGeometry>
29#include <Qt3DRender/QGeometryRenderer>
31using namespace Qt::StringLiterals;
35static QByteArray toByteArray(
const QVector<QVector3D> &points )
38 data.resize( points.size() * 3 *
sizeof(
float ) );
39 float *raw =
reinterpret_cast<float *
>( data.data() );
41 for (
const QVector3D &p : points )
52 altClamping = clamping;
55 renderContext = context;
59void QgsLineVertexData::addLineString(
const QgsLineString &lineString,
float extraHeightOffset,
bool closePolygon )
62 if ( inVertexCount == 0 )
75 QVector<double> xs( inVertexCount );
76 QVector<double> ys( inVertexCount );
77 QVector<double> zs( inVertexCount );
78 for (
int i = 0; i < inVertexCount; ++i )
82 if ( geocentricCoordinates )
93 xs[i] = p.
x() - origin.x();
94 ys[i] = p.
y() - origin.y();
95 zs[i] = z - origin.z();
99 line.removeDuplicateNodes( 4 * std::numeric_limits<double>::epsilon(),
true );
101 int vertexCount = line.vertexCount();
102 if ( vertexCount == 0 )
105 QVector<QVector3D> points;
106 points.reserve( vertexCount );
107 for (
int i = 0; i < vertexCount; ++i )
108 points << QVector3D(
static_cast<float>( line.xAt( i ) ),
static_cast<float>( line.yAt( i ) ),
static_cast<float>( line.zAt( i ) ) );
110 const QVector3D first = points.constFirst();
112 QVector3D prevPrev = first;
113 QVector3D prev = first;
114 bool havePrevPrev =
false;
115 for (
int i = 1; i < vertexCount; ++i )
117 const QVector3D curr = points.at( i );
123 pointsPrev << ( closePolygon ? points.constLast() : prev + ( prev - curr ) );
125 pointsPrev << prevPrev;
127 if ( i == vertexCount - 1 )
128 pointsNext << ( closePolygon ? first : curr + ( curr - prev ) );
130 pointsNext << points.at( i + 1 );
134 joinPointA << prevPrev;
144 if ( closePolygon && vertexCount >= 2 )
148 pointsPrev << prevPrev;
149 pointsNext << points.at( 1 );
151 if ( vertexCount >= 3 )
153 joinPointA << prevPrev;
159 joinPointC << points.at( 1 );
164void QgsLineVertexData::addVerticalLines(
const QgsLineString &lineString,
float verticalLength,
float extraHeightOffset )
167 switch ( altBinding )
176 for (
int i = 0; i < lineString.
vertexCount(); ++i )
179 const float z =
Qgs3DUtils::clampAltitude( p, altClamping, altBinding, baseHeight + extraHeightOffset, centroid, renderContext );
180 const float x =
static_cast<float>( p.
x() - origin.x() );
181 const float y =
static_cast<float>( p.
y() - origin.y() );
182 const QVector3D a( x, y, z );
183 const QVector3D b( x, y, z + verticalLength );
186 pointsPrev << a + ( a - b );
187 pointsNext << b + ( b - a );
191QByteArray QgsLineVertexData::createPointABuffer()
const
193 return toByteArray( pointsA );
196QByteArray QgsLineVertexData::createPointBBuffer()
const
198 return toByteArray( pointsB );
201QByteArray QgsLineVertexData::createPointPrevBuffer()
const
203 return toByteArray( pointsPrev );
206QByteArray QgsLineVertexData::createPointNextBuffer()
const
208 return toByteArray( pointsNext );
211QByteArray QgsLineVertexData::createJoinPointABuffer()
const
213 return toByteArray( joinPointA );
216QByteArray QgsLineVertexData::createJoinPointBBuffer()
const
218 return toByteArray( joinPointB );
221QByteArray QgsLineVertexData::createJoinPointCBuffer()
const
223 return toByteArray( joinPointC );
226Qt3DCore::QGeometry *QgsLineVertexData::createGeometry( Qt3DCore::QNode *parent )
228 Q_ASSERT( pointsA.size() == pointsB.size() );
229 Q_ASSERT( pointsA.size() == pointsPrev.size() );
230 Q_ASSERT( pointsA.size() == pointsNext.size() );
232 static constexpr float quadVertices[] = {
247 Qt3DCore::QBuffer *quadBuffer =
new Qt3DCore::QBuffer( parent );
248 quadBuffer->setData( QByteArray(
reinterpret_cast<const char *
>( quadVertices ),
sizeof( quadVertices ) ) );
250 Qt3DCore::QAttribute *positionAttribute =
new Qt3DCore::QAttribute( parent );
251 positionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
252 positionAttribute->setBuffer( quadBuffer );
253 positionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
254 positionAttribute->setVertexSize( 2 );
255 positionAttribute->setByteStride( 2 *
sizeof(
float ) );
256 positionAttribute->setByteOffset( 0 );
257 positionAttribute->setCount( 6 );
258 positionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
260 Qt3DCore::QBuffer *pointABuffer =
new Qt3DCore::QBuffer( parent );
261 pointABuffer->setData( createPointABuffer() );
263 Qt3DCore::QAttribute *pointAAttribute =
new Qt3DCore::QAttribute( parent );
264 pointAAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
265 pointAAttribute->setBuffer( pointABuffer );
266 pointAAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
267 pointAAttribute->setVertexSize( 3 );
268 pointAAttribute->setByteStride( 3 *
sizeof(
float ) );
269 pointAAttribute->setByteOffset( 0 );
270 pointAAttribute->setCount( pointsA.size() );
271 pointAAttribute->setDivisor( 1 );
272 pointAAttribute->setName( u
"pointA"_s );
274 Qt3DCore::QBuffer *pointBBuffer =
new Qt3DCore::QBuffer( parent );
275 pointBBuffer->setData( createPointBBuffer() );
277 Qt3DCore::QAttribute *pointBAttribute =
new Qt3DCore::QAttribute( parent );
278 pointBAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
279 pointBAttribute->setBuffer( pointBBuffer );
280 pointBAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
281 pointBAttribute->setVertexSize( 3 );
282 pointBAttribute->setByteStride( 3 *
sizeof(
float ) );
283 pointBAttribute->setByteOffset( 0 );
284 pointBAttribute->setCount( pointsB.size() );
285 pointBAttribute->setDivisor( 1 );
286 pointBAttribute->setName( u
"pointB"_s );
288 Qt3DCore::QBuffer *pointPrevBuffer =
new Qt3DCore::QBuffer( parent );
289 pointPrevBuffer->setData( createPointPrevBuffer() );
291 Qt3DCore::QAttribute *pointPrevAttribute =
new Qt3DCore::QAttribute( parent );
292 pointPrevAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
293 pointPrevAttribute->setBuffer( pointPrevBuffer );
294 pointPrevAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
295 pointPrevAttribute->setVertexSize( 3 );
296 pointPrevAttribute->setByteStride( 3 *
sizeof(
float ) );
297 pointPrevAttribute->setByteOffset( 0 );
298 pointPrevAttribute->setCount( pointsPrev.size() );
299 pointPrevAttribute->setDivisor( 1 );
300 pointPrevAttribute->setName( u
"pointPrev"_s );
302 Qt3DCore::QBuffer *pointNextBuffer =
new Qt3DCore::QBuffer( parent );
303 pointNextBuffer->setData( createPointNextBuffer() );
305 Qt3DCore::QAttribute *pointNextAttribute =
new Qt3DCore::QAttribute( parent );
306 pointNextAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
307 pointNextAttribute->setBuffer( pointNextBuffer );
308 pointNextAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
309 pointNextAttribute->setVertexSize( 3 );
310 pointNextAttribute->setByteStride( 3 *
sizeof(
float ) );
311 pointNextAttribute->setByteOffset( 0 );
312 pointNextAttribute->setCount( pointsNext.size() );
313 pointNextAttribute->setDivisor( 1 );
314 pointNextAttribute->setName( u
"pointNext"_s );
316 Qt3DCore::QGeometry *geom =
new Qt3DCore::QGeometry;
317 geom->addAttribute( positionAttribute );
318 geom->addAttribute( pointAAttribute );
319 geom->addAttribute( pointBAttribute );
320 geom->addAttribute( pointPrevAttribute );
321 geom->addAttribute( pointNextAttribute );
323 geom->setBoundingVolumePositionAttribute( pointAAttribute );
328Qt3DCore::QGeometry *QgsLineVertexData::createJoinGeometry( Qt3DCore::QNode *parent )
330 static constexpr float selectorVertices[] = {
359 Qt3DCore::QBuffer *selectorBuffer =
new Qt3DCore::QBuffer( parent );
360 selectorBuffer->setData( QByteArray(
reinterpret_cast<const char *
>( selectorVertices ),
sizeof( selectorVertices ) ) );
362 Qt3DCore::QAttribute *positionAttribute =
new Qt3DCore::QAttribute( parent );
363 positionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
364 positionAttribute->setBuffer( selectorBuffer );
365 positionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
366 positionAttribute->setVertexSize( 4 );
367 positionAttribute->setByteStride( 4 *
sizeof(
float ) );
368 positionAttribute->setByteOffset( 0 );
369 positionAttribute->setCount( 6 );
370 positionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
372 Qt3DCore::QBuffer *pointABuffer =
new Qt3DCore::QBuffer( parent );
373 pointABuffer->setData( createJoinPointABuffer() );
375 Qt3DCore::QAttribute *pointAAttribute =
new Qt3DCore::QAttribute( parent );
376 pointAAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
377 pointAAttribute->setBuffer( pointABuffer );
378 pointAAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
379 pointAAttribute->setVertexSize( 3 );
380 pointAAttribute->setByteStride( 3 *
sizeof(
float ) );
381 pointAAttribute->setByteOffset( 0 );
382 pointAAttribute->setCount( joinPointA.size() );
383 pointAAttribute->setDivisor( 1 );
384 pointAAttribute->setName( u
"pointA"_s );
386 Qt3DCore::QBuffer *pointBBuffer =
new Qt3DCore::QBuffer( parent );
387 pointBBuffer->setData( createJoinPointBBuffer() );
389 Qt3DCore::QAttribute *pointBAttribute =
new Qt3DCore::QAttribute( parent );
390 pointBAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
391 pointBAttribute->setBuffer( pointBBuffer );
392 pointBAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
393 pointBAttribute->setVertexSize( 3 );
394 pointBAttribute->setByteStride( 3 *
sizeof(
float ) );
395 pointBAttribute->setByteOffset( 0 );
396 pointBAttribute->setCount( joinPointB.size() );
397 pointBAttribute->setDivisor( 1 );
398 pointBAttribute->setName( u
"pointB"_s );
400 Qt3DCore::QBuffer *pointCBuffer =
new Qt3DCore::QBuffer( parent );
401 pointCBuffer->setData( createJoinPointCBuffer() );
403 Qt3DCore::QAttribute *pointCAttribute =
new Qt3DCore::QAttribute( parent );
404 pointCAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
405 pointCAttribute->setBuffer( pointCBuffer );
406 pointCAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
407 pointCAttribute->setVertexSize( 3 );
408 pointCAttribute->setByteStride( 3 *
sizeof(
float ) );
409 pointCAttribute->setByteOffset( 0 );
410 pointCAttribute->setCount( joinPointC.size() );
411 pointCAttribute->setDivisor( 1 );
412 pointCAttribute->setName( u
"pointC"_s );
414 Qt3DCore::QGeometry *geom =
new Qt3DCore::QGeometry;
415 geom->addAttribute( positionAttribute );
416 geom->addAttribute( pointAAttribute );
417 geom->addAttribute( pointBAttribute );
418 geom->addAttribute( pointCAttribute );
420 geom->setBoundingVolumePositionAttribute( pointBAttribute );
427 if ( pointsA.isEmpty() )
430 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
432 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
433 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
434 Qt3DCore::QGeometry *geometry = createGeometry( entity );
436 if ( materialHandler && materialSettings && !materialDataDefined.isEmpty() )
439 renderer->setGeometry( geometry );
440 renderer->setVertexCount( 6 );
441 renderer->setInstanceCount( pointsA.size() );
443 entity->addComponent( renderer );
445 entity->addComponent( material );
452 if ( joinPointA.isEmpty() )
455 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
457 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
458 renderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
459 Qt3DCore::QGeometry *geometry = createJoinGeometry( entity );
461 if ( materialHandler && materialSettings && !materialDataDefinedJoins.isEmpty() )
464 renderer->setGeometry( geometry );
465 renderer->setVertexCount( 6 );
466 renderer->setInstanceCount( joinPointA.size() );
468 QgsLineMaterial *joinMaterial =
new QgsLineMaterial( QgsLineMaterial::LinePart::Join );
469 if ( segmentMaterial )
470 segmentMaterial->copyLineParametersTo( joinMaterial );
472 entity->addComponent( renderer );
473 entity->addComponent( joinMaterial );
AltitudeClamping
Altitude clamping.
AltitudeBinding
Altitude binding.
@ Centroid
Clamp just centroid of feature.
@ Vertex
Clamp every vertex of feature.
Rendering context for preparation of 3D entities.
static float clampAltitude(const QgsPoint &p, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, float offset, const QgsPoint ¢roid, const Qgs3DRenderContext &context)
Clamps altitude of a vertex according to the settings, returns Z value.
Abstract base class for material 3D handlers.
virtual void applyDataDefinedToGeometry(const QgsAbstractMaterialSettings *settings, Qt3DCore::QGeometry *geometry, int vertexCount, const QByteArray &dataDefinedBytes) const
Applies the data defined bytes, dataDefinedBytes, on the geometry by filling a specific vertex buffer...
Abstract base class for material settings.
int vertexCount(int part=0, int ring=0) const override
Returns the number of vertices of which this geometry is built.
Line string geometry type, with support for z-dimension and m-values.
QgsPoint centroid() const override
Returns the centroid of the geometry.
Base class for all materials used within QGIS 3D views.
Point geometry type, with support for z-dimension and m-values.
QgsPoint pointN(int i) const
Returns the specified point from inside the simple curve.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...