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/QDiffuseMapMaterial>
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 Qt3DRender::QBufferDataGeneratorPtr dataGenerator = buffer->dataGenerator();
150 if ( bytes.isNull() )
152 if ( !dataGenerator.isNull() )
153 bytes = dataGenerator->operator()();
160 Qt3DRender::QAttribute *
findAttribute( Qt3DRender::QGeometry *geometry,
const QString &name, Qt3DRender::QAttribute::AttributeType type )
162 for ( Qt3DRender::QAttribute *attribute : geometry->attributes() )
164 if ( attribute->attributeType() != type )
continue;
165 if ( attribute->name() == name )
return attribute;
170 template<
typename Component>
173 if ( entity ==
nullptr )
return nullptr;
174 for ( Qt3DCore::QComponent *component : entity->components() )
176 Component *typedComponent = qobject_cast<Component *>( component );
177 if ( typedComponent !=
nullptr )
178 return typedComponent;
186 QString rendererType = abstractRenderer->
type();
188 if ( rendererType ==
"mesh" )
195 if ( rendererType ==
"rulebased" )
198 QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
199 for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
201 Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( renderer->parent() );
202 if ( entity ==
nullptr )
continue;
203 Qgs3DExportObject *
object = processGeometryRenderer( renderer, layer->
name() + QStringLiteral(
"_" ) );
204 if (
object ==
nullptr )
continue;
205 if ( mExportTextures )
206 processEntityMaterial( entity,
object );
207 mObjects.push_back(
object );
215 bool exported = symbol->
exportGeometries(
this, entity, layer->
name() + QStringLiteral(
"_" ) );
222 void Qgs3DSceneExporter::processEntityMaterial( Qt3DCore::QEntity *entity,
Qgs3DExportObject *
object )
224 Qt3DExtras::QPhongMaterial *phongMaterial = findTypedComponent<Qt3DExtras::QPhongMaterial>( entity );
225 if ( phongMaterial !=
nullptr )
228 object->setupMaterial( &material );
230 Qt3DExtras::QDiffuseMapMaterial *diffuseMapMaterial = findTypedComponent<Qt3DExtras::QDiffuseMapMaterial>( entity );
231 if ( diffuseMapMaterial !=
nullptr )
233 QVector<Qt3DRender::QAbstractTextureImage *> textureImages = diffuseMapMaterial->diffuse()->textureImages();
235 for ( Qt3DRender::QAbstractTextureImage *tex : textureImages )
238 if ( imageTexture !=
nullptr )
break;
240 if ( imageTexture !=
nullptr )
242 QImage image = imageTexture->
getImage();
243 object->setTextureImage( image );
251 QgsChunkNode *node = terrain->rootNode();
254 QgsTerrainTileEntity *terrainTile =
nullptr;
255 QgsTerrainTextureGenerator *textureGenerator = terrain->textureGenerator();
256 textureGenerator->waitForFinished();
257 QSize oldResolution = textureGenerator->textureSize();
258 textureGenerator->setTextureSize( QSize( mTerrainTextureResolution, mTerrainTextureResolution ) );
259 switch ( generator->
type() )
262 terrainTile = getDemTerrainEntity( terrain, node );
263 parseDemTile( terrainTile, layerName + QStringLiteral(
"_" ) );
266 terrainTile = getFlatTerrainEntity( terrain, node );
267 parseFlatTile( terrainTile, layerName + QStringLiteral(
"_" ) );
271 terrainTile = getMeshTerrainEntity( terrain, node );
272 parseMeshTile( terrainTile, layerName + QStringLiteral(
"_" ) );
277 textureGenerator->setTextureSize( oldResolution );
280 QgsTerrainTileEntity *Qgs3DSceneExporter::getFlatTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
283 FlatTerrainChunkLoader *flatTerrainLoader = qobject_cast<FlatTerrainChunkLoader *>( generator->
createChunkLoader( node ) );
284 if ( mExportTextures )
285 terrain->textureGenerator()->waitForFinished();
287 Qt3DCore::QEntity *entity = flatTerrainLoader->createEntity(
this );
288 QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( entity );
292 QgsTerrainTileEntity *Qgs3DSceneExporter::getDemTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
298 QgsDemTerrainTileLoader *loader = qobject_cast<QgsDemTerrainTileLoader *>( generator->
createChunkLoader( node ) );
300 if ( mExportTextures )
301 terrain->textureGenerator()->waitForFinished();
302 QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( loader->createEntity(
this ) );
307 QgsTerrainTileEntity *Qgs3DSceneExporter::getMeshTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
309 QgsMeshTerrainGenerator *generator =
dynamic_cast<QgsMeshTerrainGenerator *
>( terrain->map3D().terrainGenerator() );
310 QgsMeshTerrainTileLoader *loader = qobject_cast<QgsMeshTerrainTileLoader *>( generator->createChunkLoader( node ) );
312 QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( loader->createEntity(
this ) );
316 void Qgs3DSceneExporter::parseFlatTile( QgsTerrainTileEntity *tileEntity,
const QString &layerName )
318 Qt3DRender::QGeometryRenderer *mesh = findTypedComponent<Qt3DRender::QGeometryRenderer>( tileEntity );
319 Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( tileEntity );
321 Qt3DRender::QGeometry *geometry = mesh->geometry();
322 Qt3DExtras::QPlaneGeometry *tileGeometry = qobject_cast<Qt3DExtras::QPlaneGeometry *>( geometry );
323 if ( tileGeometry ==
nullptr )
325 QgsDebugMsg(
"Qt3DExtras::QPlaneGeometry* is expected but something else was given" );
329 float scale = transform->scale();
330 QVector3D translation = transform->translation();
333 Qt3DRender::QAttribute *positionAttribute = tileGeometry->positionAttribute();
334 QByteArray verticesBytes =
getData( positionAttribute->buffer() );
335 QVector<float> positionBuffer = getAttributeData<float>( positionAttribute, verticesBytes );
338 Qt3DRender::QAttribute *indexAttribute = tileGeometry->indexAttribute();
339 QByteArray indexBytes =
getData( indexAttribute->buffer() );
340 QVector<uint> indexesBuffer =
getIndexData( indexAttribute, indexBytes );
342 QString objectNamePrefix = layerName;
343 if ( objectNamePrefix != QString() ) objectNamePrefix += QString();
346 mObjects.push_back(
object );
348 object->setSmoothEdges( mSmoothEdges );
349 object->setupPositionCoordinates( positionBuffer,
scale, translation );
350 object->setupFaces( indexesBuffer );
352 if ( mExportNormals )
355 QVector<float> normalsBuffer;
356 for (
int i = 0; i < positionBuffer.size(); i += 3 ) normalsBuffer << 0.0f << 1.0f << 0.0f;
357 object->setupNormalCoordinates( normalsBuffer );
360 Qt3DRender::QAttribute *texCoordsAttribute = tileGeometry->texCoordAttribute();
361 if ( mExportTextures && texCoordsAttribute !=
nullptr )
364 QVector<float> texCoords = getAttributeData<float>( texCoordsAttribute, verticesBytes );
365 object->setupTextureCoordinates( texCoords );
367 QgsTerrainTextureImage *textureImage = tileEntity->textureImage();
368 QImage img = textureImage->getImage();
369 object->setTextureImage( img );
373 void Qgs3DSceneExporter::parseDemTile( QgsTerrainTileEntity *tileEntity,
const QString &layerName )
375 Qt3DRender::QGeometryRenderer *mesh = findTypedComponent<Qt3DRender::QGeometryRenderer>( tileEntity );
376 Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( tileEntity );
378 Qt3DRender::QGeometry *geometry = mesh->geometry();
379 DemTerrainTileGeometry *tileGeometry = qobject_cast<DemTerrainTileGeometry *>( geometry );
380 if ( tileGeometry ==
nullptr )
382 QgsDebugMsg(
"DemTerrainTileGeometry* is expected but something else was given" );
386 float scale = transform->scale();
387 QVector3D translation = transform->translation();
389 Qt3DRender::QAttribute *positionAttribute = tileGeometry->positionAttribute();
390 QByteArray positionBytes = positionAttribute->buffer()->data();
391 QVector<float> positionBuffer = getAttributeData<float>( positionAttribute, positionBytes );
393 Qt3DRender::QAttribute *indexAttribute = tileGeometry->indexAttribute();
394 QByteArray indexBytes = indexAttribute->buffer()->data();
395 QVector<unsigned int> indexBuffer =
getIndexData( indexAttribute, indexBytes );
397 QString objectNamePrefix = layerName;
398 if ( objectNamePrefix != QString() ) objectNamePrefix += QStringLiteral(
"_" );
401 mObjects.push_back(
object );
403 object->setSmoothEdges( mSmoothEdges );
404 object->setupPositionCoordinates( positionBuffer,
scale, translation );
405 object->setupFaces( indexBuffer );
407 Qt3DRender::QAttribute *normalsAttributes = tileGeometry->normalAttribute();
408 if ( mExportNormals && normalsAttributes !=
nullptr )
410 QByteArray normalsBytes = normalsAttributes->buffer()->data();
411 QVector<float> normalsBuffer = getAttributeData<float>( normalsAttributes, normalsBytes );
412 object->setupNormalCoordinates( normalsBuffer );
415 Qt3DRender::QAttribute *texCoordsAttribute = tileGeometry->texCoordsAttribute();
416 if ( mExportTextures && texCoordsAttribute !=
nullptr )
418 QByteArray texCoordsBytes = texCoordsAttribute->buffer()->data();
419 QVector<float> texCoordsBuffer = getAttributeData<float>( texCoordsAttribute, texCoordsBytes );
420 object->setupTextureCoordinates( texCoordsBuffer );
422 QgsTerrainTextureImage *textureImage = tileEntity->textureImage();
423 QImage img = textureImage->getImage();
424 object->setTextureImage( img );
428 void Qgs3DSceneExporter::parseMeshTile( QgsTerrainTileEntity *tileEntity,
const QString &layerName )
430 QString objectNamePrefix = layerName;
431 if ( objectNamePrefix != QString() ) objectNamePrefix += QStringLiteral(
"_" );
433 QList<Qt3DRender::QGeometryRenderer *> renderers = tileEntity->findChildren<Qt3DRender::QGeometryRenderer *>();
434 for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
437 if ( obj ==
nullptr )
continue;
442 QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processInstancedPointGeometry( Qt3DCore::QEntity *entity,
const QString &objectNamePrefix )
444 QVector<Qgs3DExportObject *> objects;
445 QList<Qt3DRender::QGeometry *> geometriesList = entity->findChildren<Qt3DRender::QGeometry *>();
446 for ( Qt3DRender::QGeometry *geometry : geometriesList )
448 Qt3DRender::QAttribute *positionAttribute =
findAttribute( geometry, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
449 Qt3DRender::QAttribute *indexAttribute =
nullptr;
450 for ( Qt3DRender::QAttribute *attribute : geometry->attributes() )
452 if ( attribute->attributeType() == Qt3DRender::QAttribute::IndexAttribute )
453 indexAttribute = attribute;
455 if ( positionAttribute ==
nullptr || indexAttribute ==
nullptr )
457 QByteArray vertexBytes =
getData( positionAttribute->buffer() );
458 QByteArray indexBytes =
getData( indexAttribute->buffer() );
459 QVector<float> positionData = getAttributeData<float>( positionAttribute, vertexBytes );
460 QVector<uint> indexData =
getIndexData( indexAttribute, indexBytes );
462 Qt3DRender::QAttribute *instanceDataAttribute =
findAttribute( geometry, QStringLiteral(
"pos" ), Qt3DRender::QAttribute::VertexAttribute );
463 QByteArray instancePositionBytes =
getData( instanceDataAttribute->buffer() );
464 QVector<float> instancePosition = getAttributeData<float>( instanceDataAttribute, instancePositionBytes );
465 for (
int i = 0; i < instancePosition.size(); i += 3 )
468 objects.push_back(
object );
469 object->setupPositionCoordinates( positionData, 1.0f, QVector3D( instancePosition[i], instancePosition[i + 1], instancePosition[i + 2] ) );
470 object->setupFaces( indexData );
472 object->setSmoothEdges( mSmoothEdges );
474 Qt3DRender::QAttribute *normalsAttribute =
findAttribute( geometry, Qt3DRender::QAttribute::defaultNormalAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
475 if ( mExportNormals && normalsAttribute !=
nullptr )
478 QVector<float> normalsData = getAttributeData<float>( normalsAttribute, vertexBytes );
479 object->setupNormalCoordinates( normalsData );
486 QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processSceneLoaderGeometries( Qt3DRender::QSceneLoader *sceneLoader,
const QString &objectNamePrefix )
488 QVector<Qgs3DExportObject *> objects;
489 Qt3DCore::QEntity *sceneLoaderParent = qobject_cast<Qt3DCore::QEntity *>( sceneLoader->parent() );
490 Qt3DCore::QTransform *entityTransform = findTypedComponent<Qt3DCore::QTransform>( sceneLoaderParent );
491 float sceneScale = 1.0f;
492 QVector3D sceneTranslation( 0.0f, 0.0f, 0.0f );
493 if ( entityTransform !=
nullptr )
495 sceneScale = entityTransform->scale();
496 sceneTranslation = entityTransform->translation();
498 for ( QString entityName : sceneLoader->entityNames() )
500 Qt3DRender::QGeometryRenderer *mesh = qobject_cast<Qt3DRender::QGeometryRenderer *>( sceneLoader->component( entityName, Qt3DRender::QSceneLoader::GeometryRendererComponent ) );
501 Qgs3DExportObject *
object = processGeometryRenderer( mesh, objectNamePrefix, sceneScale, sceneTranslation );
502 if (
object ==
nullptr )
continue;
503 objects.push_back(
object );
508 Qgs3DExportObject *Qgs3DSceneExporter::processGeometryRenderer( Qt3DRender::QGeometryRenderer *mesh,
const QString &objectNamePrefix,
float sceneScale, QVector3D sceneTranslation )
511 if ( mesh->primitiveType() != Qt3DRender::QGeometryRenderer::Triangles )
return nullptr;
514 QVector3D translation( 0.0f, 0.0f, 0.0f );
515 QObject *parent = mesh->parent();
516 while ( parent !=
nullptr )
518 Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( parent );
519 Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( entity );
520 if ( transform !=
nullptr )
522 scale *= transform->scale();
523 translation += transform->translation();
525 parent = parent->parent();
528 Qt3DRender::QGeometry *geometry = mesh->geometry();
530 Qt3DRender::QAttribute *positionAttribute =
findAttribute( geometry, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
531 Qt3DRender::QAttribute *indexAttribute =
nullptr;
532 QByteArray indexBytes, vertexBytes;
533 QVector<uint> indexData;
534 QVector<float> positionData;
535 for ( Qt3DRender::QAttribute *attribute : geometry->attributes() )
537 if ( attribute->attributeType() == Qt3DRender::QAttribute::IndexAttribute )
538 indexAttribute = attribute;
541 if ( indexAttribute !=
nullptr )
543 indexBytes =
getData( indexAttribute->buffer() );
547 if ( positionAttribute !=
nullptr )
549 vertexBytes =
getData( positionAttribute->buffer() );
550 positionData = getAttributeData<float>( positionAttribute, vertexBytes );
554 if ( positionAttribute !=
nullptr && indexAttribute ==
nullptr )
556 for (
int i = 0; i < positionData.size() / 3; ++i )
557 indexData.push_back( i );
560 if ( positionAttribute ==
nullptr )
562 QgsDebugMsg(
"Geometry renderer with null data was being processed" );
567 object->setupPositionCoordinates( positionData,
scale * sceneScale, translation + sceneTranslation );
568 object->setupFaces( indexData );
570 Qt3DRender::QAttribute *normalsAttribute =
findAttribute( geometry, Qt3DRender::QAttribute::defaultNormalAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
571 if ( mExportNormals && normalsAttribute !=
nullptr )
574 QVector<float> normalsData = getAttributeData<float>( normalsAttribute, vertexBytes );
575 object->setupNormalCoordinates( normalsData );
578 Qt3DRender::QAttribute *texCoordsAttribute =
findAttribute( geometry, Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
579 if ( mExportTextures && texCoordsAttribute !=
nullptr )
582 QVector<float> texCoordsData = getAttributeData<float>( texCoordsAttribute, vertexBytes );
583 object->setupTextureCoordinates( texCoordsData );
589 QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processLines( Qt3DCore::QEntity *entity,
const QString &objectNamePrefix )
591 QVector<Qgs3DExportObject *> objs;
592 QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
593 for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
595 if ( renderer->primitiveType() != Qt3DRender::QGeometryRenderer::LineStripAdjacency )
continue;
596 Qt3DRender::QGeometry *geom = renderer->geometry();
597 Qt3DRender::QAttribute *positionAttribute =
findAttribute( geom, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
598 Qt3DRender::QAttribute *indexAttribute =
nullptr;
599 for ( Qt3DRender::QAttribute *attribute : geom->attributes() )
601 if ( attribute->attributeType() == Qt3DRender::QAttribute::IndexAttribute )
603 indexAttribute = attribute;
607 if ( positionAttribute ==
nullptr || indexAttribute ==
nullptr )
609 QgsDebugMsg(
"Position or index attribute was not found" );
613 QByteArray vertexBytes =
getData( positionAttribute->buffer() );
614 QByteArray indexBytes =
getData( indexAttribute->buffer() );
615 QVector<float> positionData = getAttributeData<float>( positionAttribute, vertexBytes );
616 QVector<uint> indexData =
getIndexData( indexAttribute, indexBytes );
623 objs.push_back( exportObject );
628 Qgs3DExportObject *Qgs3DSceneExporter::processPoints( Qt3DCore::QEntity *entity,
const QString &objectNamePrefix )
630 QVector<float> points;
631 QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
632 for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
634 Qt3DRender::QGeometry *geometry = qobject_cast<QgsBillboardGeometry *>( renderer->geometry() );
635 if ( geometry ==
nullptr )
637 Qt3DRender::QAttribute *positionAttribute =
findAttribute( geometry, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
638 QByteArray positionBytes =
getData( positionAttribute->buffer() );
639 if ( positionBytes.size() == 0 )
641 QVector<float> positions = getAttributeData<float>( positionAttribute, positionBytes );
652 QString objFilePath = QDir( sceneFolderPath ).filePath( sceneName + QStringLiteral(
".obj" ) );
653 QString mtlFilePath = QDir( sceneFolderPath ).filePath( sceneName + QStringLiteral(
".mtl" ) );
655 QFile file( objFilePath );
656 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
658 QFile mtlFile( mtlFilePath );
659 if ( !mtlFile.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
662 float maxfloat = std::numeric_limits<float>::max(), minFloat = std::numeric_limits<float>::lowest();
663 float minX = maxfloat, minY = maxfloat, minZ = maxfloat, maxX = minFloat, maxY = minFloat, maxZ = minFloat;
666 float diffX = 1.0f, diffY = 1.0f, diffZ = 1.0f;
671 float centerX = ( minX + maxX ) / 2.0f;
672 float centerY = ( minY + maxY ) / 2.0f;
673 float centerZ = ( minZ + maxZ ) / 2.0f;
675 float scale = std::max( diffX, std::max( diffY, diffZ ) );
677 QTextStream out( &file );
679 QString mtlLibName = sceneName +
".mtl";
680 out <<
"mtllib " << mtlLibName <<
"\n";
682 QTextStream mtlOut( &mtlFile );
685 if ( obj ==
nullptr )
continue;
687 QString material = obj->
saveMaterial( mtlOut, sceneFolderPath );
688 out <<
"o " << obj->
name() <<
"\n";
689 if ( material != QString() )
690 out <<
"usemtl " << material <<
"\n";
691 obj->
saveTo( out,
scale / mScale, QVector3D( centerX, centerY, centerZ ) );
695 QString Qgs3DSceneExporter::getObjectName(
const QString &name )
698 if ( usedObjectNamesCounter.contains( name ) )
700 ret = QStringLiteral(
"%1%2" ).arg( name ).arg( usedObjectNamesCounter[name] );
701 usedObjectNamesCounter[name]++;
704 usedObjectNamesCounter[name] = 2;