19 #include <Qt3DCore/QEntity> 
   20 #include <Qt3DCore/QComponent> 
   21 #include <Qt3DCore/QNode> 
   22 #include <Qt3DRender/QGeometry> 
   23 #include <Qt3DRender/QAttribute> 
   24 #include <Qt3DRender/QBuffer> 
   25 #include <Qt3DRender/QGeometryRenderer> 
   26 #include <Qt3DExtras/QPlaneGeometry> 
   27 #include <Qt3DCore/QTransform> 
   28 #include <Qt3DRender/QMaterial> 
   29 #include <Qt3DExtras/QDiffuseSpecularMaterial> 
   30 #include <Qt3DExtras/QTextureMaterial> 
   31 #include <Qt3DRender/QTextureImage> 
   32 #include <Qt3DRender/QTexture> 
   33 #include <Qt3DRender/QBufferDataGenerator> 
   34 #include <Qt3DRender/QBufferDataGeneratorPtr> 
   35 #include <Qt3DRender/QMesh> 
   36 #include <Qt3DRender/QSceneLoader> 
   37 #include <Qt3DRender/QAbstractTexture> 
   38 #include <Qt3DExtras/QCylinderGeometry> 
   39 #include <Qt3DExtras/QConeGeometry> 
   40 #include <Qt3DExtras/QSphereGeometry> 
   41 #include <Qt3DExtras/QCuboidGeometry> 
   42 #include <Qt3DExtras/QTorusGeometry> 
   43 #include <Qt3DExtras/QExtrudedTextMesh> 
   44 #include <Qt3DExtras/QPhongMaterial> 
   45 #include <Qt3DRender/QAbstractTextureImage> 
   49 #include <QTextStream> 
   64 #include "qgsmesh3dgeometry_p.h" 
   66 #include "qgsmesh3dentity_p.h" 
   67 #include "qgsmeshterraingenerator.h" 
   83 QVector<T> 
getAttributeData( Qt3DRender::QAttribute *attribute, 
const QByteArray &data )
 
   85   const uint bytesOffset = attribute->byteOffset();
 
   86   const uint bytesStride = attribute->byteStride();
 
   87   const uint vertexSize = attribute->vertexSize();
 
   90   if ( bytesStride == 0 )
 
   92     QgsDebugMsg( 
"bytesStride==0, the attribute probably was not set properly" );
 
   96   const char *pData = data.constData();
 
   97   for ( 
int i = bytesOffset; i < data.size(); i += bytesStride )
 
   99     for ( 
unsigned int j = 0; j < vertexSize * 
sizeof( T ); j += 
sizeof( T ) )
 
  102       memcpy( &v, pData + i + j, 
sizeof( T ) );
 
  103       result.push_back( v );
 
  112   QVector<uint> result;
 
  113   const char *pData = data.constData();
 
  114   for ( 
int i = 0; i < data.size(); i += 
sizeof( T ) )
 
  117     memcpy( &v, pData + i, 
sizeof( T ) );
 
  118     result.push_back( ( uint ) v );
 
  123 QVector<uint> 
getIndexData( Qt3DRender::QAttribute *indexAttribute, 
const QByteArray &data )
 
  125   switch ( indexAttribute->vertexBaseType() )
 
  127     case Qt3DRender::QAttribute::VertexBaseType::Int:
 
  128       return _getIndexDataImplementation<int>( data );
 
  129     case Qt3DRender::QAttribute::VertexBaseType::UnsignedInt:
 
  130       return _getIndexDataImplementation<uint>( data );
 
  131     case Qt3DRender::QAttribute::VertexBaseType::Short:
 
  132       return _getIndexDataImplementation<short>( data );
 
  133     case Qt3DRender::QAttribute::VertexBaseType::UnsignedShort:
 
  134       return _getIndexDataImplementation<ushort>( data );
 
  135     case Qt3DRender::QAttribute::VertexBaseType::Byte:
 
  136       return _getIndexDataImplementation<char>( data );
 
  137     case Qt3DRender::QAttribute::VertexBaseType::UnsignedByte:
 
  138       return _getIndexDataImplementation<uchar>( data );
 
  140       QgsDebugMsg( 
"Probably trying to get index data using an attribute that has vertex data" );
 
  143   return QVector<uint>();
 
  146 QByteArray 
