19#include <Qt3DCore/QEntity> 
   20#include <Qt3DCore/QComponent> 
   21#include <Qt3DCore/QNode> 
   23#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
   24#include <Qt3DRender/QAttribute> 
   25#include <Qt3DRender/QBuffer> 
   26#include <Qt3DRender/QGeometry> 
   32#include <Qt3DCore/QAttribute> 
   33#include <Qt3DCore/QBuffer> 
   34#include <Qt3DCore/QGeometry> 
   41#include <Qt3DRender/QGeometryRenderer> 
   42#include <Qt3DExtras/QPlaneGeometry> 
   43#include <Qt3DCore/QTransform> 
   44#include <Qt3DRender/QMaterial> 
   45#include <Qt3DExtras/QDiffuseSpecularMaterial> 
   46#include <Qt3DExtras/QTextureMaterial> 
   47#include <Qt3DRender/QTextureImage> 
   48#include <Qt3DRender/QTexture> 
   49#include <Qt3DRender/QMesh> 
   50#include <Qt3DRender/QSceneLoader> 
   51#include <Qt3DRender/QAbstractTexture> 
   52#include <Qt3DExtras/QCylinderGeometry> 
   53#include <Qt3DExtras/QConeGeometry> 
   54#include <Qt3DExtras/QSphereGeometry> 
   55#include <Qt3DExtras/QCuboidGeometry> 
   56#include <Qt3DExtras/QTorusGeometry> 
   57#include <Qt3DExtras/QExtrudedTextMesh> 
   58#include <Qt3DExtras/QPhongMaterial> 
   59#include <Qt3DRender/QAbstractTextureImage> 
   78#include "qgsmeshterraingenerator.h" 
   91  const uint bytesOffset = attribute->byteOffset();
 
   92  const uint bytesStride = attribute->byteStride();
 
   93  const uint vertexSize = attribute->vertexSize();
 
   96  if ( bytesStride == 0 )
 
   98    QgsDebugError( 
"bytesStride==0, the attribute probably was not set properly" );
 
  102  const char *pData = data.constData();
 
  103  for ( 
int i = bytesOffset; i < data.size(); i += bytesStride )
 
  105    for ( 
unsigned int j = 0; j < vertexSize * 
sizeof( T ); j += 
sizeof( T ) )
 
  108      memcpy( &v, pData + i + j, 
sizeof( T ) );
 
  109      result.push_back( v );
 
  118  QVector<uint> result;
 
  119  const char *pData = data.constData();
 
  120  for ( 
int i = 0; i < data.size(); i += 
sizeof( T ) )
 
  123    memcpy( &v, pData + i, 
sizeof( T ) );
 
  124    result.push_back( ( uint ) v );
 
  131  switch ( indexAttribute->vertexBaseType() )
 
  133    case Qt3DQAttribute::VertexBaseType::Int:
 
  134      return _getIndexDataImplementation<int>( data );
 
  135    case Qt3DQAttribute::VertexBaseType::UnsignedInt:
 
  136      return _getIndexDataImplementation<uint>( data );
 
  137    case Qt3DQAttribute::VertexBaseType::Short:
 
  138      return _getIndexDataImplementation<short>( data );
 
  139    case Qt3DQAttribute::VertexBaseType::UnsignedShort:
 
  140      return _getIndexDataImplementation<ushort>( data );
 
  141    case Qt3DQAttribute::VertexBaseType::Byte:
 
  142      return _getIndexDataImplementation<char>( data );
 
  143    case Qt3DQAttribute::VertexBaseType::UnsignedByte:
 
  144      return _getIndexDataImplementation<uchar>( data );
 
  146      QgsDebugError( 
"Probably trying to get index data using an attribute that has vertex data" );
 
  149  return QVector<uint>();
 
  154  QByteArray bytes = buffer->data();
 
  155  if ( bytes.isNull() )
 
  166    if ( attribute->attributeType() != type ) 
continue;
 
  167    if ( attribute->name() == name ) 
return attribute;
 
  172template<
typename Component>
 
  175  if ( entity == 
nullptr ) 
return nullptr;
 
  176  for ( Qt3DCore::QComponent *component : entity->components() )
 
  178    Component *typedComponent = qobject_cast<Component *>( component );
 
  179    if ( typedComponent != 
nullptr )
 
  180      return typedComponent;
 
  188  const QString rendererType = abstractRenderer->
