QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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"
32 
33 static QgsExpressionContext _expressionContext3D()
34 {
38  return ctx;
39 }
40 
42 
43 QgsMesh3DSymbolEntity::QgsMesh3DSymbolEntity( const Qgs3DMapSettings &map,
44  QgsMeshLayer *layer,
45  const QgsMesh3DSymbol &symbol,
46  Qt3DCore::QNode *parent )
47  : Qt3DCore::QEntity( parent )
48 {
49  // build the default material
50  Qt3DExtras::QPhongMaterial *mat = material( symbol );
51 
52  // build a transform function
53  Qt3DCore::QTransform *tform = new Qt3DCore::QTransform;
54  tform->setTranslation( QVector3D( 0, 0, 0 ) );
55 
56  // build the entity
57  QgsMesh3DSymbolEntityNode *entity = new QgsMesh3DSymbolEntityNode( map, layer, symbol );
58  entity->findChild<Qt3DRender::QGeometryRenderer *>()->setObjectName( QStringLiteral( "main" ) ); // temporary measure to distinguish between "selected" and "main"
59  entity->addComponent( mat );
60  entity->addComponent( tform );
61  entity->setParent( this );
62 }
63 
64 Qt3DExtras::QPhongMaterial *QgsMesh3DSymbolEntity::material( const QgsMesh3DSymbol &symbol ) const
65 {
66  Qt3DExtras::QPhongMaterial *material = new Qt3DExtras::QPhongMaterial;
67 
68  // front/back side culling
69  auto techniques = material->effect()->techniques();
70  for ( auto tit = techniques.constBegin(); tit != techniques.constEnd(); ++tit )
71  {
72  auto renderPasses = ( *tit )->renderPasses();
73  for ( auto rpit = renderPasses.begin(); rpit != renderPasses.end(); ++rpit )
74  {
75  Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
76  cullFace->setMode( Qt3DRender::QCullFace::Back );
77  ( *rpit )->addRenderState( cullFace );
78  }
79  }
80 
81  material->setAmbient( symbol.material().ambient() );
82  material->setDiffuse( symbol.material().diffuse() );
83  material->setSpecular( symbol.material().specular() );
84  material->setShininess( symbol.material().shininess() );
85  return material;
86 }
87 
88 QgsMesh3DSymbolEntityNode::QgsMesh3DSymbolEntityNode( const Qgs3DMapSettings &map,
89  QgsMeshLayer *layer,
90  const QgsMesh3DSymbol &symbol,
91  Qt3DCore::QNode *parent ) : Qt3DCore::QEntity( parent )
92 {
93  addComponent( renderer( map, symbol, layer ) );
94 }
95 
96 Qt3DRender::QGeometryRenderer *QgsMesh3DSymbolEntityNode::renderer( const Qgs3DMapSettings &map,
97  const QgsMesh3DSymbol &symbol,
98  const QgsMeshLayer *layer )
99 {
100  QgsPointXY origin( map.origin().x(), map.origin().y() );
101  QList<QgsPolygon *> polygons;
102  QList<QgsFeatureId> fids;
103 
104  QgsExpressionContext ctx( _expressionContext3D() );
105  const QgsPropertyCollection &ddp = symbol.dataDefinedProperties();
106  bool hasDDHeight = ddp.isActive( QgsAbstract3DSymbol::PropertyHeight );
107  float height = symbol.height();
108  if ( hasDDHeight )
109  {
110  height = static_cast<float>( ddp.valueAsDouble( QgsAbstract3DSymbol::PropertyHeight,
111  ctx,
112  static_cast<double>( height )
113  )
114  );
115  }
116 
117  const QgsTriangularMesh *mesh = layer->triangularMesh();
118  if ( layer && mesh )
119  {
120  const QVector<QgsMeshFace> &triangles = mesh->triangles();
121  const QVector<QgsMeshVertex> &vertices = mesh->vertices();
122  for ( int i = 0; i < triangles.size(); ++i )
123  {
124  const QgsMeshFace &triangle = triangles.at( i );
125  Q_ASSERT( triangle.size() == 3 );
126  std::unique_ptr< QgsPolygon > polygon = QgsMeshUtils::toPolygon( triangle, vertices );
127  Qgs3DUtils::clampAltitudes( polygon.get(),
128  symbol.altitudeClamping(),
129  Qgs3DTypes::AltitudeBinding::AltBindVertex,
130  height,
131  map );
132  polygons.append( polygon.release() );
133  fids.append( i );
134  }
135  }
136 
137  // Polygons from mesh are already triangles, but
138  // call QgsTessellatedPolygonGeometry to
139  // use symbol settings for back faces, normals, etc
140  mGeometry = new QgsTessellatedPolygonGeometry;
141  mGeometry->setInvertNormals( false );
142  mGeometry->setAddBackFaces( symbol.addBackFaces() );
143  QList<float> extrusionHeightPerPolygon;
144  mGeometry->setPolygons( polygons, fids, origin, 0.0, extrusionHeightPerPolygon );
145 
146  Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
147  renderer->setGeometry( mGeometry );
148 
149  return renderer;
150 }
float shininess() const
Returns shininess of the surface.
Triangular/Derived Mesh is mesh with vertices in map coordinates.
3 3D symbol that draws mesh geometry as planar triangles.
void setInvertNormals(bool invert)
Sets whether the normals of triangles will be inverted (useful for fixing clockwise / counter-clockwi...
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...
QColor specular() const
Returns specular color component.
A class to represent a 2D point.
Definition: qgspointxy.h:43
float height() const
Returns height (altitude) of the symbol (in map units)
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer&#39;s property collection, used for data defined overrides...
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
double y() const
Returns Y coordinate.
Definition: qgsvector3d.h:51
3 Definition of the world
QgsVector3D origin() const
Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
bool addBackFaces() const
Returns whether also triangles facing the other side will be created.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
3 Class derived from Qt3DRender::QGeometry that represents polygons tessellated into 3D geometry...
CORE_EXPORT std::unique_ptr< QgsPolygon > toPolygon(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry, caller is responsible for delete.
QgsPhongMaterialSettings material() const
Returns material used for shading of the symbol.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:438
QVector< int > QgsMeshFace
List of vertex indexes.
QColor ambient() const
Returns ambient color component.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
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
QColor diffuse() const
Returns diffuse color component.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:90
Qgs3DTypes::AltitudeClamping altitudeClamping() const
Returns method that determines altitude (whether to clamp to feature to terrain)
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
QgsTriangularMesh * triangularMesh()
Returns triangular mesh (nullptr before rendering)
void setAmbient(const QColor &ambient)
Sets ambient color component.
double x() const
Returns X coordinate.
Definition: qgsvector3d.h:49