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

Quantized Mesh fixes #58869

Merged
merged 6 commits into from
Sep 29, 2024
Merged
Show file tree
Hide file tree
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
11 changes: 9 additions & 2 deletions src/3d/qgs3dmapsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,10 @@ void Qgs3DMapSettings::resolveReferences( const QgsProject &project )
}

mTerrainGenerator->resolveReferences( project );

// Set extent now that layer-based generators actually have a chance to know their CRS
QgsRectangle terrainExtent = Qgs3DUtils::tryReprojectExtent2D( mExtent, mCrs, mTerrainGenerator->crs(), mTransformContext );
mTerrainGenerator->setExtent( terrainExtent );
}

QgsRectangle Qgs3DMapSettings::extent() const
Expand Down Expand Up @@ -795,8 +799,11 @@ void Qgs3DMapSettings::setTerrainGenerator( QgsTerrainGenerator *gen )
disconnect( mTerrainGenerator.get(), &QgsTerrainGenerator::terrainChanged, this, &Qgs3DMapSettings::terrainGeneratorChanged );
}

QgsRectangle terrainExtent = Qgs3DUtils::tryReprojectExtent2D( mExtent, mCrs, gen->crs(), mTransformContext );
gen->setExtent( terrainExtent );
if ( gen->crs().isValid() ) // Don't bother setting an extent rect in the wrong CRS
{
QgsRectangle terrainExtent = Qgs3DUtils::tryReprojectExtent2D( mExtent, mCrs, gen->crs(), mTransformContext );
gen->setExtent( terrainExtent );
}
mTerrainGenerator.reset( gen );
connect( mTerrainGenerator.get(), &QgsTerrainGenerator::terrainChanged, this, &Qgs3DMapSettings::terrainGeneratorChanged );

Expand Down
2 changes: 1 addition & 1 deletion src/3d/terrain/qgsdemterraingenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ void QgsDemTerrainGenerator::setExtent( const QgsRectangle &extent )
void QgsDemTerrainGenerator::updateGenerator()
{
QgsRasterLayer *dem = layer();
if ( dem )
if ( dem && mCrs.isValid() )
{
mTerrainTilingScheme = QgsTilingScheme( mExtent, mCrs );
delete mHeightMapGenerator;
Expand Down
1 change: 1 addition & 0 deletions src/3d/terrain/qgsdemterraingenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class _3D_EXPORT QgsDemTerrainGenerator : public QgsTerrainGenerator

//! Sets CRS of the terrain
void setCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context );
QgsCoordinateReferenceSystem crs() const override { return mCrs; }

//! Sets resolution of the generator (how many elevation samples on one side of a terrain tile)
void setResolution( int resolution ) { mResolution = resolution; updateGenerator(); }
Expand Down
11 changes: 2 additions & 9 deletions src/3d/terrain/qgsflatterraingenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,6 @@ void QgsFlatTerrainGenerator::setExtent( const QgsRectangle &extent )

void QgsFlatTerrainGenerator::updateTilingScheme()
{
if ( mExtent.isNull() )
{
mTerrainTilingScheme = QgsTilingScheme();
}
else
{
// the real extent will be a square where the given extent fully fits
mTerrainTilingScheme = QgsTilingScheme( mExtent, mCrs );
}
// the real extent will be a square where the given extent fully fits
mTerrainTilingScheme = QgsTilingScheme( mExtent, mCrs );
}
2 changes: 1 addition & 1 deletion src/3d/terrain/qgsflatterraingenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class _3D_EXPORT QgsFlatTerrainGenerator : public QgsTerrainGenerator
//! Sets CRS of the terrain
void setCrs( const QgsCoordinateReferenceSystem &crs );
//! Returns CRS of the terrain
QgsCoordinateReferenceSystem crs() const { return mCrs; }
QgsCoordinateReferenceSystem crs() const override { return mCrs; }

private:

Expand Down
2 changes: 1 addition & 1 deletion src/3d/terrain/qgsonlineterraingenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class _3D_EXPORT QgsOnlineTerrainGenerator : public QgsTerrainGenerator
//! Sets CRS of the terrain
void setCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context );
//! Returns CRS of the terrain
QgsCoordinateReferenceSystem crs() const { return mCrs; }
QgsCoordinateReferenceSystem crs() const override { return mCrs; }

