37 #include <QtConcurrent> 
   38 #include <Qt3DRender/QAttribute> 
   39 #include <Qt3DRender/QTechnique> 
   40 #include <Qt3DRender/QShaderProgram> 
   41 #include <Qt3DRender/QGraphicsApiFilter> 
   49 QgsPointCloudLayerChunkLoader::QgsPointCloudLayerChunkLoader( 
const QgsPointCloudLayerChunkLoaderFactory *factory, QgsChunkNode *node, std::unique_ptr< QgsPointCloud3DSymbol > symbol,
 
   51   : QgsChunkLoader( node )
 
   53   , mContext( factory->mMap, coordinateTransform, std::move( symbol ), zValueScale, zValueOffset )
 
   59   QgsChunkNodeId nodeId = node->tileId();
 
   62   Q_ASSERT( pc->
hasNode( pcNode ) );
 
   64   QgsDebugMsgLevel( QStringLiteral( 
"loading entity %1" ).arg( node->tileId().text() ), 2 );
 
   66   if ( mContext.symbol()->symbolType() == QLatin1String( 
"single-color" ) )
 
   67     mHandler.reset( 
new QgsSingleColorPointCloud3DSymbolHandler() );
 
   68   else if ( mContext.symbol()->symbolType() == QLatin1String( 
"color-ramp" ) )
 
   69     mHandler.reset( 
new QgsColorRampPointCloud3DSymbolHandler() );
 
   70   else if ( mContext.symbol()->symbolType() == QLatin1String( 
"rgb" ) )
 
   71     mHandler.reset( 
new QgsRGBPointCloud3DSymbolHandler() );
 
   72   else if ( mContext.symbol()->symbolType() == QLatin1String( 
"classification" ) )
 
   74     mHandler.reset( 
new QgsClassificationPointCloud3DSymbolHandler() );
 
   82   QFuture<void> future = QtConcurrent::run( [pc, pcNode, 
this]
 
   84     QgsEventTracing::ScopedEvent e( QStringLiteral( 
"3D" ), QStringLiteral( 
"PC chunk load" ) );
 
   86     if ( mContext.isCanceled() )
 
   91     mHandler->processNode( pc, pcNode, mContext );
 
   95   mFutureWatcher = 
new QFutureWatcher<void>( 
this );
 
   96   mFutureWatcher->setFuture( future );
 
   97   connect( mFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsChunkQueueJob::finished );
 
  101 QgsPointCloudLayerChunkLoader::~QgsPointCloudLayerChunkLoader()
 
  103   if ( mFutureWatcher && !mFutureWatcher->isFinished() )
 
  105     disconnect( mFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsChunkQueueJob::finished );
 
  106     mContext.cancelRendering();
 
  107     mFutureWatcher->waitForFinished();
 
  111 void QgsPointCloudLayerChunkLoader::cancel()
 
  113   mContext.cancelRendering();
 
  116 Qt3DCore::QEntity *QgsPointCloudLayerChunkLoader::createEntity( Qt3DCore::QEntity *parent )
 
  119   QgsChunkNodeId nodeId = mNode->tileId();
 
  121   Q_ASSERT( pc->
hasNode( pcNode ) );
 
  123   Qt3DCore::QEntity *entity = 
new Qt3DCore::QEntity( parent );
 
  124   mHandler->finalize( entity, mContext );
 
  132     double zValueScale, 
double zValueOffset, 
int pointBudget )
 
  134   , mCoordinateTransform( coordinateTransform )
 
  135   , mPointCloudIndex( pc )
 
  136   , mZValueScale( zValueScale )
 
  137   , mZValueOffset( zValueOffset )
 
  138   , mPointBudget( pointBudget )
 
  140   mSymbol.reset( symbol );
 
  143 QgsChunkLoader *QgsPointCloudLayerChunkLoaderFactory::createChunkLoader( QgsChunkNode *node )
 const 
  145   QgsChunkNodeId 
id = node->tileId();
 
  149   return new QgsPointCloudLayerChunkLoader( 
this, node, std::unique_ptr< QgsPointCloud3DSymbol >( symbol ), mCoordinateTransform, mZValueScale, mZValueOffset );
 
  152 int QgsPointCloudLayerChunkLoaderFactory::primitivesCount( QgsChunkNode *node )
 const 
  154   QgsChunkNodeId 
id = node->tileId();
 
  156   Q_ASSERT( mPointCloudIndex->hasNode( n ) );
 
  157   return mPointCloudIndex->nodePointCount( n );
 
  162 QgsChunkNode *QgsPointCloudLayerChunkLoaderFactory::createRootNode()
 const 
  164   QgsAABB bbox = nodeBoundsToAABB( mPointCloudIndex->nodeBounds( 
IndexedPointCloudNode( 0, 0, 0, 0 ) ), mPointCloudIndex->offset(), mPointCloudIndex->scale(), mMap, mCoordinateTransform, mZValueOffset );
 
  166   return new QgsChunkNode( QgsChunkNodeId( 0, 0, 0, 0 ), bbox, error );
 
  169 QVector<QgsChunkNode *> QgsPointCloudLayerChunkLoaderFactory::createChildren( QgsChunkNode *node )
 const 
  171   QVector<QgsChunkNode *> children;
 
  172   QgsChunkNodeId nodeId = node->tileId();
 
  174   float childError = node->error() / 2;
 
  177   for ( 
int i = 0; i < 8; ++i )
 
  179     int dx = i & 1, dy = !!( i & 2 ), dz = !!( i & 4 );
 
  180     QgsChunkNodeId childId( nodeId.d + 1, nodeId.x * 2 + dx, nodeId.y * 2 + dy, nodeId.z * 2 + dz );
 
  182     if ( !mPointCloudIndex->hasNode( 
IndexedPointCloudNode( childId.d, childId.x, childId.y, childId.z ) ) )
 
  188     float chXMin = dx ? xc : bbox.
xMin;
 
  189     float chXMax = dx ? bbox.
xMax : xc;
 
  191     float chZMin = !dy ? zc : bbox.
zMin;
 
  192     float chZMax = !dy ? bbox.
zMax : zc;
 
  193     float chYMin = dz ? yc : bbox.
yMin;
 
  194     float chYMax = dz ? bbox.
yMax : yc;
 
  195     children << 
new QgsChunkNode( childId, 
QgsAABB( chXMin, chYMin, chZMin, chXMax, chYMax, chZMax ), childError, node );
 
  205   QgsVector3D extentMin3D( nodeBounds.
xMin() * scale.
x() + offset.
x(), nodeBounds.
yMin() * scale.
y() + offset.
y(), nodeBounds.
zMin() * scale.
z() + offset.
z() + zValueOffset );
 
  206   QgsVector3D extentMax3D( nodeBounds.
xMax() * scale.
x() + offset.
x(), nodeBounds.
yMax() * scale.
y() + offset.
y(), nodeBounds.
zMax() * scale.
z() + offset.
z() + zValueOffset );
 
  209     extentMin3D = coordinateTransform.
transform( extentMin3D );
 
  210     extentMax3D = coordinateTransform.
transform( extentMax3D );
 
  214     QgsDebugMsg( QStringLiteral( 
"Error transforming node bounds coordinate" ) );
 
  218   QgsAABB rootBbox( worldExtentMin3D.
x(), worldExtentMin3D.
y(), worldExtentMin3D.
z(),
 
  219                     worldExtentMax3D.
x(), worldExtentMax3D.
y(), worldExtentMax3D.
z() );
 
  225   : QgsChunkedEntity( maximumScreenSpaceError,
 
  226                       new QgsPointCloudLayerChunkLoaderFactory( map, coordinateTransform, pc, symbol, zValueScale, zValueOffset, pointBudget ), true, pointBudget )
 
  228   setUsingAdditiveStrategy( 
true );
 
  229   setShowBoundingBoxes( showBoundingBoxes );
 
  232 QgsPointCloudLayerChunkedEntity::~QgsPointCloudLayerChunkedEntity()
 
Represents a indexed point cloud node in octree.
QgsVector3D origin() const
Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
static QgsVector3D mapToWorldCoordinates(const QgsVector3D &mapCoords, const QgsVector3D &origin)
Converts map coordinates to 3D world coordinates (applies offset and turns (x,y,z) into (x,...
float xCenter() const
Returns center in X axis.
float yCenter() const
Returns center in Y axis.
float zCenter() const
Returns center in Z axis.
QgsPointCloudCategoryList getFilteredOutCategories() const
Gets the list of categories of the classification that should not be rendered.
Custom exception class for Coordinate Reference System related exceptions.
Represents packaged data bounds.
qint32 xMax() const
Returns x max.
qint32 xMin() const
Returns x min.
qint32 yMax() const
Returns y max.
qint32 zMax() const
Returns z max.
qint32 yMin() const
Returns y min.
qint32 zMin() const
Returns z min.
Represents a indexed point clouds data in octree.
virtual bool hasNode(const IndexedPointCloudNode &n) const
Returns whether the octree contain given node.
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Sets native attributes of the data.
QgsPointCloudAttributeCollection attributes() const
Returns all attributes that are stored in the file.
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
double x() const
Returns X coordinate.
#define QgsDebugMsgLevel(str, level)