type();
 
  190  if ( rendererType == 
"mesh" )
 
  197    if ( rendererType == 
"rulebased" )
 
  200      const QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
 
  201      for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
 
  203        Qt3DCore::QEntity *parentEntity = qobject_cast<Qt3DCore::QEntity *>( renderer->parent() );
 
  206        Qgs3DExportObject *
object = processGeometryRenderer( renderer, layer->
name() + QStringLiteral( 
"_" ) );
 
  207        if ( 
object == 
nullptr ) 
continue;
 
  208        if ( mExportTextures )
 
  209          processEntityMaterial( parentEntity, 
object );
 
  210        mObjects.push_back( 
object );
 
  217      if ( vectorLayerRenderer )
 
  220        const bool exported = symbol->
exportGeometries( 
this, entity, layer->
name() + QStringLiteral( 
"_" ) );
 
  230void Qgs3DSceneExporter::processEntityMaterial( Qt3DCore::QEntity *entity, 
Qgs3DExportObject *
object )
 
  232  Qt3DExtras::QPhongMaterial *phongMaterial = findTypedComponent<Qt3DExtras::QPhongMaterial>( entity );
 
  233  if ( phongMaterial != 
nullptr )
 
  236    object->setupMaterial( &material );
 
  239  Qt3DExtras::QDiffuseSpecularMaterial *diffuseMapMaterial = findTypedComponent<Qt3DExtras::QDiffuseSpecularMaterial>( entity );
 
  240  if ( diffuseMapMaterial != 
nullptr )
 
  242    const Qt3DRender::QTexture2D *diffuseTexture = diffuseMapMaterial->diffuse().value< Qt3DRender::QTexture2D * >();
 
  243    if ( diffuseTexture != 
nullptr )
 
  245      const QVector<Qt3DRender::QAbstractTextureImage *> textureImages = diffuseTexture->textureImages();
 
  247      for ( Qt3DRender::QAbstractTextureImage *tex : textureImages )
 
  250        if ( imageTexture != 
nullptr ) 
break;
 
  252      if ( imageTexture != 
nullptr )
 
  254        const QImage image = imageTexture->
getImage();
 
  255        object->setTextureImage( image );
 
  267  QgsChunkNode *node = terrain->rootNode();
 
  272  QgsTerrainTileEntity *terrainTile = 
nullptr;
 
  273  QgsTerrainTextureGenerator *textureGenerator = terrain->textureGenerator();
 
  274  textureGenerator->waitForFinished();
 
  275  const QSize oldResolution = textureGenerator->textureSize();
 
  276  textureGenerator->setTextureSize( QSize( mTerrainTextureResolution, mTerrainTextureResolution ) );
 
  277  switch ( generator->
type() )
 
  280      terrainTile = getDemTerrainEntity( terrain, node );
 
  281      parseDemTile( terrainTile, layerName + QStringLiteral( 
"_" ) );
 
  284      terrainTile = getFlatTerrainEntity( terrain, node );
 
  285      parseFlatTile( terrainTile, layerName + QStringLiteral( 
"_" ) );
 
  289      terrainTile = getMeshTerrainEntity( terrain, node );
 
  290      parseMeshTile( terrainTile, layerName + QStringLiteral( 
"_" ) );
 
  295  textureGenerator->setTextureSize( oldResolution );
 
  298QgsTerrainTileEntity *Qgs3DSceneExporter::getFlatTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
 
  301  FlatTerrainChunkLoader *flatTerrainLoader = qobject_cast<FlatTerrainChunkLoader *>( generator->
createChunkLoader( node ) );
 
  302  if ( mExportTextures )
 
  303    terrain->textureGenerator()->waitForFinished();
 
  305  Qt3DCore::QEntity *entity = flatTerrainLoader->createEntity( 
this );
 
  306  QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( entity );
 
  310QgsTerrainTileEntity *Qgs3DSceneExporter::getDemTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
 
  316  QgsDemTerrainTileLoader *loader = qobject_cast<QgsDemTerrainTileLoader *>( generator->
createChunkLoader( node ) );
 
  318  if ( mExportTextures )
 
  319    terrain->textureGenerator()->waitForFinished();
 
  320  QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( loader->createEntity( 
this ) );
 
  325QgsTerrainTileEntity *Qgs3DSceneExporter::getMeshTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
 
  327  QgsMeshTerrainGenerator *generator = 
