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 Qt3DExtras::QSphereGeometry *g =
new Qt3DExtras::QSphereGeometry;
435 g->setRadius( radius );
441 const float length = symbol->
shapeProperty( u
"length"_s ).toFloat();
442 const float bottomRadius = symbol->
shapeProperty( u
"bottomRadius"_s ).toFloat();
443 const float topRadius = symbol->
shapeProperty( u
"topRadius"_s ).toFloat();
445 Qt3DExtras::QConeGeometry *g =
new Qt3DExtras::QConeGeometry;
446 g->setLength( length );
447 g->setBottomRadius( bottomRadius );
448 g->setTopRadius( topRadius );
456 const float size = symbol->
shapeProperty( u
"size"_s ).toFloat();
457 Qt3DExtras::QCuboidGeometry *g =
new Qt3DExtras::QCuboidGeometry;
458 g->setXExtent( size );
459 g->setYExtent( size );
460 g->setZExtent( size );
466 const float radius = symbol->
shapeProperty( u
"radius"_s ).toFloat();
467 const float minorRadius = symbol->
shapeProperty( u
"minorRadius"_s ).toFloat();
468 Qt3DExtras::QTorusGeometry *g =
new Qt3DExtras::QTorusGeometry;
469 g->setRadius( radius );
470 g->setMinorRadius( minorRadius );
476 const float size = symbol->
shapeProperty( u
"size"_s ).toFloat();
477 Qt3DExtras::QPlaneGeometry *g =
new Qt3DExtras::QPlaneGeometry;
479 g->setHeight( size );
485 const float depth = symbol->
shapeProperty( u
"depth"_s ).toFloat();
486 const QString text = symbol->
shapeProperty( u
"text"_s ).toString();
487 Qt3DExtras::QExtrudedTextGeometry *g =
new Qt3DExtras::QExtrudedTextGeometry;
488 g->setDepth( depth );
504class QgsModelPoint3DSymbolHandler :
public QgsFeature3DHandler
507 QgsModelPoint3DSymbolHandler(
const QgsPoint3DSymbol *symbol,
const QgsFeatureIds &selectedIds )
508 : mSymbol( static_cast<QgsPoint3DSymbol *>( symbol->clone() ) )
509 , mSelectedIds( selectedIds )
512 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
override;
513 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
514 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
517 static void addSceneEntities(
518 const Qgs3DRenderContext &context,
519 const QVector<QVector3D> &positions,
520 const QVector<QVector3D> &scales,
521 const QVector<QQuaternion> &rotations,
522 const QgsVector3D &chunkOrigin,
523 const QgsPoint3DSymbol *symbol,
524 Qt3DCore::QEntity *parent
526 static void addMeshEntities(
527 const Qgs3DRenderContext &context,
528 const QVector<QVector3D> &positions,
529 const QVector<QVector3D> &scales,
530 const QVector<QQuaternion> &rotations,
531 const QgsVector3D &chunkOrigin,
532 const QgsPoint3DSymbol *symbol,
533 Qt3DCore::QEntity *parent,
537 static QgsGeoTransform *transform( QVector3D position,
const QMatrix4x4 &transform,
const QgsVector3D &chunkOrigin );
542 QVector<QVector3D> positions;
543 QVector<QVector3D> scales;
544 QVector<QQuaternion> rotations;
547 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
550 std::unique_ptr<QgsPoint3DSymbol> mSymbol;
552 QVector3D mSymbolScale;
553 QQuaternion mSymbolRotation;
554 QVector3D mPointTranslation;
560 PointData outSelected;
563bool QgsModelPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
566 Q_UNUSED( attributeNames )
568 mChunkOrigin = chunkExtent.
center();
569 mChunkExtent = chunkExtent;
571 QSet<QString> attrs = mSymbol->dataDefinedProperties().referencedFields( context.
expressionContext() );
572 attributeNames.unite( attrs );
580 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
591 if ( hasDDTranslation )
596 translation =
QgsVector3D( translationX, translationY, translationZ );
599 const std::size_t oldSize = out.positions.size();
601 const std::size_t added = out.positions.size() - oldSize;
603 QVector3D scale = mSymbolScale;
610 scale = QVector3D(
static_cast< float >( scaleX ),
static_cast< float >( scaleY ),
static_cast< float >( scaleZ ) );
613 out.scales.resize( out.positions.size() );
614 QVector3D *outScale = out.scales.data() + oldSize;
615 for ( std::size_t i = 0; i < added; ++i )
617 ( *outScale++ ) = scale;
620 QQuaternion rotation = mSymbolRotation;
627 const QVector3D baseEuler = mSymbolRotation.toEulerAngles();
634 rotation = QQuaternion::fromEulerAngles(
static_cast< float >( rotationX ),
static_cast< float >( rotationY ),
static_cast< float >( rotationZ ) );
637 out.rotations.resize( out.positions.size() );
638 QQuaternion *outRotation = out.rotations.data() + oldSize;
639 for ( std::size_t i = 0; i < added; ++i )
641 ( *outRotation++ ) = rotation;
647void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
649 makeEntity( parent, context, outNormal,
false );
650 makeEntity( parent, context, outSelected,
true );
652 updateZRangeFromPositions( outNormal.positions );
653 updateZRangeFromPositions( outSelected.positions );
656 const float symbolHeight = mSymbol->transform().data()[14];
658 mZMin +=
static_cast<float>( symbolHeight + mChunkOrigin.z() );
659 mZMax +=
static_cast<float>( symbolHeight + mChunkOrigin.z() );
662void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
664 if ( out.positions.isEmpty() )
671 addMeshEntities( context, out.positions, out.scales, out.rotations, mChunkOrigin, mSymbol.get(), parent,
true, mHighlightingEnabled );
676 if ( mSymbol->shapeProperty( u
"overwriteMaterial"_s ).toBool() || ( mSymbol->materialSettings() && mSymbol->materialSettings()->type() !=
"null"_L1 ) || mHighlightingEnabled )
678 addMeshEntities( context, out.positions, out.scales, out.rotations, mChunkOrigin, mSymbol.get(), parent,
false, mHighlightingEnabled );
682 addSceneEntities( context, out.positions, out.scales, out.rotations, mChunkOrigin, mSymbol.get(), parent );
687QVector3D stringToAxis(
const QString &axis )
689 if ( axis ==
"x"_L1 )
690 return QVector3D( 1.0f, 0.0f, 0.0f );
691 if ( axis ==
"-x"_L1 )
692 return QVector3D( -1.0f, 0.0f, 0.0f );
693 if ( axis ==
"y"_L1 )
694 return QVector3D( 0.0f, 1.0f, 0.0f );
695 if ( axis ==
"-y"_L1 )
696 return QVector3D( 0.0f, -1.0f, 0.0f );
697 if ( axis ==
"z"_L1 )
698 return QVector3D( 0.0f, 0.0f, 1.0f );
699 if ( axis ==
"-z"_L1 )
700 return QVector3D( 0.0f, 0.0f, -1.0f );
705QMatrix4x4 createZUpTransform(
const QString &upAxis,
const QString &forwardAxis )
707 QVector3D up = stringToAxis( upAxis );
708 QVector3D forward = stringToAxis( forwardAxis );
710 if ( up.isNull() || forward.isNull() || std::abs( QVector3D::dotProduct( up, forward ) ) > 1e-6f )
716 QVector3D right = QVector3D::crossProduct( forward, up ).normalized();
717 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 );
720void QgsModelPoint3DSymbolHandler::addSceneEntities(
722 const QVector<QVector3D> &positions,
723 const QVector<QVector3D> &scales,
724 const QVector<QQuaternion> &rotations,
727 Qt3DCore::QEntity *parent
734 const QString upAxis = symbol->
shapeProperty( u
"upAxis"_s ).toString();
735 const QString forwardAxis = symbol->
shapeProperty( u
"forwardAxis"_s ).toString();
736 const QMatrix4x4 zUpMatrix = createZUpTransform( upAxis, forwardAxis );
738 if ( !source.isEmpty() )
741 for (
const QVector3D &position : positions )
744 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
746 const QUrl url = QUrl::fromLocalFile( source );
747 Qt3DRender::QSceneLoader *modelLoader =
new Qt3DRender::QSceneLoader;
748 modelLoader->setSource( url );
750 QMatrix4x4 entityTransform;
751 entityTransform.scale( scales.at( index ) );
752 entityTransform.rotate( rotations.at( index ) );
753 entityTransform *= zUpMatrix;
755 entity->addComponent( modelLoader );
756 entity->addComponent( transform( position, entityTransform, chunkOrigin ) );
757 entity->setParent( parent );
770void QgsModelPoint3DSymbolHandler::addMeshEntities(
772 const QVector<QVector3D> &positions,
773 const QVector<QVector3D> &scales,
774 const QVector<QQuaternion> &rotations,
777 Qt3DCore::QEntity *parent,
782 if ( positions.empty() )
785 const QString upAxis = symbol->
shapeProperty( u
"upAxis"_s ).toString();
786 const QString forwardAxis = symbol->
shapeProperty( u
"forwardAxis"_s ).toString();
787 const QMatrix4x4 zUpMatrix = createZUpTransform( upAxis, forwardAxis );
790 if ( !source.isEmpty() )
801 const QUrl url = QUrl::fromLocalFile( source );
805 for (
const QVector3D &position : positions )
808 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
810 Qt3DRender::QMesh *mesh =
new Qt3DRender::QMesh;
811 mesh->setSource( url );
813 entity->addComponent( mesh );
814 entity->addComponent( mat );
816 QMatrix4x4 entityTransform;
817 entityTransform.scale( scales.at( index ) );
818 entityTransform.rotate( rotations.at( index ) );
819 entityTransform *= zUpMatrix;
821 entity->addComponent( transform( position, entityTransform, chunkOrigin ) );
822 entity->setParent( parent );
835QgsGeoTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position,
const QMatrix4x4 &transform,
const QgsVector3D &chunkOrigin )
838 QgsGeoTransform *tr =
new QgsGeoTransform;
839 tr->setMatrix( transform );
840 tr->setGeoTranslation( chunkOrigin + position + tr->translation() );
848class QgsPoint3DBillboardSymbolHandler :
public QgsFeature3DHandler
851 QgsPoint3DBillboardSymbolHandler(
const QgsPoint3DSymbol *symbol,
const QgsFeatureIds &selectedIds )
852 : mSymbol( static_cast<QgsPoint3DSymbol *>( symbol->clone() ) )
853 , mSelectedIds( selectedIds )
856 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
override;
857 void processFeature(
const QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
858 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
864 QVector<QVector3D> positions;
867 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
870 std::unique_ptr<QgsPoint3DSymbol> mSymbol;
875 PointData outSelected;
878bool QgsPoint3DBillboardSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames,
const QgsBox3D &chunkExtent )
881 Q_UNUSED( attributeNames )
883 mChunkOrigin = chunkExtent.
center();
884 mChunkExtent = chunkExtent;
891 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
900void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
902 makeEntity( parent, context, outNormal,
false );
903 makeEntity( parent, context, outSelected,
true );
905 updateZRangeFromPositions( outNormal.positions );
906 updateZRangeFromPositions( outSelected.positions );
909 const float billboardHeight = mSymbol->billboardHeight();
911 mZMin +=
static_cast<float>( billboardHeight + mChunkOrigin.z() );
912 mZMax +=
static_cast<float>( billboardHeight + mChunkOrigin.z() );
915void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
917 if ( out.positions.isEmpty() )
927 Qt3DRender::QGeometryRenderer *billboardGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
928 billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
929 billboardGeometryRenderer->setGeometry( billboardGeometry );
930 billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
946 QgsGeoTransform *billboardTransform =
new QgsGeoTransform;
947 billboardTransform->setGeoTranslation( mChunkOrigin +
QgsVector3D( 0, 0, mSymbol->billboardHeight() ) );
950 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
952 entity->addComponent( billboardMaterial );
953 entity->addComponent( billboardTransform );
954 entity->addComponent( billboardGeometryRenderer );
955 entity->setParent( parent );
962namespace Qgs3DSymbolImpl
965 QgsFeature3DHandler *handlerForPoint3DSymbol(
const QgsVectorLayer *layer,
const QgsAbstract3DSymbol *symbol )
967 const QgsPoint3DSymbol *pointSymbol =
dynamic_cast<const QgsPoint3DSymbol *
>( symbol );
975 return new QgsPoint3DBillboardSymbolHandler( pointSymbol, layer->
selectedFeatureIds() );
977 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.
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)