tests/3d: Factor out mesh tests into its own file

This commit is contained in:
Jean Felder 2023-10-18 10:39:20 +02:00 committed by Nyall Dawson
parent 9bbae4c6ac
commit 4e16d45521
3 changed files with 337 additions and 270 deletions

View File

@ -28,6 +28,7 @@ set(TESTS
testqgsgltf3dutils.cpp
testqgslayout3dmap.cpp
testqgsmaterialregistry.cpp
testqgsmesh3drendering.cpp
testqgspointcloud3drendering.cpp
testqgstessellator.cpp
testqgstilingscheme.cpp

View File

@ -18,8 +18,6 @@
#include "qgslinestring.h"
#include "qgsmaplayerstylemanager.h"
#include "qgsmapthemecollection.h"
#include "qgsmeshlayer.h"
#include "qgsmeshrenderersettings.h"
#include "qgsproject.h"
#include "qgsrasterlayer.h"
#include "qgsrastershader.h"
@ -34,17 +32,14 @@
#include "qgscameracontroller.h"
#include "qgsdemterraingenerator.h"
#include "qgsflatterraingenerator.h"
#include "qgsmeshterraingenerator.h"
#include "qgsline3dsymbol.h"
#include "qgsoffscreen3dengine.h"
#include "qgspolygon3dsymbol.h"
#include "qgsrulebased3drenderer.h"
#include "qgsvectorlayer3drenderer.h"
#include "qgsmeshlayer3drenderer.h"
#include "qgspoint3dsymbol.h"
#include "qgssymbollayer.h"
#include "qgsmarkersymbollayer.h"
#include "qgsmaplayertemporalproperties.h"
#include "qgssymbol.h"
#include "qgssinglesymbolrenderer.h"
#include "qgsfillsymbollayer.h"
@ -74,7 +69,6 @@ class TestQgs3DRendering : public QgsTest
void testFlatTerrain();
void testDemTerrain();
void testTerrainShading();
void testMeshTerrain();
void testEpsg4978LineRendering();
void testExtrudedPolygons();
void testExtrudedPolygonsDataDefined();
@ -85,9 +79,6 @@ class TestQgs3DRendering : public QgsTest
void testBufferedLineRendering();
void testBufferedLineRenderingWidth();
void testMapTheme();
void testMesh();
void testMesh_datasetOnFaces();
void testMeshSimplified();
void testRuleBasedRenderer();
void testAnimationExport();
void testBillboardRendering();
@ -95,7 +86,6 @@ class TestQgs3DRendering : public QgsTest
void testFilteredFlatTerrain();
void testFilteredDemTerrain();
void testFilteredExtrudedPolygons();
void testFilteredMesh();
void testDepthBuffer();
void testAmbientOcclusion();
void testDebugMap();
@ -111,10 +101,6 @@ class TestQgs3DRendering : public QgsTest
QgsRasterLayer *mLayerDtm = nullptr;
QgsRasterLayer *mLayerRgb = nullptr;
QgsVectorLayer *mLayerBuildings = nullptr;
QgsMeshLayer *mLayerMeshTerrain = nullptr;
QgsMeshLayer *mLayerMeshDataset = nullptr;
QgsMeshLayer *mLayerMeshSimplified = nullptr;
};
/**
@ -208,36 +194,6 @@ void TestQgs3DRendering::initTestCase()
QgsVectorLayer3DRenderer *renderer3d = new QgsVectorLayer3DRenderer( symbol3d );
mLayerBuildings->setRenderer3D( renderer3d );
mLayerMeshTerrain = new QgsMeshLayer( testDataPath( "/mesh/quad_flower.2dm" ), "mesh", "mdal" );
QVERIFY( mLayerMeshTerrain->isValid() );
mLayerMeshTerrain->setCrs( mLayerDtm->crs() ); // this testing mesh does not have any CRS defined originally
mProject->addMapLayer( mLayerMeshTerrain );
mLayerMeshDataset = new QgsMeshLayer( testDataPath( "/mesh/quad_and_triangle.2dm" ), "mesh", "mdal" );
mLayerMeshDataset->dataProvider()->addDataset( testDataPath( "/mesh/quad_and_triangle_vertex_scalar.dat" ) );
mLayerMeshDataset->dataProvider()->addDataset( testDataPath( "/mesh/quad_and_triangle_vertex_vector.dat" ) );
mLayerMeshDataset->dataProvider()->addDataset( testDataPath( "/mesh/quad_and_triangle_els_face_scalar.dat" ) );
QVERIFY( mLayerMeshDataset->isValid() );
mLayerMeshDataset->setCrs( mLayerDtm->crs() ); // this testing mesh does not have any CRS defined originally
mLayerMeshDataset->temporalProperties()->setIsActive( false );
mLayerMeshDataset->setStaticScalarDatasetIndex( QgsMeshDatasetIndex( 1, 0 ) );
mLayerMeshDataset->setStaticVectorDatasetIndex( QgsMeshDatasetIndex( 2, 0 ) );
mProject->addMapLayer( mLayerMeshDataset );
mLayerMeshSimplified = new QgsMeshLayer( testDataPath( "/mesh/trap_steady_05_3D.nc" ), "mesh", "mdal" );
mLayerMeshSimplified->setCrs( mProject->crs() );
QVERIFY( mLayerMeshSimplified->isValid() );
mProject->addMapLayer( mLayerMeshSimplified );
QgsMesh3DSymbol *symbolMesh3d = new QgsMesh3DSymbol;
symbolMesh3d->setVerticalDatasetGroupIndex( 0 );
symbolMesh3d->setVerticalScale( 10 );
symbolMesh3d->setRenderingStyle( QgsMesh3DSymbol::ColorRamp2DRendering );
symbolMesh3d->setArrowsEnabled( true );
symbolMesh3d->setArrowsSpacing( 300 );
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolMesh3d );
mLayerMeshDataset->setRenderer3D( meshDatasetRenderer3d );
mProject->setCrs( mLayerDtm->crs() );
//
@ -407,43 +363,6 @@ void TestQgs3DRendering::testTerrainShading()
QVERIFY( imageCheck( "shaded_terrain_no_layers", "shaded_terrain_no_layers", img3, QString(), 40, QSize( 0, 0 ), 2 ) );
}
void TestQgs3DRendering::testMeshTerrain()
{
if ( !QgsTest::runFlakyTests() )
QSKIP( "This test is flaky and disabled on CI" );
const QgsRectangle fullExtent = mLayerMeshTerrain->extent();
Qgs3DMapSettings *map = new Qgs3DMapSettings;
map->setCrs( mProject->crs() );
map->setExtent( fullExtent );
QgsMeshTerrainGenerator *meshTerrain = new QgsMeshTerrainGenerator;
meshTerrain->setCrs( mProject->crs(), mProject->transformContext() );
meshTerrain->setLayer( mLayerMeshTerrain );
map->setTerrainGenerator( meshTerrain );
QCOMPARE( meshTerrain->heightAt( 750, 2500, *map ), 500.0 );
QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
engine.setRootEntity( scene );
// look from the top
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
// When running the test on Travis, it would initially return empty rendered image.
// Capturing the initial image and throwing it away fixes that. Hopefully we will
// find a better fix in the future.
Qgs3DUtils::captureSceneImage( engine, scene );
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
delete scene;
delete map;
QVERIFY( imageCheck( "mesh_terrain_1", "mesh_terrain_1", img, QString(), 40, QSize( 0, 0 ), 2 ) );
}
void TestQgs3DRendering::testExtrudedPolygons()
{
const QgsRectangle fullExtent = mLayerDtm->extent();
@ -888,150 +807,6 @@ void TestQgs3DRendering::testMapTheme()
QVERIFY( imageCheck( "terrain_theme", "terrain_theme", img, QString(), 40, QSize( 0, 0 ), 2 ) );
}
void TestQgs3DRendering::testMesh()
{
const QgsRectangle fullExtent = mLayerMeshDataset->extent();
Qgs3DMapSettings *map = new Qgs3DMapSettings;
map->setCrs( mProject->crs() );
map->setExtent( fullExtent );
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshDataset );
QgsPointLightSettings defaultLight;
defaultLight.setIntensity( 0.5 );
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
map->setLightSources( { defaultLight.clone() } );
QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator;
flatTerrain->setCrs( map->crs() );
map->setTerrainGenerator( flatTerrain );
QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
engine.setRootEntity( scene );
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
Qgs3DUtils::captureSceneImage( engine, scene );
// When running the test on Travis, it would initially return empty rendered image.
// Capturing the initial image and throwing it away fixes that. Hopefully we will
// find a better fix in the future.
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
delete scene;
delete map;
QVERIFY( imageCheck( "mesh3d", "mesh3d", img, QString(), 40, QSize( 0, 0 ), 2 ) );
}
void TestQgs3DRendering::testMesh_datasetOnFaces()
{
const QgsRectangle fullExtent = mLayerMeshDataset->extent();
QgsMesh3DSymbol *symbolMesh3d = new QgsMesh3DSymbol;
symbolMesh3d->setVerticalDatasetGroupIndex( 3 );
symbolMesh3d->setVerticalScale( 10 );
symbolMesh3d->setRenderingStyle( QgsMesh3DSymbol::ColorRamp2DRendering );
symbolMesh3d->setArrowsEnabled( true );
symbolMesh3d->setArrowsSpacing( 300 );
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolMesh3d );
mLayerMeshDataset->setRenderer3D( meshDatasetRenderer3d );
Qgs3DMapSettings *map = new Qgs3DMapSettings;
map->setCrs( mProject->crs() );
map->setExtent( fullExtent );
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshDataset );
QgsPointLightSettings defaultLight;
defaultLight.setIntensity( 0.5 );
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
map->setLightSources( { defaultLight.clone() } );
QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator;
flatTerrain->setCrs( map->crs() );
map->setTerrainGenerator( flatTerrain );
QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
engine.setRootEntity( scene );
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
Qgs3DUtils::captureSceneImage( engine, scene );
// When running the test on Travis, it would initially return empty rendered image.
// Capturing the initial image and throwing it away fixes that. Hopefully we will
// find a better fix in the future.
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
delete scene;
delete map;
QVERIFY( imageCheck( "mesh3dOnFace", "mesh3dOnFace", img, QString(), 40, QSize( 0, 0 ), 2 ) );
}
void TestQgs3DRendering::testMeshSimplified()
{
if ( QgsTest::isCIRun() )
{
QSKIP( "Intermittently fails on CI" );
}
QgsMeshSimplificationSettings simplificationSettings;
simplificationSettings.setEnabled( true );
simplificationSettings.setReductionFactor( 3 );
QgsMeshRendererSettings settings;
settings.setActiveScalarDatasetGroup( 16 );
settings.setActiveVectorDatasetGroup( 6 );
mLayerMeshSimplified->setRendererSettings( settings );
const QgsRectangle fullExtent = mLayerMeshSimplified->extent();
mLayerMeshSimplified->setMeshSimplificationSettings( simplificationSettings );
mLayerMeshSimplified->temporalProperties()->setIsActive( false );
mLayerMeshSimplified->setStaticScalarDatasetIndex( QgsMeshDatasetIndex( 16, 5 ) );
mLayerMeshSimplified->setStaticVectorDatasetIndex( QgsMeshDatasetIndex( 6, 5 ) );
for ( int i = 0; i < 4; ++i )
{
Qgs3DMapSettings *map = new Qgs3DMapSettings;
map->setCrs( mProject->crs() );
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshSimplified );
map->setExtent( fullExtent );
QgsMesh3DSymbol *symbolDataset = new QgsMesh3DSymbol;
symbolDataset->setVerticalDatasetGroupIndex( 11 );
symbolDataset->setVerticalScale( 1 );
symbolDataset->setWireframeEnabled( true );
symbolDataset->setWireframeLineWidth( 0.1 );
symbolDataset->setArrowsEnabled( true );
symbolDataset->setArrowsSpacing( 20 );
symbolDataset->setSingleMeshColor( Qt::yellow );
symbolDataset->setLevelOfDetailIndex( i );
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolDataset );
mLayerMeshSimplified->setRenderer3D( meshDatasetRenderer3d );
QgsMeshTerrainGenerator *meshTerrain = new QgsMeshTerrainGenerator;
meshTerrain->setLayer( mLayerMeshSimplified );
QgsMesh3DSymbol *symbol = new QgsMesh3DSymbol;
symbol->setWireframeEnabled( true );
symbol->setWireframeLineWidth( 0.1 );
symbol->setLevelOfDetailIndex( i );
meshTerrain->setSymbol( symbol );
map->setTerrainGenerator( meshTerrain );
QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
engine.setRootEntity( scene );
// look from the top
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 1000, 25, 45 );
// When running the test on Travis, it would initially return empty rendered image.
// Capturing the initial image and throwing it away fixes that. Hopefully we will
// find a better fix in the future.
Qgs3DUtils::captureSceneImage( engine, scene );
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
delete scene;
delete map;
QVERIFY( imageCheck( QString( "mesh_simplified_%1" ).arg( i ), QString( "mesh_simplified_%1" ).arg( i ), img, QString(), 40, QSize( 0, 0 ), 2 ) );
}
}
void TestQgs3DRendering::testRuleBasedRenderer()
{
QgsPhongMaterialSettings materialSettings;
@ -1456,51 +1231,6 @@ void TestQgs3DRendering::testFilteredExtrudedPolygons()
QVERIFY( imageCheck( "polygon3d_extrusion_filtered", "polygon3d_extrusion_filtered", img, QString(), 40, QSize( 0, 0 ), 2 ) );
}
void TestQgs3DRendering::testFilteredMesh()
{
const QgsRectangle fullExtent = mLayerMeshDataset->extent();
const QgsRectangle filteredExtent = QgsRectangle( fullExtent.xMinimum(), fullExtent.yMinimum(),
fullExtent.xMinimum() + fullExtent.width() / 3.0, fullExtent.yMinimum() + fullExtent.height() / 4.0 );
QgsMesh3DSymbol *symbolMesh3d = new QgsMesh3DSymbol;
symbolMesh3d->setVerticalDatasetGroupIndex( 0 );
symbolMesh3d->setVerticalScale( 10 );
symbolMesh3d->setRenderingStyle( QgsMesh3DSymbol::ColorRamp2DRendering );
symbolMesh3d->setArrowsEnabled( true );
symbolMesh3d->setArrowsSpacing( 300 );
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolMesh3d );
mLayerMeshDataset->setRenderer3D( meshDatasetRenderer3d );
Qgs3DMapSettings *map = new Qgs3DMapSettings;
map->setCrs( mProject->crs() );
map->setExtent( filteredExtent );
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshDataset );
QgsPointLightSettings defaultLight;
defaultLight.setIntensity( 0.5 );
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
map->setLightSources( { defaultLight.clone() } );
QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator;
flatTerrain->setCrs( map->crs() );
map->setTerrainGenerator( flatTerrain );
QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
engine.setRootEntity( scene );
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
// When running the test on Travis, it would initially return empty rendered image.
// Capturing the initial image and throwing it away fixes that. Hopefully we will
// find a better fix in the future.
Qgs3DUtils::captureSceneImage( engine, scene );
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
delete scene;
delete map;
QVERIFY( imageCheck( "mesh3d_filtered", "mesh3d_filtered", img, QString(), 40, QSize( 0, 0 ), 2 ) );
}
void TestQgs3DRendering::testAmbientOcclusion()
{
// =============================================

View File

@ -0,0 +1,336 @@
/***************************************************************************
testqgsmesh3drendering.cpp
--------------------------------------
Date : October 2023
Copyright : (C) 2023 by Jean Felder
Email : jean dot felder at oslandia dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <QObject>
#include "qgstest.h"
#include "qgs3d.h"
#include "qgs3dmapscene.h"
#include "qgs3dmapsettings.h"
#include "qgs3dutils.h"
#include "qgsflatterraingenerator.h"
#include "qgsmeshlayer.h"
#include "qgsmeshrenderersettings.h"
#include "qgsmeshterraingenerator.h"
#include "qgsmeshlayer3drenderer.h"
#include "qgsmaplayertemporalproperties.h"
#include "qgsoffscreen3dengine.h"
#include "qgsproject.h"
class TestQgsMesh3DRendering : public QgsTest
{
Q_OBJECT
public:
TestQgsMesh3DRendering()
: QgsTest( QStringLiteral( "Mesh 3D Rendering Tests" ), QStringLiteral( "3d" ) ) {}
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void testMeshTerrain();
void testMesh();
void testMesh_datasetOnFaces();
void testMeshSimplified();
void testFilteredMesh();
private:
std::unique_ptr<QgsProject> mProject;
QgsMeshLayer *mLayerMeshTerrain = nullptr;
QgsMeshLayer *mLayerMeshDataset = nullptr;
QgsMeshLayer *mLayerMeshSimplified = nullptr;
};
//runs before all tests
void TestQgsMesh3DRendering::initTestCase()
{
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
Qgs3D::initialize();
mProject.reset( new QgsProject );
mLayerMeshTerrain = new QgsMeshLayer( testDataPath( "/mesh/quad_flower.2dm" ), "mesh", "mdal" );
QVERIFY( mLayerMeshTerrain->isValid() );
mLayerMeshTerrain->setCrs( QgsCoordinateReferenceSystem( "EPSG:27700" ) ); // this testing mesh does not have any CRS defined originally
mProject->addMapLayer( mLayerMeshTerrain );
mLayerMeshDataset = new QgsMeshLayer( testDataPath( "/mesh/quad_and_triangle.2dm" ), "mesh", "mdal" );
mLayerMeshDataset->dataProvider()->addDataset( testDataPath( "/mesh/quad_and_triangle_vertex_scalar.dat" ) );
mLayerMeshDataset->dataProvider()->addDataset( testDataPath( "/mesh/quad_and_triangle_vertex_vector.dat" ) );
mLayerMeshDataset->dataProvider()->addDataset( testDataPath( "/mesh/quad_and_triangle_els_face_scalar.dat" ) );
QVERIFY( mLayerMeshDataset->isValid() );
mLayerMeshDataset->setCrs( mLayerMeshTerrain->crs() ); // this testing mesh does not have any CRS defined originally
mLayerMeshDataset->temporalProperties()->setIsActive( false );
mLayerMeshDataset->setStaticScalarDatasetIndex( QgsMeshDatasetIndex( 1, 0 ) );
mLayerMeshDataset->setStaticVectorDatasetIndex( QgsMeshDatasetIndex( 2, 0 ) );
mProject->addMapLayer( mLayerMeshDataset );
mLayerMeshSimplified = new QgsMeshLayer( testDataPath( "/mesh/trap_steady_05_3D.nc" ), "mesh", "mdal" );
mLayerMeshSimplified->setCrs( mProject->crs() );
QVERIFY( mLayerMeshSimplified->isValid() );
mProject->addMapLayer( mLayerMeshSimplified );
QgsMesh3DSymbol *symbolMesh3d = new QgsMesh3DSymbol;
symbolMesh3d->setVerticalDatasetGroupIndex( 0 );
symbolMesh3d->setVerticalScale( 10 );
symbolMesh3d->setRenderingStyle( QgsMesh3DSymbol::ColorRamp2DRendering );
symbolMesh3d->setArrowsEnabled( true );
symbolMesh3d->setArrowsSpacing( 300 );
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolMesh3d );
mLayerMeshDataset->setRenderer3D( meshDatasetRenderer3d );
mProject->setCrs( mLayerMeshTerrain->crs() );
}
//runs after all tests
void TestQgsMesh3DRendering::cleanupTestCase()
{
mProject.reset();
QgsApplication::exitQgis();
}
void TestQgsMesh3DRendering::testMeshTerrain()
{
if ( !QgsTest::runFlakyTests() )
QSKIP( "This test is flaky and disabled on CI" );
const QgsRectangle fullExtent = mLayerMeshTerrain->extent();
Qgs3DMapSettings *map = new Qgs3DMapSettings;
map->setCrs( mProject->crs() );
map->setExtent( fullExtent );
QgsMeshTerrainGenerator *meshTerrain = new QgsMeshTerrainGenerator;
meshTerrain->setCrs( mProject->crs(), mProject->transformContext() );
meshTerrain->setLayer( mLayerMeshTerrain );
map->setTerrainGenerator( meshTerrain );
QCOMPARE( meshTerrain->heightAt( 750, 2500, *map ), 500.0 );
QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
engine.setRootEntity( scene );
// look from the top
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
// When running the test on Travis, it would initially return empty rendered image.
// Capturing the initial image and throwing it away fixes that. Hopefully we will
// find a better fix in the future.
Qgs3DUtils::captureSceneImage( engine, scene );
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
delete scene;
delete map;
QVERIFY( imageCheck( "mesh_terrain_1", "mesh_terrain_1", img, QString(), 40, QSize( 0, 0 ), 2 ) );
}
void TestQgsMesh3DRendering::testMesh()
{
const QgsRectangle fullExtent = mLayerMeshDataset->extent();
Qgs3DMapSettings *map = new Qgs3DMapSettings;
map->setCrs( mProject->crs() );
map->setExtent( fullExtent );
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshDataset );
QgsPointLightSettings defaultLight;
defaultLight.setIntensity( 0.5 );
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
map->setLightSources( { defaultLight.clone() } );
QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator;
flatTerrain->setCrs( map->crs() );
map->setTerrainGenerator( flatTerrain );
QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
engine.setRootEntity( scene );
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
Qgs3DUtils::captureSceneImage( engine, scene );
// When running the test on Travis, it would initially return empty rendered image.
// Capturing the initial image and throwing it away fixes that. Hopefully we will
// find a better fix in the future.
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
delete scene;
delete map;
QVERIFY( imageCheck( "mesh3d", "mesh3d", img, QString(), 40, QSize( 0, 0 ), 2 ) );
}
void TestQgsMesh3DRendering::testMesh_datasetOnFaces()
{
const QgsRectangle fullExtent = mLayerMeshDataset->extent();
QgsMesh3DSymbol *symbolMesh3d = new QgsMesh3DSymbol;
symbolMesh3d->setVerticalDatasetGroupIndex( 3 );
symbolMesh3d->setVerticalScale( 10 );
symbolMesh3d->setRenderingStyle( QgsMesh3DSymbol::ColorRamp2DRendering );
symbolMesh3d->setArrowsEnabled( true );
symbolMesh3d->setArrowsSpacing( 300 );
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolMesh3d );
mLayerMeshDataset->setRenderer3D( meshDatasetRenderer3d );
Qgs3DMapSettings *map = new Qgs3DMapSettings;
map->setCrs( mProject->crs() );
map->setExtent( fullExtent );
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshDataset );
QgsPointLightSettings defaultLight;
defaultLight.setIntensity( 0.5 );
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
map->setLightSources( { defaultLight.clone() } );
QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator;
flatTerrain->setCrs( map->crs() );
map->setTerrainGenerator( flatTerrain );
QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
engine.setRootEntity( scene );
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
Qgs3DUtils::captureSceneImage( engine, scene );
// When running the test on Travis, it would initially return empty rendered image.
// Capturing the initial image and throwing it away fixes that. Hopefully we will
// find a better fix in the future.
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
delete scene;
delete map;
QVERIFY( imageCheck( "mesh3dOnFace", "mesh3dOnFace", img, QString(), 40, QSize( 0, 0 ), 2 ) );
}
void TestQgsMesh3DRendering::testMeshSimplified()
{
if ( QgsTest::isCIRun() )
{
QSKIP( "Intermittently fails on CI" );
}
QgsMeshSimplificationSettings simplificationSettings;
simplificationSettings.setEnabled( true );
simplificationSettings.setReductionFactor( 3 );
QgsMeshRendererSettings settings;
settings.setActiveScalarDatasetGroup( 16 );
settings.setActiveVectorDatasetGroup( 6 );
mLayerMeshSimplified->setRendererSettings( settings );
const QgsRectangle fullExtent = mLayerMeshSimplified->extent();
mLayerMeshSimplified->setMeshSimplificationSettings( simplificationSettings );
mLayerMeshSimplified->temporalProperties()->setIsActive( false );
mLayerMeshSimplified->setStaticScalarDatasetIndex( QgsMeshDatasetIndex( 16, 5 ) );
mLayerMeshSimplified->setStaticVectorDatasetIndex( QgsMeshDatasetIndex( 6, 5 ) );
for ( int i = 0; i < 4; ++i )
{
Qgs3DMapSettings *map = new Qgs3DMapSettings;
map->setCrs( mProject->crs() );
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshSimplified );
map->setExtent( fullExtent );
QgsMesh3DSymbol *symbolDataset = new QgsMesh3DSymbol;
symbolDataset->setVerticalDatasetGroupIndex( 11 );
symbolDataset->setVerticalScale( 1 );
symbolDataset->setWireframeEnabled( true );
symbolDataset->setWireframeLineWidth( 0.1 );
symbolDataset->setArrowsEnabled( true );
symbolDataset->setArrowsSpacing( 20 );
symbolDataset->setSingleMeshColor( Qt::yellow );
symbolDataset->setLevelOfDetailIndex( i );
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolDataset );
mLayerMeshSimplified->setRenderer3D( meshDatasetRenderer3d );
QgsMeshTerrainGenerator *meshTerrain = new QgsMeshTerrainGenerator;
meshTerrain->setLayer( mLayerMeshSimplified );
QgsMesh3DSymbol *symbol = new QgsMesh3DSymbol;
symbol->setWireframeEnabled( true );
symbol->setWireframeLineWidth( 0.1 );
symbol->setLevelOfDetailIndex( i );
meshTerrain->setSymbol( symbol );
map->setTerrainGenerator( meshTerrain );
QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
engine.setRootEntity( scene );
// look from the top
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 1000, 25, 45 );
// When running the test on Travis, it would initially return empty rendered image.
// Capturing the initial image and throwing it away fixes that. Hopefully we will
// find a better fix in the future.
Qgs3DUtils::captureSceneImage( engine, scene );
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
delete scene;
delete map;
QVERIFY( imageCheck( QString( "mesh_simplified_%1" ).arg( i ), QString( "mesh_simplified_%1" ).arg( i ), img, QString(), 40, QSize( 0, 0 ), 2 ) );
}
}
void TestQgsMesh3DRendering::testFilteredMesh()
{
const QgsRectangle fullExtent = mLayerMeshDataset->extent();
const QgsRectangle filteredExtent = QgsRectangle( fullExtent.xMinimum(), fullExtent.yMinimum(),
fullExtent.xMinimum() + fullExtent.width() / 3.0, fullExtent.yMinimum() + fullExtent.height() / 4.0 );
QgsMesh3DSymbol *symbolMesh3d = new QgsMesh3DSymbol;
symbolMesh3d->setVerticalDatasetGroupIndex( 0 );
symbolMesh3d->setVerticalScale( 10 );
symbolMesh3d->setRenderingStyle( QgsMesh3DSymbol::ColorRamp2DRendering );
symbolMesh3d->setArrowsEnabled( true );
symbolMesh3d->setArrowsSpacing( 300 );
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolMesh3d );
mLayerMeshDataset->setRenderer3D( meshDatasetRenderer3d );
Qgs3DMapSettings *map = new Qgs3DMapSettings;
map->setCrs( mProject->crs() );
map->setExtent( filteredExtent );
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshDataset );
QgsPointLightSettings defaultLight;
defaultLight.setIntensity( 0.5 );
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
map->setLightSources( { defaultLight.clone() } );
QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator;
flatTerrain->setCrs( map->crs() );
map->setTerrainGenerator( flatTerrain );
QgsOffscreen3DEngine engine;
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
engine.setRootEntity( scene );
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
// When running the test on Travis, it would initially return empty rendered image.
// Capturing the initial image and throwing it away fixes that. Hopefully we will
// find a better fix in the future.
Qgs3DUtils::captureSceneImage( engine, scene );
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
delete scene;
delete map;
QVERIFY( imageCheck( "mesh3d_filtered", "mesh3d_filtered", img, QString(), 40, QSize( 0, 0 ), 2 ) );
}
QGSTEST_MAIN( TestQgsMesh3DRendering )
#include "testqgsmesh3drendering.moc"