dynamic_cast<QgsMeshTerrainGenerator *
>( terrain->map3D().terrainGenerator() );
 
  328  QgsMeshTerrainTileLoader *loader = qobject_cast<QgsMeshTerrainTileLoader *>( generator->createChunkLoader( node ) );
 
  330  QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( loader->createEntity( 
this ) );
 
  334void Qgs3DSceneExporter::parseFlatTile( QgsTerrainTileEntity *tileEntity, 
const QString &layerName )
 
  336  Qt3DRender::QGeometryRenderer *mesh = findTypedComponent<Qt3DRender::QGeometryRenderer>( tileEntity );
 
  337  Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( tileEntity );
 
  340  Qt3DExtras::QPlaneGeometry *tileGeometry = qobject_cast<Qt3DExtras::QPlaneGeometry *>( geometry );
 
  341  if ( tileGeometry == 
nullptr )
 
  343    QgsDebugError( 
"Qt3DExtras::QPlaneGeometry* is expected but something else was given" );
 
  347  const float scale = transform->scale();
 
  348  const QVector3D translation = transform->translation();
 
  351  Qt3DQAttribute *positionAttribute = tileGeometry->positionAttribute();
 
  352  const QByteArray verticesBytes = 
getData( positionAttribute->buffer() );
 
  353  const QVector<float> positionBuffer = getAttributeData<float>( positionAttribute, verticesBytes );
 
  357  const QByteArray indexBytes = 
getData( indexAttribute->buffer() );
 
  358  const QVector<uint> indexesBuffer = 
getIndexData( indexAttribute,  indexBytes );
 
  360  QString objectNamePrefix = layerName;
 
  361  if ( objectNamePrefix != QString() ) objectNamePrefix += QString();
 
  364  mObjects.push_back( 
object );
 
  366  object->setSmoothEdges( mSmoothEdges );
 
  367  object->setupPositionCoordinates( positionBuffer, 
scale, translation );
 
  368  object->setupFaces( indexesBuffer );
 
  370  if ( mExportNormals )
 
  373    QVector<float> normalsBuffer;
 
  374    for ( 
int i = 0; i < positionBuffer.size(); i += 3 ) normalsBuffer << 0.0f << 1.0f << 0.0f;
 
  375    object->setupNormalCoordinates( normalsBuffer );
 
  378  Qt3DQAttribute *texCoordsAttribute = tileGeometry->texCoordAttribute();
 
  379  if ( mExportTextures && texCoordsAttribute != 
nullptr )
 
  382    const QVector<float> texCoords = getAttributeData<float>( texCoordsAttribute, verticesBytes );
 
  383    object->setupTextureCoordinates( texCoords );
 
  385    QgsTerrainTextureImage *textureImage = tileEntity->textureImage();
 
  386    const QImage img = textureImage->getImage();
 
  387    object->setTextureImage( img );
 
  391void Qgs3DSceneExporter::parseDemTile( QgsTerrainTileEntity *tileEntity, 
const QString &layerName )
 
  393  Qt3DRender::QGeometryRenderer *mesh = findTypedComponent<Qt3DRender::QGeometryRenderer>( tileEntity );
 
  394  Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( tileEntity );
 
  397  DemTerrainTileGeometry *tileGeometry = qobject_cast<DemTerrainTileGeometry *>( geometry );
 
  398  if ( tileGeometry == 
nullptr )
 
  400    QgsDebugError( 
"DemTerrainTileGeometry* is expected but something else was given" );
 
  404  const float scale = transform->scale();
 
  405  const QVector3D translation = transform->translation();
 
  407  Qt3DQAttribute *positionAttribute = tileGeometry->positionAttribute();
 
  408  const QByteArray positionBytes = positionAttribute->buffer()->data();
 
  409  const QVector<float> positionBuffer = getAttributeData<float>( positionAttribute, positionBytes );
 
  412  const QByteArray indexBytes = indexAttribute->buffer()->data();
 
  413  const QVector<unsigned int> indexBuffer = 
