Skip to content

Commit a4e3a77

Browse files
pblottierewonder-sk
authored andcommitted
Encapsulate entities for selected/not selected points in a root entity
1 parent b0c98b7 commit a4e3a77

File tree

7 files changed

+133
-134
lines changed

7 files changed

+133
-134
lines changed

src/3d/pointentity.cpp

Lines changed: 114 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -32,36 +32,131 @@
3232
PointEntity::PointEntity( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol, Qt3DCore::QNode *parent )
3333
: Qt3DCore::QEntity( parent )
3434
{
35-
QgsFeatureRequest request;
36-
request.setDestinationCrs( map.crs );
37-
QList<QVector3D> pos = positions( map, layer, request );
35+
addEntityForSelectedPoints( map, layer, symbol );
36+
addEntityForNotSelectedPoints( map, layer, symbol );
37+
}
3838

39-
addComponent( renderer( symbol, pos ) );
40-
addComponent( material( map, symbol ) );
39+
Qt3DRender::QMaterial *PointEntity::material( const Point3DSymbol &symbol ) const
40+
{
41+
Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey;
42+
filterKey->setName( "renderingStyle" );
43+
filterKey->setValue( "forward" );
44+
45+
// the fragment shader implements a simplified version of phong shading that uses hardcoded light
46+
// (instead of whatever light we have defined in the scene)
47+
// TODO: use phong shading that respects lights from the scene
48+
Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram;
49+
shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( "qrc:/shaders/instanced.vert" ) ) );
50+
shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( "qrc:/shaders/instanced.frag" ) ) );
51+
52+
Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass;
53+
renderPass->setShaderProgram( shaderProgram );
54+
55+
Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
56+
technique->addFilterKey( filterKey );
57+
technique->addRenderPass( renderPass );
58+
technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
59+
technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
60+
technique->graphicsApiFilter()->setMajorVersion( 3 );
61+
technique->graphicsApiFilter()->setMinorVersion( 2 );
62+
63+
Qt3DRender::QParameter *ambientParameter = new Qt3DRender::QParameter( QStringLiteral( "ka" ), QColor::fromRgbF( 0.05f, 0.05f, 0.05f, 1.0f ) );
64+
Qt3DRender::QParameter *diffuseParameter = new Qt3DRender::QParameter( QStringLiteral( "kd" ), QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) );
65+
Qt3DRender::QParameter *specularParameter = new Qt3DRender::QParameter( QStringLiteral( "ks" ), QColor::fromRgbF( 0.01f, 0.01f, 0.01f, 1.0f ) );
66+
Qt3DRender::QParameter *shininessParameter = new Qt3DRender::QParameter( QStringLiteral( "shininess" ), 150.0f );
67+
68+
diffuseParameter->setValue( symbol.material.diffuse() );
69+
ambientParameter->setValue( symbol.material.ambient() );
70+
specularParameter->setValue( symbol.material.specular() );
71+
shininessParameter->setValue( symbol.material.shininess() );
72+
73+
QMatrix4x4 transformMatrix = symbol.transform;
74+
QMatrix3x3 normalMatrix = transformMatrix.normalMatrix(); // transponed inverse of 3x3 sub-matrix
75+
76+
// QMatrix3x3 is not supported for passing to shaders, so we pass QMatrix4x4
77+
float *n = normalMatrix.data();
78+
QMatrix4x4 normalMatrix4(
79+
n[0], n[3], n[6], 0,
80+
n[1], n[4], n[7], 0,
81+
n[2], n[5], n[8], 0,
82+
0, 0, 0, 0 );
83+
84+
Qt3DRender::QParameter *paramInst = new Qt3DRender::QParameter;
85+
paramInst->setName( "inst" );
86+
paramInst->setValue( transformMatrix );
87+
88+
Qt3DRender::QParameter *paramInstNormal = new Qt3DRender::QParameter;
89+
paramInstNormal->setName( "instNormal" );
90+
paramInstNormal->setValue( normalMatrix4 );
91+
92+
Qt3DRender::QEffect *effect = new Qt3DRender::QEffect;
93+
effect->addTechnique( technique );
94+
effect->addParameter( paramInst );
95+
effect->addParameter( paramInstNormal );
96+
97+
effect->addParameter( ambientParameter );
98+
effect->addParameter( diffuseParameter );
99+
effect->addParameter( specularParameter );
100+
effect->addParameter( shininessParameter );
101+
102+
Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial;
103+
material->setEffect( effect );
104+
105+
return material;
41106
}
42107

