Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
move logic to QgsVirtualPointCloudEntity
  • Loading branch information
uclaros authored and wonder-sk committed May 11, 2023
1 parent a6e1f6e commit 8623512
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 60 deletions.
31 changes: 1 addition & 30 deletions src/3d/qgs3dmapscene.cpp
Expand Up @@ -364,31 +364,9 @@ void Qgs3DMapScene::updateScene()
{
QgsEventTracing::addEvent( QgsEventTracing::Instant, QStringLiteral( "3D" ), QStringLiteral( "Update Scene" ) );

const QSize size = mEngine->size();
const int screenSize = std::max( size.width(), size.height() );
const float fov = mCameraController->camera()->fieldOfView();
const QVector3D &cameraPosition = mCameraController->camera()->position();
for ( QgsVirtualPointCloudEntity *entity : std::as_const( mVirtualPointCloudEntities ) )
{
QgsVirtualPointCloudProvider *provider = entity->provider();

const QVector<QgsPointCloudSubIndex> subIndexes = provider->subIndexes();
for ( int i = 0; i < subIndexes.size(); ++i )
{
const QgsAABB &bbox = entity->boundingBox( i );
// magic number 256 is the common span value for a COPC root node
constexpr int SPAN = 256;
const float epsilon = std::min( bbox.xExtent(), bbox.yExtent() ) / SPAN;
const float distance = bbox.distanceFromPoint( cameraPosition );
const float sse = Qgs3DUtils::screenSpaceError( epsilon, distance, screenSize, fov );
constexpr float THRESHOLD = .2;
const bool displayAsBbox = sse < THRESHOLD;
if ( !displayAsBbox && !subIndexes.at( i ).index() )
provider->loadSubIndex( i );

entity->setRenderSubIndexAsBbox( i, displayAsBbox );
}
entity->updateBboxEntity();
entity->handleSceneUpdate( sceneState_( mEngine ) );
}

for ( QgsChunkedEntity *entity : std::as_const( mChunkEntities ) )
Expand Down Expand Up @@ -751,23 +729,16 @@ void Qgs3DMapScene::addLayerEntity( QgsMapLayer *layer )
{
mVirtualPointCloudEntities.append( virtualPointCloudEntity );

QgsVirtualPointCloudProvider *provider = qobject_cast<QgsVirtualPointCloudProvider *>( layer->dataProvider() );
virtualPointCloudEntity->createChunkedEntitiesForLoadedSubIndexes();
const QList<QgsChunkedEntity *> chunkedEntities = virtualPointCloudEntity->chunkedEntities();
for ( QgsChunkedEntity *ce : chunkedEntities )
{
ce->setParent( virtualPointCloudEntity );
needsSceneUpdate = true;
addNewChunkedEntity( ce );
}

connect( provider, &QgsVirtualPointCloudProvider::subIndexLoaded, virtualPointCloudEntity, &QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex );

connect( virtualPointCloudEntity, &QgsVirtualPointCloudEntity::newEntityCreated, this, [ = ]( QgsChunkedEntity * newChildChunkedEntity )
{
newChildChunkedEntity->setParent( virtualPointCloudEntity );
addNewChunkedEntity( newChildChunkedEntity );
virtualPointCloudEntity->updateBboxEntity();
onCameraChanged();
} );
}
Expand Down
69 changes: 42 additions & 27 deletions src/3d/qgsvirtualpointcloudentity_p.cpp
Expand Up @@ -44,11 +44,30 @@ QgsVirtualPointCloudEntity::QgsVirtualPointCloudEntity( QgsPointCloudLayer *laye
mSymbol.reset( symbol );
mBboxesEntity = new QgsChunkBoundsEntity( this );
const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
for ( const auto &si : subIndexes )
for ( int i = 0; i < subIndexes.size(); ++i )
{
const QgsPointCloudSubIndex &si = subIndexes.at( i );
mBboxes << Qgs3DUtils::mapToWorldExtent( si.extent(), si.zRange().lower(), si.zRange().upper(), mMap.origin() );

if ( !si.index() )
continue;

QgsPointCloudLayerChunkedEntity *entity = new QgsPointCloudLayerChunkedEntity( si.index(),
mMap,
mCoordinateTransform,
static_cast< QgsPointCloud3DSymbol * >( mSymbol->clone() ),
mMaximumScreenSpaceError,
mShowBoundingBoxes,
mZValueScale,
mZValueOffset,
mPointBudget );
mChunkedEntitiesMap.insert( i, entity );
mChunkedEntities.append( entity );
entity->setParent( this );
}

updateBboxEntity();
connect( provider(), &QgsVirtualPointCloudProvider::subIndexLoaded, this, &QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex );
}

QList<QgsChunkedEntity *> QgsVirtualPointCloudEntity::chunkedEntities() const
Expand All @@ -66,32 +85,6 @@ QgsAABB QgsVirtualPointCloudEntity::boundingBox( int i ) const
return mBboxes.at( i );
}

