18 #include <Qt3DRender/QAttribute>
19 #include <Qt3DRender/QBuffer>
20 #include <Qt3DRender/QEffect>
21 #include <Qt3DRender/QGraphicsApiFilter>
22 #include <Qt3DRender/QParameter>
23 #include <Qt3DRender/QTechnique>
25 #include <Qt3DExtras/QCylinderGeometry>
26 #include <Qt3DExtras/QConeGeometry>
27 #include <Qt3DExtras/QCuboidGeometry>
28 #include <Qt3DExtras/QPlaneGeometry>
29 #include <Qt3DExtras/QSphereGeometry>
30 #include <Qt3DExtras/QTorusGeometry>
31 #include <Qt3DExtras/QPhongMaterial>
32 #include <Qt3DRender/QSceneLoader>
33 #include <Qt3DRender/QPaintedTextureImage>
35 #include <Qt3DRender/QMesh>
37 #if QT_VERSION >= 0x050900
38 #include <Qt3DExtras/QExtrudedTextGeometry>
63 class QgsInstancedPoint3DSymbolHandler :
public QgsFeature3DHandler
67 : mSymbol( symbol ), mSelectedIds( selectedIds ) {}
69 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
70 void processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
71 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
76 static Qt3DRender::QGeometryRenderer *renderer(
const QgsPoint3DSymbol &symbol,
const QVector<QVector3D> &positions );
77 static Qt3DRender::QGeometry *symbolGeometry(
QgsPoint3DSymbol::Shape shape,
const QVariantMap &shapeProperties );
82 QVector<QVector3D> positions;
85 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
94 PointData outSelected;
98 bool QgsInstancedPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
101 Q_UNUSED( attributeNames )
105 void QgsInstancedPoint3DSymbolHandler::processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
107 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
115 void QgsInstancedPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
117 makeEntity( parent, context, outNormal,
false );
118 makeEntity( parent, context, outSelected,
true );
120 updateZRangeFromPositions( outNormal.positions );
121 updateZRangeFromPositions( outSelected.positions );
124 float symbolHeight = mSymbol.transform().data()[13];
125 mZMin += symbolHeight;
126 mZMax += symbolHeight;
129 void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
132 Qt3DRender::QMaterial *mat = material( mSymbol );
137 for ( Qt3DRender::QParameter *param : mat->effect()->parameters() )
139 if ( param->name() == QLatin1String(
"kd" ) )
140 param->setValue( context.map().selectionColor() );
141 else if ( param->name() == QLatin1String(
"ka" ) )
142 param->setValue( context.map().selectionColor().darker() );
147 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
148 entity->addComponent( renderer( mSymbol, out.positions ) );
149 entity->addComponent( mat );
150 entity->setParent( parent );
158 Qt3DRender::QMaterial *QgsInstancedPoint3DSymbolHandler::material(
const QgsPoint3DSymbol &symbol )
160 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
161 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
162 filterKey->setValue(
"forward" );
167 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram;
168 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/instanced.vert" ) ) ) );
169 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/instanced.frag" ) ) ) );
171 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass;
172 renderPass->setShaderProgram( shaderProgram );
174 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
175 technique->addFilterKey( filterKey );
176 technique->addRenderPass( renderPass );
177 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
178 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
179 technique->graphicsApiFilter()->setMajorVersion( 3 );
180 technique->graphicsApiFilter()->setMinorVersion( 2 );
182 Qt3DRender::QParameter *ambientParameter =
new Qt3DRender::QParameter( QStringLiteral(
"ka" ), QColor::fromRgbF( 0.05f, 0.05f, 0.05f, 1.0f ) );
183 Qt3DRender::QParameter *diffuseParameter =
new Qt3DRender::QParameter( QStringLiteral(
"kd" ), QColor::fromRgbF( 0.7f, 0.7f, 0.7f, 1.0f ) );
184 Qt3DRender::QParameter *specularParameter =
new Qt3DRender::QParameter( QStringLiteral(
"ks" ), QColor::fromRgbF( 0.01f, 0.01f, 0.01f, 1.0f ) );
185 Qt3DRender::QParameter *shininessParameter =
new Qt3DRender::QParameter( QStringLiteral(
"shininess" ), 150.0f );
192 QMatrix4x4 transformMatrix = symbol.
transform();
193 QMatrix3x3 normalMatrix = transformMatrix.normalMatrix();
196 float *n = normalMatrix.data();
197 QMatrix4x4 normalMatrix4(
203 Qt3DRender::QParameter *paramInst =
new Qt3DRender::QParameter;
204 paramInst->setName( QStringLiteral(
"inst" ) );
205 paramInst->setValue( transformMatrix );
207 Qt3DRender::QParameter *paramInstNormal =
new Qt3DRender::QParameter;
208 paramInstNormal->setName( QStringLiteral(
"instNormal" ) );
209 paramInstNormal->setValue( normalMatrix4 );
211 Qt3DRender::QEffect *effect =
new Qt3DRender::QEffect;
212 effect->addTechnique( technique );
213 effect->addParameter( paramInst );
214 effect->addParameter( paramInstNormal );
216 effect->addParameter( ambientParameter );
217 effect->addParameter( diffuseParameter );
218 effect->addParameter( specularParameter );
219 effect->addParameter( shininessParameter );
221 Qt3DRender::QMaterial *material =
new Qt3DRender::QMaterial;
222 material->setEffect( effect );
227 Qt3DRender::QGeometryRenderer *QgsInstancedPoint3DSymbolHandler::renderer(
const QgsPoint3DSymbol &symbol,
const QVector<QVector3D> &positions )
229 int count = positions.count();
230 int byteCount = positions.count() *
sizeof( QVector3D );
232 ba.resize( byteCount );
233 memcpy( ba.data(), positions.constData(), byteCount );
235 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
236 Qt3DRender::QBuffer *instanceBuffer =
new Qt3DRender::QBuffer( Qt3DRender::QBuffer::VertexBuffer );
238 Qt3DRender::QBuffer *instanceBuffer =
new Qt3DRender::QBuffer();
240 instanceBuffer->setData( ba );
242 Qt3DRender::QAttribute *instanceDataAttribute =
new Qt3DRender::QAttribute;
243 instanceDataAttribute->setName( QStringLiteral(
"pos" ) );
244 instanceDataAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
245 instanceDataAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
246 instanceDataAttribute->setVertexSize( 3 );
247 instanceDataAttribute->setDivisor( 1 );
248 instanceDataAttribute->setBuffer( instanceBuffer );
249 instanceDataAttribute->setCount( count );
250 instanceDataAttribute->setByteStride( 3 *
sizeof(
float ) );
253 geometry->addAttribute( instanceDataAttribute );
254 geometry->setBoundingVolumePositionAttribute( instanceDataAttribute );
256 Qt3DRender::QGeometryRenderer *renderer =
new Qt3DRender::QGeometryRenderer;
257 renderer->setGeometry( geometry );
258 renderer->setInstanceCount( count );
263 Qt3DRender::QGeometry *QgsInstancedPoint3DSymbolHandler::symbolGeometry(
QgsPoint3DSymbol::Shape shape,
const QVariantMap &shapeProperties )
269 float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
270 float length = shapeProperties[QStringLiteral(
"length" )].toFloat();
271 Qt3DExtras::QCylinderGeometry *g =
new Qt3DExtras::QCylinderGeometry;
274 g->setRadius( radius ? radius : 10 );
275 g->setLength( length ? length : 10 );
281 float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
282 Qt3DExtras::QSphereGeometry *g =
new Qt3DExtras::QSphereGeometry;
283 g->setRadius( radius ? radius : 10 );
289 float length = shapeProperties[QStringLiteral(
"length" )].toFloat();
290 float bottomRadius = shapeProperties[QStringLiteral(
"bottomRadius" )].toFloat();
291 float topRadius = shapeProperties[QStringLiteral(
"topRadius" )].toFloat();
292 Qt3DExtras::QConeGeometry *g =
new Qt3DExtras::QConeGeometry;
293 g->setLength( length ? length : 10 );
294 g->setBottomRadius( bottomRadius );
295 g->setTopRadius( topRadius );
303 float size = shapeProperties[QStringLiteral(
"size" )].toFloat();
304 Qt3DExtras::QCuboidGeometry *g =
new Qt3DExtras::QCuboidGeometry;
305 g->setXExtent( size ? size : 10 );
306 g->setYExtent( size ? size : 10 );
307 g->setZExtent( size ? size : 10 );
313 float radius = shapeProperties[QStringLiteral(
"radius" )].toFloat();
314 float minorRadius = shapeProperties[QStringLiteral(
"minorRadius" )].toFloat();
315 Qt3DExtras::QTorusGeometry *g =
new Qt3DExtras::QTorusGeometry;
316 g->setRadius( radius ? radius : 10 );
317 g->setMinorRadius( minorRadius ? minorRadius : 5 );
323 float size = shapeProperties[QStringLiteral(
"size" )].toFloat();
324 Qt3DExtras::QPlaneGeometry *g =
new Qt3DExtras::QPlaneGeometry;
325 g->setWidth( size ? size : 10 );
326 g->setHeight( size ? size : 10 );
330 #if QT_VERSION >= 0x050900
333 float depth = shapeProperties[QStringLiteral(
"depth" )].toFloat();
334 QString text = shapeProperties[QStringLiteral(
"text" )].toString();
335 Qt3DExtras::QExtrudedTextGeometry *g =
new Qt3DExtras::QExtrudedTextGeometry;
336 g->setDepth( depth ? depth : 1 );
351 class QgsModelPoint3DSymbolHandler :
public QgsFeature3DHandler
355 : mSymbol( symbol ), mSelectedIds( selectedIds ) {}
357 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
358 void processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
359 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
363 static void addSceneEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol &symbol, Qt3DCore::QEntity *parent );
364 static void addMeshEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol &symbol, Qt3DCore::QEntity *parent,
bool are_selected );
365 static Qt3DCore::QTransform *transform( QVector3D position,
const QgsPoint3DSymbol &symbol );
370 QVector<QVector3D> positions;
373 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
382 PointData outSelected;
385 bool QgsModelPoint3DSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
388 Q_UNUSED( attributeNames )
392 void QgsModelPoint3DSymbolHandler::processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
394 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
402 void QgsModelPoint3DSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
404 makeEntity( parent, context, outNormal,
false );
405 makeEntity( parent, context, outSelected,
true );
407 updateZRangeFromPositions( outNormal.positions );
408 updateZRangeFromPositions( outSelected.positions );
411 float symbolHeight = mSymbol.transform().data()[13];
412 mZMin += symbolHeight;
413 mZMax += symbolHeight;
416 void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
420 addMeshEntities( context.map(), out.positions, mSymbol, parent,
true );
424 if ( mSymbol.shapeProperties()[QStringLiteral(
"overwriteMaterial" )].toBool() )
426 addMeshEntities( context.map(), out.positions, mSymbol, parent,
false );
430 addSceneEntities( context.map(), out.positions, mSymbol, parent );
437 void QgsModelPoint3DSymbolHandler::addSceneEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol &symbol, Qt3DCore::QEntity *parent )
440 for (
const QVector3D &position : positions )
443 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
445 QUrl url = QUrl::fromLocalFile( symbol.
shapeProperties()[QStringLiteral(
"model" )].toString() );
446 Qt3DRender::QSceneLoader *modelLoader =
new Qt3DRender::QSceneLoader;
447 modelLoader->setSource( url );
449 entity->addComponent( modelLoader );
450 entity->addComponent( transform( position, symbol ) );
451 entity->setParent( parent );
458 void QgsModelPoint3DSymbolHandler::addMeshEntities(
const Qgs3DMapSettings &map,
const QVector<QVector3D> &positions,
const QgsPoint3DSymbol &symbol, Qt3DCore::QEntity *parent,
bool are_selected )
470 for (
const QVector3D &position : positions )
473 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
475 QUrl url = QUrl::fromLocalFile( symbol.
shapeProperties()[QStringLiteral(
"model" )].toString() );
476 Qt3DRender::QMesh *mesh =
new Qt3DRender::QMesh;
477 mesh->setSource( url );
479 entity->addComponent( mesh );
480 entity->addComponent( mat );
481 entity->addComponent( transform( position, symbol ) );
482 entity->setParent( parent );
489 Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position,
const QgsPoint3DSymbol &symbol )
491 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
493 tr->setTranslation( position + tr->translation() );
501 class QgsPoint3DBillboardSymbolHandler :
public QgsFeature3DHandler
505 : mSymbol( symbol ), mSelectedIds( selectedIds ) {}
507 bool prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
override;
508 void processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
override;
509 void finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
override;
516 QVector<QVector3D> positions;
519 void makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected );
528 PointData outSelected;
531 bool QgsPoint3DBillboardSymbolHandler::prepare(
const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
534 Q_UNUSED( attributeNames )
538 void QgsPoint3DBillboardSymbolHandler::processFeature(
QgsFeature &feature,
const Qgs3DRenderContext &context )
540 PointData &out = mSelectedIds.contains( feature.
id() ) ? outSelected : outNormal;
548 void QgsPoint3DBillboardSymbolHandler::finalize( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context )
550 makeEntity( parent, context, outNormal,
false );
551 makeEntity( parent, context, outSelected,
true );
553 updateZRangeFromPositions( outNormal.positions );
554 updateZRangeFromPositions( outSelected.positions );
557 float billboardHeight = mSymbol.transform().data()[13];
558 mZMin += billboardHeight;
559 mZMax += billboardHeight;
562 void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const Qgs3DRenderContext &context, PointData &out,
bool selected )
566 billboardGeometry->
setPoints( out.positions );
569 Qt3DRender::QGeometryRenderer *billboardGeometryRenderer =
new Qt3DRender::QGeometryRenderer;
570 billboardGeometryRenderer->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
571 billboardGeometryRenderer->setGeometry( billboardGeometry );
572 billboardGeometryRenderer->setVertexCount( billboardGeometry->
count() );
588 Qt3DCore::QTransform *billboardTransform =
new Qt3DCore::QTransform();
589 billboardTransform->setMatrix( mSymbol.billboardTransform() );
592 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
594 entity->addComponent( billboardMaterial );
595 entity->addComponent( billboardTransform );
596 entity->addComponent( billboardGeometryRenderer );
597 entity->setParent( parent );
604 namespace Qgs3DSymbolImpl
620 QgsFeature3DHandler *handler = handlerForPoint3DSymbol( layer, symbol );
621 Qt3DCore::QEntity *e = entityFromHandler( handler, map, layer );