getData( Qt3DRender::QBuffer *buffer )
 
  148   QByteArray bytes = buffer->data();
 
  149   if ( bytes.isNull() )
 
  156 Qt3DRender::QAttribute *
findAttribute( Qt3DRender::QGeometry *geometry, 
const QString &name, Qt3DRender::QAttribute::AttributeType type )
 
  158   for ( Qt3DRender::QAttribute *attribute : geometry->attributes() )
 
  160     if ( attribute->attributeType() != type ) 
continue;
 
  161     if ( attribute->name() == name ) 
return attribute;
 
  166 template<
typename Component>
 
  169   if ( entity == 
nullptr ) 
return nullptr;
 
  170   for ( Qt3DCore::QComponent *component : entity->components() )
 
  172     Component *typedComponent = qobject_cast<Component *>( component );
 
  173     if ( typedComponent != 
nullptr )
 
  174       return typedComponent;
 
  182   const QString rendererType = abstractRenderer->
type();
 
  184   if ( rendererType == 
"mesh" )
 
  191     if ( rendererType == 
"rulebased" )
 
  194       const QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
 
  195       for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
 
  197         Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( renderer->parent() );
 
  198         if ( entity == 
nullptr ) 
continue;
 
  199         Qgs3DExportObject *
object = processGeometryRenderer( renderer, layer->
name() + QStringLiteral( 
"_" ) );
 
  200         if ( 
object == 
nullptr ) 
continue;
 
  201         if ( mExportTextures )
 
  202           processEntityMaterial( entity, 
object );
 
  203         mObjects.push_back( 
object );
 
  211       const bool exported = symbol->
exportGeometries( 
this, entity, layer->
name() + QStringLiteral( 
"_" ) );
 
  218 void Qgs3DSceneExporter::processEntityMaterial( Qt3DCore::QEntity *entity, 
Qgs3DExportObject *
object )
 
  220   Qt3DExtras::QPhongMaterial *phongMaterial = findTypedComponent<Qt3DExtras::QPhongMaterial>( entity );
 
  221   if ( phongMaterial != 
nullptr )
 
  224     object->setupMaterial( &material );
 
  226   Qt3DExtras::QDiffuseSpecularMaterial *diffuseMapMaterial = findTypedComponent<Qt3DExtras::QDiffuseSpecularMaterial>( entity );
 
  228   if ( diffuseMapMaterial != 
nullptr )
 
  230     const QVector<Qt3DRender::QAbstractTextureImage *> textureImages = diffuseMapMaterial->diffuse().value< Qt3DRender::QTexture2D * >()->textureImages();
 
  232     for ( Qt3DRender::QAbstractTextureImage *tex : textureImages )
 
  235       if ( imageTexture != 
nullptr ) 
break;
 
  237     if ( imageTexture != 
nullptr )
 
  239       const QImage image = imageTexture->
getImage();
 
  240       object->setTextureImage( image );
 
  248   QgsChunkNode *node = terrain->rootNode();
 
  253   QgsTerrainTileEntity *terrainTile = 