void QgsVirtualPointCloudEntity::createChunkedEntitiesForLoadedSubIndexes()
{
if ( !mChunkedEntities.isEmpty() )
return;

const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
for ( int i = 0; i < subIndexes.size(); ++i )
{
const QgsPointCloudSubIndex &si = subIndexes.at( i );
if ( !si.index() )
continue;

QgsPointCloudLayerChunkedEntity *entity = new QgsPointCloudLayerChunkedEntity( si.index(),
mMap,
mCoordinateTransform,
static_cast< QgsPointCloud3DSymbol * >( mSymbol->clone() ),
mMaximumScreenSpaceError,
mShowBoundingBoxes,
mZValueScale,
mZValueOffset,
mPointBudget );
mChunkedEntitiesMap.insert( i, entity );
mChunkedEntities.append( entity );
}
}

void QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex( int i )
{
const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
Expand All @@ -106,9 +99,31 @@ void QgsVirtualPointCloudEntity::createChunkedEntityForSubIndex( int i )
mPointBudget );
mChunkedEntities.append( newChunkedEntity );
mChunkedEntitiesMap.insert( i, newChunkedEntity );
newChunkedEntity->setParent( this );
emit newEntityCreated( newChunkedEntity );
}

void QgsVirtualPointCloudEntity::handleSceneUpdate( const QgsChunkedEntity::SceneState &state )
{
const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();
for ( int i = 0; i < subIndexes.size(); ++i )
{
const QgsAABB &bbox = mBboxes.at( i );
// magic number 256 is the common span value for a COPC root node
constexpr int SPAN = 256;
const float epsilon = std::min( bbox.xExtent(), bbox.yExtent() ) / SPAN;
const float distance = bbox.distanceFromPoint( state.cameraPos );
const float sse = Qgs3DUtils::screenSpaceError( epsilon, distance, state.screenSizePx, state.cameraFov );
constexpr float THRESHOLD = .2;
const bool displayAsBbox = sse < THRESHOLD;
if ( !displayAsBbox && !subIndexes.at( i ).index() )
provider()->loadSubIndex( i );

setRenderSubIndexAsBbox( i, displayAsBbox );
}
updateBboxEntity();
}

void QgsVirtualPointCloudEntity::updateBboxEntity()
{
QList<QgsAABB> bboxes;
Expand Down
7 changes: 4 additions & 3 deletions src/3d/qgsvirtualpointcloudentity_p.h
Expand Up @@ -32,15 +32,16 @@

#include "qgscoordinatetransform.h"
#include "qgspointcloudsubindex.h"
#include "qgschunkedentity_p.h"

class QgsAABB;
class QgsChunkedEntity;
class QgsChunkBoundsEntity;
class QgsPointCloudLayer;
class QgsVirtualPointCloudProvider;
class QgsPointCloud3DSymbol;
class Qgs3DMapSettings;


/**
* \ingroup 3d
* \brief Implementation of entity that handles virtual point cloud sub indexes
Expand All @@ -59,8 +60,8 @@ class QgsVirtualPointCloudEntity : public Qt3DCore::QEntity
QgsVirtualPointCloudEntity( QgsPointCloudLayer *layer, const Qgs3DMapSettings &map, const QgsCoordinateTransform &coordinateTransform, QgsPointCloud3DSymbol *symbol, float maxScreenError, bool showBoundingBoxes,
double zValueScale, double zValueOffset, int pointBudget );

//! creates a child QgsPointCloudLayerChunkedEntity for each of the already loaded sub indexes
void createChunkedEntitiesForLoadedSubIndexes();
//! This is called when the camera moves. It's responsible for loading new indexes and decides if subindex will be rendered as bbox or chunked entity.
void handleSceneUpdate( const QgsChunkedEntity::SceneState &state );

//! Updates the Bbox child entity to display the sub indexes set with setRenderSubIndexAsBbox()
void updateBboxEntity();
Expand Down

0 comments on commit 8623512

Please sign in to comment.