43-
PointEntity::PointEntity( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol, bool sel, Qt3DCore::QNode *parent )
44-
: Qt3DCore::QEntity( parent )
108+
void PointEntity::addEntityForSelectedPoints( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol )
45109
{
46-
QgsFeatureRequest request;
47-
request.setDestinationCrs( map.crs );
110+
// build the default material
111+
Qt3DRender::QMaterial *mat = material( symbol );
48112

49-
if ( sel )
50-
request.setFilterFids( layer->selectedFeatureIds() );
51-
else
113+
// update the material with selection colors
114+
Q_FOREACH ( Qt3DRender::QParameter *param, mat->effect()->parameters() )
52115
{
53-
QgsFeatureIds notSelected = layer->allFeatureIds();
54-
notSelected.subtract( layer->selectedFeatureIds() );
55-
request.setFilterFids( notSelected );
116+
if ( param->name() == "kd" ) // diffuse
117+
param->setValue( map.selectionColor() );
118+
else if ( param->name() == "ka" ) // ambient
119+
param->setValue( map.selectionColor().darker() );
56120
}
57121

58-
QList<QVector3D> pos = positions( map, layer, request );
122+
// build the feature request to select features
123+
QgsFeatureRequest req;
124+
req.setDestinationCrs( map.crs );
125+
req.setFilterFids( layer->selectedFeatureIds() );
126+
127+
// build the entity
128+
PointEntityNode *entity = new PointEntityNode( map, layer, symbol, req );
129+
entity->addComponent( mat );
130+
entity->setParent( this );
131+
}
132+
133+
void PointEntity::addEntityForNotSelectedPoints( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol )
134+
{
135+
// build the default material
136+
Qt3DRender::QMaterial *mat = material( symbol );
137+
138+
// build the feature request to select features
139+
QgsFeatureRequest req;
140+
req.setDestinationCrs( map.crs );
141+
142+
QgsFeatureIds notSelected = layer->allFeatureIds();
143+
notSelected.subtract( layer->selectedFeatureIds() );
144+
req.setFilterFids( notSelected );
59145

146+
// build the entity
147+
PointEntityNode *entity = new PointEntityNode( map, layer, symbol, req );
148+
entity->addComponent( mat );
149+
entity->setParent( this );
150+
}
151+
152+
PointEntityNode::PointEntityNode( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol, const QgsFeatureRequest &req, Qt3DCore::QNode *parent )
153+
: Qt3DCore::QEntity( parent )
154+
{
155+
QList<QVector3D> pos = positions( map, layer, req );
60156
addComponent( renderer( symbol, pos ) );
61-
addComponent( material( map, symbol, sel ) );
62157
}
63158