nullptr;
 
  254   QgsTerrainTextureGenerator *textureGenerator = terrain->textureGenerator();
 
  255   textureGenerator->waitForFinished();
 
  256   const QSize oldResolution = textureGenerator->textureSize();
 
  257   textureGenerator->setTextureSize( QSize( mTerrainTextureResolution, mTerrainTextureResolution ) );
 
  258   switch ( generator->
type() )
 
  261       terrainTile = getDemTerrainEntity( terrain, node );
 
  262       parseDemTile( terrainTile, layerName + QStringLiteral( 
"_" ) );
 
  265       terrainTile = getFlatTerrainEntity( terrain, node );
 
  266       parseFlatTile( terrainTile, layerName + QStringLiteral( 
"_" ) );
 
  270       terrainTile = getMeshTerrainEntity( terrain, node );
 
  271       parseMeshTile( terrainTile, layerName + QStringLiteral( 
"_" ) );
 
  276   textureGenerator->setTextureSize( oldResolution );
 
  279 QgsTerrainTileEntity *Qgs3DSceneExporter::getFlatTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
 
  282   FlatTerrainChunkLoader *flatTerrainLoader = qobject_cast<FlatTerrainChunkLoader *>( generator->
createChunkLoader( node ) );
 
  283   if ( mExportTextures )
 
  284     terrain->textureGenerator()->waitForFinished();
 
  286   Qt3DCore::QEntity *entity = flatTerrainLoader->createEntity( 
this );
 
  287   QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( entity );
 
  291 QgsTerrainTileEntity *Qgs3DSceneExporter::getDemTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
 
  297   QgsDemTerrainTileLoader *loader = qobject_cast<QgsDemTerrainTileLoader *>( generator->
createChunkLoader( node ) );
 
  299   if ( mExportTextures )
 
  300     terrain->textureGenerator()->waitForFinished();
 
  301   QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( loader->createEntity( 
this ) );
 
  306 QgsTerrainTileEntity *Qgs3DSceneExporter::getMeshTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
 
  308   QgsMeshTerrainGenerator *generator = 
dynamic_cast<QgsMeshTerrainGenerator *
>( terrain->map3D().terrainGenerator() );
 
  309   QgsMeshTerrainTileLoader *loader = qobject_cast<QgsMeshTerrainTileLoader *>( generator->createChunkLoader( node ) );
 
  311   QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( loader->createEntity( 
this ) );
 
  315 void Qgs3DSceneExporter::parseFlatTile( QgsTerrainTileEntity *tileEntity, 
const QString &layerName )
 
  317   Qt3DRender::QGeometryRenderer *mesh = findTypedComponent<Qt3DRender::QGeometryRenderer>( tileEntity );
 
  318   Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( tileEntity );
 
  320   Qt3DRender::QGeometry *geometry = mesh->geometry();
 
  321   Qt3DExtras::QPlaneGeometry *tileGeometry = qobject_cast<Qt3DExtras::QPlaneGeometry *>( geometry );
 
  322   if ( tileGeometry == 
nullptr )
 
  324     QgsDebugMsg( 
"Qt3DExtras::QPlaneGeometry* is expected but something else was given" );
 
  328   const float scale = transform->scale();
 
  329   const QVector3D translation = transform->translation();
 
  332   Qt3DRender::QAttribute *positionAttribute = tileGeometry->positionAttribute();
 
  333   const QByteArray verticesBytes = 
getData( positionAttribute->buffer() );
 
  334   const QVector<float> positionBuffer = getAttributeData<float>( positionAttribute, verticesBytes );
 
  337   Qt3DRender::QAttribute *indexAttribute = tileGeometry->indexAttribute();
 
  338   const QByteArray indexBytes = 
getData( indexAttribute->buffer() );
 
  339   const QVector<uint> indexesBuffer = 
