QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsterraintileloader_p.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsterraintileloader_p.cpp
3 --------------------------------------
4 Date : July 2017
5 Copyright : (C) 2017 by Martin Dobias
6 Email : wonder dot sk at gmail 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
17
18#include "qgs3dmapsettings.h"
19#include "qgs3dutils.h"
20#include "qgschunknode_p.h"
21#include "qgsterrainentity_p.h"
22#include "qgsterraingenerator.h"
27
28#include <Qt3DRender/QTexture>
29#include <Qt3DRender/QTechnique>
30#include <Qt3DRender/QCullFace>
31
32#include <Qt3DExtras/QTextureMaterial>
33#include <Qt3DExtras/QDiffuseSpecularMaterial>
34#include <Qt3DExtras/QPhongMaterial>
35
37
38QgsTerrainTileLoader::QgsTerrainTileLoader( QgsTerrainEntity *terrain, QgsChunkNode *node )
39 : QgsChunkLoader( node )
40 , mTerrain( terrain )
41{
42 const Qgs3DMapSettings &map = mTerrain->map3D();
43 const QgsChunkNodeId nodeId = node->tileId();
44 const QgsRectangle extentTerrainCrs = map.terrainGenerator()->tilingScheme().tileToExtent( nodeId );
45 mExtentMapCrs = Qgs3DUtils::tryReprojectExtent2D( extentTerrainCrs, map.terrainGenerator()->crs(), map.crs(), map.transformContext() );
46 mTileDebugText = nodeId.text();
47}
48
49void QgsTerrainTileLoader::loadTexture()
50{
51 connect( mTerrain->textureGenerator(), &QgsTerrainTextureGenerator::tileReady, this, &QgsTerrainTileLoader::onImageReady );
52 mTextureJobId = mTerrain->textureGenerator()->render( mExtentMapCrs, mNode->tileId(), mTileDebugText );
53}
54
55void QgsTerrainTileLoader::createTextureComponent( QgsTerrainTileEntity *entity, bool isShadingEnabled, const QgsPhongMaterialSettings &shadingMaterial, bool useTexture )
56{
57 Qt3DRender::QTexture2D *texture = useTexture || !isShadingEnabled ? createTexture( entity ) : nullptr;
58
59 Qt3DRender::QMaterial *material = nullptr;
60 if ( texture )
61 {
62 if ( isShadingEnabled )
63 {
64 Qt3DExtras::QDiffuseSpecularMaterial *diffuseMapMaterial = new Qt3DExtras::QDiffuseSpecularMaterial;
65 diffuseMapMaterial->setDiffuse( QVariant::fromValue( texture ) );
66 diffuseMapMaterial->setAmbient( shadingMaterial.ambient() );
67 diffuseMapMaterial->setSpecular( shadingMaterial.specular() );
68 diffuseMapMaterial->setShininess( shadingMaterial.shininess() );
69 material = diffuseMapMaterial;
70 }
71 else
72 {
73 Qt3DExtras::QTextureMaterial *textureMaterial = new Qt3DExtras::QTextureMaterial;
74 textureMaterial->setTexture( texture );
75 material = textureMaterial;
76 }
77 }
78 else
79 {
80 Qt3DExtras::QPhongMaterial *phongMaterial = new Qt3DExtras::QPhongMaterial;
81 phongMaterial->setDiffuse( shadingMaterial.diffuse() );
82 phongMaterial->setAmbient( shadingMaterial.ambient() );
83 phongMaterial->setSpecular( shadingMaterial.specular() );
84 phongMaterial->setShininess( shadingMaterial.shininess() );
85 material = phongMaterial;
86 }
87
88 // no backface culling on terrain, to allow terrain to be viewed from underground
89 const QVector<Qt3DRender::QTechnique *> techniques = material->effect()->techniques();
90 for ( Qt3DRender::QTechnique *technique : techniques )
91 {
92 const QVector<Qt3DRender::QRenderPass *> passes = technique->renderPasses();
93 for ( Qt3DRender::QRenderPass *pass : passes )
94 {
95 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
96 cullFace->setMode( Qt3DRender::QCullFace::NoCulling );
97 pass->addRenderState( cullFace );
98 }
99 }
100
101 entity->addComponent( material ); // takes ownership if the component has no parent
102}
103
104Qt3DRender::QTexture2D *QgsTerrainTileLoader::createTexture( QgsTerrainTileEntity *entity )
105{
106 Qt3DRender::QTexture2D *texture = new Qt3DRender::QTexture2D;
107 QgsTerrainTextureImage *textureImage = new QgsTerrainTextureImage( mTextureImage, mExtentMapCrs, mTileDebugText );
108 texture->addTextureImage( textureImage );//texture take the ownership of textureImage if has no parant
109 texture->setMinificationFilter( Qt3DRender::QTexture2D::Linear );
110 texture->setMagnificationFilter( Qt3DRender::QTexture2D::Linear );
111
112 entity->setTextureImage( textureImage );
113
114 return texture;
115}
116
117void QgsTerrainTileLoader::onImageReady( int jobId, const QImage &image )
118{
119 if ( mTextureJobId == jobId )
120 {
121 mTextureImage = image;
122 mTextureJobId = -1;
123 emit finished(); // TODO: this should be left for derived class!
124 }
125}
126
QgsTerrainGenerator * terrainGenerator() const
Returns the terrain generator.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used in the 3D scene.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
static QgsRectangle tryReprojectExtent2D(const QgsRectangle &extent, const QgsCoordinateReferenceSystem &crs1, const QgsCoordinateReferenceSystem &crs2, const QgsCoordinateTransformContext &context)
Reprojects extent from crs1 to crs2 coordinate reference system with context context.
Definition: qgs3dutils.cpp:594
QColor diffuse() const
Returns diffuse color component.
QColor specular() const
Returns specular color component.
QColor ambient() const
Returns ambient color component.
double shininess() const
Returns shininess of the surface.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsCoordinateReferenceSystem crs() const
Returns CRS of the terrain.
const QgsTilingScheme & tilingScheme() const
Returns tiling scheme of the terrain.
QgsRectangle tileToExtent(int x, int y, int z) const
Returns map coordinates of the extent of a tile.