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   uint bytesOffset = attribute->byteOffset();
 
   86   uint bytesStride = attribute->byteStride();
 
   87   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   QString rendererType = abstractRenderer->
type();
 
  184   if ( rendererType == 
"mesh" )
 
  191     if ( rendererType == 
"rulebased" )
 
  194       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       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     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       QImage image = imageTexture->
getImage();
 
  240       object->setTextureImage( image );
 
  248   QgsChunkNode *node = terrain->rootNode();
 
  251   QgsTerrainTileEntity *terrainTile = 
nullptr;
 
  252   QgsTerrainTextureGenerator *textureGenerator = terrain->textureGenerator();
 
  253   textureGenerator->waitForFinished();
 
  254   QSize oldResolution = textureGenerator->textureSize();
 
  255   textureGenerator->setTextureSize( QSize( mTerrainTextureResolution, mTerrainTextureResolution ) );
 
  256   switch ( generator->
type() )
 
  259       terrainTile = getDemTerrainEntity( terrain, node );
 
  260       parseDemTile( terrainTile, layerName + QStringLiteral( 
"_" ) );
 
  263       terrainTile = getFlatTerrainEntity( terrain, node );
 
  264       parseFlatTile( terrainTile, layerName + QStringLiteral( 
"_" ) );
 
  268       terrainTile = getMeshTerrainEntity( terrain, node );
 
  269       parseMeshTile( terrainTile, layerName + QStringLiteral( 
"_" ) );
 
  274   textureGenerator->setTextureSize( oldResolution );
 
  277 QgsTerrainTileEntity *Qgs3DSceneExporter::getFlatTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
 
  280   FlatTerrainChunkLoader *flatTerrainLoader = qobject_cast<FlatTerrainChunkLoader *>( generator->
createChunkLoader( node ) );
 
  281   if ( mExportTextures )
 
  282     terrain->textureGenerator()->waitForFinished();
 
  284   Qt3DCore::QEntity *entity = flatTerrainLoader->createEntity( 
this );
 
  285   QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( entity );
 
  289 QgsTerrainTileEntity *Qgs3DSceneExporter::getDemTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
 
  295   QgsDemTerrainTileLoader *loader = qobject_cast<QgsDemTerrainTileLoader *>( generator->
createChunkLoader( node ) );
 
  297   if ( mExportTextures )
 
  298     terrain->textureGenerator()->waitForFinished();
 
  299   QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( loader->createEntity( 
this ) );
 
  304 QgsTerrainTileEntity *Qgs3DSceneExporter::getMeshTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
 
  306   QgsMeshTerrainGenerator *generator = 
dynamic_cast<QgsMeshTerrainGenerator *
>( terrain->map3D().terrainGenerator() );
 
  307   QgsMeshTerrainTileLoader *loader = qobject_cast<QgsMeshTerrainTileLoader *>( generator->createChunkLoader( node ) );
 
  309   QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( loader->createEntity( 
this ) );
 
  313 void Qgs3DSceneExporter::parseFlatTile( QgsTerrainTileEntity *tileEntity, 
const QString &layerName )
 
  315   Qt3DRender::QGeometryRenderer *mesh = findTypedComponent<Qt3DRender::QGeometryRenderer>( tileEntity );
 
  316   Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( tileEntity );
 
  318   Qt3DRender::QGeometry *geometry = mesh->geometry();
 
  319   Qt3DExtras::QPlaneGeometry *tileGeometry = qobject_cast<Qt3DExtras::QPlaneGeometry *>( geometry );
 
  320   if ( tileGeometry == 
nullptr )
 
  322     QgsDebugMsg( 
"Qt3DExtras::QPlaneGeometry* is expected but something else was given" );
 
  326   float scale = transform->scale();
 
  327   QVector3D translation = transform->translation();
 
  330   Qt3DRender::QAttribute *positionAttribute = tileGeometry->positionAttribute();
 
  331   QByteArray verticesBytes = 
getData( positionAttribute->buffer() );
 
  332   QVector<float> positionBuffer = getAttributeData<float>( positionAttribute, verticesBytes );
 
  335   Qt3DRender::QAttribute *indexAttribute = tileGeometry->indexAttribute();
 
  336   QByteArray indexBytes = 
