Skip to content

Commit 1275708

Browse files
authoredNov 12, 2018
Merge pull request #8458 from wonder-sk/terrain-shading
[3d] Terrain shading
2 parents 9b04a29 + bcf8b0d commit 1275708

15 files changed

+222
-44
lines changed
 

‎python/3d/auto_generated/qgsphongmaterialsettings.sip.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ Reads settings from a DOM element
7373
Writes settings to a DOM element
7474
%End
7575

76+
bool operator==( const QgsPhongMaterialSettings &other ) const;
77+
7678
};
7779

7880

‎src/3d/qgs3dmapscene.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine *
9292
connect( &map, &Qgs3DMapSettings::mapTileResolutionChanged, this, &Qgs3DMapScene::createTerrain );
9393
connect( &map, &Qgs3DMapSettings::maxTerrainScreenErrorChanged, this, &Qgs3DMapScene::createTerrain );
9494
connect( &map, &Qgs3DMapSettings::maxTerrainGroundErrorChanged, this, &Qgs3DMapScene::createTerrain );
95+
connect( &map, &Qgs3DMapSettings::terrainShadingChanged, this, &Qgs3DMapScene::createTerrain );
9596

9697
// create entities of renderers
9798

‎src/3d/qgs3dmapsettings.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ Qgs3DMapSettings::Qgs3DMapSettings( const Qgs3DMapSettings &other )
3737
, mMapTileResolution( other.mMapTileResolution )
3838
, mMaxTerrainScreenError( other.mMaxTerrainScreenError )
3939
, mMaxTerrainGroundError( other.mMaxTerrainGroundError )
40+
, mTerrainShadingEnabled( other.mTerrainShadingEnabled )
41+
, mTerrainShadingMaterial( other.mTerrainShadingMaterial )
4042
, mShowTerrainBoundingBoxes( other.mShowTerrainBoundingBoxes )
4143
, mShowTerrainTileInfo( other.mShowTerrainTileInfo )
4244
, mShowCameraViewCenter( other.mShowCameraViewCenter )
@@ -79,6 +81,10 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte
7981
mMapTileResolution = elemTerrain.attribute( QStringLiteral( "texture-size" ), QStringLiteral( "512" ) ).toInt();
8082
mMaxTerrainScreenError = elemTerrain.attribute( QStringLiteral( "max-terrain-error" ), QStringLiteral( "3" ) ).toFloat();
8183
mMaxTerrainGroundError = elemTerrain.attribute( QStringLiteral( "max-ground-error" ), QStringLiteral( "1" ) ).toFloat();
84+
mTerrainShadingEnabled = elemTerrain.attribute( QStringLiteral( "shading-enabled" ), QStringLiteral( "0" ) ).toInt();
85+
QDomElement elemTerrainShadingMaterial = elemTerrain.firstChildElement( QStringLiteral( "shading-material" ) );
86+
if ( !elemTerrainShadingMaterial.isNull() )
87+
mTerrainShadingMaterial.readXml( elemTerrainShadingMaterial );
8288
mShowLabels = elemTerrain.attribute( QStringLiteral( "show-labels" ), QStringLiteral( "0" ) ).toInt();
8389
QDomElement elemMapLayers = elemTerrain.firstChildElement( QStringLiteral( "layers" ) );
8490
QDomElement elemMapLayer = elemMapLayers.firstChildElement( QStringLiteral( "layer" ) );
@@ -169,6 +175,10 @@ QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteCon
169175
elemTerrain.setAttribute( QStringLiteral( "texture-size" ), mMapTileResolution );
170176
elemTerrain.setAttribute( QStringLiteral( "max-terrain-error" ), QString::number( mMaxTerrainScreenError ) );
171177
elemTerrain.setAttribute( QStringLiteral( "max-ground-error" ), QString::number( mMaxTerrainGroundError ) );
178+
elemTerrain.setAttribute( QStringLiteral( "shading-enabled" ), mTerrainShadingEnabled ? 1 : 0 );
179+
QDomElement elemTerrainShadingMaterial = doc.createElement( QStringLiteral( "shading-material" ) );
180+
mTerrainShadingMaterial.writeXml( elemTerrainShadingMaterial );
181+
elemTerrain.appendChild( elemTerrainShadingMaterial );
172182
elemTerrain.setAttribute( QStringLiteral( "show-labels" ), mShowLabels ? 1 : 0 );
173183
QDomElement elemMapLayers = doc.createElement( QStringLiteral( "layers" ) );
174184
Q_FOREACH ( const QgsMapLayerRef &layerRef, mLayers )
@@ -370,6 +380,24 @@ void Qgs3DMapSettings::setTerrainGenerator( QgsTerrainGenerator *gen )
370380
emit terrainGeneratorChanged();
371381
}
372382

