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)