35#include <Qt3DCore/QAttribute>
36#include <Qt3DCore/QBuffer>
37#include <Qt3DCore/QGeometry>
38#include <Qt3DExtras/QConeGeometry>
39#include <Qt3DExtras/QCuboidGeometry>
40#include <Qt3DExtras/QCylinderGeometry>
41#include <Qt3DExtras/QExtrudedTextGeometry>
42#include <Qt3DExtras/QPhongMaterial>
43#include <Qt3DExtras/QPlaneGeometry>
44#include <Qt3DExtras/QSphereGeometry>
45#include <Qt3DExtras/QTorusGeometry>
46#include <Qt3DRender/QEffect>
47#include <Qt3DRender/QGraphicsApiFilter>
48#include <Qt3DRender/QMesh>
49#include <Qt3DRender/QPaintedTextureImage>
50#include <Qt3DRender/QParameter>
51#include <Qt3DRender/QSceneLoader>
52#include <Qt3DRender/QTechnique>
54using namespace Qt::StringLiterals;
62class QgsInstancedPoint3DSymbolHandler :
public QgsFeature3DHandler
65 QgsInstancedPoint3DSymbolHandler(
const QgsPoint3DSymbol *symbol,
const QgsFeatureIds &selectedIds )
66 : mSymbol( static_cast<QgsPoint3DSymbol *>( symbol->clone() ) )
67 , mSelectedIds( selectedIds )
70 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
override;
71 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
72 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
75 static QgsMaterial *material(
const QgsPoint3DSymbol *symbol,
const QgsMaterialContext &materialContext,
bool hasDataDefinedScale,
bool hasDataDefinedRotation );
76 static Qt3DRender::QGeometryRenderer *renderer(
const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions,
const QVector<QVector3D> &scales,
const QVector<QVector4D> rotations );
77 static Qt3DCore::QGeometry *symbolGeometry(
const QgsPoint3DSymbol *symbol );
82 QVector<QVector3D> positions;
83 QVector<QVector3D> scales;
84 QVector<QVector4D> rotations;
87 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
90 std::unique_ptr<QgsPoint3DSymbol> mSymbol;
91 QVector3D mSymbolScale;
92 QQuaternion mSymbolRotation;
93 QVector3D mPointTranslation;
98 PointData outSelected;
102bool QgsInstancedPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
104 mChunkOrigin = chunkExtent.
center();
105 mChunkExtent = chunkExtent;
107 QSet<QString> attrs = mSymbol->dataDefinedProperties().referencedFields( context.
expressionContext() );
108 attributeNames.unite( attrs );
109 attrs = mSymbol->materialSettings()->dataDefinedProperties().referencedFields( context.
expressionContext() );
110 attributeNames.unite( attrs );
119 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
130 if ( hasDDTranslation )
135 translation =
QgsVector3D( translationX, translationY, translationZ );
138 const std::size_t oldSize = out.positions.size();
141 const std::size_t added = out.positions.size() - oldSize;
147 out.scales.resize( out.positions.size() );
148 QVector3D *outScale = out.scales.data() + oldSize;
154 for ( std::size_t i = 0; i < added; ++i )
156 ( *outScale++ ) = QVector3D(
static_cast< float >( scaleX ),
static_cast< float >( scaleY ),
static_cast< float >( scaleZ ) );
165 out.rotations.resize( out.positions.size() );
166 QVector4D *outRotation = out.rotations.data() + oldSize;
169 const QVector3D baseEuler = mSymbolRotation.toEulerAngles();
176 const QQuaternion finalQuat = QQuaternion::fromEulerAngles(
static_cast< float >( rotationX ),
static_cast< float >( rotationY ),
static_cast< float >( rotationZ ) );
177 const QVector4D finalVec4 = finalQuat.toVector4D();
179 for ( std::size_t i = 0; i < added; ++i )
181 ( *outRotation++ ) = finalVec4;
188void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
190 makeEntity( parent, context, outNormal,
false );
191 makeEntity( parent, context, outSelected,
true );
193 auto updateZRangeFromPointData = [
this](
const PointData &pointData ) {
194 const QVector3D *scales = pointData.scales.empty() ? nullptr : pointData.scales.constData();
195 for (
const QVector3D &pos : std::as_const( pointData.positions ) )
202 switch ( mSymbol->shape() )
206 const float length = mSymbol->shapeProperty( u
"length"_s ).toFloat();
207 minZ -= length * 0.5f;
208 maxZ += length * 0.5f;
214 const float radius = mSymbol->shapeProperty( u
"radius"_s ).toFloat();
222 const float length = mSymbol->shapeProperty( u
"length"_s ).toFloat();
223 minZ -= length * 0.5f;
224 maxZ += length * 0.5f;
230 const float size = mSymbol->shapeProperty( u
"size"_s ).toFloat();
238 const float radius = mSymbol->shapeProperty( u
"radius"_s ).toFloat();
248 const float size = mSymbol->shapeProperty( u
"size"_s ).toFloat();
262 const double zScale = ( *scales++ )[2];
268 minZ += pos.z() + mChunkOrigin.z();
269 maxZ += pos.z() + mChunkOrigin.z();
272 mZMin =
static_cast< float >( minZ );
274 mZMax =
static_cast< float >( maxZ );
278 updateZRangeFromPointData( outNormal );
279 updateZRangeFromPointData( outSelected );
282void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
284 if ( out.positions.isEmpty() )
293 QgsMaterial *mat = material( mSymbol.get(), materialContext, !out.scales.empty(), !out.rotations.empty() );
297 mat->addParameter(
new Qt3DRender::QParameter(
"symbolScale", mSymbolScale, mat ) );
298 mat->addParameter(
new Qt3DRender::QParameter(
"symbolRotation", mSymbolRotation.toVector4D(), mat ) );
301 QgsGeoTransform *tr =
new QgsGeoTransform;
302 tr->setGeoTranslation( mChunkOrigin );
305 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
306 entity->addComponent( renderer( mSymbol.get(), out.positions, out.scales, out.rotations ) );
307 entity->addComponent( mat );
308 entity->addComponent( tr );
309 entity->setParent( parent );
325 if ( hasDataDefinedScale )
327 if ( hasDataDefinedRotation )
329 return handler->toInstancedMaterial( settings, materialContext, flags );
335Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer(
336 const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions,
const QVector<QVector3D> &scales,
const QVector<QVector4D> rotations
339 const std::size_t count = positions.count();
340 const std::size_t byteCount = positions.count() *
sizeof( QVector3D );
342 ba.resize( byteCount );
343 memcpy( ba.data(), positions.constData(), byteCount );
345 Qt3DCore::QBuffer *instanceBuffer =
new Qt3DCore::QBuffer();
346 instanceBuffer->setData( ba );
348 Qt3DCore::QAttribute *instanceTranslationAttribute =
new Qt3DCore::QAttribute;
349 instanceTranslationAttribute->setName( u
"instanceTranslation"_s );
350 instanceTranslationAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
351 instanceTranslationAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
352 instanceTranslationAttribute->setVertexSize( 3 );
353 instanceTranslationAttribute->setByteOffset( 0 );
354 instanceTranslationAttribute->setDivisor( 1 );
355 instanceTranslationAttribute->setBuffer( instanceBuffer );
356 instanceTranslationAttribute->setCount( count );
357 instanceTranslationAttribute->setByteStride( 3 *
sizeof(
float ) );
359 Qt3DCore::QGeometry *geometry = symbolGeometry( symbol );
360 geometry->addAttribute( instanceTranslationAttribute );
361 geometry->setBoundingVolumePositionAttribute( instanceTranslationAttribute );
363 if ( !scales.empty() )
365 auto scaleBuffer =
new Qt3DCore::QBuffer();
366 auto instanceScaleAttribute =
new Qt3DCore::QAttribute;
367 instanceScaleAttribute->setName( u
"instanceScale"_s );
368 instanceScaleAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
369 instanceScaleAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
370 instanceScaleAttribute->setVertexSize( 3 );
371 instanceScaleAttribute->setByteOffset( 0 );
372 instanceScaleAttribute->setDivisor( 1 );
373 instanceScaleAttribute->setByteStride( 3 *
sizeof(
float ) );
375 scaleBa.resize( byteCount );
376 memcpy( scaleBa.data(), scales.constData(), byteCount );
378 scaleBuffer->setData( scaleBa );
379 instanceScaleAttribute->setCount( count );
381 instanceScaleAttribute->setBuffer( scaleBuffer );
382 geometry->addAttribute( instanceScaleAttribute );
385 if ( !rotations.empty() )
387 auto rotationBuffer =
new Qt3DCore::QBuffer();
388 auto instanceRotationAttribute =
new Qt3DCore::QAttribute;
389 instanceRotationAttribute->setName( u
"instanceRotation"_s );
390 instanceRotationAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
391 instanceRotationAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
392 instanceRotationAttribute->setVertexSize( 4 );
393 instanceRotationAttribute->setByteOffset( 0 );
394 instanceRotationAttribute->setDivisor( 1 );
395 instanceRotationAttribute->setByteStride( 4 *
sizeof(
float ) );
397 QByteArray rotationBa;
398 const std::size_t rotationByteCount = positions.count() *
sizeof( QVector4D );
399 rotationBa.resize( rotationByteCount );
400 memcpy( rotationBa.data(), rotations.constData(), rotationByteCount );
401 rotationBuffer->setData( rotationBa );
402 instanceRotationAttribute->setCount( count );
404 instanceRotationAttribute->setBuffer( rotationBuffer );
405 geometry->addAttribute( instanceRotationAttribute );
408 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
409 renderer->setGeometry( geometry );
410 renderer->setInstanceCount( count );
415Qt3DCore::QGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry(
const QgsPoint3DSymbol *symbol )
417 switch ( symbol->
shape() )
421 const float radius = symbol->
shapeProperty( u
"radius"_s ).toFloat();
422 const float length = symbol->
shapeProperty( u
"length"_s ).toFloat();
423 Qt3DExtras::QCylinderGeometry *g =
new Qt3DExtras::QCylinderGeometry;
426 g->setRadius( radius );
427 g->setLength( length );
433 const float radius = symbol->
shapeProperty( u
"radius"_s ).toFloat();
434 const int rings = symbol->
shapeProperty( u
"rings"_s ).toInt();
435 const int slices = symbol->
shapeProperty( u
"slices"_s ).toInt();
438 Qt3DExtras::QSphereGeometry *g =
new Qt3DExtras::QSphereGeometry;
439 g->setRadius( radius );
440 g->setRings( rings );
441 g->setSlices( slices );
442 g->setGenerateTangents( tangents );
448 const float length = symbol->
shapeProperty( u
"length"_s ).toFloat();
449 const float bottomRadius = symbol->
shapeProperty( u
"bottomRadius"_s ).toFloat();
450 const float topRadius = symbol->
shapeProperty( u
"topRadius"_s ).toFloat();
452 Qt3DExtras::QConeGeometry *g =
new Qt3DExtras::QConeGeometry;
453 g->setLength( length );
454 g->setBottomRadius( bottomRadius );
455 g->setTopRadius( topRadius );
463 const float size = symbol->
shapeProperty( u
"size"_s ).toFloat();
464 Qt3DExtras::QCuboidGeometry *g =
new Qt3DExtras::QCuboidGeometry;
465 g->setXExtent( size );
466 g->setYExtent( size );
467 g->setZExtent( size );
473 const float radius = symbol->
shapeProperty( u
"radius"_s ).toFloat();
474 const float minorRadius = symbol->
shapeProperty( u
"minorRadius"_s ).toFloat();
475 Qt3DExtras::QTorusGeometry *g =
new Qt3DExtras::QTorusGeometry;
476 g->setRadius( radius );
477 g->setMinorRadius( minorRadius );
483 const float size = symbol->
shapeProperty( u
"size"_s ).toFloat();
484 Qt3DExtras::QPlaneGeometry *g =
new Qt3DExtras::QPlaneGeometry;
486 g->setHeight( size );
492 const float depth = symbol->
shapeProperty( u
"depth"_s ).toFloat();
493 const QString text = symbol->
shapeProperty( u
"text"_s ).toString();
494 Qt3DExtras::QExtrudedTextGeometry *g =
new Qt3DExtras::QExtrudedTextGeometry;
495 g->setDepth( depth );
511class QgsModelPoint3DSymbolHandler :
public QgsFeature3DHandler
514 QgsModelPoint3DSymbolHandler(
const QgsPoint3DSymbol *symbol,
const QgsFeatureIds &selectedIds )
515 : mSymbol( static_cast<QgsPoint3DSymbol *>( symbol->clone() ) )
516 , mSelectedIds( selectedIds )
519 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
override;
520 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
521 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
524 static void addSceneEntities(
525 const Qgs3DRenderContext &context,
526 const QVector<QVector3D> &positions,
527 const QVector<QVector3D> &scales,
528 const QVector<QQuaternion> &rotations,
529 const QgsVector3D &chunkOrigin,
530 const QgsPoint3DSymbol *symbol,
531 Qt3DCore::QEntity *parent
533 static void addMeshEntities(
534 const Qgs3DRenderContext &context,
535 const QVector<QVector3D> &positions,
536 const QVector<QVector3D> &scales,
537 const QVector<QQuaternion> &rotations,
538 const QgsVector3D &chunkOrigin,
539 const QgsPoint3DSymbol *symbol,
540 Qt3DCore::QEntity *parent,
544 static QgsGeoTransform *transform( QVector3D position,
const QMatrix4x4 &transform,
const QgsVector3D &chunkOrigin );
549 QVector<QVector3D> positions;
550 QVector<QVector3D> scales;
551 QVector<QQuaternion> rotations;
554 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
557 std::unique_ptr<QgsPoint3DSymbol> mSymbol;
559 QVector3D mSymbolScale;
560 QQuaternion mSymbolRotation;
561 QVector3D mPointTranslation;
567 PointData outSelected;
570bool QgsModelPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
573 Q_UNUSED( attributeNames )
575 mChunkOrigin = chunkExtent.
center();
576 mChunkExtent = chunkExtent;
578 QSet<QString> attrs = mSymbol->dataDefinedProperties().referencedFields( context.
expressionContext() );
579 attributeNames.unite( attrs );
587 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
598 if ( hasDDTranslation )
603 translation =
QgsVector3D( translationX, translationY, translationZ );
606 const std::size_t oldSize = out.positions.size();
608 const std::size_t added = out.positions.size() - oldSize;
610 QVector3D scale = mSymbolScale;
617 scale = QVector3D(
static_cast< float >( scaleX ),
static_cast< float >( scaleY ),
static_cast< float >( scaleZ ) );
620 out.scales.resize( out.positions.size() );
621 QVector3D *outScale = out.scales.data() + oldSize;
622 for ( std::size_t i = 0; i < added; ++i )
624 ( *outScale++ ) = scale;
627 QQuaternion rotation = mSymbolRotation;
634 const QVector3D baseEuler = mSymbolRotation.toEulerAngles();
641 rotation = QQuaternion::fromEulerAngles(
static_cast< float >( rotationX ),
static_cast< float >( rotationY ),
static_cast< float >( rotationZ ) );
644 out.rotations.resize( out.positions.size() );
645 QQuaternion *outRotation = out.rotations.data() + oldSize;
646 for ( std::size_t i = 0; i < added; ++i )
648 ( *outRotation++ ) = rotation;
654void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
656 makeEntity( parent, context, outNormal,
false );
657 makeEntity( parent, context, outSelected,
true );
659 updateZRangeFromPositions( outNormal.positions );
660 updateZRangeFromPositions( outSelected.positions );
663 const float symbolHeight = mSymbol->transform().data()[14];
665 mZMin +=
static_cast<float>( symbolHeight + mChunkOrigin.z() );
666 mZMax +=
static_cast<float>( symbolHeight + mChunkOrigin.z() );
669void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
671 if ( out.positions.isEmpty() )
678 addMeshEntities( context, out.positions, out.scales, out.rotations, mChunkOrigin, mSymbol.get(), parent,
true, mHighlightingEnabled );
683 if ( mSymbol->shapeProperty( u
"overwriteMaterial"_s ).toBool() || ( mSymbol->materialSettings() && mSymbol->materialSettings()->type() !=
"null"_L1 ) || mHighlightingEnabled )
685 addMeshEntities( context, out.positions, out.scales, out.rotations, mChunkOrigin, mSymbol.get(), parent,
false, mHighlightingEnabled );
689 addSceneEntities( context, out.positions, out.scales, out.rotations, mChunkOrigin, mSymbol.get(), parent );
694QVector3D stringToAxis(
const QString &axis )
696 if ( axis ==
"x"_L1 )
697 return QVector3D( 1.0f, 0.0f, 0.0f );
698 if ( axis ==
"-x"_L1 )
699 return QVector3D( -1.0f, 0.0f, 0.0f );
700 if ( axis ==
"y"_L1 )
701 return QVector3D( 0.0f, 1.0f, 0.0f );
702 if ( axis ==
"-y"_L1 )
703 return QVector3D( 0.0f, -1.0f, 0.0f );
704 if ( axis ==
"z"_L1 )
705 return QVector3D( 0.0f, 0.0f, 1.0f );
706 if ( axis ==
"-z"_L1 )
707 return QVector3D( 0.0f, 0.0f, -1.0f );
712QMatrix4x4 createZUpTransform(
const QString &upAxis,
const QString &forwardAxis )
714 QVector3D up = stringToAxis( upAxis );
715 QVector3D forward = stringToAxis( forwardAxis );
717 if ( up.isNull() || forward.isNull() || std::abs( QVector3D::dotProduct( up, forward ) ) > 1e-6f )
723 QVector3D right = QVector3D::crossProduct( forward, up ).normalized();
724 return QMatrix4x4( right.x(), right.y(), right.z(), 0.0f, forward.x(), forward.y(), forward.z(), 0.0f, up.x(), up.y(), up.z(), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f );
727void QgsModelPoint3DSymbolHandler::addSceneEntities(
729 const QVector<QVector3D> &positions,
730 const QVector<QVector3D> &scales,
731 const QVector<QQuaternion> &rotations,
734 Qt3DCore::QEntity *parent
741 const QString upAxis = symbol->
shapeProperty( u
"upAxis"_s ).toString();
742 const QString forwardAxis = symbol->
shapeProperty( u
"forwardAxis"_s ).toString();
743 const QMatrix4x4 zUpMatrix = createZUpTransform( upAxis, forwardAxis );
745 if ( !source.isEmpty() )
748 for (
const QVector3D &position : positions )
751 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
753 const QUrl url = QUrl::fromLocalFile( source );
754 Qt3DRender::QSceneLoader *modelLoader =
new Qt3DRender::QSceneLoader;
755 modelLoader->setSource( url );
757 QMatrix4x4 entityTransform;
758 entityTransform.scale( scales.at( index ) );
759 entityTransform.rotate( rotations.at( index ) );
760 entityTransform *= zUpMatrix;
762 entity->addComponent( modelLoader );
763 entity->addComponent( transform( position, entityTransform, chunkOrigin ) );
764 entity->setParent( parent );
777void QgsModelPoint3DSymbolHandler::addMeshEntities(
779 const QVector<QVector3D> &positions,
780 const QVector<QVector3D> &scales,
781 const QVector<QQuaternion> &rotations,
784 Qt3DCore::QEntity *parent,
789 if ( positions.empty() )
792 const QString upAxis = symbol->
shapeProperty( u
"upAxis"_s ).toString();
793 const QString forwardAxis = symbol->
shapeProperty( u
"forwardAxis"_s ).toString();
794 const QMatrix4x4 zUpMatrix = createZUpTransform( upAxis, forwardAxis );
797 if ( !source.isEmpty() )
808 const QUrl url = QUrl::fromLocalFile( source );
812 for (
const QVector3D &position : positions )
815 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
817 Qt3DRender::QMesh *mesh =
new Qt3DRender::QMesh;
818 mesh->setSource( url );
820 entity->addComponent( mesh );
821 entity->addComponent( mat );
823 QMatrix4x4 entityTransform;
824 entityTransform.scale( scales.at( index ) );
825 entityTransform.rotate( rotations.at( index ) );
826 entityTransform *= zUpMatrix;
828 entity->addComponent( transform( position, entityTransform, chunkOrigin ) );
829 entity->setParent( parent );
842QgsGeoTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position,
const QMatrix4x4 &transform,
const QgsVector3D &chunkOrigin )
845 QgsGeoTransform *tr =
new QgsGeoTransform;
846 tr->setMatrix( transform );
847 tr->setGeoTranslation( chunkOrigin + position + tr->translation() );
855class QgsPoint3DBillboardSymbolHandler :
public QgsFeature3DHandler
858 QgsPoint3DBillboardSymbolHandler(
const QgsPoint3DSymbol *symbol,
const QgsFeatureIds &selectedIds )
859 : mSymbol( static_cast<QgsPoint3DSymbol *>( symbol->clone() ) )
860 , mSelectedIds( selectedIds )
863 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
override;
864 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
865 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
871 QVector<QVector3D> positions;
874 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
877 std::unique_ptr<QgsPoint3DSymbol> mSymbol;
882 PointData outSelected;
885bool QgsPoint3DBillboardSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
888 Q_UNUSED( attributeNames )
890 mChunkOrigin = chunkExtent.
center();
891 mChunkExtent = chunkExtent;
898 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
907void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
909 makeEntity( parent, context, outNormal,
false );
910 makeEntity( parent, context, outSelected,
true );
912 updateZRangeFromPositions( outNormal.positions );
913 updateZRangeFromPositions( outSelected.positions );
916 const float billboardHeight = mSymbol->billboardHeight();
918 mZMin +=
static_cast<float>( billboardHeight + mChunkOrigin.z() );
919 mZMax +=
static_cast<float>( billboardHeight + mChunkOrigin.z() );
922void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
924 if ( out.positions.isEmpty() )
934 Qt3DRender::QGeometryRenderer *billboardGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
935 billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
936 billboardGeometryRenderer->setGeometry( billboardGeometry );
937 billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
953 QgsGeoTransform *billboardTransform =
new QgsGeoTransform;
954 billboardTransform->setGeoTranslation( mChunkOrigin +
QgsVector3D( 0, 0, mSymbol->billboardHeight() ) );
957 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
959 entity->addComponent( billboardMaterial );
960 entity->addComponent( billboardTransform );
961 entity->addComponent( billboardGeometryRenderer );
962 entity->setParent( parent );
969namespace Qgs3DSymbolImpl
972 QgsFeature3DHandler *handlerForPoint3DSymbol(
const QgsVectorLayer *layer,
const QgsAbstract3DSymbol *symbol )
974 const QgsPoint3DSymbol *pointSymbol =
dynamic_cast<const QgsPoint3DSymbol *
>( symbol );
982 return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
984 return new QgsInstancedPoint3DSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
@ ExtrudedText
Extruded text.
@ Triangles
Triangle based rendering (default).
@ InstancedPoints
Instanced based rendering, requiring triangles and point data.
QFlags< InstancedMaterialFlag > InstancedMaterialFlags
@ DataDefinedRotation
Per-instance data-defined rotation.
@ DataDefinedScale
Per-instance data-defined scale.
Rendering context for preparation of 3D entities.
QgsExpressionContext & expressionContext()
Gets the expression context.
static void decomposeTransformMatrix(const QMatrix4x4 &matrix, QVector3D &translation, QQuaternion &rotation, QVector3D &scale)
Tries to decompose a 4x4 transform matrix into translation, rotation and scale components.
static void extractPointPositions(const QgsFeature &f, const Qgs3DRenderContext &context, const QgsVector3D &chunkOrigin, Qgis::AltitudeClamping altClamp, QVector< QVector3D > &positions, const QgsVector3D &translation=QgsVector3D(0, 0, 0))
Calculates (x,y,z) positions of (multi)point from the given feature.
static QgsMaterial * toMaterial(const QgsAbstractMaterialSettings *settings, Qgis::MaterialRenderingTechnique technique, const QgsMaterialContext &context)
Creates a new QgsMaterial object representing the material settings.
static const QgsAbstractMaterial3DHandler * handlerForMaterialSettings(const QgsAbstractMaterialSettings *settings)
Returns the handler to use for a material settings.
@ RotationX
X-axis rotation.
@ TranslationY
Y-axis translation.
@ RotationY
Y-axis rotation.
@ TranslationZ
Z-axis translation.
@ TranslationX
X-axis translation.
@ RotationZ
Z-axis rotation.
Abstract base class for material 3D handlers.
Abstract base class for material settings.
virtual bool requiresTangents() const
Returns true if the material requires tangents generated during triangulation.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
static QgsSourceCache * sourceCache()
Returns the application's source cache, used for caching embedded and remote source strings as local ...
Geometry of the billboard rendering for points in 3D map view.
void setPositions(const QVector< QVector3D > &vertices)
Sets the vertex positions for the billboards.
A 3-dimensional box composed of x, y, z coordinates.
QgsVector3D center() const
Returns the center of the box as a vector.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
A marker symbol type, for rendering Point and MultiPoint geometries.
Context settings for a material.
void setIsSelected(bool isSelected)
Sets whether the material should represent a selected state.
bool isHighlighted() const
Returns true if the material should represent a highlighted state.
void setIsHighlighted(bool isHighlighted)
Sets whether the material should represent a highlighted state.
static QgsMaterialContext fromRenderContext(const Qgs3DRenderContext &context)
Constructs a material context from the settings in a 3D render context.
Base class for all materials used within QGIS 3D views.
Material of the billboard rendering for points in 3D map view.
void useDefaultSymbol(const Qgs3DRenderContext &context, bool selected=false)
Set default symbol for the texture with context and selected parameter for rendering.
void setTexture2DFromSymbol(const QgsMarkerSymbol *markerSymbol, const Qgs3DRenderContext &context, bool selected=false)
Set markerSymbol for the texture with context and selected parameter for rendering.
3D symbol that draws point geometries as 3D objects using one of the predefined shapes.
QgsMarkerSymbol * billboardSymbol() const
Returns a symbol for billboard.
Qgis::Point3DShape shape() const
Returns 3D shape for points.
QgsAbstractMaterialSettings * materialSettings() const override
Returns material settings used for shading of the symbol.
QVariant shapeProperty(const QString &property) const
Returns the value for a specific shape property.
A grouped map of multiple QgsProperty objects, each referenced by an integer key value.
bool isActive(int key) const final
Returns true if the collection contains an active property with the specified key.
QString localFilePath(const QString &path, bool blocking=false)
Returns a local file path reflecting the content of a specified source path.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
double x() const
Returns X coordinate.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QSet< QgsFeatureId > QgsFeatureIds
#define QgsDebugMsgLevel(str, level)