QGIS API Documentation 3.32.0-Lima (311a8cb8a6)
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 "qgspolygon.h"
30#include "qgsmeshlayer.h"
31#include "qgstriangularmesh.h"
34
35static QgsExpressionContext _expressionContext3D()
36{
40 return ctx;
41}
42
44
45QgsMesh3DSymbolEntity::QgsMesh3DSymbolEntity( const Qgs3DMapSettings &map,
46 QgsMeshLayer *layer,
47 const QgsMesh3DSymbol &symbol,
48 Qt3DCore::QNode *parent )
49 : Qt3DCore::QEntity( parent )
50{
51 // build the default material
52 Qt3DRender::QMaterial *mat = material( symbol );
53
54 // build a transform function
55 Qt3DCore::QTransform *tform = new Qt3DCore::QTransform;
56 tform->setTranslation( QVector3D( 0, 0, 0 ) );
57
58 // build the entity
59 QgsMesh3DSymbolEntityNode *entity = new QgsMesh3DSymbolEntityNode( map, layer, symbol );
60 entity->findChild<Qt3DRender::QGeometryRenderer *>()->setProperty( Qgs3DTypes::PROP_NAME_3D_RENDERER_FLAG, Qgs3DTypes::Main3DRenderer ); // temporary measure to distinguish between "selected" and "main"
61 entity->addComponent( mat );
62 entity->addComponent( tform );
63 entity->setParent( this );
64}
65
66Qt3DRender::QMaterial *QgsMesh3DSymbolEntity::material( const QgsMesh3DSymbol &symbol ) const
67{
68 const QgsMaterialContext context;
69 Qt3DRender::QMaterial *material = symbol.materialSettings()->toMaterial( QgsMaterialSettingsRenderingTechnique::Triangles, context );
70
71 // front/back side culling
72 const auto techniques = material->effect()->techniques();
73 for ( auto tit = techniques.constBegin(); tit != techniques.constEnd(); ++tit )
74 {
75 auto renderPasses = ( *tit )->renderPasses();
76 for ( auto rpit = renderPasses.begin(); rpit != renderPasses.end(); ++rpit )
77 {
78 Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace;
79 cullFace->setMode( Qt3DRender::QCullFace::Back );
80 ( *rpit )->addRenderState( cullFace );
81 }
82 }
83 return material;
84}
85
86QgsMesh3DSymbolEntityNode::QgsMesh3DSymbolEntityNode( const Qgs3DMapSettings &map,
87 QgsMeshLayer *layer,
88 const QgsMesh3DSymbol &symbol,
89 Qt3DCore::QNode *parent ) : Qt3DCore::QEntity( parent )
90{
91 addComponent( renderer( map, symbol, layer ) );
92}
93
94Qt3DRender::QGeometryRenderer *QgsMesh3DSymbolEntityNode::renderer( const Qgs3DMapSettings &map,
95 const QgsMesh3DSymbol &symbol,
96 const QgsMeshLayer *layer )
97{
98 const QgsPointXY origin( map.origin().x(), map.origin().y() );
99 QList<QgsPolygon *> polygons;
100 QList<QgsFeatureId> fids;
101
102 const QgsExpressionContext ctx( _expressionContext3D() );
103 const QgsPropertyCollection &ddp = symbol.dataDefinedProperties();
104 const bool hasDDHeight = ddp.isActive( QgsAbstract3DSymbol::PropertyHeight );
105 float height = symbol.height();
106 if ( hasDDHeight )
107 {
108 height = static_cast<float>( ddp.valueAsDouble( QgsAbstract3DSymbol::PropertyHeight,
109 ctx,
110 static_cast<double>( height )
111 )
112 );
113 }
114
115 const QgsTriangularMesh *mesh = layer->triangularMesh();
116 if ( mesh )
117 {
118 const QVector<QgsMeshFace> &triangles = mesh->triangles();
119 const QVector<QgsMeshVertex> &vertices = mesh->vertices();
120 for ( int i = 0; i < triangles.size(); ++i )
121 {
122 const QgsMeshFace &triangle = triangles.at( i );
123 Q_ASSERT( triangle.size() == 3 );
124 std::unique_ptr< QgsPolygon > polygon = QgsMeshUtils::toPolygon( triangle, vertices );
125 Qgs3DUtils::clampAltitudes( polygon.get(),
126 symbol.altitudeClamping(),
128 height,
129 map );
130 polygons.append( polygon.release() );
131 fids.append( i );
132 }
133 }
134
135 // Polygons from mesh are already triangles, but
136 // call QgsTessellatedPolygonGeometry to
137 // use symbol settings for back faces, normals, etc
138
139 const QgsPhongTexturedMaterialSettings *texturedMaterialSettings = dynamic_cast< const QgsPhongTexturedMaterialSettings * >( symbol.materialSettings() );
140
141 mGeometry = new QgsTessellatedPolygonGeometry( true, false, symbol.addBackFaces(), texturedMaterialSettings ? texturedMaterialSettings->requiresTextureCoordinates() : false );
142 const QList<float> extrusionHeightPerPolygon;
143 mGeometry->setPolygons( polygons, fids, origin, 0.0, extrusionHeightPerPolygon );
144
145 Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
146 renderer->setGeometry( mGeometry );
147
148 return renderer;
149}
@ Vertex
Clamp every vertex of feature.
QgsVector3D origin() const
Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
@ Main3DRenderer
Renderer for normal entities.
Definition: qgs3dtypes.h:49
static const char * PROP_NAME_3D_RENDERER_FLAG
Qt property name to hold the 3D geometry renderer flag.
Definition: qgs3dtypes.h:44
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:365
@ PropertyHeight
Height (altitude)
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer's property collection, used for data defined overrides.
virtual Qt3DRender::QMaterial * toMaterial(QgsMaterialSettingsRenderingTechnique technique, const QgsMaterialContext &context) const =0
Creates a new QMaterial object representing the material settings.
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.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsAbstractMaterialSettings * materialSettings() const
Returns material settings used for shading of the symbol.
Qgis::AltitudeClamping altitudeClamping() const
Returns method that determines altitude (whether to clamp to feature to terrain)
bool addBackFaces() const
Returns whether also triangles facing the other side will be created.
float height() const
Returns height (altitude) of the symbol (in map units)
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:100
QgsTriangularMesh * triangularMesh(double minimumTriangleSize=0) const
Returns triangular mesh (nullptr before rendering or calling to updateMesh).
bool requiresTextureCoordinates() const
Returns true if the material requires texture coordinates to be generated during triangulation....
A class to represent a 2D point.
Definition: qgspointxy.h:59
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:484
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
Triangular/Derived Mesh is mesh with vertices in map coordinates.
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
double y() const
Returns Y coordinate.
Definition: qgsvector3d.h:51
double x() const
Returns X coordinate.
Definition: qgsvector3d.h:49
@ Triangles
Triangle based rendering (default)
CORE_EXPORT std::unique_ptr< QgsPolygon > toPolygon(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry, caller is responsible for delete.
QVector< int > QgsMeshFace
List of vertex indexes.