//! Sets resolution of the generator (how many elevation samples on one side of a terrain tile)
void setResolution( int resolution ) { mResolution = resolution; updateGenerator(); }
Expand Down
14 changes: 11 additions & 3 deletions src/3d/terrain/qgsquantizedmeshterraingenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ QgsTerrainGenerator::Type QgsQuantizedMeshTerrainGenerator::type() const
return QgsTerrainGenerator::QuantizedMesh;
}

void QgsQuantizedMeshTerrainGenerator::setExtent( const QgsRectangle &extent )
{
mMapExtent = extent;
}

QgsRectangle QgsQuantizedMeshTerrainGenerator::rootChunkExtent() const
{
return mMetadata->mBoundingVolume.bounds().toRectangle();
Expand Down Expand Up @@ -302,12 +307,15 @@ QVector<QgsChunkNode *> QgsQuantizedMeshTerrainGenerator::createChildren( QgsChu
continue;

QgsTileMatrix zoomedTileMatrix = QgsTileMatrix::fromTileMatrix( tile.zoomLevel(), mMetadata->mTileMatrix );
QgsRectangle extent2d = mTileCrsToMapCrs.transform( zoomedTileMatrix.tileExtent( tile ) );
QgsRectangle extent2d = zoomedTileMatrix.tileExtent( tile );
if ( !extent2d.intersects( mMapExtent ) )
continue; // Don't render terrain inside layer extent, but outside map extent
Q_ASSERT( mTerrain );
QgsRectangle mapExtent2d = mTileCrsToMapCrs.transform( extent2d );
QgsVector3D corner1 = mTerrain->mapSettings()->mapToWorldCoordinates(
{extent2d.xMinimum(), extent2d.yMinimum(), mMetadata->dummyZRange.lower()} );
{mapExtent2d.xMinimum(), mapExtent2d.yMinimum(), mMetadata->dummyZRange.lower()} );
QgsVector3D corner2 = mTerrain->mapSettings()->mapToWorldCoordinates(
{extent2d.xMaximum(), extent2d.yMaximum(), mMetadata->dummyZRange.upper()} );
{mapExtent2d.xMaximum(), mapExtent2d.yMaximum(), mMetadata->dummyZRange.upper()} );
children.push_back(
new QgsChunkNode(
childId,
Expand Down
3 changes: 3 additions & 0 deletions src/3d/terrain/qgsquantizedmeshterraingenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "qgschunknode_p.h"
#include "qgscoordinatetransform.h"
#include "qgsmaplayerref.h"
#include "qgsrectangle.h"
#include "qgsterrainentity_p.h"
#include "qgsterraingenerator.h"
#include "qgsquantizedmeshdataprovider.h"
Expand All @@ -41,6 +42,7 @@ class _3D_EXPORT QgsQuantizedMeshTerrainGenerator : public QgsTerrainGenerator
virtual void setTerrain( QgsTerrainEntity *t ) override;
virtual QgsTerrainGenerator *clone() const override SIP_FACTORY;
virtual QgsTerrainGenerator::Type type() const override;
virtual void setExtent( const QgsRectangle &extent ) override;
virtual QgsRectangle rootChunkExtent() const override;
virtual float rootChunkError( const Qgs3DMapSettings &map ) const override;
virtual void rootChunkHeightRange( float &hMin, float &hMax ) const override;
Expand All @@ -67,6 +69,7 @@ class _3D_EXPORT QgsQuantizedMeshTerrainGenerator : public QgsTerrainGenerator
std::optional<QgsQuantizedMeshMetadata> mMetadata;
QgsCoordinateTransform mTileCrsToMapCrs;
QgsTiledSceneIndex mIndex;
QgsRectangle mMapExtent;

QgsQuantizedMeshTerrainGenerator( QgsMapLayerRef layerRef, const QgsQuantizedMeshMetadata &metadata );
QgsTileXYZ nodeIdToTile( QgsChunkNodeId nodeId ) const;
Expand Down
2 changes: 1 addition & 1 deletion src/3d/terrain/qgsterraingenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class _3D_EXPORT QgsTerrainGenerator : public QgsQuadtreeChunkLoaderFactory
const QgsTilingScheme &tilingScheme() const { return mTerrainTilingScheme; }

//! Returns CRS of the terrain
QgsCoordinateReferenceSystem crs() const { return mTerrainTilingScheme.crs(); }
virtual QgsCoordinateReferenceSystem crs() const { return mTerrainTilingScheme.crs(); }

//! Returns whether the terrain generator is valid
bool isValid() const;
Expand Down
8 changes: 5 additions & 3 deletions src/core/tiledscene/qgsquantizedmeshdataprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ QgsQuantizedMeshMetadata::QgsQuantizedMeshMetadata(
QgsSetRequestInitiatorClass( requestData,
QStringLiteral( "QgsQuantizedMeshDataProvider" ) );
QgsBlockingNetworkRequest request;
request.setAuthCfg( mAuthCfg );
if ( !mAuthCfg.isEmpty() )
request.setAuthCfg( mAuthCfg );
auto respCode = request.get( requestData );
if ( respCode != QgsBlockingNetworkRequest::ErrorCode::NoError )
{
Expand Down Expand Up @@ -413,7 +414,8 @@ QByteArray QgsQuantizedMeshIndex::fetchContent( const QString &uri,
requestData.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
requestData.setRawHeader( "Accept", "application/vnd.quantized-mesh,application/octet-stream;q=0.9" );
mMetadata.mHeaders.updateNetworkRequest( requestData );
QgsApplication::authManager()->updateNetworkRequest( requestData, mMetadata.mAuthCfg );
if ( !mMetadata.mAuthCfg.isEmpty() )
QgsApplication::authManager()->updateNetworkRequest( requestData, mMetadata.mAuthCfg );
QgsSetRequestInitiatorClass( requestData,
QStringLiteral( "QgsQuantizedMeshIndex" ) );

Expand All @@ -427,7 +429,7 @@ QByteArray QgsQuantizedMeshIndex::fetchContent( const QString &uri,

if ( reply->error() != QNetworkReply::NoError )
{
QgsDebugError( QStringLiteral( "Request failed: %1" ).arg( uri ) );
QgsDebugError( QStringLiteral( "Request failed (%1): %2" ).arg( uri ).arg( reply->errorString() ) );
return {};
}
return reply->data();
Expand Down
42 changes: 36 additions & 6 deletions src/core/tiledscene/qgsquantizedmeshtiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,24 +469,54 @@ tinygltf::Model QgsQuantizedMeshTile::toGltf( bool addSkirt, double skirtDepth,
// Create texture coordinates matching X, Y

tinygltf::Buffer textureCoordBuffer;
textureCoordBuffer.data.resize( mVertexCoords.size() / 3 * 2 * sizeof( float ) );
textureCoordBuffer.data.resize( vertexBuffer.data.size() / 3 * 2 );
std::vector<double> texCoordMinimums = {1.0, 1.0};
std::vector<double> texCoordMaximums = {0.0, 0.0};
auto textureCoordFloats = reinterpret_cast<float *>( textureCoordBuffer.data.data() );

for ( size_t i = 0; i < mVertexCoords.size() / 3; i++ )
auto addTexCoordForVertex = [&]( size_t vertexIdx )
{
double u = mVertexCoords[i * 3] / 32767.0;
double u = mVertexCoords[vertexIdx * 3] / 32767.0;
// V coord needs to be flipped for terrain for some reason
double v = 1.0 - ( mVertexCoords[i * 3 + 1] / 32767.0 );
double v = 1.0 - ( mVertexCoords[vertexIdx * 3 + 1] / 32767.0 );
if ( texCoordMinimums[0] > u ) texCoordMinimums[0] = u;
if ( texCoordMinimums[1] > v ) texCoordMinimums[1] = v;
if ( texCoordMaximums[0] < u ) texCoordMaximums[0] = u;
if ( texCoordMaximums[1] < v ) texCoordMaximums[1] = v;
textureCoordFloats[i * 2] = u;
textureCoordFloats[i * 2 + 1] = v;
*textureCoordFloats++ = u;
*textureCoordFloats++ = v;
};

for ( size_t i = 0; i < mVertexCoords.size() / 3; i++ )
{
addTexCoordForVertex( i );
}

if ( addSkirt )
{
// Add UV for generated bottom vertices matching the top edge vertices
auto addSkirtVertexUVs = [&]( const std::vector<uint32_t> &idxs )
{
for ( uint32_t idx : idxs )
{
addTexCoordForVertex( idx );
}

if ( idxs.size() > 1 )
{
// The two bottom corner vertices get UVs too
addTexCoordForVertex( idxs[0] );
addTexCoordForVertex( idxs[idxs.size() - 1] );
}
};
addSkirtVertexUVs( mWestVertices );
addSkirtVertexUVs( mSouthVertices );
addSkirtVertexUVs( mEastVertices );
addSkirtVertexUVs( mNorthVertices );
}

Q_ASSERT( textureCoordFloats == ( float * )( textureCoordBuffer.data.data() + textureCoordBuffer.data.size() ) );

model.buffers.push_back( textureCoordBuffer );

tinygltf::BufferView textureCoordBufferView;
Expand Down
14 changes: 13 additions & 1 deletion tests/src/3d/testqgs3drendering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,9 +325,11 @@ void TestQgs3DRendering::testDemTerrain()
map->setLayers( QList<QgsMapLayer *>() << mLayerRgb );

QgsDemTerrainGenerator *demTerrain = new QgsDemTerrainGenerator;
demTerrain->setCrs( mProject->crs(), mProject->transformContext() );
demTerrain->setLayer( mLayerDtm );
map->setTerrainGenerator( demTerrain );
map->setTerrainVerticalScale( 3 );
QVERIFY( demTerrain->isValid() );

QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
Expand Down Expand Up @@ -358,9 +360,11 @@ void TestQgs3DRendering::testTerrainShading()
// no terrain layers set!

QgsDemTerrainGenerator *demTerrain = new QgsDemTerrainGenerator;
demTerrain->setCrs( mProject->crs(), mProject->transformContext() );
demTerrain->setLayer( mLayerDtm );
map->setTerrainGenerator( demTerrain );
map->setTerrainVerticalScale( 3 );
QVERIFY( demTerrain->isValid() );

QgsPhongMaterialSettings terrainMaterial;
terrainMaterial.setAmbient( QColor( 0, 0, 0 ) );
Expand Down Expand Up @@ -1452,9 +1456,11 @@ void TestQgs3DRendering::testFilteredDemTerrain()
map->setLayers( QList<QgsMapLayer *>() << mLayerRgb );

QgsDemTerrainGenerator *demTerrain = new QgsDemTerrainGenerator;
demTerrain->setCrs( mProject->crs(), mProject->transformContext() );
demTerrain->setLayer( mLayerDtm );
map->setTerrainGenerator( demTerrain );
map->setTerrainVerticalScale( 3 );
QVERIFY( demTerrain->isValid() );

QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
Expand Down Expand Up @@ -1550,9 +1556,11 @@ void TestQgs3DRendering::testAmbientOcclusion()
mapSettings.setMapThemeCollection( project.mapThemeCollection() );

QgsDemTerrainGenerator *demTerrain = new QgsDemTerrainGenerator;
demTerrain->setCrs( mProject->crs(), mProject->transformContext() );
demTerrain->setLayer( layerDtm );
mapSettings.setTerrainGenerator( demTerrain );
mapSettings.setTerrainVerticalScale( 3 );
QVERIFY( demTerrain->isValid() );

QgsPointLightSettings defaultPointLight;
defaultPointLight.setPosition( QgsVector3D( 0, 400, 0 ) );
Expand Down Expand Up @@ -1615,9 +1623,11 @@ void TestQgs3DRendering::testDepthBuffer()
mapSettings.setMapThemeCollection( project.mapThemeCollection() );

QgsDemTerrainGenerator *demTerrain = new QgsDemTerrainGenerator;
demTerrain->setCrs( mProject->crs(), mProject->transformContext() );
demTerrain->setLayer( layerDtm );
mapSettings.setTerrainGenerator( demTerrain );
mapSettings.setTerrainVerticalScale( 3 );
QVERIFY( demTerrain->isValid() );

QgsPointLightSettings defaultPointLight;
defaultPointLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
Expand Down Expand Up @@ -1943,10 +1953,12 @@ void TestQgs3DRendering::test3DSceneExporterBig()
mapSettings.setPathResolver( project.pathResolver() );
mapSettings.setMapThemeCollection( project.mapThemeCollection() );

QgsDemTerrainGenerator *demTerrain = new QgsDemTerrainGenerator();
QgsDemTerrainGenerator *demTerrain = new QgsDemTerrainGenerator;
demTerrain->setCrs( mProject->crs(), mProject->transformContext() );
demTerrain->setLayer( layerDtm );
mapSettings.setTerrainGenerator( demTerrain );
mapSettings.setTerrainVerticalScale( 3 );
QVERIFY( demTerrain->isValid() );

QgsPointLightSettings defaultPointLight;
defaultPointLight.setPosition( QgsVector3D( 0, 400, 0 ) );
Expand Down
Loading