QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsmesh3dsymbol_p.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmesh3dsymbol_p.cpp
3  ---------------------
4  Date : January 2019
5  Copyright : (C) 2019 by Peter Petrik
6  Email : zilolv 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 
16 #include "qgsmesh3dsymbol_p.h"
17 
18 #include "qgsmesh3dsymbol.h"
20 #include "qgs3dmapsettings.h"
21 #include "qgs3dutils.h"
22 
23 #include <Qt3DCore/QTransform>
24 #include <Qt3DRender/QEffect>
25 #include <Qt3DRender/QTechnique>
26 #include <Qt3DRender/QCullFace>
27 
28 #include "qgsmultipolygon.h"
29 #include "qgsmeshlayer.h"
30 #include "qgstriangularmesh.h"
33 
34 static QgsExpressionContext _expressionContext3D()
35 {
39  return ctx;
40 }
41 
43 
44 QgsMesh3DSymbolEntity::QgsMesh3DSymbolEntity( const Qgs3DMapSettings &map,
45  QgsMeshLayer *layer,
46  const QgsMesh3DSymbol &symbol,
47  Qt3DCore::QNode *parent )
48  : Qt3DCore::QEntity( parent )
49 {
50  // build the default material
51  Qt3DRender::QMaterial *mat = material( symbol );
52 
53  // build a transform function
54  Qt3DCore::QTransform *tform = new Qt3DCore::QTransform;
55  tform->setTranslation( QVector3D( 0, 0, 0 ) );
56 
57  // build the entity
58  QgsMesh3DSymbolEntityNode *entity = new QgsMesh3DSymbolEntityNode( map, layer, symbol );
59  entity->findChild<Qt3DRender::QGeometryRenderer *>()->setObjectName( QStringLiteral( "main" ) ); // temporary measure to distinguish between "selected" and "main"
60  entity->addComponent( mat );
61  entity->addComponent( tform );
62  entity->setParent( this );
63 }
64 
65 Qt3DRender::QMaterial *QgsMesh3DSymbolEntity::material( const QgsMesh3DSymbol &symbol ) const
66 {
67  QgsMaterialContext context;
68  Qt3DRender::QMaterial *material = symbol.material()->toMaterial( QgsMaterialSettingsRenderingTechnique::Triangles, context );
69 
70  // front/back side culling
71  auto techniques = material->effect()->techniques();
72  for ( auto tit = techniques.constBegin(); tit != techniques.constEnd(); ++tit )
73  {
74  auto renderPasses = ( *tit )->renderPasses();
75  for ( auto rpit = renderPasses.begin(); rpit != renderPasses.end(); ++rpit )
76  {
77  Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
78  cullFace->setMode( Qt3DRender::QCullFace::Back );
79  ( *rpit )->addRenderState( cullFace );
80  }
81  }
82  return material;
83 }
84 
85 QgsMesh3DSymbolEntityNode::QgsMesh3DSymbolEntityNode( const Qgs3DMapSettings &map,
86  QgsMeshLayer *layer,
87  const QgsMesh3DSymbol &symbol,
88  Qt3DCore::QNode *parent ) : Qt3DCore::QEntity( parent )
89 {
90  addComponent( renderer( map, symbol, layer ) );
91 }
92 
93 Qt3DRender::QGeometryRenderer *QgsMesh3DSymbolEntityNode::renderer( const Qgs3DMapSettings &map,
94  const QgsMesh3DSymbol &symbol,
95  const QgsMeshLayer *layer )
96 {
97  QgsPointXY origin( map.origin().x(), map.origin().y() );
98  QList<QgsPolygon *> polygons;
99  QList<QgsFeatureId> fids;
100 
101  QgsExpressionContext ctx( _expressionContext3D() );
102  const QgsPropertyCollection &ddp = symbol.dataDefinedProperties();
103  bool hasDDHeight = ddp.isActive( QgsAbstract3DSymbol::PropertyHeight );
104  float height = symbol.height();
105  if ( hasDDHeight )
106  {
107  height = static_cast<float>( ddp.valueAsDouble( QgsAbstract3DSymbol::PropertyHeight,
108  ctx,
109  static_cast<double>( height )
110  )
111  );
112  }
113 
114  const QgsTriangularMesh *mesh = layer->triangularMesh();
115  if ( mesh )
116  {
117  const QVector<QgsMeshFace> &triangles = mesh->triangles();
118  const QVector<QgsMeshVertex> &vertices = mesh->vertices();
119  for ( int i = 0; i < triangles.size(); ++i )
120  {
121  const QgsMeshFace &triangle = triangles.at( i );
122  Q_ASSERT( triangle.size() == 3 );
123  std::unique_ptr< QgsPolygon > polygon = QgsMeshUtils::toPolygon( triangle, vertices );
124  Qgs3DUtils::clampAltitudes( polygon.get(),
125  symbol.altitudeClamping(),
126  Qgs3DTypes::AltitudeBinding::AltBindVertex,
127  height,
128  map );
129  polygons.append( polygon.release() );
130  fids.append( i );
131  }
132  }
133 
134  // Polygons from mesh are already triangles, but
135  // call QgsTessellatedPolygonGeometry to
136  // use symbol settings for back faces, normals, etc
137 
138  const QgsPhongTexturedMaterialSettings *texturedMaterialSettings = dynamic_cast< const QgsPhongTexturedMaterialSettings * >( symbol.material() );
139 
140  mGeometry = new QgsTessellatedPolygonGeometry( true, false, symbol.addBackFaces(), texturedMaterialSettings ? texturedMaterialSettings->requiresTextureCoordinates() : false );
141  QList<float> extrusionHeightPerPolygon;
142  mGeometry->setPolygons( polygons, fids, origin, 0.0, extrusionHeightPerPolygon );
143 
144  Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
145  renderer->setGeometry( mGeometry );
146 
147  return renderer;
148 }
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:370
qgsexpressioncontextutils.h
QgsAbstractPropertyCollection::valueAsDouble
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
Definition: qgspropertycollection.cpp:66
qgstessellatedpolygongeometry.h
QgsTriangularMesh::vertices
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
Definition: qgstriangularmesh.cpp:287
QgsExpressionContextUtils::globalScope
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Definition: qgsexpressioncontextutils.cpp:34
QgsVector3D::y
double y() const
Returns Y coordinate.
Definition: qgsvector3d.h:51
qgsphongtexturedmaterialsettings.h
qgsmesh3dsymbol.h
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:468
QgsTriangularMesh::triangles
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
Definition: qgstriangularmesh.cpp:292
QgsMesh3DSymbol
3 3D symbol that draws mesh geometry as planar triangles.
Definition: qgsmesh3dsymbol.h:44
QgsMesh3DSymbol::height
float height() const
Returns height (altitude) of the symbol (in map units)
Definition: qgsmesh3dsymbol.h:105
QgsAbstract3DSymbol::PropertyHeight
@ PropertyHeight
Height (altitude)
Definition: qgsabstract3dsymbol.h:70
QgsMesh3DSymbol::material
QgsAbstractMaterialSettings * material() const
Returns material used for shading of the symbol.
Definition: qgsmesh3dsymbol.cpp:287
Qgs3DUtils::clampAltitudes
static void clampAltitudes(QgsLineString *lineString, Qgs3DTypes::AltitudeClamping altClamp, Qgs3DTypes::AltitudeBinding altBind, const QgsPoint &centroid, float height, const Qgs3DMapSettings &map)
Clamps altitude of vertices of a linestring according to the settings.
Definition: qgs3dutils.cpp:267
QgsMeshLayer::triangularMesh
QgsTriangularMesh * triangularMesh(double minimumTriangleSize=0) const
Returns triangular mesh (nullptr before rendering or calling to updateMesh).
Definition: qgsmeshlayer.cpp:248
QgsMesh3DSymbol::addBackFaces
bool addBackFaces() const
Returns whether also triangles facing the other side will be created.
Definition: qgsmesh3dsymbol.h:122
QgsMesh3DSymbol::altitudeClamping
Qgs3DTypes::AltitudeClamping altitudeClamping() const
Returns method that determines altitude (whether to clamp to feature to terrain)
Definition: qgsmesh3dsymbol.h:100
QgsMaterialContext
3 Context settings for a material.
Definition: qgsabstractmaterialsettings.h:55
qgstriangularmesh.h
QgsExpressionContextUtils::projectScope
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
Definition: qgsexpressioncontextutils.cpp:222
qgsmultipolygon.h
qgs3dutils.h
QgsMeshUtils::toPolygon
CORE_EXPORT std::unique_ptr< QgsPolygon > toPolygon(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry, caller is responsible for delete.
Definition: qgstriangularmesh.cpp:509
QgsMeshLayer
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:95
Qt3DCore
Definition: qgsabstract3drenderer.h:31
Qgs3DMapSettings
3 Definition of the world
Definition: qgs3dmapsettings.h:54
qgsmesh3dsymbol_p.h
Qgs3DMapSettings::origin
QgsVector3D origin() const
Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
Definition: qgs3dmapsettings.h:86
QgsMeshFace
QVector< int > QgsMeshFace
List of vertex indexes.
Definition: qgsmeshdataprovider.h:41
qgsmeshlayer.h
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:44
QgsPhongTexturedMaterialSettings
3 A phong shading model with diffuse texture map.
Definition: qgsphongtexturedmaterialsettings.h:36
QgsPropertyCollection
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
Definition: qgspropertycollection.h:319
qgs3dmapsettings.h
QgsAbstractMaterialSettings::toMaterial
virtual Qt3DRender::QMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const =0
Creates a new QMaterial object representing the material settings.
QgsAbstract3DSymbol::dataDefinedProperties
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
Definition: qgsabstract3dsymbol.h:78
QgsTriangularMesh
Triangular/Derived Mesh is mesh with vertices in map coordinates.
Definition: qgstriangularmesh.h:50
QgsPropertyCollection::isActive
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
Definition: qgspropertycollection.cpp:268
QgsVector3D::x
double x() const
Returns X coordinate.
Definition: qgsvector3d.h:49
QgsTessellatedPolygonGeometry
3 Class derived from Qt3DRender::QGeometry that represents polygons tessellated into 3D geometry.
Definition: qgstessellatedpolygongeometry.h:45
QgsPhongTexturedMaterialSettings::requiresTextureCoordinates
bool requiresTextureCoordinates() const
Returns true if the material requires texture coordinates to be generated during triangulation....
Definition: qgsphongtexturedmaterialsettings.h:85