QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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  const QgsMaterialContext context;
68  Qt3DRender::QMaterial *material = symbol.material()->toMaterial( QgsMaterialSettingsRenderingTechnique::Triangles, context );
69 
70  // front/back side culling
71  const 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  const QgsPointXY origin( map.origin().x(), map.origin().y() );
98  QList<QgsPolygon *> polygons;
99  QList<QgsFeatureId> fids;
100 
101  const QgsExpressionContext ctx( _expressionContext3D() );
102  const QgsPropertyCollection &ddp = symbol.dataDefinedProperties();
103  const 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(),
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  const 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:406
qgsexpressioncontextutils.h
Qgis::AltitudeBinding::Vertex
@ Vertex
Clamp every vertex of feature.
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:352
QgsExpressionContextUtils::globalScope
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Definition: qgsexpressioncontextutils.cpp:40
QgsVector3D::y
double y() const
Returns Y coordinate.
Definition: qgsvector3d.h:64
qgsphongtexturedmaterialsettings.h
qgsmesh3dsymbol.h
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:480
QgsTriangularMesh::triangles
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
Definition: qgstriangularmesh.cpp:357
QgsMesh3DSymbol
3D symbol that draws mesh geometry as planar triangles.
Definition: qgsmesh3dsymbol.h:43
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:71
QgsMesh3DSymbol::material
QgsAbstractMaterialSettings * material() const
Returns material used for shading of the symbol.
Definition: qgsmesh3dsymbol.cpp:296
QgsMeshLayer::triangularMesh
QgsTriangularMesh * triangularMesh(double minimumTriangleSize=0) const
Returns triangular mesh (nullptr before rendering or calling to updateMesh).
Definition: qgsmeshlayer.cpp:285
QgsMesh3DSymbol::addBackFaces
bool addBackFaces() const
Returns whether also triangles facing the other side will be created.
Definition: qgsmesh3dsymbol.h:122
QgsMaterialContext
Context settings for a material.
Definition: qgsabstractmaterialsettings.h:64
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:291
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:623
QgsMeshLayer
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:98
Qt3DCore
Definition: qgsabstract3drenderer.h:30
QgsMaterialSettingsRenderingTechnique::Triangles
@ Triangles
Triangle based rendering (default)
Qgs3DMapSettings
Definition of the world.
Definition: qgs3dmapsettings.h:57
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:89
QgsMeshFace
QVector< int > QgsMeshFace
List of vertex indexes.
Definition: qgsmeshdataprovider.h:42
qgsmeshlayer.h
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
QgsPhongTexturedMaterialSettings
A phong shading model with diffuse texture map.
Definition: qgsphongtexturedmaterialsettings.h:35
QgsPropertyCollection
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
Definition: qgspropertycollection.h:318
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:79
Qgs3DUtils::clampAltitudes
static void clampAltitudes(QgsLineString *lineString, Qgis::AltitudeClamping altClamp, Qgis::AltitudeBinding altBind, const QgsPoint &centroid, float height, const Qgs3DMapSettings &map)
Clamps altitude of vertices of a linestring according to the settings.
Definition: qgs3dutils.cpp:351
QgsTriangularMesh
Triangular/Derived Mesh is mesh with vertices in map coordinates.
Definition: qgstriangularmesh.h:51
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:62
QgsMesh3DSymbol::altitudeClamping
Qgis::AltitudeClamping altitudeClamping() const
Returns method that determines altitude (whether to clamp to feature to terrain)
Definition: qgsmesh3dsymbol.h:100
QgsTessellatedPolygonGeometry
Class derived from Qt3DRender::QGeometry that represents polygons tessellated into 3D geometry.
Definition: qgstessellatedpolygongeometry.h:44
QgsPhongTexturedMaterialSettings::requiresTextureCoordinates
bool requiresTextureCoordinates() const
Returns true if the material requires texture coordinates to be generated during triangulation....
Definition: qgsphongtexturedmaterialsettings.h:85