64-
Qt3DRender::QGeometryRenderer *PointEntity::renderer( const Point3DSymbol &symbol, const QList<QVector3D> &positions ) const
159+
Qt3DRender::QGeometryRenderer *PointEntityNode::renderer( const Point3DSymbol &symbol, const QList<QVector3D> &positions ) const
65160
{
66161
int count = positions.count();
67162

@@ -168,82 +263,7 @@ Qt3DRender::QGeometryRenderer *PointEntity::renderer( const Point3DSymbol &symbo
168263
return renderer;
169264
}
170265

171-
Qt3DRender::QMaterial *PointEntity::material( const Map3D &map, const Point3DSymbol &symbol, bool sel ) const
172-
{
173-
Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey;
174-
filterKey->setName( "renderingStyle" );
175-
filterKey->setValue( "forward" );
176-
177-
// the fragment shader implements a simplified version of phong shading that uses hardcoded light
178-
// (instead of whatever light we have defined in the scene)
179-
// TODO: use phong shading that respects lights from the scene
180-
Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram;
181-
shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( "qrc:/shaders/instanced.vert" ) ) );
182-
shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( "qrc:/shaders/instanced.frag" ) ) );
183-
184-
Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass;
185-
renderPass->setShaderProgram( shaderProgram );
186-
187-
Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
188-
technique->addFilterKey( filterKey );
189-
technique->addRenderPass( renderPass );
190-
technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
191-
technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
192-
technique->graphicsApiFilter()->setMajorVersion( 3 );
193-
technique->graphicsApiFilter()->setMinorVersion( 2 );
194-
195-
Qt3DRender::QParameter *ambientParameter = new Qt3DRender::QParameter( QStringLiteral( "ka" ), QColor::fromRgbF( 0.05f, 0.05f, 0.05f, 1.0f ) );
196-
Qt3DRender::QParameter *diffuseParameter = new Qt3DRender::QParameter( QStringLiteral( "kd" ), QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) );
197-
Qt3DRender::QParameter *specularParameter = new Qt3DRender::QParameter( QStringLiteral( "ks" ), QColor::fromRgbF( 0.01f, 0.01f, 0.01f, 1.0f ) );
198-
Qt3DRender::QParameter *shininessParameter = new Qt3DRender::QParameter( QStringLiteral( "shininess" ), 150.0f );
199-
200-
diffuseParameter->setValue( symbol.material.diffuse() );
201-
ambientParameter->setValue( symbol.material.ambient() );
202-
specularParameter->setValue( symbol.material.specular() );
203-
shininessParameter->setValue( symbol.material.shininess() );
204-
205-
if ( sel )
206-
{
207-
diffuseParameter->setValue( map.selectionColor() );
208-
ambientParameter->setValue( map.selectionColor().darker() );
209-
}
210-
211-
QMatrix4x4 transformMatrix = symbol.transform;
212-
QMatrix3x3 normalMatrix = transformMatrix.normalMatrix(); // transponed inverse of 3x3 sub-matrix
213-
214-
// QMatrix3x3 is not supported for passing to shaders, so we pass QMatrix4x4
215-
float *n = normalMatrix.data();
216-
QMatrix4x4 normalMatrix4(
217-
n[0], n[3], n[6], 0,
218-
n[1], n[4], n[7], 0,
219-
n[2], n[5], n[8], 0,
220-
0, 0, 0, 0 );
221-
222-
Qt3DRender::QParameter *paramInst = new Qt3DRender::QParameter;
223-
paramInst->setName( "inst" );
224-
paramInst->setValue( transformMatrix );
225-
226-
Qt3DRender::QParameter *paramInstNormal = new Qt3DRender::QParameter;
227-
paramInstNormal->setName( "instNormal" );
228-
paramInstNormal->setValue( normalMatrix4 );
229-
230-
Qt3DRender::QEffect *effect = new Qt3DRender::QEffect;
231-
effect->addTechnique( technique );
232-
effect->addParameter( paramInst );
233-
effect->addParameter( paramInstNormal );
234-
235-
effect->addParameter( ambientParameter );
236-
effect->addParameter( diffuseParameter );
237-
effect->addParameter( specularParameter );
238-
effect->addParameter( shininessParameter );
239-
240-
Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial;
241-
material->setEffect( effect );
242-
243-
return material;
244-
}
245-
246-
QList<QVector3D> PointEntity::positions( const Map3D &map, const QgsVectorLayer *layer, const QgsFeatureRequest &request ) const
266+
QList<QVector3D> PointEntityNode::positions( const Map3D &map, const QgsVectorLayer *layer, const QgsFeatureRequest &request ) const
247267
{
248268
QList<QVector3D> positions;
249269
QgsFeature f;

src/3d/pointentity.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,20 @@ class PointEntity : public Qt3DCore::QEntity
1818
public:
1919
PointEntity( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol, Qt3DCore::QNode *parent = nullptr );
2020

21-
PointEntity( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol, bool sel, Qt3DCore::QNode *parent = nullptr );
21+
private:
22+
void addEntityForSelectedPoints( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol );
23+
void addEntityForNotSelectedPoints( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol );
24+
25+
Qt3DRender::QMaterial *material( const Point3DSymbol &symbol ) const;
26+
};
27+
28+
class PointEntityNode : public Qt3DCore::QEntity
29+
{
30+
public:
31+
PointEntityNode( const Map3D &map, QgsVectorLayer *layer, const Point3DSymbol &symbol, const QgsFeatureRequest &req, Qt3DCore::QNode *parent = nullptr );
2232

2333
private:
2434
Qt3DRender::QGeometryRenderer *renderer( const Point3DSymbol &symbol, const QList<QVector3D> &positions ) const;
25-
Qt3DRender::QMaterial *material( const Map3D &map, const Point3DSymbol &symbol, bool sel = false ) const;
2635
QList<QVector3D> positions( const Map3D &map, const QgsVectorLayer *layer, const QgsFeatureRequest &req ) const;
2736
};
2837

