Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #41903 point cloud crash on macos #43743

Merged
merged 2 commits into from
Jun 16, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 38 additions & 16 deletions src/3d/chunks/qgschunkedentity_p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,22 +245,48 @@ int QgsChunkedEntity::pendingJobsCount() const
return mChunkLoaderQueue->count() + mActiveJobs.count();
}

struct ResidencyRequest
{
QgsChunkNode *node = nullptr;
float dist = 0.0;
int level = -1;
ResidencyRequest() = default;
ResidencyRequest(
QgsChunkNode *n,
float d,
int l )
: node( n )
, dist( d )
, level( l )
{}
};

struct
{
bool operator()( const ResidencyRequest &request, const ResidencyRequest &otherRequest ) const
{
if ( request.level == otherRequest.level )
return request.dist > otherRequest.dist;
return request.level > otherRequest.level;
}
} ResidencyRequestSorter;

void QgsChunkedEntity::update( QgsChunkNode *root, const SceneState &state )
{
QSet<QgsChunkNode *> nodes;
QVector<std::tuple<QgsChunkNode *, float, int>> residencyRequests;
QVector<ResidencyRequest> residencyRequests;

using slot = std::pair<QgsChunkNode *, float>;
auto cmp_funct = []( slot & p1, slot & p2 )
using slotItem = std::pair<QgsChunkNode *, float>;
auto cmp_funct = []( slotItem & p1, slotItem & p2 )
{
return p1.second <= p2.second;
};
int renderedCount = 0;
std::priority_queue<slot, std::vector<slot>, decltype( cmp_funct )> pq( cmp_funct );
std::priority_queue<slotItem, std::vector<slotItem>, decltype( cmp_funct )> pq( cmp_funct );
pq.push( std::make_pair( root, screenSpaceError( root, state ) ) );
while ( !pq.empty() && renderedCount <= mPrimitivesBudget )
{
slot s = pq.top();
slotItem s = pq.top();
pq.pop();
QgsChunkNode *node = s.first;

Expand All @@ -277,7 +303,7 @@ void QgsChunkedEntity::update( QgsChunkNode *root, const SceneState &state )
// make sure all nodes leading to children are always loaded
// so that zooming out does not create issues
double dist = node->bbox().center().distanceToPoint( state.cameraPos );
residencyRequests.push_back( std::make_tuple( node, dist, node->level() ) );
residencyRequests.push_back( ResidencyRequest( node, dist, node->level() ) );

if ( !node->entity() )
{
Expand All @@ -286,7 +312,7 @@ void QgsChunkedEntity::update( QgsChunkNode *root, const SceneState &state )
}
bool becomesActive = false;

//QgsDebugMsgLevel( QStringLiteral( "%1|%2|%3 %4 %5" ).arg( node->tileX() ).arg( node->tileY() ).arg( node->tileZ() ).arg( mTau ).arg( screenSpaceError( node, state ) ), 2 );
// QgsDebugMsgLevel( QStringLiteral( "%1|%2|%3 %4 %5" ).arg( node->tileId().x ).arg( node->tileId().y ).arg( node->tileId().z ).arg( mTau ).arg( screenSpaceError( node, state ) ), 2 );
if ( node->childCount() == 0 )
{
// there's no children available for this node, so regardless of whether it has an acceptable error
Expand Down Expand Up @@ -321,7 +347,7 @@ void QgsChunkedEntity::update( QgsChunkNode *root, const SceneState &state )
for ( int i = 0; i < node->childCount(); ++i )
{
double dist = children[i]->bbox().center().distanceToPoint( state.cameraPos );
residencyRequests.push_back( std::make_tuple( children[i], dist, children[i]->level() ) );
residencyRequests.push_back( ResidencyRequest( children[i], dist, children[i]->level() ) );
}
}
if ( becomesActive )
Expand All @@ -337,15 +363,11 @@ void QgsChunkedEntity::update( QgsChunkNode *root, const SceneState &state )
nodes.insert( node );
}
}

// sort nodes by their level and their distance from the camera
std::sort( residencyRequests.begin(), residencyRequests.end(), [&]( std::tuple<QgsChunkNode *, float, int> &n1, std::tuple<QgsChunkNode *, float, int> &n2 )
{
if ( std::get<2>( n1 ) == std::get<2>( n2 ) )
return std::get<1>( n1 ) >= std::get<1>( n1 );
return std::get<2>( n1 ) >= std::get<2>( n2 );
} );
for ( std::tuple<QgsChunkNode *, float, int> n : residencyRequests )
requestResidency( std::get<0>( n ) );
std::sort( residencyRequests.begin(), residencyRequests.end(), ResidencyRequestSorter );
for ( const auto &request : residencyRequests )
requestResidency( request.node );
}

void QgsChunkedEntity::requestResidency( QgsChunkNode *node )
Expand Down