getData( indexAttribute->buffer() );
 
  337   QVector<uint> indexesBuffer = 
getIndexData( indexAttribute,  indexBytes );
 
  339   QString objectNamePrefix = layerName;
 
  340   if ( objectNamePrefix != QString() ) objectNamePrefix += QString();
 
  343   mObjects.push_back( 
object );
 
  345   object->setSmoothEdges( mSmoothEdges );
 
  346   object->setupPositionCoordinates( positionBuffer, 
scale, translation );
 
  347   object->setupFaces( indexesBuffer );
 
  349   if ( mExportNormals )
 
  352     QVector<float> normalsBuffer;
 
  353     for ( 
int i = 0; i < positionBuffer.size(); i += 3 ) normalsBuffer << 0.0f << 1.0f << 0.0f;
 
  354     object->setupNormalCoordinates( normalsBuffer );
 
  357   Qt3DRender::QAttribute *texCoordsAttribute = tileGeometry->texCoordAttribute();
 
  358   if ( mExportTextures && texCoordsAttribute != 
nullptr )
 
  361     QVector<float> texCoords = getAttributeData<float>( texCoordsAttribute, verticesBytes );
 
  362     object->setupTextureCoordinates( texCoords );
 
  364     QgsTerrainTextureImage *textureImage = tileEntity->textureImage();
 
  365     QImage img = textureImage->getImage();
 
  366     object->setTextureImage( img );
 
  370 void Qgs3DSceneExporter::parseDemTile( QgsTerrainTileEntity *tileEntity, 
const QString &layerName )
 
  372   Qt3DRender::QGeometryRenderer *mesh = findTypedComponent<Qt3DRender::QGeometryRenderer>( tileEntity );
 
  373   Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( tileEntity );
 
  375   Qt3DRender::QGeometry *geometry = mesh->geometry();
 
  376   DemTerrainTileGeometry *tileGeometry = qobject_cast<DemTerrainTileGeometry *>( geometry );
 
  377   if ( tileGeometry == 
nullptr )
 
  379     QgsDebugMsg( 
"DemTerrainTileGeometry* is expected but something else was given" );
 
  383   float scale = transform->scale();
 
  384   QVector3D translation = transform->translation();
 
  386   Qt3DRender::QAttribute *positionAttribute = tileGeometry->positionAttribute();
 
  387   QByteArray positionBytes = positionAttribute->buffer()->data();
 
  388   QVector<float> positionBuffer = getAttributeData<float>( positionAttribute, positionBytes );
 
  390   Qt3DRender::QAttribute *indexAttribute = tileGeometry->indexAttribute();
 
  391   QByteArray indexBytes = indexAttribute->buffer()->data();
 
  392   QVector<unsigned int> indexBuffer = 