getIndexData( indexAttribute,  indexBytes );
 
  341   QString objectNamePrefix = layerName;
 
  342   if ( objectNamePrefix != QString() ) objectNamePrefix += QString();
 
  345   mObjects.push_back( 
object );
 
  347   object->setSmoothEdges( mSmoothEdges );
 
  348   object->setupPositionCoordinates( positionBuffer, 
scale, translation );
 
  349   object->setupFaces( indexesBuffer );
 
  351   if ( mExportNormals )
 
  354     QVector<float> normalsBuffer;
 
  355     for ( 
int i = 0; i < positionBuffer.size(); i += 3 ) normalsBuffer << 0.0f << 1.0f << 0.0f;
 
  356     object->setupNormalCoordinates( normalsBuffer );
 
  359   Qt3DRender::QAttribute *texCoordsAttribute = tileGeometry->texCoordAttribute();
 
  360   if ( mExportTextures && texCoordsAttribute != 
nullptr )
 
  363     const QVector<float> texCoords = getAttributeData<float>( texCoordsAttribute, verticesBytes );
 
  364     object->setupTextureCoordinates( texCoords );
 
  366     QgsTerrainTextureImage *textureImage = tileEntity->textureImage();
 
  367     const QImage img = textureImage->getImage();
 
  368     object->setTextureImage( img );
 
  372 void Qgs3DSceneExporter::parseDemTile( QgsTerrainTileEntity *tileEntity, 
const QString &layerName )
 
  374   Qt3DRender::QGeometryRenderer *mesh = findTypedComponent<Qt3DRender::QGeometryRenderer>( tileEntity );
 
  375   Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( tileEntity );
 
  377   Qt3DRender::QGeometry *geometry = mesh->geometry();
 
  378   DemTerrainTileGeometry *tileGeometry = qobject_cast<DemTerrainTileGeometry *>( geometry );
 
  379   if ( tileGeometry == 
nullptr )
 
  381     QgsDebugMsg( 
"DemTerrainTileGeometry* is expected but something else was given" );
 
  385   const float scale = transform->scale();
 
  386   const QVector3D translation = transform->translation();
 
  388   Qt3DRender::QAttribute *positionAttribute = tileGeometry->positionAttribute();
 
  389   const QByteArray positionBytes = positionAttribute->buffer()->data();
 
  390   const QVector<float> positionBuffer = getAttributeData<float>( positionAttribute, positionBytes );
 
  392   Qt3DRender::QAttribute *indexAttribute = tileGeometry->indexAttribute();
 
  393   const QByteArray indexBytes = indexAttribute->buffer()->data();
 
  394   const QVector<unsigned int> indexBuffer = 
getIndexData( indexAttribute, indexBytes );
 
  396   QString objectNamePrefix = layerName;
 
  397   if ( objectNamePrefix != QString() ) objectNamePrefix += QStringLiteral( 
"_" );
 
  400   mObjects.push_back( 
object );
 
  402   object->setSmoothEdges( mSmoothEdges );
 
  403   object->setupPositionCoordinates( positionBuffer, 
scale, translation );
 
  404   object->setupFaces( indexBuffer );
 
  406   Qt3DRender::QAttribute *normalsAttributes = tileGeometry->normalAttribute();
 
  407   if ( mExportNormals && normalsAttributes != 
nullptr )
 
  409     const QByteArray normalsBytes = normalsAttributes->buffer()->data();
 
  410     const QVector<float> normalsBuffer = getAttributeData<float>( normalsAttributes, normalsBytes );
 
  411     object->setupNormalCoordinates( normalsBuffer );
 
  414   Qt3DRender::QAttribute *texCoordsAttribute = tileGeometry->texCoordsAttribute();
 
  415   if ( mExportTextures && texCoordsAttribute != 
nullptr )
 
  417     const QByteArray texCoordsBytes = texCoordsAttribute->buffer()->data();
 
  418     const QVector<float> texCoordsBuffer = getAttributeData<float>( texCoordsAttribute, texCoordsBytes );
 
  419     object->setupTextureCoordinates( texCoordsBuffer );
 
  421     QgsTerrainTextureImage *textureImage = tileEntity->textureImage();
 
  422     const QImage img = textureImage->getImage();
 
  423     object->setTextureImage( img );
 
  427 void Qgs3DSceneExporter::parseMeshTile( QgsTerrainTileEntity *tileEntity, 
const QString &layerName )
 
  429   QString objectNamePrefix = layerName;
 
  430   if ( objectNamePrefix != QString() ) objectNamePrefix += QStringLiteral( 
"_" );
 
  432   const QList<Qt3DRender::QGeometryRenderer *> renderers = tileEntity->findChildren<Qt3DRender::QGeometryRenderer *>();
 
  433   for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
 
  436     if ( obj == 
nullptr ) 
continue;
 
  441 QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processInstancedPointGeometry( Qt3DCore::QEntity *entity, 
const QString &objectNamePrefix )
 
  443   QVector<Qgs3DExportObject *> objects;
 
  444   const QList<Qt3DRender::QGeometry *> geometriesList =  entity->findChildren<Qt3DRender::QGeometry *>();
 
  445   for ( Qt3DRender::QGeometry *geometry : geometriesList )
 
  447     Qt3DRender::QAttribute *positionAttribute = 
