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];
271 mZMin =
static_cast< float >( minZ );
273 mZMax =
static_cast< float >( maxZ );
277 updateZRangeFromPointData( outNormal );
278 updateZRangeFromPointData( outSelected );
281void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
283 if ( out.positions.isEmpty() )
293 QgsMaterial *mat = material( mSymbol.get(), materialContext, !out.scales.empty(), !out.rotations.empty() );
295 mat->addParameter(
new Qt3DRender::QParameter(
"symbolScale", mSymbolScale, mat ) );
296 mat->addParameter(
new Qt3DRender::QParameter(
"symbolRotation", mSymbolRotation.toVector4D(), mat ) );
299 QgsGeoTransform *tr =
new QgsGeoTransform;
300 tr->setGeoTranslation( mChunkOrigin );
303 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
304 entity->addComponent( renderer( mSymbol.get(), out.positions, out.scales, out.rotations ) );
305 entity->addComponent( mat );
306 entity->addComponent( tr );
307 entity->setParent( parent );
316 std::unique_ptr<QgsMaterial> material;
324 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
325 filterKey->setName( u
"renderingStyle"_s );
326 filterKey->setValue(
"forward" );
328 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram;
330 const QByteArray vertexShaderCode = Qt3DRender::QShaderProgram::loadSource( QUrl( u
"qrc:/shaders/instanced.vert"_s ) );
332 if ( hasDataDefinedScale )
333 defines << u
"USE_INSTANCE_SCALE"_s;
334 if ( hasDataDefinedRotation )
335 defines << u
"USE_INSTANCE_ROTATION"_s;
338 shaderProgram->setVertexShaderCode( finalVertexShaderCode );
339 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( u
"qrc:/shaders/phong.frag"_s ) ) );
341 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass;
342 renderPass->setShaderProgram( shaderProgram );
344 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
345 technique->addFilterKey( filterKey );
346 technique->addRenderPass( renderPass );
347 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
348 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
349 technique->graphicsApiFilter()->setMajorVersion( 3 );
350 technique->graphicsApiFilter()->setMinorVersion( 2 );
352 Qt3DRender::QEffect *effect =
new Qt3DRender::QEffect;
353 effect->addTechnique( technique );
357 material = std::make_unique<QgsMaterial>();
358 material->setEffect( effect );
361 return material.release();
364Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer(
365 const QgsPoint3DSymbol *symbol,
const QVector<QVector3D> &positions,
const QVector<QVector3D> &scales,
const QVector<QVector4D> rotations
368 const std::size_t count = positions.count();
369 const std::size_t byteCount = positions.count() *
sizeof( QVector3D );
371 ba.resize( byteCount );
372 memcpy( ba.data(), positions.constData(), byteCount );
374 Qt3DCore::QBuffer *instanceBuffer =
new Qt3DCore::QBuffer();
375 instanceBuffer->setData( ba );
377 Qt3DCore::QAttribute *instanceTranslationAttribute =
new Qt3DCore::QAttribute;
378 instanceTranslationAttribute->setName( u
"instanceTranslation"_s );
379 instanceTranslationAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
380 instanceTranslationAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
381 instanceTranslationAttribute->setVertexSize( 3 );
382 instanceTranslationAttribute->setByteOffset( 0 );
383 instanceTranslationAttribute->setDivisor( 1 );
384 instanceTranslationAttribute->setBuffer( instanceBuffer );
385 instanceTranslationAttribute->setCount( count );
386 instanceTranslationAttribute->setByteStride( 3 *
sizeof(
float ) );
388 Qt3DCore::QGeometry *geometry = symbolGeometry( symbol );
389 geometry->addAttribute( instanceTranslationAttribute );
390 geometry->setBoundingVolumePositionAttribute( instanceTranslationAttribute );
392 if ( !scales.empty() )
394 auto scaleBuffer =
new Qt3DCore::QBuffer();
395 auto instanceScaleAttribute =
new Qt3DCore::QAttribute;
396 instanceScaleAttribute->setName( u
"instanceScale"_s );
397 instanceScaleAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
398 instanceScaleAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
399 instanceScaleAttribute->setVertexSize( 3 );
400 instanceScaleAttribute->setByteOffset( 0 );
401 instanceScaleAttribute->setDivisor( 1 );
402 instanceScaleAttribute->setByteStride( 3 *
sizeof(
float ) );
404 scaleBa.resize( byteCount );
405 memcpy( scaleBa.data(), scales.constData(), byteCount );
407 scaleBuffer->setData( scaleBa );
408 instanceScaleAttribute->setCount( count );
410 instanceScaleAttribute->setBuffer( scaleBuffer );
411 geometry->addAttribute( instanceScaleAttribute );
414 if ( !rotations.empty() )
416 auto rotationBuffer =
new Qt3DCore::QBuffer();
417 auto instanceRotationAttribute =
new Qt3DCore::QAttribute;
418 instanceRotationAttribute->setName( u
"instanceRotation"_s );
419 instanceRotationAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
420 instanceRotationAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
421 instanceRotationAttribute->setVertexSize( 4 );
422 instanceRotationAttribute->setByteOffset( 0 );
423 instanceRotationAttribute->setDivisor( 1 );
424 instanceRotationAttribute->setByteStride( 4 *
sizeof(
float ) );
426 QByteArray rotationBa;
427 const std::size_t rotationByteCount = positions.count() *
sizeof( QVector4D );
428 rotationBa.resize( rotationByteCount );
429 memcpy( rotationBa.data(), rotations.constData(), rotationByteCount );
430 rotationBuffer->setData( rotationBa );
431 instanceRotationAttribute->setCount( count );
433 instanceRotationAttribute->setBuffer( rotationBuffer );
434 geometry->addAttribute( instanceRotationAttribute );
437 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
438 renderer->setGeometry( geometry );
439 renderer->setInstanceCount( count );
444Qt3DCore::QGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry(
const QgsPoint3DSymbol *symbol )
446 switch ( symbol->
shape() )
450 const float radius = symbol->
shapeProperty( u
"radius"_s ).toFloat();
451 const float length = symbol->
shapeProperty( u
"length"_s ).toFloat();
452 Qt3DExtras::QCylinderGeometry *g =
new Qt3DExtras::QCylinderGeometry;
455 g->setRadius( radius );
456 g->setLength( length );
462 const float radius = symbol->
shapeProperty( u
"radius"_s ).toFloat();
463 Qt3DExtras::QSphereGeometry *g =
new Qt3DExtras::QSphereGeometry;
464 g->setRadius( radius );
470 const float length = symbol->
shapeProperty( u
"length"_s ).toFloat();
471 const float bottomRadius = symbol->
shapeProperty( u
"bottomRadius"_s ).toFloat();
472 const float topRadius = symbol->
shapeProperty( u
"topRadius"_s ).toFloat();
474 Qt3DExtras::QConeGeometry *g =
new Qt3DExtras::QConeGeometry;
475 g->setLength( length );
476 g->setBottomRadius( bottomRadius );
477 g->setTopRadius( topRadius );
485 const float size = symbol->
shapeProperty( u
"size"_s ).toFloat();
486 Qt3DExtras::QCuboidGeometry *g =
new Qt3DExtras::QCuboidGeometry;
487 g->setXExtent( size );
488 g->setYExtent( size );
489 g->setZExtent( size );
495 const float radius = symbol->
shapeProperty( u
"radius"_s ).toFloat();
496 const float minorRadius = symbol->
shapeProperty( u
"minorRadius"_s ).toFloat();
497 Qt3DExtras::QTorusGeometry *g =
new Qt3DExtras::QTorusGeometry;
498 g->setRadius( radius );
499 g->setMinorRadius( minorRadius );
505 const float size = symbol->
shapeProperty( u
"size"_s ).toFloat();
506 Qt3DExtras::QPlaneGeometry *g =
new Qt3DExtras::QPlaneGeometry;
508 g->setHeight( size );
514 const float depth = symbol->
shapeProperty( u
"depth"_s ).toFloat();
515 const QString text = symbol->
shapeProperty( u
"text"_s ).toString();
516 Qt3DExtras::QExtrudedTextGeometry *g =
new Qt3DExtras::QExtrudedTextGeometry;
517 g->setDepth( depth );
533class QgsModelPoint3DSymbolHandler :
public QgsFeature3DHandler
536 QgsModelPoint3DSymbolHandler(
const QgsPoint3DSymbol *symbol,
const QgsFeatureIds &selectedIds )
537 : mSymbol( static_cast<QgsPoint3DSymbol *>( symbol->clone() ) )
538 , mSelectedIds( selectedIds )
541 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
override;
542 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
543 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
546 static void addSceneEntities(
547 const Qgs3DRenderContext &context,
548 const QVector<QVector3D> &positions,
549 const QVector<QVector3D> &scales,
550 const QVector<QQuaternion> &rotations,
551 const QgsVector3D &chunkOrigin,
552 const QgsPoint3DSymbol *symbol,
553 Qt3DCore::QEntity *parent
555 static void addMeshEntities(
556 const Qgs3DRenderContext &context,
557 const QVector<QVector3D> &positions,
558 const QVector<QVector3D> &scales,
559 const QVector<QQuaternion> &rotations,
560 const QgsVector3D &chunkOrigin,
561 const QgsPoint3DSymbol *symbol,
562 Qt3DCore::QEntity *parent,
566 static QgsGeoTransform *transform( QVector3D position,
const QMatrix4x4 &transform,
const QgsVector3D &chunkOrigin );
571 QVector<QVector3D> positions;
572 QVector<QVector3D> scales;
573 QVector<QQuaternion> rotations;
576 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
579 std::unique_ptr<QgsPoint3DSymbol> mSymbol;
581 QVector3D mSymbolScale;
582 QQuaternion mSymbolRotation;
583 QVector3D mPointTranslation;
589 PointData outSelected;
592bool QgsModelPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
595 Q_UNUSED( attributeNames )
597 mChunkOrigin = chunkExtent.
center();
598 mChunkExtent = chunkExtent;
600 QSet<QString> attrs = mSymbol->dataDefinedProperties().referencedFields( context.
expressionContext() );
601 attributeNames.unite( attrs );
609 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
620 if ( hasDDTranslation )
625 translation =
QgsVector3D( translationX, translationY, translationZ );
628 const std::size_t oldSize = out.positions.size();
630 const std::size_t added = out.positions.size() - oldSize;
632 QVector3D scale = mSymbolScale;
639 scale = QVector3D(
static_cast< float >( scaleX ),
static_cast< float >( scaleY ),
static_cast< float >( scaleZ ) );
642 out.scales.resize( out.positions.size() );
643 QVector3D *outScale = out.scales.data() + oldSize;
644 for ( std::size_t i = 0; i < added; ++i )
646 ( *outScale++ ) = scale;
649 QQuaternion rotation = mSymbolRotation;
656 const QVector3D baseEuler = mSymbolRotation.toEulerAngles();
663 rotation = QQuaternion::fromEulerAngles(
static_cast< float >( rotationX ),
static_cast< float >( rotationY ),
static_cast< float >( rotationZ ) );
666 out.rotations.resize( out.positions.size() );
667 QQuaternion *outRotation = out.rotations.data() + oldSize;
668 for ( std::size_t i = 0; i < added; ++i )
670 ( *outRotation++ ) = rotation;
676void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
678 makeEntity( parent, context, outNormal,
false );
679 makeEntity( parent, context, outSelected,
true );
681 updateZRangeFromPositions( outNormal.positions );
682 updateZRangeFromPositions( outSelected.positions );
685 const float symbolHeight = mSymbol->transform().data()[14];
686 mZMin += symbolHeight;
687 mZMax += symbolHeight;
690void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
692 if ( out.positions.isEmpty() )
699 addMeshEntities( context, out.positions, out.scales, out.rotations, mChunkOrigin, mSymbol.get(), parent,
true, mHighlightingEnabled );
704 if ( mSymbol->shapeProperty( u
"overwriteMaterial"_s ).toBool() || ( mSymbol->materialSettings() && mSymbol->materialSettings()->type() !=
"null"_L1 ) || mHighlightingEnabled )
706 addMeshEntities( context, out.positions, out.scales, out.rotations, mChunkOrigin, mSymbol.get(), parent,
false, mHighlightingEnabled );
710 addSceneEntities( context, out.positions, out.scales, out.rotations, mChunkOrigin, mSymbol.get(), parent );
715QVector3D stringToAxis(
const QString &axis )
717 if ( axis ==
"x"_L1 )
718 return QVector3D( 1.0f, 0.0f, 0.0f );
719 if ( axis ==
"-x"_L1 )
720 return QVector3D( -1.0f, 0.0f, 0.0f );
721 if ( axis ==
"y"_L1 )
722 return QVector3D( 0.0f, 1.0f, 0.0f );
723 if ( axis ==
"-y"_L1 )
724 return QVector3D( 0.0f, -1.0f, 0.0f );
725 if ( axis ==
"z"_L1 )
726 return QVector3D( 0.0f, 0.0f, 1.0f );
727 if ( axis ==
"-z"_L1 )
728 return QVector3D( 0.0f, 0.0f, -1.0f );
733QMatrix4x4 createZUpTransform(
const QString &upAxis,
const QString &forwardAxis )
735 QVector3D up = stringToAxis( upAxis );
736 QVector3D forward = stringToAxis( forwardAxis );
738 if ( up.isNull() || forward.isNull() || std::abs( QVector3D::dotProduct( up, forward ) ) > 1e-6f )
744 QVector3D right = QVector3D::crossProduct( forward, up ).normalized();
745 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 );
748void QgsModelPoint3DSymbolHandler::addSceneEntities(
750 const QVector<QVector3D> &positions,
751 const QVector<QVector3D> &scales,
752 const QVector<QQuaternion> &rotations,
755 Qt3DCore::QEntity *parent
762 const QString upAxis = symbol->
shapeProperty( u
"upAxis"_s ).toString();
763 const QString forwardAxis = symbol->
shapeProperty( u
"forwardAxis"_s ).toString();
764 const QMatrix4x4 zUpMatrix = createZUpTransform( upAxis, forwardAxis );
766 if ( !source.isEmpty() )
769 for (
const QVector3D &position : positions )
772 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
774 const QUrl url = QUrl::fromLocalFile( source );
775 Qt3DRender::QSceneLoader *modelLoader =
new Qt3DRender::QSceneLoader;
776 modelLoader->setSource( url );
778 QMatrix4x4 entityTransform;
779 entityTransform.scale( scales.at( index ) );
780 entityTransform.rotate( rotations.at( index ) );
781 entityTransform *= zUpMatrix;
783 entity->addComponent( modelLoader );
784 entity->addComponent( transform( position, entityTransform, chunkOrigin ) );
785 entity->setParent( parent );
798void QgsModelPoint3DSymbolHandler::addMeshEntities(
800 const QVector<QVector3D> &positions,
801 const QVector<QVector3D> &scales,
802 const QVector<QQuaternion> &rotations,
805 Qt3DCore::QEntity *parent,
810 if ( positions.empty() )
813 const QString upAxis = symbol->
shapeProperty( u
"upAxis"_s ).toString();
814 const QString forwardAxis = symbol->
shapeProperty( u
"forwardAxis"_s ).toString();
815 const QMatrix4x4 zUpMatrix = createZUpTransform( upAxis, forwardAxis );
818 if ( !source.isEmpty() )
830 const QUrl url = QUrl::fromLocalFile( source );
834 for (
const QVector3D &position : positions )
837 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
839 Qt3DRender::QMesh *mesh =
new Qt3DRender::QMesh;
840 mesh->setSource( url );
842 entity->addComponent( mesh );
843 entity->addComponent( mat );
845 QMatrix4x4 entityTransform;
846 entityTransform.scale( scales.at( index ) );
847 entityTransform.rotate( rotations.at( index ) );
848 entityTransform *= zUpMatrix;
850 entity->addComponent( transform( position, entityTransform, chunkOrigin ) );
851 entity->setParent( parent );
864QgsGeoTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position,
const QMatrix4x4 &transform,
const QgsVector3D &chunkOrigin )
867 QgsGeoTransform *tr =
new QgsGeoTransform;
868 tr->setMatrix( transform );
869 tr->setGeoTranslation( chunkOrigin + position + tr->translation() );
877class QgsPoint3DBillboardSymbolHandler :
public QgsFeature3DHandler
880 QgsPoint3DBillboardSymbolHandler(
const QgsPoint3DSymbol *symbol,
const QgsFeatureIds &selectedIds )
881 : mSymbol( static_cast<QgsPoint3DSymbol *>( symbol->clone() ) )
882 , mSelectedIds( selectedIds )
885 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
override;
886 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
887 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
893 QVector<QVector3D> positions;
896 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
899 std::unique_ptr<QgsPoint3DSymbol> mSymbol;
904 PointData outSelected;
907bool QgsPoint3DBillboardSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
910 Q_UNUSED( attributeNames )
912 mChunkOrigin = chunkExtent.
center();
913 mChunkExtent = chunkExtent;
920 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
929void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
931 makeEntity( parent, context, outNormal,
false );
932 makeEntity( parent, context, outSelected,
true );
934 updateZRangeFromPositions( outNormal.positions );
935 updateZRangeFromPositions( outSelected.positions );
938 const float billboardHeight = mSymbol->billboardHeight();
939 mZMin += billboardHeight;
940 mZMax += billboardHeight;
943void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
945 if ( out.positions.isEmpty() )
955 Qt3DRender::QGeometryRenderer *billboardGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
956 billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
957 billboardGeometryRenderer->setGeometry( billboardGeometry );
958 billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
974 QgsGeoTransform *billboardTransform =
new QgsGeoTransform;
975 billboardTransform->setGeoTranslation( mChunkOrigin +
QgsVector3D( 0, 0, mSymbol->billboardHeight() ) );
978 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
980 entity->addComponent( billboardMaterial );
981 entity->addComponent( billboardTransform );
982 entity->addComponent( billboardGeometryRenderer );
983 entity->setParent( parent );
990namespace Qgs3DSymbolImpl
993 QgsFeature3DHandler *handlerForPoint3DSymbol( QgsVectorLayer *layer,
const QgsAbstract3DSymbol *symbol )
995 const QgsPoint3DSymbol *pointSymbol =
dynamic_cast<const QgsPoint3DSymbol *
>( symbol );
1003 return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
1005 return new QgsInstancedPoint3DSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
@ ExtrudedText
Extruded text.
@ Triangles
Triangle based rendering (default).
@ InstancedPoints
Instanced based rendering, requiring triangles and point data.
Rendering context for preparation of 3D entities.
QColor selectionColor() const
Returns color used for selected features.
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 QByteArray addDefinesToShaderCode(const QByteArray &shaderCode, const QStringList &defines)
Inserts some define macros into a shader source code.
static QgsMaterial * toMaterial(const QgsAbstractMaterialSettings *settings, Qgis::MaterialRenderingTechnique technique, const QgsMaterialContext &context)
Creates a new QgsMaterial object representing the material settings.
static void addMaterialParametersToEffect(Qt3DRender::QEffect *effect, const QgsAbstractMaterialSettings *settings, const QgsMaterialContext &materialContext)
Adds parameters from the material settings to a destination effect.
@ RotationX
X-axis rotation.
@ TranslationY
Y-axis translation.
@ RotationY
Y-axis rotation.
@ TranslationZ
Z-axis translation.
@ TranslationX
X-axis translation.
@ RotationZ
Z-axis rotation.
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.
void setSelectionColor(const QColor &color)
Sets the color for representing materials in 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.
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.
QgsAbstractMaterialSettings * materialSettings() const
Returns material settings used for shading of the symbol.
QgsMarkerSymbol * billboardSymbol() const
Returns a symbol for billboard.
Qgis::Point3DShape shape() const
Returns 3D shape for points.
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)