getIndexData( indexAttribute, indexBytes );
 
  394   QString objectNamePrefix = layerName;
 
  395   if ( objectNamePrefix != QString() ) objectNamePrefix += QStringLiteral( 
"_" );
 
  398   mObjects.push_back( 
object );
 
  400   object->setSmoothEdges( mSmoothEdges );
 
  401   object->setupPositionCoordinates( positionBuffer, 
scale, translation );
 
  402   object->setupFaces( indexBuffer );
 
  404   Qt3DRender::QAttribute *normalsAttributes = tileGeometry->normalAttribute();
 
  405   if ( mExportNormals && normalsAttributes != 
nullptr )
 
  407     QByteArray normalsBytes = normalsAttributes->buffer()->data();
 
  408     QVector<float> normalsBuffer = getAttributeData<float>( normalsAttributes, normalsBytes );
 
  409     object->setupNormalCoordinates( normalsBuffer );
 
  412   Qt3DRender::QAttribute *texCoordsAttribute = tileGeometry->texCoordsAttribute();
 
  413   if ( mExportTextures && texCoordsAttribute != 
nullptr )
 
  415     QByteArray texCoordsBytes = texCoordsAttribute->buffer()->data();
 
  416     QVector<float> texCoordsBuffer = getAttributeData<float>( texCoordsAttribute, texCoordsBytes );
 
  417     object->setupTextureCoordinates( texCoordsBuffer );
 
  419     QgsTerrainTextureImage *textureImage = tileEntity->textureImage();
 
  420     QImage img = textureImage->getImage();
 
  421     object->setTextureImage( img );
 
  425 void Qgs3DSceneExporter::parseMeshTile( QgsTerrainTileEntity *tileEntity, 
const QString &layerName )
 
  427   QString objectNamePrefix = layerName;
 
  428   if ( objectNamePrefix != QString() ) objectNamePrefix += QStringLiteral( 
"_" );
 
  430   QList<Qt3DRender::QGeometryRenderer *> renderers = tileEntity->findChildren<Qt3DRender::QGeometryRenderer *>();
 
  431   for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
 
  434     if ( obj == 
nullptr ) 
continue;
 
  439 QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processInstancedPointGeometry( Qt3DCore::QEntity *entity, 
const QString &objectNamePrefix )
 
  441   QVector<Qgs3DExportObject *> objects;
 
  442   QList<Qt3DRender::QGeometry *> geometriesList =  entity->findChildren<Qt3DRender::QGeometry *>();
 
  443   for ( Qt3DRender::QGeometry *geometry : geometriesList )
 
  445     Qt3DRender::QAttribute *positionAttribute = 