findAttribute( geometry, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  448     Qt3DRender::QAttribute *indexAttribute = 
nullptr;
 
  449     for ( Qt3DRender::QAttribute *attribute : geometry->attributes() )
 
  451       if ( attribute->attributeType() == Qt3DRender::QAttribute::IndexAttribute )
 
  452         indexAttribute = attribute;
 
  454     if ( positionAttribute == 
nullptr || indexAttribute == 
nullptr )
 
  456     const QByteArray vertexBytes = 
getData( positionAttribute->buffer() );
 
  457     const QByteArray indexBytes = 
getData( indexAttribute->buffer() );
 
  458     const QVector<float> positionData = getAttributeData<float>( positionAttribute, vertexBytes );
 
  459     const QVector<uint> indexData = 
getIndexData( indexAttribute, indexBytes );
 
  461     Qt3DRender::QAttribute *instanceDataAttribute = 
findAttribute( geometry,  QStringLiteral( 
"pos" ), Qt3DRender::QAttribute::VertexAttribute );
 
  462     const QByteArray instancePositionBytes = 
getData( instanceDataAttribute->buffer() );
 
  463     QVector<float> instancePosition = getAttributeData<float>( instanceDataAttribute, instancePositionBytes );
 
  464     for ( 
int i = 0; i < instancePosition.size(); i += 3 )
 
  467       objects.push_back( 
object );
 
  468       object->setupPositionCoordinates( positionData, 1.0f, QVector3D( instancePosition[i], instancePosition[i + 1], instancePosition[i + 2] ) );
 
  469       object->setupFaces( indexData );
 
  471       object->setSmoothEdges( mSmoothEdges );
 
  473       Qt3DRender::QAttribute *normalsAttribute = 
findAttribute( geometry, Qt3DRender::QAttribute::defaultNormalAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  474       if ( mExportNormals && normalsAttribute != 
nullptr )
 
  477         const QVector<float> normalsData = getAttributeData<float>( normalsAttribute, vertexBytes );
 
  478         object->setupNormalCoordinates( normalsData );
 
  485 QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processSceneLoaderGeometries( Qt3DRender::QSceneLoader *sceneLoader, 
const QString &objectNamePrefix )
 
  487   QVector<Qgs3DExportObject *> objects;
 
  488   Qt3DCore::QEntity *sceneLoaderParent = qobject_cast<Qt3DCore::QEntity *>( sceneLoader->parent() );
 
  489   Qt3DCore::QTransform *entityTransform = findTypedComponent<Qt3DCore::QTransform>( sceneLoaderParent );
 
  490   float sceneScale = 1.0f;
 
  491   QVector3D sceneTranslation( 0.0f, 0.0f, 0.0f );
 
  492   if ( entityTransform != 
nullptr )
 
  494     sceneScale = entityTransform->scale();
 
  495     sceneTranslation = entityTransform->translation();
 
  497   for ( 
const QString &entityName : sceneLoader->entityNames() )
 
  499     Qt3DRender::QGeometryRenderer *mesh = qobject_cast<Qt3DRender::QGeometryRenderer *>( sceneLoader->component( entityName, Qt3DRender::QSceneLoader::GeometryRendererComponent ) );
 
  500     Qgs3DExportObject *
object = processGeometryRenderer( mesh, objectNamePrefix, sceneScale, sceneTranslation );
 
  501     if ( 
object == 
nullptr ) 
continue;
 
  502     objects.push_back( 
object );
 
  507 Qgs3DExportObject *Qgs3DSceneExporter::processGeometryRenderer( Qt3DRender::QGeometryRenderer *mesh, 
const QString &objectNamePrefix, 
float sceneScale, QVector3D sceneTranslation )
 
  510   if ( mesh->primitiveType() != Qt3DRender::QGeometryRenderer::Triangles ) 
return nullptr;
 
  513   QVector3D translation( 0.0f, 0.0f, 0.0f );
 
  514   QObject *parent = mesh->parent();
 
  515   while ( parent != 
nullptr )
 
  517     Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( parent );
 
  518     Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( entity );
 
  519     if ( transform != 
nullptr )
 
  521       scale *= transform->scale();
 
  522       translation += transform->translation();
 
  524     parent = parent->parent();
 
  527   Qt3DRender::QGeometry *geometry = mesh->geometry();
 
  529   Qt3DRender::QAttribute *positionAttribute = 
findAttribute( geometry, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  530   Qt3DRender::QAttribute *indexAttribute = 
nullptr;
 
  531   QByteArray indexBytes, vertexBytes;
 
  532   QVector<uint> indexData;
 
  533   QVector<float> positionData;
 
  534   for ( Qt3DRender::QAttribute *attribute : geometry->attributes() )
 
  536     if ( attribute->attributeType() == Qt3DRender::QAttribute::IndexAttribute )
 
  537       indexAttribute = attribute;
 
  540   if ( indexAttribute != 
nullptr )
 
  542     indexBytes = 
getData( indexAttribute->buffer() );
 
  546   if ( positionAttribute != 
nullptr )
 
  548     vertexBytes = 
getData( positionAttribute->buffer() );
 
  549     positionData = getAttributeData<float>( positionAttribute, vertexBytes );
 
  553   if ( positionAttribute != 
nullptr && indexAttribute == 
nullptr )
 
  555     for ( 
int i = 0; i < positionData.size() / 3; ++i )
 
  556       indexData.push_back( i );
 
  559   if ( positionAttribute == 
nullptr )
 
  561     QgsDebugMsg( 
"Geometry renderer with null data was being processed" );
 
  566   object->setupPositionCoordinates( positionData, 
scale * sceneScale, translation + sceneTranslation );
 
  567   object->setupFaces( indexData );
 
  569   Qt3DRender::QAttribute *normalsAttribute = 
findAttribute( geometry, Qt3DRender::QAttribute::defaultNormalAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  570   if ( mExportNormals && normalsAttribute != 
nullptr )
 
  573     const QVector<float> normalsData = getAttributeData<float>( normalsAttribute, vertexBytes );
 
  574     object->setupNormalCoordinates( normalsData );
 
  577   Qt3DRender::QAttribute *texCoordsAttribute = 
findAttribute( geometry, Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  578   if ( mExportTextures && texCoordsAttribute != 
nullptr )
 
  581     const QVector<float> texCoordsData = getAttributeData<float>( texCoordsAttribute, vertexBytes );
 
  582     object->setupTextureCoordinates( texCoordsData );
 
  588 QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processLines( Qt3DCore::QEntity *entity, 
const QString &objectNamePrefix )
 
  590   QVector<Qgs3DExportObject *> objs;
 
  591   const QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
 
  592   for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
 
  594     if ( renderer->primitiveType() != Qt3DRender::QGeometryRenderer::LineStripAdjacency ) 
continue;
 
  595     Qt3DRender::QGeometry *geom = renderer->geometry();
 
  596     Qt3DRender::QAttribute *positionAttribute = 
findAttribute( geom, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  597     Qt3DRender::QAttribute *indexAttribute = 
nullptr;
 
  598     for ( Qt3DRender::QAttribute *attribute : geom->attributes() )
 
  600       if ( attribute->attributeType() == Qt3DRender::QAttribute::IndexAttribute )
 
  602         indexAttribute = attribute;
 
  606     if ( positionAttribute == 
nullptr || indexAttribute == 
nullptr )
 
  608       QgsDebugMsg( 
"Position or index attribute was not found" );
 
  612     const QByteArray vertexBytes = 
getData( positionAttribute->buffer() );
 
  613     const QByteArray indexBytes = 
getData( indexAttribute->buffer() );
 
  614     const QVector<float> positionData = getAttributeData<float>( positionAttribute, vertexBytes );
 
  615     const QVector<uint> indexData = 
getIndexData( indexAttribute, indexBytes );
 
  622     objs.push_back( exportObject );
 
  627 Qgs3DExportObject *Qgs3DSceneExporter::processPoints( Qt3DCore::QEntity *entity, 
const QString &objectNamePrefix )
 
  629   QVector<float> points;
 
  630   const QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
 
  631   for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
 
  633     Qt3DRender::QGeometry *geometry = qobject_cast<QgsBillboardGeometry *>( renderer->geometry() );
 
  634     if ( geometry == 
nullptr )
 
  636     Qt3DRender::QAttribute *positionAttribute = 
findAttribute( geometry, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  637     const QByteArray positionBytes = 
getData( positionAttribute->buffer() );
 
  638     if ( positionBytes.size() == 0 )
 
  640     const QVector<float> positions = getAttributeData<float>( positionAttribute, positionBytes );
 
  651   const QString objFilePath = QDir( sceneFolderPath ).filePath( sceneName + QStringLiteral( 
".obj" ) );
 
  652   const QString mtlFilePath = QDir( sceneFolderPath ).filePath( sceneName + QStringLiteral( 
".mtl" ) );
 
  654   QFile file( objFilePath );
 
  655   if ( !file.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
 
  657   QFile mtlFile( mtlFilePath );
 
  658   if ( !mtlFile.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
 
  661   float maxfloat = std::numeric_limits<float>::max(), minFloat = std::numeric_limits<float>::lowest();
 
  662   float minX = maxfloat, minY = maxfloat, minZ = maxfloat, maxX = minFloat, maxY = minFloat, maxZ = minFloat;
 
  665   float diffX = 1.0f, diffY = 1.0f, diffZ = 1.0f;
 
  670   const float centerX = ( minX + maxX ) / 2.0f;
 
  671   const float centerY = ( minY + maxY ) / 2.0f;
 
  672   const float centerZ = ( minZ + maxZ ) / 2.0f;
 
  674   const float scale = std::max( diffX, std::max( diffY, diffZ ) );
 
  676   QTextStream out( &file );
 
  678   const QString mtlLibName = sceneName + 
".mtl";
 
  679   out << 
"mtllib " << mtlLibName << 
"\n";
 
  681   QTextStream mtlOut( &mtlFile );
 
  684     if ( obj == 
nullptr ) 
continue;
 
  686     const QString material = obj->
saveMaterial( mtlOut, sceneFolderPath );
 
  687     out << 
"o " << obj->
name() << 
"\n";
 
  688     if ( material != QString() )
 
  689       out << 
"usemtl " << material << 
"\n";
 
  690     obj->
saveTo( out, 
scale / mScale, QVector3D( centerX, centerY, centerZ ) );
 
  694 QString Qgs3DSceneExporter::getObjectName( 
const QString &name )
 
  697   if ( usedObjectNamesCounter.contains( name ) )
 
  699     ret = QStringLiteral( 
"%1%2" ).arg( name ).arg( usedObjectNamesCounter[name] );
 
  700     usedObjectNamesCounter[name]++;
 
  703     usedObjectNamesCounter[name] = 2;
 
Manages the data of each object of the scene (positions, normals, texture coordinates ....
 
void saveTo(QTextStream &out, float scale, const QVector3D ¢er)
Saves the current object to the output stream while scaling the object and centering it to be visible...
 
void setType(ObjectType type)
Sets the object type.
 
void objectBounds(float &minX, float &minY, float &minZ, float &maxX, float &maxY, float &maxZ)
Updates the box bounds explained with the current object bounds This expands the bounding box if the ...
 
void setupPositionCoordinates(const QVector< float > &positionsBuffer, float scale=1.0f, const QVector3D &translation=QVector3D(0, 0, 0))
Sets positions coordinates and does the translation and scaling.
 
QString name() const
Returns the object name.
 
QString saveMaterial(QTextStream &mtlOut, const QString &folder)
saves the texture of the object and material information
 
void setupLine(const QVector< uint > &facesIndexes)
sets line vertex indexes
 
QgsTerrainGenerator * terrainGenerator() const
Returns terrain generator. It takes care of producing terrain tiles from the input data.
 
void parseTerrain(QgsTerrainEntity *terrain, const QString &layer)
Creates terrain export objects from the terrain entity.
 
void save(const QString &sceneName, const QString &sceneFolderPath)
Saves the scene to a .obj file.
 
float scale() const
Returns the scale of the exported 3D model.
 
bool parseVectorLayerEntity(Qt3DCore::QEntity *entity, QgsVectorLayer *layer)
Creates necessary export objects from entity if it represents valid vector layer entity Returns false...
 
static QgsPhongMaterialSettings phongMaterialFromQt3DComponent(Qt3DExtras::QPhongMaterial *material)
Returns phong material settings object based on the Qt3D material.
 
Base class for all renderers that may to participate in 3D view.
 
virtual QString type() const =0
Returns unique identifier of the renderer class (used to identify subclass)
 
virtual bool exportGeometries(Qgs3DSceneExporter *exporter, Qt3DCore::QEntity *entity, const QString &objectNamePrefix) const
Exports the geometries contained within the hierarchy of entity.
 
QgsDemHeightMapGenerator * heightMapGenerator()
Returns height map generator object - takes care of extraction of elevations from the layer)
 
QgsChunkLoader * createChunkLoader(QgsChunkNode *node) const override
 
void setResolution(int resolution)
Sets resolution of the generator (how many elevation samples on one side of a terrain tile)
 
QgsChunkLoader * createChunkLoader(QgsChunkNode *node) const override SIP_FACTORY
 
Holds an image that can be used as a texture in the 3D view.
 
QImage getImage() const
Returns the image.
 
QgsAbstract3DRenderer * renderer3D() const
Returns 3D renderer associated with the layer.
 
@ Dem
Terrain is built from raster layer with digital elevation model.
 
@ Online
Terrain is built from downloaded tiles with digital elevation model.
 
@ Mesh
Terrain is built from mesh layer with z value on vertices.
 
@ Flat
The whole terrain is flat area.
 
virtual Type type() const =0
What texture generator implementation is this.
 
3D renderer that renders all features of a vector layer with the same 3D symbol.
 
const QgsAbstract3DSymbol * symbol() const
Returns 3D symbol associated with the renderer.
 
Represents a vector layer which manages a vector based data sets.
 
QVector< uint > getIndexData(Qt3DRender::QAttribute *indexAttribute, const QByteArray &data)
 
Qt3DRender::QAttribute * findAttribute(Qt3DRender::QGeometry *geometry, const QString &name, Qt3DRender::QAttribute::AttributeType type)
 
Component * findTypedComponent(Qt3DCore::QEntity *entity)
 
QVector< T > getAttributeData(Qt3DRender::QAttribute *attribute, const QByteArray &data)
 
QByteArray getData(Qt3DRender::QBuffer *buffer)
 
QVector< uint > _getIndexDataImplementation(const QByteArray &data)