Skip to content

Commit 4e16d45

Browse files
ptitjanonyalldawson
authored andcommittedOct 19, 2023
tests/3d: Factor out mesh tests into its own file
1 parent 9bbae4c commit 4e16d45

File tree

3 files changed

+337
-270
lines changed

3 files changed

+337
-270
lines changed
 

‎tests/src/3d/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ set(TESTS
2828
testqgsgltf3dutils.cpp
2929
testqgslayout3dmap.cpp
3030
testqgsmaterialregistry.cpp
31+
testqgsmesh3drendering.cpp
3132
testqgspointcloud3drendering.cpp
3233
testqgstessellator.cpp
3334
testqgstilingscheme.cpp

‎tests/src/3d/testqgs3drendering.cpp

Lines changed: 0 additions & 270 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
#include "qgslinestring.h"
1919
#include "qgsmaplayerstylemanager.h"
2020
#include "qgsmapthemecollection.h"
21-
#include "qgsmeshlayer.h"
22-
#include "qgsmeshrenderersettings.h"
2321
#include "qgsproject.h"
2422
#include "qgsrasterlayer.h"
2523
#include "qgsrastershader.h"
@@ -34,17 +32,14 @@
3432
#include "qgscameracontroller.h"
3533
#include "qgsdemterraingenerator.h"
3634
#include "qgsflatterraingenerator.h"
37-
#include "qgsmeshterraingenerator.h"
3835
#include "qgsline3dsymbol.h"
3936
#include "qgsoffscreen3dengine.h"
4037
#include "qgspolygon3dsymbol.h"
4138
#include "qgsrulebased3drenderer.h"
4239
#include "qgsvectorlayer3drenderer.h"
43-
#include "qgsmeshlayer3drenderer.h"
4440
#include "qgspoint3dsymbol.h"
4541
#include "qgssymbollayer.h"
4642
#include "qgsmarkersymbollayer.h"
47-
#include "qgsmaplayertemporalproperties.h"
4843
#include "qgssymbol.h"
4944
#include "qgssinglesymbolrenderer.h"
5045
#include "qgsfillsymbollayer.h"
@@ -74,7 +69,6 @@ class TestQgs3DRendering : public QgsTest
7469
void testFlatTerrain();
7570
void testDemTerrain();
7671
void testTerrainShading();
77-
void testMeshTerrain();
7872
void testEpsg4978LineRendering();
7973
void testExtrudedPolygons();
8074
void testExtrudedPolygonsDataDefined();
@@ -85,17 +79,13 @@ class TestQgs3DRendering : public QgsTest
8579
void testBufferedLineRendering();
8680
void testBufferedLineRenderingWidth();
8781
void testMapTheme();
88-
void testMesh();
89-
void testMesh_datasetOnFaces();
90-
void testMeshSimplified();
9182
void testRuleBasedRenderer();
9283
void testAnimationExport();
9384
void testBillboardRendering();
9485
void testInstancedRendering();
9586
void testFilteredFlatTerrain();
9687
void testFilteredDemTerrain();
9788
void testFilteredExtrudedPolygons();
98-
void testFilteredMesh();
9989
void testDepthBuffer();
10090
void testAmbientOcclusion();
10191
void testDebugMap();
@@ -111,10 +101,6 @@ class TestQgs3DRendering : public QgsTest
111101
QgsRasterLayer *mLayerDtm = nullptr;
112102
QgsRasterLayer *mLayerRgb = nullptr;
113103
QgsVectorLayer *mLayerBuildings = nullptr;
114-
QgsMeshLayer *mLayerMeshTerrain = nullptr;
115-
QgsMeshLayer *mLayerMeshDataset = nullptr;
116-
QgsMeshLayer *mLayerMeshSimplified = nullptr;
117-
118104
};
119105

