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 const 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 mFutureWatcher =
new QFutureWatcher<void>(
this );
83 connect( mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsChunkQueueJob::finished );
85 const QFuture<void> future = QtConcurrent::run( [pc, pcNode,
this]
87 const QgsEventTracing::ScopedEvent e( QStringLiteral(
"3D" ), QStringLiteral(
"PC chunk load" ) );
89 if ( mContext.isCanceled() )
94 mHandler->processNode( pc, pcNode, mContext );
98 mFutureWatcher->setFuture( future );
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 const 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 const 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 const QgsChunkNodeId
id = node->tileId();
156 Q_ASSERT( mPointCloudIndex->hasNode( n ) );
157 return mPointCloudIndex->nodePointCount( n );
162 QgsChunkNode *QgsPointCloudLayerChunkLoaderFactory::createRootNode()
const
164 const 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 const QgsChunkNodeId nodeId = node->tileId();
173 const QgsAABB bbox = node->bbox();
174 const 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 const 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 const float chXMin = dx ? xc : bbox.
xMin;
189 const float chXMax = dx ? bbox.
xMax : xc;
191 const float chZMin = !dy ? zc : bbox.
zMin;
192 const float chZMax = !dy ? bbox.
zMax : zc;
193 const float chYMin = dz ? yc : bbox.
yMin;
194 const 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 );
211 extentMin3D = extentTransform.
transform( extentMin3D );
212 extentMax3D = extentTransform.
transform( extentMax3D );
216 QgsDebugMsg( QStringLiteral(
"Error transforming node bounds coordinate" ) );
220 QgsAABB rootBbox( worldExtentMin3D.
x(), worldExtentMin3D.
y(), worldExtentMin3D.
z(),
221 worldExtentMax3D.
x(), worldExtentMax3D.
y(), worldExtentMax3D.
z() );
227 : QgsChunkedEntity( maximumScreenSpaceError,
228 new QgsPointCloudLayerChunkLoaderFactory( map, coordinateTransform, pc, symbol, zValueScale, zValueOffset, pointBudget ), true, pointBudget )
230 setUsingAdditiveStrategy(
true );
231 setShowBoundingBoxes( showBoundingBoxes );
234 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)