getIndexData( indexAttribute, indexBytes );
 
  416  mObjects.push_back( 
object );
 
  418  object->setSmoothEdges( mSmoothEdges );
 
  419  object->setupPositionCoordinates( positionBuffer, 
scale, translation );
 
  420  object->setupFaces( indexBuffer );
 
  422  Qt3DQAttribute *normalsAttributes = tileGeometry->normalAttribute();
 
  423  if ( mExportNormals && normalsAttributes != 
nullptr )
 
  425    const QByteArray normalsBytes = normalsAttributes->buffer()->data();
 
  426    const QVector<float> normalsBuffer = getAttributeData<float>( normalsAttributes, normalsBytes );
 
  427    object->setupNormalCoordinates( normalsBuffer );
 
  430  Qt3DQAttribute *texCoordsAttribute = tileGeometry->texCoordsAttribute();
 
  431  if ( mExportTextures && texCoordsAttribute != 
nullptr )
 
  433    const QByteArray texCoordsBytes = texCoordsAttribute->buffer()->data();
 
  434    const QVector<float> texCoordsBuffer = getAttributeData<float>( texCoordsAttribute, texCoordsBytes );
 
  435    object->setupTextureCoordinates( texCoordsBuffer );
 
  437    QgsTerrainTextureImage *textureImage = tileEntity->textureImage();
 
  438    const QImage img = textureImage->getImage();
 
  439    object->setTextureImage( img );
 
  443void Qgs3DSceneExporter::parseMeshTile( QgsTerrainTileEntity *tileEntity, 
const QString &layerName )
 
  445  QString objectNamePrefix = layerName;
 
  446  if ( objectNamePrefix != QString() ) objectNamePrefix += QStringLiteral( 
"_" );
 
  448  const QList<Qt3DRender::QGeometryRenderer *> renderers = tileEntity->findChildren<Qt3DRender::QGeometryRenderer *>();
 
  449  for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
 
  452    if ( obj == 
nullptr ) 
continue;
 
  457QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processInstancedPointGeometry( Qt3DCore::QEntity *entity, 
const QString &objectNamePrefix )
 
  459  QVector<Qgs3DExportObject *> objects;
 
  460  const QList<Qt3DQGeometry *> geometriesList =  entity->findChildren<
Qt3DQGeometry *>();
 
  463    Qt3DQAttribute *positionAttribute = 
findAttribute( geometry, Qt3DQAttribute::defaultPositionAttributeName(), Qt3DQAttribute::VertexAttribute );
 
  467      if ( attribute->attributeType() == Qt3DQAttribute::IndexAttribute )
 
  468        indexAttribute = attribute;
 
  470    if ( positionAttribute == 
nullptr || indexAttribute == 
nullptr )
 
  472    const QByteArray vertexBytes = 
getData( positionAttribute->buffer() );
 
  473    const QByteArray indexBytes = 
getData( indexAttribute->buffer() );
 
  474    const QVector<float> positionData = getAttributeData<float>( positionAttribute, vertexBytes );
 
  475    const QVector<uint> indexData = 
getIndexData( indexAttribute, indexBytes );
 
  478    const QByteArray instancePositionBytes = 
getData( instanceDataAttribute->buffer() );
 
  479    QVector<float> instancePosition = getAttributeData<float>( instanceDataAttribute, instancePositionBytes );
 
  480    for ( 
int i = 0; i < instancePosition.size(); i += 3 )
 
  483      objects.push_back( 
object );
 
  484      object->setupPositionCoordinates( positionData, 1.0f, QVector3D( instancePosition[i], instancePosition[i + 1], instancePosition[i + 2] ) );
 
  485      object->setupFaces( indexData );
 
  487      object->setSmoothEdges( mSmoothEdges );
 
  489      Qt3DQAttribute *normalsAttribute = 
findAttribute( geometry, Qt3DQAttribute::defaultNormalAttributeName(), Qt3DQAttribute::VertexAttribute );
 
  490      if ( mExportNormals && normalsAttribute != 
nullptr )
 
  493        const QVector<float> normalsData = getAttributeData<float>( normalsAttribute, vertexBytes );
 
  494        object->setupNormalCoordinates( normalsData );
 
  501QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processSceneLoaderGeometries( Qt3DRender::QSceneLoader *sceneLoader, 
const QString &objectNamePrefix )
 
  503  QVector<Qgs3DExportObject *> objects;
 
  504  Qt3DCore::QEntity *sceneLoaderParent = qobject_cast<Qt3DCore::QEntity *>( sceneLoader->parent() );
 
  505  Qt3DCore::QTransform *entityTransform = findTypedComponent<Qt3DCore::QTransform>( sceneLoaderParent );
 
  506  float sceneScale = 1.0f;
 
  507  QVector3D sceneTranslation( 0.0f, 0.0f, 0.0f );
 
  508  if ( entityTransform != 
nullptr )
 
  510    sceneScale = entityTransform->scale();
 
  511    sceneTranslation = entityTransform->translation();
 
  513  for ( 
const QString &entityName : sceneLoader->entityNames() )
 
  515    Qt3DRender::QGeometryRenderer *mesh = qobject_cast<Qt3DRender::QGeometryRenderer *>( sceneLoader->component( entityName, Qt3DRender::QSceneLoader::GeometryRendererComponent ) );
 
  516    Qgs3DExportObject *