383+
void Qgs3DMapSettings::setTerrainShadingEnabled( bool enabled )
384+
{
385+
if ( mTerrainShadingEnabled == enabled )
386+
return;
387+
388+
mTerrainShadingEnabled = enabled;
389+
emit terrainShadingChanged();
390+
}
391+
392+
void Qgs3DMapSettings::setTerrainShadingMaterial( const QgsPhongMaterialSettings &material )
393+
{
394+
if ( mTerrainShadingMaterial == material )
395+
return;
396+
397+
mTerrainShadingMaterial = material;
398+
emit terrainShadingChanged();
399+
}
400+
373401
void Qgs3DMapSettings::setRenderers( const QList<QgsAbstract3DRenderer *> &renderers )
374402
{
375403
mRenderers = renderers;

‎src/3d/qgs3dmapsettings.h

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "qgscoordinatereferencesystem.h"
2626
#include "qgsmaplayerref.h"
27+
#include "qgsphongmaterialsettings.h"
2728
#include "qgsterraingenerator.h"
2829
#include "qgsvector3d.h"
2930

@@ -153,7 +154,7 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
153154

154155
/**
155156
* Sets resolution (in pixels) of the texture of a terrain tile
156-
* \sa mapTileResolution()
157+
* \see mapTileResolution()
157158
*/
158159
void setMapTileResolution( int res );
159160

@@ -165,7 +166,7 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
165166

166167
/**
167168
* Sets maximum allowed screen error of terrain tiles in pixels.
168-
* \sa maxTerrainScreenError()
169+
* \see maxTerrainScreenError()
169170
*/
170171
void setMaxTerrainScreenError( float error );
171172

@@ -180,7 +181,7 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
180181

181182
/**
182183
* Returns maximum ground error of terrain tiles in world units.
183-
* \sa maxTerrainGroundError()
184+
* \see maxTerrainGroundError()
184185
*/
185186
void setMaxTerrainGroundError( float error );
186187

@@ -200,6 +201,35 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
200201
//! Returns terrain generator. It takes care of producing terrain tiles from the input data.
201202
QgsTerrainGenerator *terrainGenerator() const { return mTerrainGenerator.get(); }
202203

204+
/**
205+
* Sets whether terrain shading is enabled.
206+
* \see isTerrainShadingEnabled()
207+
* \since QGIS 3.6
208+
*/
209+
void setTerrainShadingEnabled( bool enabled );
210+
211+
/**
212+
* Returns whether terrain shading is enabled. When enabled, in addition to the terrain texture
213+
* generated from the map, the terrain rendering will take into account position of the lights,
214+
* terrain normals and terrain shading material (ambient and specular colors, shininess).
215+
* \since QGIS 3.6
216+
*/
217+
bool isTerrainShadingEnabled() const { return mTerrainShadingEnabled; }
218+
219+
/**
220+
* Sets terrain shading material.
221+
* \see terrainShadingMaterial()
222+
* \since QGIS 3.6
223+
*/
224+
void setTerrainShadingMaterial( const QgsPhongMaterialSettings &material );
225+
226+
/**
227+
* Returns terrain shading material. Diffuse color component is ignored since the diffuse component
228+
* is provided by 2D rendered map texture. Only used when isTerrainShadingEnabled() is true.
229+
* \since QGIS 3.6
230+
*/
231+
QgsPhongMaterialSettings terrainShadingMaterial() const { return mTerrainShadingMaterial; }
232+
203233
//! Sets list of extra 3D renderers to use in the scene. Takes ownership of the objects.
204234
void setRenderers( const QList<QgsAbstract3DRenderer *> &renderers SIP_TRANSFER );
205235
//! Returns list of extra 3D renderers
@@ -261,6 +291,12 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
261291
void maxTerrainScreenErrorChanged();
262292
//! Emitted when the maximum terrain ground error has changed
263293
void maxTerrainGroundErrorChanged();
294+
295+
/**
296+
* Emitted when terrain shading enabled flag or terrain shading material has changed
297+
* \since QGIS 3.6
298+
*/
299+
void terrainShadingChanged();
264300
//! Emitted when the flag whether terrain's bounding boxes are shown has changed
265301
void showTerrainBoundingBoxesChanged();
266302
//! Emitted when the flag whether terrain's tile info is shown has changed
@@ -285,6 +321,8 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
285321
int mMapTileResolution = 512; //!< Size of map textures of tiles in pixels (width/height)
286322
float mMaxTerrainScreenError = 3.f; //!< Maximum allowed terrain error in pixels (determines when tiles are switched to more detailed ones)
287323
float mMaxTerrainGroundError = 1.f; //!< Maximum allowed horizontal map error in map units (determines how many zoom levels will be used)
324+
bool mTerrainShadingEnabled = false; //!< Whether terrain should be shaded taking lights into account
325+
QgsPhongMaterialSettings mTerrainShadingMaterial; //!< Material to use for the terrain (if shading is enabled). Diffuse color is ignored.
288326
bool mShowTerrainBoundingBoxes = false; //!< Whether to show bounding boxes of entities - useful for debugging
289327
bool mShowTerrainTileInfo = false; //!< Whether to draw extra information about terrain tiles to the textures - useful for debugging
290328
bool mShowCameraViewCenter = false; //!< Whether to show camera view center as a sphere - useful for debugging

‎src/3d/qgsphongmaterialsettings.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ class _3D_EXPORT QgsPhongMaterialSettings
6565
//! Writes settings to a DOM element
6666
void writeXml( QDomElement &elem ) const;
6767

68+
bool operator==( const QgsPhongMaterialSettings &other ) const
69+
{
70+
return mAmbient == other.mAmbient &&
71+
mDiffuse == other.mDiffuse &&
72+
mSpecular == other.mSpecular &&
73+
mShininess == other.mShininess;
74+
}
75+
6876
private:
6977
QColor mAmbient;
7078
QColor mDiffuse;

‎src/3d/terrain/qgsdemterraintilegeometry_p.cpp

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
using namespace Qt3DRender;
2828

2929

30-
static QByteArray createPlaneVertexData( int res, float skirtHeight, const QByteArray &heights )
30+
static QByteArray createPlaneVertexData( int res, float side, float vertScale, float skirtHeight, const QByteArray &heights )
3131
{
3232
Q_ASSERT( res >= 2 );
3333
Q_ASSERT( heights.count() == res * res * static_cast<int>( sizeof( float ) ) );
@@ -58,17 +58,20 @@ static QByteArray createPlaneVertexData( int res, float skirtHeight, const QByte
5858
// as we do not create valid triangles that would use such vertices
5959
const float noDataHeight = 0;
6060

61+
const int iMax = resolution.width() - 1;
62+
const int jMax = resolution.height() - 1;
63+
6164
// Iterate over z
6265
for ( int j = -1; j <= resolution.height(); ++j )
6366
{
64-
int jBound = qBound( 0, j, resolution.height() - 1 );
67+
int jBound = qBound( 0, j, jMax );
6568
const float z = z0 + static_cast<float>( jBound ) * dz;
6669
const float v = static_cast<float>( jBound ) * dv;
6770

6871
// Iterate over x
6972
for ( int i = -1; i <= resolution.width(); ++i )
7073
{
71-
int iBound = qBound( 0, i, resolution.width() - 1 );
74+
int iBound = qBound( 0, i, iMax );
7275
const float x = x0 + static_cast<float>( iBound ) * dx;
7376
const float u = static_cast<float>( iBound ) * du;
7477

@@ -83,18 +86,49 @@ static QByteArray createPlaneVertexData( int res, float skirtHeight, const QByte
8386

8487
// position
8588
*fptr++ = x;
86-
*fptr++ = height;
89+
*fptr++ = height / side * vertScale;
8790
*fptr++ = z;
8891

8992
// texture coordinates
9093
*fptr++ = u;
9194
*fptr++ = v;
9295

93-
// TODO: compute correct normals based on neighboring pixels
94-
// normal
95-
*fptr++ = 0.0f;
96-
*fptr++ = 1.0f;
97-
*fptr++ = 0.0f;
96+
// calculate normal coordinates
97+
#define zAt( ii, jj ) zData[ jj * resolution.width() + ii ] * vertScale
98+
float zi0 = zAt( qBound( 0, i - 1, iMax ), jBound );
99+
float zi1 = zAt( qBound( 0, i + 1, iMax ), jBound );
100+
float zj0 = zAt( iBound, qBound( 0, j - 1, jMax ) );
101+
float zj1 = zAt( iBound, qBound( 0, j + 1, jMax ) );
102+
103+
QVector3D n;
104+
if ( std::isnan( zi0 ) || std::isnan( zi1 ) || std::isnan( zj0 ) || std::isnan( zj1 ) )
105+
n = QVector3D( 0, 1, 0 );
106+
else
107+
{
108+
float di, dj;
109+
float zij = height * vertScale;
110+
111+
if ( i == 0 )
112+
di = 2 * ( zij - zi1 );
113+
else if ( i == iMax )
114+
di = 2 * ( zi0 - zij );
115+
else
116+
di = zi0 - zi1;
117+
118+
if ( j == 0 )
119+
dj = 2 * ( zij - zj1 );
120+
else if ( j == jMax )
121+
dj = 2 * ( zj0 - zij );
122+
else
123+
dj = zj0 - zj1;
124+
125+
n = QVector3D( di, 2 * side / res, dj );
126+
n.normalize();
127+
}
128+
129+
*fptr++ = n.x();
130+
*fptr++ = n.y();
131+
*fptr++ = n.z();
98132
}
99133
}
100134

@@ -176,22 +210,26 @@ static QByteArray createPlaneIndexData( int res, const QByteArray &heightMap )
176210
class PlaneVertexBufferFunctor : public QBufferDataGenerator
177211
{
178212
public:
179-
explicit PlaneVertexBufferFunctor( int resolution, float skirtHeight, const QByteArray &heightMap )
213+
explicit PlaneVertexBufferFunctor( int resolution, float side, float vertScale, float skirtHeight, const QByteArray &heightMap )
180214
: mResolution( resolution )
215+
, mSide( side )
216+
, mVertScale( vertScale )
181217
, mSkirtHeight( skirtHeight )
182218
, mHeightMap( heightMap )
183219
{}
184220

185221
QByteArray operator()() final
186222
{
187-
return createPlaneVertexData( mResolution, mSkirtHeight, mHeightMap );
223+
return createPlaneVertexData( mResolution, mSide, mVertScale, mSkirtHeight, mHeightMap );
188224
}
189225

190226
bool operator ==( const QBufferDataGenerator &other ) const final
191227
{
192228
const PlaneVertexBufferFunctor *otherFunctor = functor_cast<PlaneVertexBufferFunctor>( &other );
193229
if ( otherFunctor != nullptr )
194230
return ( otherFunctor->mResolution == mResolution &&
231+
otherFunctor->mSide == mSide &&
232+
otherFunctor->mVertScale == mVertScale &&
195233
otherFunctor->mSkirtHeight == mSkirtHeight &&
196234
otherFunctor->mHeightMap == mHeightMap );
197235
return false;
@@ -201,6 +239,8 @@ class PlaneVertexBufferFunctor : public QBufferDataGenerator
201239

202240
private:
203241
int mResolution;
242+
float mSide;
243+
float mVertScale;
204244
float mSkirtHeight;
205245
QByteArray mHeightMap;
206246
};
@@ -239,9 +279,11 @@ class PlaneIndexBufferFunctor : public QBufferDataGenerator
239279
// ------------
240280

241281

242-
DemTerrainTileGeometry::DemTerrainTileGeometry( int resolution, float skirtHeight, const QByteArray &heightMap, DemTerrainTileGeometry::QNode *parent )
282+
DemTerrainTileGeometry::DemTerrainTileGeometry( int resolution, float side, float vertScale, float skirtHeight, const QByteArray &heightMap, DemTerrainTileGeometry::QNode *parent )
243283
: QGeometry( parent )
244284
, mResolution( resolution )
285+
, mSide( side )
286+
, mVertScale( vertScale )
245287
, mSkirtHeight( skirtHeight )
246288
, mHeightMap( heightMap )
247289
{
@@ -357,7 +399,7 @@ void DemTerrainTileGeometry::init()
357399

358400
// switched to setting data instead of just setting data generators because we also need the buffers
359401
// available for ray-mesh intersections and we can't access the private copy of data in Qt (if there is any)
360-
mVertexBuffer->setData( PlaneVertexBufferFunctor( mResolution, mSkirtHeight, mHeightMap )() );
402+
mVertexBuffer->setData( PlaneVertexBufferFunctor( mResolution, mSide, mVertScale, mSkirtHeight, mHeightMap )() );
361403
mIndexBuffer->setData( PlaneIndexBufferFunctor( mResolution, mHeightMap )() );
362404

363405
addAttribute( mPositionAttribute );

‎src/3d/terrain/qgsdemterraintilegeometry_p.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,16 @@ class DemTerrainTileGeometry : public Qt3DRender::QGeometry
5959
* Constructs a terrain tile geometry. Resolution is the number of vertices on one side of the tile,
6060
* heightMap is array of float values with one height value for each vertex
6161
*/
62-
explicit DemTerrainTileGeometry( int resolution, float skirtHeight, const QByteArray &heightMap, QNode *parent = nullptr );
62+
explicit DemTerrainTileGeometry( int resolution, float side, float vertScale, float skirtHeight, const QByteArray &heightMap, QNode *parent = nullptr );
6363

6464
bool rayIntersection( const QgsRayCastingUtils::Ray3D &ray, const QMatrix4x4 &worldTransform, QVector3D &intersectionPoint );
6565

6666
private:
6767
void init();
6868

6969
int mResolution;
70+
float mSide;
71+
float mVertScale;
7072
float mSkirtHeight;
7173
QByteArray mHeightMap;
7274
Qt3DRender::QAttribute *mPositionAttribute = nullptr;

‎src/3d/terrain/qgsdemterraintileloader_p.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,32 +76,33 @@ Qt3DCore::QEntity *QgsDemTerrainTileLoader::createEntity( Qt3DCore::QEntity *par
7676
return nullptr;
7777
}
7878

79+
const Qgs3DMapSettings &map = terrain()->map3D();
80+
QgsRectangle extent = map.terrainGenerator()->tilingScheme().tileToExtent( mNode->tileX(), mNode->tileY(), mNode->tileZ() ); //node->extent;
81+
double x0 = extent.xMinimum() - map.origin().x();
82+
double y0 = extent.yMinimum() - map.origin().y();
83+
double side = extent.width();
84+
double half = side / 2;
85+
86+
7987
QgsTerrainTileEntity *entity = new QgsTerrainTileEntity;
8088

8189
// create geometry renderer
8290

8391
Qt3DRender::QGeometryRenderer *mesh = new Qt3DRender::QGeometryRenderer;
84-
mesh->setGeometry( new DemTerrainTileGeometry( mResolution, mSkirtHeight, mHeightMap, mesh ) );
92+
mesh->setGeometry( new DemTerrainTileGeometry( mResolution, side, map.terrainVerticalScale(), mSkirtHeight, mHeightMap, mesh ) );
8593
entity->addComponent( mesh ); // takes ownership if the component has no parent
8694

8795
// create material
8896

89-
createTextureComponent( entity );
97+
createTextureComponent( entity, map.isTerrainShadingEnabled(), map.terrainShadingMaterial() );
9098

9199
// create transform
92100

93101
Qt3DCore::QTransform *transform = nullptr;
94102
transform = new Qt3DCore::QTransform();
95103
entity->addComponent( transform );
96104

97-
const Qgs3DMapSettings &map = terrain()->map3D();
98-
QgsRectangle extent = map.terrainGenerator()->tilingScheme().tileToExtent( mNode->tileX(), mNode->tileY(), mNode->tileZ() ); //node->extent;
99-
double x0 = extent.xMinimum() - map.origin().x();
100-
double y0 = extent.yMinimum() - map.origin().y();
101-
double side = extent.width();
102-
double half = side / 2;
103-
104-
transform->setScale3D( QVector3D( side, map.terrainVerticalScale(), side ) );
105+
transform->setScale( side );
105106
transform->setTranslation( QVector3D( x0 + half, 0, - ( y0 + half ) ) );
106107

107108
mNode->setExactBbox( QgsAABB( x0, zMin * map.terrainVerticalScale(), -y0, x0 + side, zMax * map.terrainVerticalScale(), -( y0 + side ) ) );

‎src/3d/terrain/qgsflatterraingenerator.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ Qt3DCore::QEntity *FlatTerrainChunkLoader::createEntity( Qt3DCore::QEntity *pare
5252

5353
// create material
5454

55-
createTextureComponent( entity );
55+
const Qgs3DMapSettings &map = terrain()->map3D();
56+
createTextureComponent( entity, map.isTerrainShadingEnabled(), map.terrainShadingMaterial() );
5657

5758
// create transform
5859

‎src/3d/terrain/qgsterraintileloader_p.cpp

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,8 @@
2525

2626
#include <Qt3DRender/QTexture>
2727

28-
#if QT_VERSION >= 0x050900
2928
#include <Qt3DExtras/QTextureMaterial>
30-
#else
3129
#include <Qt3DExtras/QDiffuseMapMaterial>
32-
#endif
3330

3431
#include "quantizedmeshterraingenerator.h"
3532

@@ -67,23 +64,32 @@ void QgsTerrainTileLoader::loadTexture()
6764
mTextureJobId = mTerrain->textureGenerator()->render( mExtentMapCrs, mTileDebugText );
6865
}
6966

70-
void QgsTerrainTileLoader::createTextureComponent( QgsTerrainTileEntity *entity )
67+
void QgsTerrainTileLoader::createTextureComponent( QgsTerrainTileEntity *entity, bool isShadingEnabled, const QgsPhongMaterialSettings &shadingMaterial )
7168
{
7269
Qt3DRender::QTexture2D *texture = new Qt3DRender::QTexture2D( entity );
7370
QgsTerrainTextureImage *textureImage = new QgsTerrainTextureImage( mTextureImage, mExtentMapCrs, mTileDebugText );
7471
texture->addTextureImage( textureImage );
7572
texture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
7673
texture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
77-
Qt3DExtras::QTextureMaterial *material = nullptr;
78-
#if QT_VERSION >= 0x050900
79-
material = new Qt3DExtras::QTextureMaterial;
80-
material->setTexture( texture );
81-
#else
82-
material = new Qt3DExtras::QDiffuseMapMaterial;
83-
material->setDiffuse( texture );
84-
material->setShininess( 1 );
85-
material->setAmbient( Qt::white );
86-
#endif
74+
75+
Qt3DRender::QMaterial *material = nullptr;
76+
if ( isShadingEnabled )
77+
{
78+
Qt3DExtras::QDiffuseMapMaterial *diffuseMapMaterial;
79+
diffuseMapMaterial = new Qt3DExtras::QDiffuseMapMaterial;
80+
diffuseMapMaterial->setDiffuse( texture );
81+
diffuseMapMaterial->setAmbient( shadingMaterial.ambient() );
82+
diffuseMapMaterial->setSpecular( shadingMaterial.specular() );
83+
diffuseMapMaterial->setShininess( shadingMaterial.shininess() );
84+
material = diffuseMapMaterial;
85+
}
86+
else
87+
{
88+
Qt3DExtras::QTextureMaterial *textureMaterial = new Qt3DExtras::QTextureMaterial;
89+
textureMaterial->setTexture( texture );
90+
material = textureMaterial;
91+
}
92+
8793
entity->setTextureImage( textureImage );
8894
entity->addComponent( material ); // takes ownership if the component has no parent
8995
}

‎src/3d/terrain/qgsterraintileloader_p.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <QImage>
3333
#include "qgsrectangle.h"
3434

35+
class QgsPhongMaterialSettings;
3536
class QgsTerrainEntity;
3637
class QgsTerrainTileEntity;
3738

@@ -54,7 +55,7 @@ class QgsTerrainTileLoader : public QgsChunkLoader
5455
//! Starts asynchronous rendering of map texture
5556
void loadTexture();
5657
//! Creates material component for the entity with the rendered map as a texture
57-
void createTextureComponent( QgsTerrainTileEntity *entity );
58+
void createTextureComponent( QgsTerrainTileEntity *entity, bool isShadingEnabled, const QgsPhongMaterialSettings &shadingMaterial );
5859
//! Gives access to the terain entity
5960
QgsTerrainEntity *terrain() { return mTerrain; }
6061

‎src/app/3d/qgs3dmapconfigwidget.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas
6969
chkShowBoundingBoxes->setChecked( mMap->showTerrainBoundingBoxes() );
7070
chkShowCameraViewCenter->setChecked( mMap->showCameraViewCenter() );
7171

72+
groupTerrainShading->setChecked( mMap->isTerrainShadingEnabled() );
73+
widgetTerrainMaterial->setDiffuseVisible( false );
74+
widgetTerrainMaterial->setMaterial( mMap->terrainShadingMaterial() );
75+
7276
connect( cboTerrainLayer, static_cast<void ( QComboBox::* )( int )>( &QgsMapLayerComboBox::currentIndexChanged ), this, &Qgs3DMapConfigWidget::onTerrainLayerChanged );
7377
connect( spinMapResolution, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &Qgs3DMapConfigWidget::updateMaxZoomLevel );
7478
connect( spinGroundError, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &Qgs3DMapConfigWidget::updateMaxZoomLevel );
@@ -134,6 +138,9 @@ void Qgs3DMapConfigWidget::apply()
134138
mMap->setShowTerrainTilesInfo( chkShowTileInfo->isChecked() );
135139
mMap->setShowTerrainBoundingBoxes( chkShowBoundingBoxes->isChecked() );
136140
mMap->setShowCameraViewCenter( chkShowCameraViewCenter->isChecked() );
141+
142+
mMap->setTerrainShadingEnabled( groupTerrainShading->isChecked() );
143+
mMap->setTerrainShadingMaterial( widgetTerrainMaterial->material() );
137144
}
138145

139146
void Qgs3DMapConfigWidget::onTerrainLayerChanged()

‎src/app/3d/qgsphongmaterialwidget.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ QgsPhongMaterialWidget::QgsPhongMaterialWidget( QWidget *parent )
3131
connect( spinShininess, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, &QgsPhongMaterialWidget::changed );
3232
}
3333

34+
void QgsPhongMaterialWidget::setDiffuseVisible( bool visible )
35+
{
36+
label->setVisible( visible );
37+
btnDiffuse->setVisible( visible );
38+
}
39+
40+
bool QgsPhongMaterialWidget::isDiffuseVisible() const
41+
{
42+
return btnDiffuse->isVisible();
43+
}
44+
3445
void QgsPhongMaterialWidget::setMaterial( const QgsPhongMaterialSettings &material )
3546
{
3647
btnDiffuse->setColor( material.diffuse() );

‎src/app/3d/qgsphongmaterialwidget.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ class QgsPhongMaterialWidget : public QWidget, private Ui::PhongMaterialWidget
3030
public:
3131
explicit QgsPhongMaterialWidget( QWidget *parent = nullptr );
3232

33+
void setDiffuseVisible( bool visible );
34+
bool isDiffuseVisible() const;
35+
3336
void setMaterial( const QgsPhongMaterialSettings &material );
3437
QgsPhongMaterialSettings material() const;
3538

‎src/ui/3d/map3dconfigwidget.ui

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<x>0</x>
88
<y>0</y>
99
<width>691</width>
10-
<height>830</height>
10+
<height>1135</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
@@ -87,6 +87,21 @@
8787
</layout>
8888
</widget>
8989
</item>
90+
<item>
91+
<widget class="QgsCollapsibleGroupBox" name="groupTerrainShading">
92+
<property name="title">
93+
<string>Terrain shading</string>
94+
</property>
95+
<property name="checkable">
96+
<bool>true</bool>
97+
</property>
98+
<layout class="QVBoxLayout" name="verticalLayout_2">
99+
<item>
100+
<widget class="QgsPhongMaterialWidget" name="widgetTerrainMaterial" native="true"/>
101+
</item>
102+
</layout>
103+
</widget>
104+
</item>
90105
<item>
91106
<layout class="QGridLayout" name="gridLayout_2">
92107
<item row="2" column="0">
@@ -224,6 +239,18 @@
224239
<extends>QSpinBox</extends>
225240
<header>qgsspinbox.h</header>
226241
</customwidget>
242+
<customwidget>
243+
<class>QgsPhongMaterialWidget</class>
244+
<extends>QWidget</extends>
245+
<header>qgsphongmaterialwidget.h</header>
246+
<container>1</container>
247+
</customwidget>
248+
<customwidget>
249+
<class>QgsCollapsibleGroupBox</class>
250+
<extends>QGroupBox</extends>
251+
<header>qgscollapsiblegroupbox.h</header>
252+
<container>1</container>
253+
</customwidget>
227254
</customwidgets>
228255
<tabstops>
229256
<tabstop>cboTerrainLayer</tabstop>

0 commit comments

Comments
 (0)
Please sign in to comment.