findAttribute( geometry, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  446     Qt3DRender::QAttribute *indexAttribute = 
nullptr;
 
  447     for ( Qt3DRender::QAttribute *attribute : geometry->attributes() )
 
  449       if ( attribute->attributeType() == Qt3DRender::QAttribute::IndexAttribute )
 
  450         indexAttribute = attribute;
 
  452     if ( positionAttribute == 
nullptr || indexAttribute == 
nullptr )
 
  454     QByteArray vertexBytes = 
getData( positionAttribute->buffer() );
 
  455     QByteArray indexBytes = 
getData( indexAttribute->buffer() );
 
  456     QVector<float> positionData = getAttributeData<float>( positionAttribute, vertexBytes );
 
  457     QVector<uint> indexData = 
getIndexData( indexAttribute, indexBytes );
 
  459     Qt3DRender::QAttribute *instanceDataAttribute = 
findAttribute( geometry,  QStringLiteral( 
"pos" ), Qt3DRender::QAttribute::VertexAttribute );
 
  460     QByteArray instancePositionBytes = 
getData( instanceDataAttribute->buffer() );
 
  461     QVector<float> instancePosition = getAttributeData<float>( instanceDataAttribute, instancePositionBytes );
 
  462     for ( 
int i = 0; i < instancePosition.size(); i += 3 )
 
  465       objects.push_back( 
object );
 
  466       object->setupPositionCoordinates( positionData, 1.0f, QVector3D( instancePosition[i], instancePosition[i + 1], instancePosition[i + 2] ) );
 
  467       object->setupFaces( indexData );
 
  469       object->setSmoothEdges( mSmoothEdges );
 
  471       Qt3DRender::QAttribute *normalsAttribute = 
findAttribute( geometry, Qt3DRender::QAttribute::defaultNormalAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  472       if ( mExportNormals && normalsAttribute != 
nullptr )
 
  475         QVector<float> normalsData = getAttributeData<float>( normalsAttribute, vertexBytes );
 
  476         object->setupNormalCoordinates( normalsData );
 
  483 QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processSceneLoaderGeometries( Qt3DRender::QSceneLoader *sceneLoader, 
const QString &objectNamePrefix )
 
  485   QVector<Qgs3DExportObject *> objects;
 
  486   Qt3DCore::QEntity *sceneLoaderParent = qobject_cast<Qt3DCore::QEntity *>( sceneLoader->parent() );
 
  487   Qt3DCore::QTransform *entityTransform = findTypedComponent<Qt3DCore::QTransform>( sceneLoaderParent );
 
  488   float sceneScale = 1.0f;
 
  489   QVector3D sceneTranslation( 0.0f, 0.0f, 0.0f );
 
  490   if ( entityTransform != 
nullptr )
 
  492     sceneScale = entityTransform->scale();
 
  493     sceneTranslation = entityTransform->translation();
 
  495   for ( QString entityName : sceneLoader->entityNames() )
 
  497     Qt3DRender::QGeometryRenderer *mesh = qobject_cast<Qt3DRender::QGeometryRenderer *>( sceneLoader->component( entityName, Qt3DRender::QSceneLoader::GeometryRendererComponent ) );
 
  498     Qgs3DExportObject *
object = processGeometryRenderer( mesh, objectNamePrefix, sceneScale, sceneTranslation );
 
  499     if ( 
object == 
nullptr ) 
continue;
 
  500     objects.push_back( 
object );
 
  505 Qgs3DExportObject *Qgs3DSceneExporter::processGeometryRenderer( Qt3DRender::QGeometryRenderer *mesh, 
const QString &objectNamePrefix, 
float sceneScale, QVector3D sceneTranslation )
 
  508   if ( mesh->primitiveType() != Qt3DRender::QGeometryRenderer::Triangles ) 
return nullptr;
 
  511   QVector3D translation( 0.0f, 0.0f, 0.0f );
 
  512   QObject *parent = mesh->parent();
 
  513   while ( parent != 
nullptr )
 
  515     Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( parent );
 
  516     Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( entity );
 
  517     if ( transform != 
nullptr )
 
  519       scale *= transform->scale();
 
  520       translation += transform->translation();
 
  522     parent = parent->parent();
 
  525   Qt3DRender::QGeometry *geometry = mesh->geometry();
 
  527   Qt3DRender::QAttribute *positionAttribute = 
findAttribute( geometry, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  528   Qt3DRender::QAttribute *indexAttribute = 
nullptr;
 
  529   QByteArray indexBytes, vertexBytes;
 
  530   QVector<uint> indexData;
 
  531   QVector<float> positionData;
 
  532   for ( Qt3DRender::QAttribute *attribute : geometry->attributes() )
 
  534     if ( attribute->attributeType() == Qt3DRender::QAttribute::IndexAttribute )
 
  535       indexAttribute = attribute;
 
  538   if ( indexAttribute != 
nullptr )
 
  540     indexBytes = 
getData( indexAttribute->buffer() );
 
  544   if ( positionAttribute != 
nullptr )
 
  546     vertexBytes = 
getData( positionAttribute->buffer() );
 
  547     positionData = getAttributeData<float>( positionAttribute, vertexBytes );
 
  551   if ( positionAttribute != 
nullptr && indexAttribute == 
nullptr )
 
  553     for ( 
int i = 0; i < positionData.size() / 3; ++i )
 
  554       indexData.push_back( i );
 
  557   if ( positionAttribute == 
nullptr )
 
  559     QgsDebugMsg( 
"Geometry renderer with null data was being processed" );
 
  564   object->setupPositionCoordinates( positionData, 
scale * sceneScale, translation + sceneTranslation );
 
  565   object->setupFaces( indexData );
 
  567   Qt3DRender::QAttribute *normalsAttribute = 
findAttribute( geometry, Qt3DRender::QAttribute::defaultNormalAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  568   if ( mExportNormals && normalsAttribute != 
nullptr )
 
  571     QVector<float> normalsData = getAttributeData<float>( normalsAttribute, vertexBytes );
 
  572     object->setupNormalCoordinates( normalsData );
 
  575   Qt3DRender::QAttribute *texCoordsAttribute = 
findAttribute( geometry, Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  576   if ( mExportTextures && texCoordsAttribute != 
nullptr )
 
  579     QVector<float> texCoordsData = getAttributeData<float>( texCoordsAttribute, vertexBytes );
 
  580     object->setupTextureCoordinates( texCoordsData );
 
  586 QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processLines( Qt3DCore::QEntity *entity, 
const QString &objectNamePrefix )
 
  588   QVector<Qgs3DExportObject *> objs;
 
  589   QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
 
  590   for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
 
  592     if ( renderer->primitiveType() != Qt3DRender::QGeometryRenderer::LineStripAdjacency ) 
continue;
 
  593     Qt3DRender::QGeometry *geom = renderer->geometry();
 
  594     Qt3DRender::QAttribute *positionAttribute = 
findAttribute( geom, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  595     Qt3DRender::QAttribute *indexAttribute = 
nullptr;
 
  596     for ( Qt3DRender::QAttribute *attribute : geom->attributes() )
 
  598       if ( attribute->attributeType() == Qt3DRender::QAttribute::IndexAttribute )
 
  600         indexAttribute = attribute;
 
  604     if ( positionAttribute == 
nullptr || indexAttribute == 
nullptr )
 
  606       QgsDebugMsg( 
"Position or index attribute was not found" );
 
  610     QByteArray vertexBytes = 
getData( positionAttribute->buffer() );
 
  611     QByteArray indexBytes = 
getData( indexAttribute->buffer() );
 
  612     QVector<float> positionData = getAttributeData<float>( positionAttribute, vertexBytes );
 
  613     QVector<uint> indexData = 
getIndexData( indexAttribute, indexBytes );
 
  620     objs.push_back( exportObject );
 
  625 Qgs3DExportObject *Qgs3DSceneExporter::processPoints( Qt3DCore::QEntity *entity, 
const QString &objectNamePrefix )
 
  627   QVector<float> points;
 
  628   QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
 
  629   for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
 
  631     Qt3DRender::QGeometry *geometry = qobject_cast<QgsBillboardGeometry *>( renderer->geometry() );
 
  632     if ( geometry == 
nullptr )
 
  634     Qt3DRender::QAttribute *positionAttribute = 
findAttribute( geometry, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
 
  635     QByteArray positionBytes = 
getData( positionAttribute->buffer() );
 
  636     if ( positionBytes.size() == 0 )
 
  638     QVector<float> positions = getAttributeData<float>( positionAttribute, positionBytes );
 
  649   QString objFilePath = QDir( sceneFolderPath ).filePath( sceneName + QStringLiteral( 
".obj" ) );
 
  650   QString mtlFilePath = QDir( sceneFolderPath ).filePath( sceneName + QStringLiteral( 
".mtl" ) );
 
  652   QFile file( objFilePath );
 
  653   if ( !file.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
 
  655   QFile mtlFile( mtlFilePath );
 
  656   if ( !mtlFile.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
 
  659   float maxfloat = std::numeric_limits<float>::max(), minFloat = std::numeric_limits<float>::lowest();
 
  660   float minX = maxfloat, minY = maxfloat, minZ = maxfloat, maxX = minFloat, maxY = minFloat, maxZ = minFloat;
 
  663   float diffX = 1.0f, diffY = 1.0f, diffZ = 1.0f;
 
  668   float centerX = ( minX + maxX ) / 2.0f;
 
  669   float centerY = ( minY + maxY ) / 2.0f;
 
  670   float centerZ = ( minZ + maxZ ) / 2.0f;
 
  672   float scale = std::max( diffX, std::max( diffY, diffZ ) );
 
  674   QTextStream out( &file );
 
  676   QString mtlLibName = sceneName + 
".mtl";
 
  677   out << 
"mtllib " << mtlLibName << 
"\n";
 
  679   QTextStream mtlOut( &mtlFile );
 
  682     if ( obj == 
nullptr ) 
continue;
 
  684     QString material = obj->
saveMaterial( mtlOut, sceneFolderPath );
 
  685     out << 
"o " << obj->
name() << 
"\n";
 
  686     if ( material != QString() )
 
  687       out << 
"usemtl " << material << 
"\n";
 
  688     obj->
saveTo( out, 
scale / mScale, QVector3D( centerX, centerY, centerZ ) );
 
  692 QString Qgs3DSceneExporter::getObjectName( 
const QString &name )
 
  695   if ( usedObjectNamesCounter.contains( name ) )
 
  697     ret = QStringLiteral( 
"%1%2" ).arg( name ).arg( usedObjectNamesCounter[name] );
 
  698     usedObjectNamesCounter[name]++;
 
  701     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)