object = processGeometryRenderer( mesh, objectNamePrefix, sceneScale, sceneTranslation );
 
  517    if ( 
object == 
nullptr ) 
continue;
 
  518    objects.push_back( 
object );
 
  523Qgs3DExportObject *Qgs3DSceneExporter::processGeometryRenderer( Qt3DRender::QGeometryRenderer *geomRenderer, 
const QString &objectNamePrefix, 
float sceneScale, QVector3D sceneTranslation )
 
  526  if ( geomRenderer->primitiveType() != Qt3DRender::QGeometryRenderer::Triangles ) 
return nullptr;
 
  529  QVector3D translation( 0.0f, 0.0f, 0.0f );
 
  530  QObject *parent = geomRenderer->parent();
 
  531  while ( parent != 
nullptr )
 
  533    Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( parent );
 
  534    Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( entity );
 
  535    if ( transform != 
nullptr )
 
  537      scale *= transform->scale();
 
  538      translation += transform->translation();
 
  540    parent = parent->parent();
 
  545  Qt3DQAttribute *positionAttribute = 
findAttribute( geometry, Qt3DQAttribute::defaultPositionAttributeName(), Qt3DQAttribute::VertexAttribute );
 
  547  QByteArray indexBytes, vertexBytes;
 
  548  QVector<uint> indexData;
 
  549  QVector<float> positionData;
 
  552    if ( attribute->attributeType() == Qt3DQAttribute::IndexAttribute )
 
  553      indexAttribute = attribute;
 
  556  if ( indexAttribute != 
nullptr )
 
  558    indexBytes = 
getData( indexAttribute->buffer() );
 
  562  if ( positionAttribute != 
nullptr )
 
  564    vertexBytes = 
getData( positionAttribute->buffer() );
 
  565    positionData = getAttributeData<float>( positionAttribute, vertexBytes );
 
  569  if ( positionAttribute != 
nullptr && indexAttribute == 
nullptr )
 
  571    for ( 
int i = 0; i < positionData.size() / 3; ++i )
 
  572      indexData.push_back( i );
 
  575  if ( positionAttribute == 
nullptr )
 
  577    QgsDebugError( 
"Geometry renderer with null data was being processed" );
 
  582  object->setupPositionCoordinates( positionData, 
scale * sceneScale, translation + sceneTranslation );
 
  583  object->setupFaces( indexData );
 
  585  Qt3DQAttribute *normalsAttribute = 
findAttribute( geometry, Qt3DQAttribute::defaultNormalAttributeName(), Qt3DQAttribute::VertexAttribute );
 
  586  if ( mExportNormals && normalsAttribute != 
nullptr )
 
  589    const QVector<float> normalsData = getAttributeData<float>( normalsAttribute, vertexBytes );
 
  590    object->setupNormalCoordinates( normalsData );
 
  593  Qt3DQAttribute *texCoordsAttribute = 
findAttribute( geometry, Qt3DQAttribute::defaultTextureCoordinateAttributeName(), Qt3DQAttribute::VertexAttribute );
 
  594  if ( mExportTextures && texCoordsAttribute != 
nullptr )
 
  597    const QVector<float> texCoordsData = getAttributeData<float>( texCoordsAttribute, vertexBytes );
 
  598    object->setupTextureCoordinates( texCoordsData );
 
  604QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processLines( Qt3DCore::QEntity *entity, 
const QString &objectNamePrefix )
 
  606  QVector<Qgs3DExportObject *> objs;
 
  607  const QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
 
  608  for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
 
  610    if ( renderer->primitiveType() != Qt3DRender::QGeometryRenderer::LineStripAdjacency ) 
continue;
 
  612    Qt3DQAttribute *positionAttribute = 
findAttribute( geom, Qt3DQAttribute::defaultPositionAttributeName(), Qt3DQAttribute::VertexAttribute );
 
  616      if ( attribute->attributeType() == Qt3DQAttribute::IndexAttribute )
 
  618        indexAttribute = attribute;
 
  622    if ( positionAttribute == 
nullptr || indexAttribute == 
nullptr )
 
  624      QgsDebugError( 
"Position or index attribute was not found" );
 
  628    const QByteArray vertexBytes = 
getData( positionAttribute->buffer() );
 
  629    const QByteArray indexBytes = 