src/3d/scene.cpp

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,8 @@ Scene::Scene( const Map3D &map, Qt3DExtras::QForwardRenderer *defaultFrameGraph,
7272

7373
Q_FOREACH ( const QgsAbstract3DRenderer *renderer, map.renderers )
7474
{
75-
QList<Qt3DCore::QEntity *> entities = renderer->createEntities( map );
76-
77-
Q_FOREACH ( Qt3DCore::QEntity *entity, entities )
78-
entity->setParent( this );
75+
Qt3DCore::QEntity *newEntity = renderer->createEntity( map );
76+
newEntity->setParent( this );
7977
}
8078

8179
// listen to changes of layers in order to add/remove 3D renderer entities
@@ -282,13 +280,9 @@ void Scene::addLayerEntity( QgsMapLayer *layer )
282280
QgsAbstract3DRenderer *renderer = layer->renderer3D();
283281
if ( renderer )
284282
{
285-
QList<Qt3DCore::QEntity *> entities = renderer->createEntities( mMap );
286-
287-
Q_FOREACH ( Qt3DCore::QEntity *entity, entities )
288-
{
289-
entity->setParent( this );
290-
mLayerEntities.insert( layer, entity );
291-
}
283+
Qt3DCore::QEntity *newEntity = renderer->createEntity( mMap );
284+
newEntity->setParent( this );
285+
mLayerEntities.insert( layer, newEntity );
292286
}
293287

294288
connect( layer, &QgsMapLayer::renderer3DChanged, this, &Scene::onLayerRenderer3DChanged );
@@ -302,8 +296,8 @@ void Scene::addLayerEntity( QgsMapLayer *layer )
302296

303297
void Scene::removeLayerEntity( QgsMapLayer *layer )
304298
{
305-
Qt3DCore::QEntity *entity;
306-
while ( ( entity = mLayerEntities.take( layer ) ) )
299+
Qt3DCore::QEntity *entity = mLayerEntities.take( layer );
300+
if ( entity )
307301
entity->deleteLater();
308302

309303
disconnect( layer, &QgsMapLayer::renderer3DChanged, this, &Scene::onLayerRenderer3DChanged );

src/3d/scene.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class _3D_EXPORT Scene : public Qt3DCore::QEntity
6262
Qt3DExtras::QForwardRenderer *mForwardRenderer;
6363
QList<ChunkedEntity *> chunkEntities;
6464
//! Keeps track of entities that belong to a particular layer
65-
QMultiMap<QgsMapLayer *, Qt3DCore::QEntity *> mLayerEntities;
65+
QMap<QgsMapLayer *, Qt3DCore::QEntity *> mLayerEntities;
6666
bool mTerrainUpdateScheduled = false;
6767
};
6868

src/3d/vectorlayer3drenderer.cpp

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -78,28 +78,6 @@ Qt3DCore::QEntity *VectorLayer3DRenderer::createEntity( const Map3D &map ) const
7878
return nullptr;
7979
}
8080

81-
QList<Qt3DCore::QEntity *> VectorLayer3DRenderer::createEntities( const Map3D &map ) const
82-
{
83-
QList<Qt3DCore::QEntity *> entities;
84-
85-
QgsVectorLayer *vl = layer();
86-
87-
if ( !mSymbol || !vl )
88-
return entities;
89-
90-
if ( mSymbol->type() == "polygon" )
91-
entities.append( new PolygonEntity( map, vl, *static_cast<Polygon3DSymbol *>( mSymbol.get() ) ) );
92-
else if ( mSymbol->type() == "point" )
93-
{
94-
entities.append( new PointEntity( map, vl, *static_cast<Point3DSymbol *>( mSymbol.get() ), false ) );
95-
entities.append( new PointEntity( map, vl, *static_cast<Point3DSymbol *>( mSymbol.get() ), true ) );
96-
}
97-
else if ( mSymbol->type() == "line" )
98-
entities.append( new LineEntity( map, vl, *static_cast<Line3DSymbol *>( mSymbol.get() ) ) );
99-
100-
return entities;
101-
}
102-
10381
void VectorLayer3DRenderer::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
10482
{
10583
QDomDocument doc = elem.ownerDocument();

src/3d/vectorlayer3drenderer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ class _3D_EXPORT VectorLayer3DRenderer : public QgsAbstract3DRenderer
4848
QString type() const override { return "vector"; }
4949
VectorLayer3DRenderer *clone() const override;
5050
Qt3DCore::QEntity *createEntity( const Map3D &map ) const override;
51-
QList<Qt3DCore::QEntity *> createEntities( const Map3D &map ) const override;
5251

5352
void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const override;
5453
void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) override;

src/core/3d/qgsabstract3drenderer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ class CORE_EXPORT QgsAbstract3DRenderer //: public QObject
2525
virtual QString type() const = 0;
2626
virtual QgsAbstract3DRenderer *clone() const = 0;
2727
virtual Qt3DCore::QEntity *createEntity( const Map3D &map ) const = 0;
28-
virtual QList<Qt3DCore::QEntity *> createEntities( const Map3D &map ) const = 0;
2928

3029
virtual void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const = 0;
3130
virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context ) = 0;

0 commit comments

Comments
 (0)