120106
/**
@@ -208,36 +194,6 @@ void TestQgs3DRendering::initTestCase()
208194
QgsVectorLayer3DRenderer *renderer3d = new QgsVectorLayer3DRenderer( symbol3d );
209195
mLayerBuildings->setRenderer3D( renderer3d );
210196

211-
mLayerMeshTerrain = new QgsMeshLayer( testDataPath( "/mesh/quad_flower.2dm" ), "mesh", "mdal" );
212-
QVERIFY( mLayerMeshTerrain->isValid() );
213-
mLayerMeshTerrain->setCrs( mLayerDtm->crs() ); // this testing mesh does not have any CRS defined originally
214-
mProject->addMapLayer( mLayerMeshTerrain );
215-
216-
mLayerMeshDataset = new QgsMeshLayer( testDataPath( "/mesh/quad_and_triangle.2dm" ), "mesh", "mdal" );
217-
mLayerMeshDataset->dataProvider()->addDataset( testDataPath( "/mesh/quad_and_triangle_vertex_scalar.dat" ) );
218-
mLayerMeshDataset->dataProvider()->addDataset( testDataPath( "/mesh/quad_and_triangle_vertex_vector.dat" ) );
219-
mLayerMeshDataset->dataProvider()->addDataset( testDataPath( "/mesh/quad_and_triangle_els_face_scalar.dat" ) );
220-
QVERIFY( mLayerMeshDataset->isValid() );
221-
mLayerMeshDataset->setCrs( mLayerDtm->crs() ); // this testing mesh does not have any CRS defined originally
222-
mLayerMeshDataset->temporalProperties()->setIsActive( false );
223-
mLayerMeshDataset->setStaticScalarDatasetIndex( QgsMeshDatasetIndex( 1, 0 ) );
224-
mLayerMeshDataset->setStaticVectorDatasetIndex( QgsMeshDatasetIndex( 2, 0 ) );
225-
mProject->addMapLayer( mLayerMeshDataset );
226-
227-
mLayerMeshSimplified = new QgsMeshLayer( testDataPath( "/mesh/trap_steady_05_3D.nc" ), "mesh", "mdal" );
228-
mLayerMeshSimplified->setCrs( mProject->crs() );
229-
QVERIFY( mLayerMeshSimplified->isValid() );
230-
mProject->addMapLayer( mLayerMeshSimplified );
231-
232-
QgsMesh3DSymbol *symbolMesh3d = new QgsMesh3DSymbol;
233-
symbolMesh3d->setVerticalDatasetGroupIndex( 0 );
234-
symbolMesh3d->setVerticalScale( 10 );
235-
symbolMesh3d->setRenderingStyle( QgsMesh3DSymbol::ColorRamp2DRendering );
236-
symbolMesh3d->setArrowsEnabled( true );
237-
symbolMesh3d->setArrowsSpacing( 300 );
238-
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolMesh3d );
239-
mLayerMeshDataset->setRenderer3D( meshDatasetRenderer3d );
240-
241197
mProject->setCrs( mLayerDtm->crs() );
242198

243199
//
@@ -407,43 +363,6 @@ void TestQgs3DRendering::testTerrainShading()
407363
QVERIFY( imageCheck( "shaded_terrain_no_layers", "shaded_terrain_no_layers", img3, QString(), 40, QSize( 0, 0 ), 2 ) );
408364
}
409365

410-
void TestQgs3DRendering::testMeshTerrain()
411-
{
412-
if ( !QgsTest::runFlakyTests() )
413-
QSKIP( "This test is flaky and disabled on CI" );
414-
415-
const QgsRectangle fullExtent = mLayerMeshTerrain->extent();
416-
417-
Qgs3DMapSettings *map = new Qgs3DMapSettings;
418-
map->setCrs( mProject->crs() );
419-
map->setExtent( fullExtent );
420-
421-
QgsMeshTerrainGenerator *meshTerrain = new QgsMeshTerrainGenerator;
422-
meshTerrain->setCrs( mProject->crs(), mProject->transformContext() );
423-
meshTerrain->setLayer( mLayerMeshTerrain );
424-
map->setTerrainGenerator( meshTerrain );
425-
426-
QCOMPARE( meshTerrain->heightAt( 750, 2500, *map ), 500.0 );
427-
428-
QgsOffscreen3DEngine engine;
429-
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
430-
engine.setRootEntity( scene );
431-
432-
// look from the top
433-
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
434-
435-
// When running the test on Travis, it would initially return empty rendered image.
436-
// Capturing the initial image and throwing it away fixes that. Hopefully we will
437-
// find a better fix in the future.
438-
Qgs3DUtils::captureSceneImage( engine, scene );
439-
440-
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
441-
delete scene;
442-
delete map;
443-
444-
QVERIFY( imageCheck( "mesh_terrain_1", "mesh_terrain_1", img, QString(), 40, QSize( 0, 0 ), 2 ) );
445-
}
446-
447366
void TestQgs3DRendering::testExtrudedPolygons()
448367
{
449368
const QgsRectangle fullExtent = mLayerDtm->extent();
@@ -888,150 +807,6 @@ void TestQgs3DRendering::testMapTheme()
888807
QVERIFY( imageCheck( "terrain_theme", "terrain_theme", img, QString(), 40, QSize( 0, 0 ), 2 ) );
889808
}
890809

891-
void TestQgs3DRendering::testMesh()
892-
{
893-
const QgsRectangle fullExtent = mLayerMeshDataset->extent();
894-
895-
Qgs3DMapSettings *map = new Qgs3DMapSettings;
896-
map->setCrs( mProject->crs() );
897-
map->setExtent( fullExtent );
898-
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshDataset );
899-
QgsPointLightSettings defaultLight;
900-
defaultLight.setIntensity( 0.5 );
901-
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
902-
map->setLightSources( { defaultLight.clone() } );
903-
904-
QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator;
905-
flatTerrain->setCrs( map->crs() );
906-
map->setTerrainGenerator( flatTerrain );
907-
908-
QgsOffscreen3DEngine engine;
909-
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
910-
engine.setRootEntity( scene );
911-
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
912-
913-
Qgs3DUtils::captureSceneImage( engine, scene );
914-
// When running the test on Travis, it would initially return empty rendered image.
915-
// Capturing the initial image and throwing it away fixes that. Hopefully we will
916-
// find a better fix in the future.
917-
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
918-
delete scene;
919-
delete map;
920-
921-
QVERIFY( imageCheck( "mesh3d", "mesh3d", img, QString(), 40, QSize( 0, 0 ), 2 ) );
922-
}
923-
924-
void TestQgs3DRendering::testMesh_datasetOnFaces()
925-
{
926-
const QgsRectangle fullExtent = mLayerMeshDataset->extent();
927-
928-
QgsMesh3DSymbol *symbolMesh3d = new QgsMesh3DSymbol;
929-
symbolMesh3d->setVerticalDatasetGroupIndex( 3 );
930-
symbolMesh3d->setVerticalScale( 10 );
931-
symbolMesh3d->setRenderingStyle( QgsMesh3DSymbol::ColorRamp2DRendering );
932-
symbolMesh3d->setArrowsEnabled( true );
933-
symbolMesh3d->setArrowsSpacing( 300 );
934-
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolMesh3d );
935-
mLayerMeshDataset->setRenderer3D( meshDatasetRenderer3d );
936-
937-
Qgs3DMapSettings *map = new Qgs3DMapSettings;
938-
map->setCrs( mProject->crs() );
939-
map->setExtent( fullExtent );
940-
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshDataset );
941-
QgsPointLightSettings defaultLight;
942-
defaultLight.setIntensity( 0.5 );
943-
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
944-
map->setLightSources( { defaultLight.clone() } );
945-
946-
QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator;
947-
flatTerrain->setCrs( map->crs() );
948-
map->setTerrainGenerator( flatTerrain );
949-
950-
QgsOffscreen3DEngine engine;
951-
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
952-
engine.setRootEntity( scene );
953-
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
954-
955-
Qgs3DUtils::captureSceneImage( engine, scene );
956-
// When running the test on Travis, it would initially return empty rendered image.
957-
// Capturing the initial image and throwing it away fixes that. Hopefully we will
958-
// find a better fix in the future.
959-
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
960-
delete scene;
961-
delete map;
962-
963-
QVERIFY( imageCheck( "mesh3dOnFace", "mesh3dOnFace", img, QString(), 40, QSize( 0, 0 ), 2 ) );
964-
}
965-
966-
void TestQgs3DRendering::testMeshSimplified()
967-
{
968-
if ( QgsTest::isCIRun() )
969-
{
970-
QSKIP( "Intermittently fails on CI" );
971-
}
972-
973-
QgsMeshSimplificationSettings simplificationSettings;
974-
simplificationSettings.setEnabled( true );
975-
simplificationSettings.setReductionFactor( 3 );
976-
977-
QgsMeshRendererSettings settings;
978-
settings.setActiveScalarDatasetGroup( 16 );
979-
settings.setActiveVectorDatasetGroup( 6 );
980-
mLayerMeshSimplified->setRendererSettings( settings );
981-
982-
const QgsRectangle fullExtent = mLayerMeshSimplified->extent();
983-
mLayerMeshSimplified->setMeshSimplificationSettings( simplificationSettings );
984-
mLayerMeshSimplified->temporalProperties()->setIsActive( false );
985-
mLayerMeshSimplified->setStaticScalarDatasetIndex( QgsMeshDatasetIndex( 16, 5 ) );
986-
mLayerMeshSimplified->setStaticVectorDatasetIndex( QgsMeshDatasetIndex( 6, 5 ) );
987-
988-
for ( int i = 0; i < 4; ++i )
989-
{
990-
Qgs3DMapSettings *map = new Qgs3DMapSettings;
991-
map->setCrs( mProject->crs() );
992-
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshSimplified );
993-
map->setExtent( fullExtent );
994-
995-
QgsMesh3DSymbol *symbolDataset = new QgsMesh3DSymbol;
996-
symbolDataset->setVerticalDatasetGroupIndex( 11 );
997-
symbolDataset->setVerticalScale( 1 );
998-
symbolDataset->setWireframeEnabled( true );
999-
symbolDataset->setWireframeLineWidth( 0.1 );
1000-
symbolDataset->setArrowsEnabled( true );
1001-
symbolDataset->setArrowsSpacing( 20 );
1002-
symbolDataset->setSingleMeshColor( Qt::yellow );
1003-
symbolDataset->setLevelOfDetailIndex( i );
1004-
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolDataset );
1005-
mLayerMeshSimplified->setRenderer3D( meshDatasetRenderer3d );
1006-
1007-
QgsMeshTerrainGenerator *meshTerrain = new QgsMeshTerrainGenerator;
1008-
meshTerrain->setLayer( mLayerMeshSimplified );
1009-
QgsMesh3DSymbol *symbol = new QgsMesh3DSymbol;
1010-
symbol->setWireframeEnabled( true );
1011-
symbol->setWireframeLineWidth( 0.1 );
1012-
symbol->setLevelOfDetailIndex( i );
1013-
meshTerrain->setSymbol( symbol );
1014-
map->setTerrainGenerator( meshTerrain );
1015-
1016-
QgsOffscreen3DEngine engine;
1017-
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
1018-
engine.setRootEntity( scene );
1019-
1020-
// look from the top
1021-
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 1000, 25, 45 );
1022-
1023-
// When running the test on Travis, it would initially return empty rendered image.
1024-
// Capturing the initial image and throwing it away fixes that. Hopefully we will
1025-
// find a better fix in the future.
1026-
Qgs3DUtils::captureSceneImage( engine, scene );
1027-
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
1028-
delete scene;
1029-
delete map;
1030-
1031-
QVERIFY( imageCheck( QString( "mesh_simplified_%1" ).arg( i ), QString( "mesh_simplified_%1" ).arg( i ), img, QString(), 40, QSize( 0, 0 ), 2 ) );
1032-
}
1033-
}
1034-
1035810
void TestQgs3DRendering::testRuleBasedRenderer()
1036811
{
1037812
QgsPhongMaterialSettings materialSettings;
@@ -1456,51 +1231,6 @@ void TestQgs3DRendering::testFilteredExtrudedPolygons()
14561231
QVERIFY( imageCheck( "polygon3d_extrusion_filtered", "polygon3d_extrusion_filtered", img, QString(), 40, QSize( 0, 0 ), 2 ) );
14571232
}
14581233

1459-
void TestQgs3DRendering::testFilteredMesh()
1460-
{
1461-
const QgsRectangle fullExtent = mLayerMeshDataset->extent();
1462-
const QgsRectangle filteredExtent = QgsRectangle( fullExtent.xMinimum(), fullExtent.yMinimum(),
1463-
fullExtent.xMinimum() + fullExtent.width() / 3.0, fullExtent.yMinimum() + fullExtent.height() / 4.0 );
1464-
1465-
QgsMesh3DSymbol *symbolMesh3d = new QgsMesh3DSymbol;
1466-
symbolMesh3d->setVerticalDatasetGroupIndex( 0 );
1467-
symbolMesh3d->setVerticalScale( 10 );
1468-
symbolMesh3d->setRenderingStyle( QgsMesh3DSymbol::ColorRamp2DRendering );
1469-
symbolMesh3d->setArrowsEnabled( true );
1470-
symbolMesh3d->setArrowsSpacing( 300 );
1471-
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolMesh3d );
1472-
mLayerMeshDataset->setRenderer3D( meshDatasetRenderer3d );
1473-
1474-
Qgs3DMapSettings *map = new Qgs3DMapSettings;
1475-
map->setCrs( mProject->crs() );
1476-
map->setExtent( filteredExtent );
1477-
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshDataset );
1478-
QgsPointLightSettings defaultLight;
1479-
defaultLight.setIntensity( 0.5 );
1480-
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
1481-
map->setLightSources( { defaultLight.clone() } );
1482-
1483-
QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator;
1484-
flatTerrain->setCrs( map->crs() );
1485-
map->setTerrainGenerator( flatTerrain );
1486-
1487-
QgsOffscreen3DEngine engine;
1488-
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
1489-
engine.setRootEntity( scene );
1490-
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
1491-
1492-
// When running the test on Travis, it would initially return empty rendered image.
1493-
// Capturing the initial image and throwing it away fixes that. Hopefully we will
1494-
// find a better fix in the future.
1495-
Qgs3DUtils::captureSceneImage( engine, scene );
1496-
1497-
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
1498-
delete scene;
1499-
delete map;
1500-
1501-
QVERIFY( imageCheck( "mesh3d_filtered", "mesh3d_filtered", img, QString(), 40, QSize( 0, 0 ), 2 ) );
1502-
}
1503-
15041234
void TestQgs3DRendering::testAmbientOcclusion()
15051235
{
15061236
// =============================================
Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
/***************************************************************************
2+
testqgsmesh3drendering.cpp
3+
--------------------------------------
4+
Date : October 2023
5+
Copyright : (C) 2023 by Jean Felder
6+
Email : jean dot felder at oslandia dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include <QObject>
17+
18+
#include "qgstest.h"
19+
20+
#include "qgs3d.h"
21+
#include "qgs3dmapscene.h"
22+
#include "qgs3dmapsettings.h"
23+
#include "qgs3dutils.h"
24+
#include "qgsflatterraingenerator.h"
25+
#include "qgsmeshlayer.h"
26+
#include "qgsmeshrenderersettings.h"
27+
#include "qgsmeshterraingenerator.h"
28+
#include "qgsmeshlayer3drenderer.h"
29+
#include "qgsmaplayertemporalproperties.h"
30+
#include "qgsoffscreen3dengine.h"
31+
#include "qgsproject.h"
32+
33+
class TestQgsMesh3DRendering : public QgsTest
34+
{
35+
Q_OBJECT
36+
37+
public:
38+
TestQgsMesh3DRendering()
39+
: QgsTest( QStringLiteral( "Mesh 3D Rendering Tests" ), QStringLiteral( "3d" ) ) {}
40+
41+
private slots:
42+
void initTestCase();// will be called before the first testfunction is executed.
43+
void cleanupTestCase();// will be called after the last testfunction was executed.
44+
void testMeshTerrain();
45+
void testMesh();
46+
void testMesh_datasetOnFaces();
47+
void testMeshSimplified();
48+
void testFilteredMesh();
49+
50+
private:
51+
52+
std::unique_ptr<QgsProject> mProject;
53+
QgsMeshLayer *mLayerMeshTerrain = nullptr;
54+
QgsMeshLayer *mLayerMeshDataset = nullptr;
55+
QgsMeshLayer *mLayerMeshSimplified = nullptr;
56+
57+
};
58+
59+
//runs before all tests
60+
void TestQgsMesh3DRendering::initTestCase()
61+
{
62+
// init QGIS's paths - true means that all path will be inited from prefix
63+
QgsApplication::init();
64+
QgsApplication::initQgis();
65+
Qgs3D::initialize();
66+
67+
mProject.reset( new QgsProject );
68+
69+
mLayerMeshTerrain = new QgsMeshLayer( testDataPath( "/mesh/quad_flower.2dm" ), "mesh", "mdal" );
70+
QVERIFY( mLayerMeshTerrain->isValid() );
71+
mLayerMeshTerrain->setCrs( QgsCoordinateReferenceSystem( "EPSG:27700" ) ); // this testing mesh does not have any CRS defined originally
72+
mProject->addMapLayer( mLayerMeshTerrain );
73+
74+
mLayerMeshDataset = new QgsMeshLayer( testDataPath( "/mesh/quad_and_triangle.2dm" ), "mesh", "mdal" );
75+
mLayerMeshDataset->dataProvider()->addDataset( testDataPath( "/mesh/quad_and_triangle_vertex_scalar.dat" ) );
76+
mLayerMeshDataset->dataProvider()->addDataset( testDataPath( "/mesh/quad_and_triangle_vertex_vector.dat" ) );
77+
mLayerMeshDataset->dataProvider()->addDataset( testDataPath( "/mesh/quad_and_triangle_els_face_scalar.dat" ) );
78+
QVERIFY( mLayerMeshDataset->isValid() );
79+
mLayerMeshDataset->setCrs( mLayerMeshTerrain->crs() ); // this testing mesh does not have any CRS defined originally
80+
mLayerMeshDataset->temporalProperties()->setIsActive( false );
81+
mLayerMeshDataset->setStaticScalarDatasetIndex( QgsMeshDatasetIndex( 1, 0 ) );
82+
mLayerMeshDataset->setStaticVectorDatasetIndex( QgsMeshDatasetIndex( 2, 0 ) );
83+
mProject->addMapLayer( mLayerMeshDataset );
84+
85+
mLayerMeshSimplified = new QgsMeshLayer( testDataPath( "/mesh/trap_steady_05_3D.nc" ), "mesh", "mdal" );
86+
mLayerMeshSimplified->setCrs( mProject->crs() );
87+
QVERIFY( mLayerMeshSimplified->isValid() );
88+
mProject->addMapLayer( mLayerMeshSimplified );
89+
90+
QgsMesh3DSymbol *symbolMesh3d = new QgsMesh3DSymbol;
91+
symbolMesh3d->setVerticalDatasetGroupIndex( 0 );
92+
symbolMesh3d->setVerticalScale( 10 );
93+
symbolMesh3d->setRenderingStyle( QgsMesh3DSymbol::ColorRamp2DRendering );
94+
symbolMesh3d->setArrowsEnabled( true );
95+
symbolMesh3d->setArrowsSpacing( 300 );
96+
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolMesh3d );
97+
mLayerMeshDataset->setRenderer3D( meshDatasetRenderer3d );
98+
99+
mProject->setCrs( mLayerMeshTerrain->crs() );
100+
}
101+
102+
//runs after all tests
103+
void TestQgsMesh3DRendering::cleanupTestCase()
104+
{
105+
mProject.reset();
106+
QgsApplication::exitQgis();
107+
}
108+
109+
void TestQgsMesh3DRendering::testMeshTerrain()
110+
{
111+
if ( !QgsTest::runFlakyTests() )
112+
QSKIP( "This test is flaky and disabled on CI" );
113+
114+
const QgsRectangle fullExtent = mLayerMeshTerrain->extent();
115+
116+
Qgs3DMapSettings *map = new Qgs3DMapSettings;
117+
map->setCrs( mProject->crs() );
118+
map->setExtent( fullExtent );
119+
120+
QgsMeshTerrainGenerator *meshTerrain = new QgsMeshTerrainGenerator;
121+
meshTerrain->setCrs( mProject->crs(), mProject->transformContext() );
122+
meshTerrain->setLayer( mLayerMeshTerrain );
123+
map->setTerrainGenerator( meshTerrain );
124+
125+
QCOMPARE( meshTerrain->heightAt( 750, 2500, *map ), 500.0 );
126+
127+
QgsOffscreen3DEngine engine;
128+
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
129+
engine.setRootEntity( scene );
130+
131+
// look from the top
132+
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
133+
134+
// When running the test on Travis, it would initially return empty rendered image.
135+
// Capturing the initial image and throwing it away fixes that. Hopefully we will
136+
// find a better fix in the future.
137+
Qgs3DUtils::captureSceneImage( engine, scene );
138+
139+
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
140+
delete scene;
141+
delete map;
142+
143+
QVERIFY( imageCheck( "mesh_terrain_1", "mesh_terrain_1", img, QString(), 40, QSize( 0, 0 ), 2 ) );
144+
}
145+
146+
void TestQgsMesh3DRendering::testMesh()
147+
{
148+
const QgsRectangle fullExtent = mLayerMeshDataset->extent();
149+
150+
Qgs3DMapSettings *map = new Qgs3DMapSettings;
151+
map->setCrs( mProject->crs() );
152+
map->setExtent( fullExtent );
153+
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshDataset );
154+
QgsPointLightSettings defaultLight;
155+
defaultLight.setIntensity( 0.5 );
156+
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
157+
map->setLightSources( { defaultLight.clone() } );
158+
159+
QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator;
160+
flatTerrain->setCrs( map->crs() );
161+
map->setTerrainGenerator( flatTerrain );
162+
163+
QgsOffscreen3DEngine engine;
164+
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
165+
engine.setRootEntity( scene );
166+
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
167+
168+
Qgs3DUtils::captureSceneImage( engine, scene );
169+
// When running the test on Travis, it would initially return empty rendered image.
170+
// Capturing the initial image and throwing it away fixes that. Hopefully we will
171+
// find a better fix in the future.
172+
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
173+
delete scene;
174+
delete map;
175+
176+
QVERIFY( imageCheck( "mesh3d", "mesh3d", img, QString(), 40, QSize( 0, 0 ), 2 ) );
177+
}
178+
179+
void TestQgsMesh3DRendering::testMesh_datasetOnFaces()
180+
{
181+
const QgsRectangle fullExtent = mLayerMeshDataset->extent();
182+
183+
QgsMesh3DSymbol *symbolMesh3d = new QgsMesh3DSymbol;
184+
symbolMesh3d->setVerticalDatasetGroupIndex( 3 );
185+
symbolMesh3d->setVerticalScale( 10 );
186+
symbolMesh3d->setRenderingStyle( QgsMesh3DSymbol::ColorRamp2DRendering );
187+
symbolMesh3d->setArrowsEnabled( true );
188+
symbolMesh3d->setArrowsSpacing( 300 );
189+
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolMesh3d );
190+
mLayerMeshDataset->setRenderer3D( meshDatasetRenderer3d );
191+
192+
Qgs3DMapSettings *map = new Qgs3DMapSettings;
193+
map->setCrs( mProject->crs() );
194+
map->setExtent( fullExtent );
195+
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshDataset );
196+
QgsPointLightSettings defaultLight;
197+
defaultLight.setIntensity( 0.5 );
198+
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
199+
map->setLightSources( { defaultLight.clone() } );
200+
201+
QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator;
202+
flatTerrain->setCrs( map->crs() );
203+
map->setTerrainGenerator( flatTerrain );
204+
205+
QgsOffscreen3DEngine engine;
206+
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
207+
engine.setRootEntity( scene );
208+
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
209+
210+
Qgs3DUtils::captureSceneImage( engine, scene );
211+
// When running the test on Travis, it would initially return empty rendered image.
212+
// Capturing the initial image and throwing it away fixes that. Hopefully we will
213+
// find a better fix in the future.
214+
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
215+
delete scene;
216+
delete map;
217+
218+
QVERIFY( imageCheck( "mesh3dOnFace", "mesh3dOnFace", img, QString(), 40, QSize( 0, 0 ), 2 ) );
219+
}
220+
221+
void TestQgsMesh3DRendering::testMeshSimplified()
222+
{
223+
if ( QgsTest::isCIRun() )
224+
{
225+
QSKIP( "Intermittently fails on CI" );
226+
}
227+
228+
QgsMeshSimplificationSettings simplificationSettings;
229+
simplificationSettings.setEnabled( true );
230+
simplificationSettings.setReductionFactor( 3 );
231+
232+
QgsMeshRendererSettings settings;
233+
settings.setActiveScalarDatasetGroup( 16 );
234+
settings.setActiveVectorDatasetGroup( 6 );
235+
mLayerMeshSimplified->setRendererSettings( settings );
236+
237+
const QgsRectangle fullExtent = mLayerMeshSimplified->extent();
238+
mLayerMeshSimplified->setMeshSimplificationSettings( simplificationSettings );
239+
mLayerMeshSimplified->temporalProperties()->setIsActive( false );
240+
mLayerMeshSimplified->setStaticScalarDatasetIndex( QgsMeshDatasetIndex( 16, 5 ) );
241+
mLayerMeshSimplified->setStaticVectorDatasetIndex( QgsMeshDatasetIndex( 6, 5 ) );
242+
243+
for ( int i = 0; i < 4; ++i )
244+
{
245+
Qgs3DMapSettings *map = new Qgs3DMapSettings;
246+
map->setCrs( mProject->crs() );
247+
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshSimplified );
248+
map->setExtent( fullExtent );
249+
250+
QgsMesh3DSymbol *symbolDataset = new QgsMesh3DSymbol;
251+
symbolDataset->setVerticalDatasetGroupIndex( 11 );
252+
symbolDataset->setVerticalScale( 1 );
253+
symbolDataset->setWireframeEnabled( true );
254+
symbolDataset->setWireframeLineWidth( 0.1 );
255+
symbolDataset->setArrowsEnabled( true );
256+
symbolDataset->setArrowsSpacing( 20 );
257+
symbolDataset->setSingleMeshColor( Qt::yellow );
258+
symbolDataset->setLevelOfDetailIndex( i );
259+
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolDataset );
260+
mLayerMeshSimplified->setRenderer3D( meshDatasetRenderer3d );
261+
262+
QgsMeshTerrainGenerator *meshTerrain = new QgsMeshTerrainGenerator;
263+
meshTerrain->setLayer( mLayerMeshSimplified );
264+
QgsMesh3DSymbol *symbol = new QgsMesh3DSymbol;
265+
symbol->setWireframeEnabled( true );
266+
symbol->setWireframeLineWidth( 0.1 );
267+
symbol->setLevelOfDetailIndex( i );
268+
meshTerrain->setSymbol( symbol );
269+
map->setTerrainGenerator( meshTerrain );
270+
271+
QgsOffscreen3DEngine engine;
272+
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
273+
engine.setRootEntity( scene );
274+
275+
// look from the top
276+
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 1000, 25, 45 );
277+
278+
// When running the test on Travis, it would initially return empty rendered image.
279+
// Capturing the initial image and throwing it away fixes that. Hopefully we will
280+
// find a better fix in the future.
281+
Qgs3DUtils::captureSceneImage( engine, scene );
282+
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
283+
delete scene;
284+
delete map;
285+
286+
QVERIFY( imageCheck( QString( "mesh_simplified_%1" ).arg( i ), QString( "mesh_simplified_%1" ).arg( i ), img, QString(), 40, QSize( 0, 0 ), 2 ) );
287+
}
288+
}
289+
290+
void TestQgsMesh3DRendering::testFilteredMesh()
291+
{
292+
const QgsRectangle fullExtent = mLayerMeshDataset->extent();
293+
const QgsRectangle filteredExtent = QgsRectangle( fullExtent.xMinimum(), fullExtent.yMinimum(),
294+
fullExtent.xMinimum() + fullExtent.width() / 3.0, fullExtent.yMinimum() + fullExtent.height() / 4.0 );
295+
296+
QgsMesh3DSymbol *symbolMesh3d = new QgsMesh3DSymbol;
297+
symbolMesh3d->setVerticalDatasetGroupIndex( 0 );
298+
symbolMesh3d->setVerticalScale( 10 );
299+
symbolMesh3d->setRenderingStyle( QgsMesh3DSymbol::ColorRamp2DRendering );
300+
symbolMesh3d->setArrowsEnabled( true );
301+
symbolMesh3d->setArrowsSpacing( 300 );
302+
QgsMeshLayer3DRenderer *meshDatasetRenderer3d = new QgsMeshLayer3DRenderer( symbolMesh3d );
303+
mLayerMeshDataset->setRenderer3D( meshDatasetRenderer3d );
304+
305+
Qgs3DMapSettings *map = new Qgs3DMapSettings;
306+
map->setCrs( mProject->crs() );
307+
map->setExtent( filteredExtent );
308+
map->setLayers( QList<QgsMapLayer *>() << mLayerMeshDataset );
309+
QgsPointLightSettings defaultLight;
310+
defaultLight.setIntensity( 0.5 );
311+
defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) );
312+
map->setLightSources( { defaultLight.clone() } );
313+
314+
QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator;
315+
flatTerrain->setCrs( map->crs() );
316+
map->setTerrainGenerator( flatTerrain );
317+
318+
QgsOffscreen3DEngine engine;
319+
Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine );
320+
engine.setRootEntity( scene );
321+
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 3000, 25, 45 );
322+
323+
// When running the test on Travis, it would initially return empty rendered image.
324+
// Capturing the initial image and throwing it away fixes that. Hopefully we will
325+
// find a better fix in the future.
326+
Qgs3DUtils::captureSceneImage( engine, scene );
327+
328+
QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
329+
delete scene;
330+
delete map;
331+
332+
QVERIFY( imageCheck( "mesh3d_filtered", "mesh3d_filtered", img, QString(), 40, QSize( 0, 0 ), 2 ) );
333+
}
334+
335+
QGSTEST_MAIN( TestQgsMesh3DRendering )
336+
#include "testqgsmesh3drendering.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.