getData( indexAttribute->buffer() );
 
  630    const QVector<float> positionData = getAttributeData<float>( positionAttribute, vertexBytes );
 
  631    const QVector<uint> indexData = 
getIndexData( indexAttribute, indexBytes );
 
  638    objs.push_back( exportObject );
 
  643Qgs3DExportObject *Qgs3DSceneExporter::processPoints( Qt3DCore::QEntity *entity, 
const QString &objectNamePrefix )
 
  645  QVector<float> points;
 
  646  const QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
 
  647  for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
 
  649    Qt3DQGeometry *geometry = qobject_cast<QgsBillboardGeometry *>( renderer->geometry() );
 
  650    if ( geometry == 
nullptr )
 
  652    Qt3DQAttribute *positionAttribute = 
findAttribute( geometry, Qt3DQAttribute::defaultPositionAttributeName(), Qt3DQAttribute::VertexAttribute );
 
  653    const QByteArray positionBytes = 
getData( positionAttribute->buffer() );
 
  654    if ( positionBytes.size() == 0 )
 
  656    const QVector<float> positions = getAttributeData<float>( positionAttribute, positionBytes );
 
  667  const QString objFilePath = QDir( sceneFolderPath ).filePath( sceneName + QStringLiteral( 
".obj" ) );
 
  668  const QString mtlFilePath = QDir( sceneFolderPath ).filePath( sceneName + QStringLiteral( 
".mtl" ) );
 
  670  QFile file( objFilePath );
 
  671  if ( !file.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
 
  673  QFile mtlFile( mtlFilePath );
 
  674  if ( !mtlFile.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
 
  677  float maxfloat = std::numeric_limits<float>::max(), minFloat = std::numeric_limits<float>::lowest();
 
  678  float minX = maxfloat, minY = maxfloat, minZ = maxfloat, maxX = minFloat, maxY = minFloat, maxZ = minFloat;
 
  681  float diffX = 1.0f, diffY = 1.0f, diffZ = 1.0f;
 
  686  const float centerX = ( minX + maxX ) / 2.0f;
 
  687  const float centerY = ( minY + maxY ) / 2.0f;
 
  688  const float centerZ = ( minZ + maxZ ) / 2.0f;
 
  690  const float scale = std::max( diffX, std::max( diffY, diffZ ) );
 
  692  QTextStream out( &file );
 
  694  const QString mtlLibName = sceneName + 
".mtl";
 
  695  out << 
"mtllib " << mtlLibName << 
"\n";
 
  697  QTextStream mtlOut( &mtlFile );
 
  700    if ( obj == 
nullptr ) 
continue;
 
  702    const QString material = obj->
saveMaterial( mtlOut, sceneFolderPath );
 
  703    out << 
"o " << obj->
name() << 
"\n";
 
  704    if ( material != QString() )
 
  705      out << 
"usemtl " << material << 
"\n";
 
  706    obj->
saveTo( out, 
scale / mScale, QVector3D( centerX, centerY, centerZ ) );
 
  710QString Qgs3DSceneExporter::getObjectName( 
const QString &name )
 
  713  if ( usedObjectNamesCounter.contains( name ) )
 
  715    ret = QStringLiteral( 
"%1%2" ).arg( name ).arg( usedObjectNamesCounter[name] );
 
  716    usedObjectNamesCounter[name]++;
 
  719    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 the terrain generator.
 
bool terrainRenderingEnabled() const
Returns whether the 2D terrain surface will be rendered.
 
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.
 
Qt3DCore::QAttribute Qt3DQAttribute
 
Qt3DCore::QBuffer Qt3DQBuffer
 
Qt3DCore::QGeometry Qt3DQGeometry
 
QVector< T > getAttributeData(Qt3DQAttribute *attribute, const QByteArray &data)
 
Qt3DQAttribute * findAttribute(Qt3DQGeometry *geometry, const QString &name, Qt3DQAttribute::AttributeType type)
 
Qt3DCore::QAttribute Qt3DQAttribute
 
QVector< uint > getIndexData(Qt3DQAttribute *indexAttribute, const QByteArray &data)
 
QByteArray getData(Qt3DQBuffer *buffer)
 
Qt3DCore::QBuffer Qt3DQBuffer
 
QVector< uint > _getIndexDataImplementation(const QByteArray &data)
 
Component * findTypedComponent(Qt3DCore::QEntity *entity)
 
Qt3DCore::QGeometry Qt3DQGeometry
 
#define QgsDebugError(str)