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 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
30 #include <Qt3DExtras/QDiffuseMapMaterial>
32 #include <Qt3DExtras/QDiffuseSpecularMaterial>
34 #include <Qt3DExtras/QTextureMaterial>
35 #include <Qt3DRender/QTextureImage>
36 #include <Qt3DRender/QTexture>
37 #include <Qt3DRender/QBufferDataGenerator>
38 #include <Qt3DRender/QBufferDataGeneratorPtr>
39 #include <Qt3DRender/QMesh>
40 #include <Qt3DRender/QSceneLoader>
41 #include <Qt3DRender/QAbstractTexture>
42 #include <Qt3DExtras/QCylinderGeometry>
43 #include <Qt3DExtras/QConeGeometry>
44 #include <Qt3DExtras/QSphereGeometry>
45 #include <Qt3DExtras/QCuboidGeometry>
46 #include <Qt3DExtras/QTorusGeometry>
47 #include <Qt3DExtras/QExtrudedTextMesh>
48 #include <Qt3DExtras/QPhongMaterial>
49 #include <Qt3DRender/QAbstractTextureImage>
53 #include <QTextStream>
68 #include "qgsmesh3dgeometry_p.h"
70 #include "qgsmesh3dentity_p.h"
71 #include "qgsmeshterraingenerator.h"
87 QVector<T>
getAttributeData( Qt3DRender::QAttribute *attribute,
const QByteArray &data )
89 uint bytesOffset = attribute->byteOffset();
90 uint bytesStride = attribute->byteStride();
91 uint vertexSize = attribute->vertexSize();
94 if ( bytesStride == 0 )
96 QgsDebugMsg(
"bytesStride==0, the attribute probably was not set properly" );
100 const char *pData = data.constData();
101 for (
int i = bytesOffset; i < data.size(); i += bytesStride )
103 for (
unsigned int j = 0; j < vertexSize *
sizeof( T ); j +=
sizeof( T ) )
106 memcpy( &v, pData + i + j,
sizeof( T ) );
107 result.push_back( v );
116 QVector<uint> result;
117 const char *pData = data.constData();
118 for (
int i = 0; i < data.size(); i +=
sizeof( T ) )
121 memcpy( &v, pData + i,
sizeof( T ) );
122 result.push_back( ( uint ) v );
127 QVector<uint>
getIndexData( Qt3DRender::QAttribute *indexAttribute,
const QByteArray &data )
129 switch ( indexAttribute->vertexBaseType() )
131 case Qt3DRender::QAttribute::VertexBaseType::Int:
132 return _getIndexDataImplementation<int>( data );
133 case Qt3DRender::QAttribute::VertexBaseType::UnsignedInt:
134 return _getIndexDataImplementation<uint>( data );
135 case Qt3DRender::QAttribute::VertexBaseType::Short:
136 return _getIndexDataImplementation<short>( data );
137 case Qt3DRender::QAttribute::VertexBaseType::UnsignedShort:
138 return _getIndexDataImplementation<ushort>( data );
139 case Qt3DRender::QAttribute::VertexBaseType::Byte:
140 return _getIndexDataImplementation<char>( data );
141 case Qt3DRender::QAttribute::VertexBaseType::UnsignedByte:
142 return _getIndexDataImplementation<uchar>( data );
144 QgsDebugMsg(
"Probably trying to get index data using an attribute that has vertex data" );
147 return QVector<uint>();
150 QByteArray
getData( Qt3DRender::QBuffer *buffer )
152 QByteArray bytes = buffer->data();
153 Qt3DRender::QBufferDataGeneratorPtr dataGenerator = buffer->dataGenerator();
154 if ( bytes.isNull() )
156 if ( !dataGenerator.isNull() )
157 bytes = dataGenerator->operator()();
164 Qt3DRender::QAttribute *
findAttribute( Qt3DRender::QGeometry *geometry,
const QString &name, Qt3DRender::QAttribute::AttributeType type )
166 for ( Qt3DRender::QAttribute *attribute : geometry->attributes() )
168 if ( attribute->attributeType() != type )
continue;
169 if ( attribute->name() == name )
return attribute;
174 template<
typename Component>
177 if ( entity ==
nullptr )
return nullptr;
178 for ( Qt3DCore::QComponent *component : entity->components() )
180 Component *typedComponent = qobject_cast<Component *>( component );
181 if ( typedComponent !=
nullptr )
182 return typedComponent;
190 QString rendererType = abstractRenderer->
type();
192 if ( rendererType ==
"mesh" )
199 if ( rendererType ==
"rulebased" )
202 QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
203 for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
205 Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( renderer->parent() );
206 if ( entity ==
nullptr )
continue;
207 Qgs3DExportObject *
object = processGeometryRenderer( renderer, layer->
name() + QStringLiteral(
"_" ) );
208 if (
object ==
nullptr )
continue;
209 if ( mExportTextures )
210 processEntityMaterial( entity,
object );
211 mObjects.push_back(
object );
219 bool exported = symbol->
exportGeometries(
this, entity, layer->
name() + QStringLiteral(
"_" ) );
226 void Qgs3DSceneExporter::processEntityMaterial( Qt3DCore::QEntity *entity,
Qgs3DExportObject *
object )
228 Qt3DExtras::QPhongMaterial *phongMaterial = findTypedComponent<Qt3DExtras::QPhongMaterial>( entity );
229 if ( phongMaterial !=
nullptr )
232 object->setupMaterial( &material );
234 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
235 Qt3DExtras::QDiffuseMapMaterial *diffuseMapMaterial = findTypedComponent<Qt3DExtras::QDiffuseMapMaterial>( entity );
237 Qt3DExtras::QDiffuseSpecularMaterial *diffuseMapMaterial = findTypedComponent<Qt3DExtras::QDiffuseSpecularMaterial>( entity );
240 if ( diffuseMapMaterial !=
nullptr )
242 #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
243 QVector<Qt3DRender::QAbstractTextureImage *> textureImages = diffuseMapMaterial->diffuse()->textureImages();
245 QVector<Qt3DRender::QAbstractTextureImage *> textureImages = diffuseMapMaterial->diffuse().value< Qt3DRender::QTexture2D * >()->textureImages();
248 for ( Qt3DRender::QAbstractTextureImage *tex : textureImages )
251 if ( imageTexture !=
nullptr )
break;
253 if ( imageTexture !=
nullptr )
255 QImage image = imageTexture->
getImage();
256 object->setTextureImage( image );
264 QgsChunkNode *node = terrain->rootNode();
267 QgsTerrainTileEntity *terrainTile =
nullptr;
268 QgsTerrainTextureGenerator *textureGenerator = terrain->textureGenerator();
269 textureGenerator->waitForFinished();
270 QSize oldResolution = textureGenerator->textureSize();
271 textureGenerator->setTextureSize( QSize( mTerrainTextureResolution, mTerrainTextureResolution ) );
272 switch ( generator->
type() )
275 terrainTile = getDemTerrainEntity( terrain, node );
276 parseDemTile( terrainTile, layerName + QStringLiteral(
"_" ) );
279 terrainTile = getFlatTerrainEntity( terrain, node );
280 parseFlatTile( terrainTile, layerName + QStringLiteral(
"_" ) );
284 terrainTile = getMeshTerrainEntity( terrain, node );
285 parseMeshTile( terrainTile, layerName + QStringLiteral(
"_" ) );
290 textureGenerator->setTextureSize( oldResolution );
293 QgsTerrainTileEntity *Qgs3DSceneExporter::getFlatTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
296 FlatTerrainChunkLoader *flatTerrainLoader = qobject_cast<FlatTerrainChunkLoader *>( generator->
createChunkLoader( node ) );
297 if ( mExportTextures )
298 terrain->textureGenerator()->waitForFinished();
300 Qt3DCore::QEntity *entity = flatTerrainLoader->createEntity(
this );
301 QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( entity );
305 QgsTerrainTileEntity *Qgs3DSceneExporter::getDemTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
311 QgsDemTerrainTileLoader *loader = qobject_cast<QgsDemTerrainTileLoader *>( generator->
createChunkLoader( node ) );
313 if ( mExportTextures )
314 terrain->textureGenerator()->waitForFinished();
315 QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( loader->createEntity(
this ) );
320 QgsTerrainTileEntity *Qgs3DSceneExporter::getMeshTerrainEntity( QgsTerrainEntity *terrain, QgsChunkNode *node )
322 QgsMeshTerrainGenerator *generator =
dynamic_cast<QgsMeshTerrainGenerator *
>( terrain->map3D().terrainGenerator() );
323 QgsMeshTerrainTileLoader *loader = qobject_cast<QgsMeshTerrainTileLoader *>( generator->createChunkLoader( node ) );
325 QgsTerrainTileEntity *tileEntity = qobject_cast<QgsTerrainTileEntity *>( loader->createEntity(
this ) );
329 void Qgs3DSceneExporter::parseFlatTile( QgsTerrainTileEntity *tileEntity,
const QString &layerName )
331 Qt3DRender::QGeometryRenderer *mesh = findTypedComponent<Qt3DRender::QGeometryRenderer>( tileEntity );
332 Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( tileEntity );
334 Qt3DRender::QGeometry *geometry = mesh->geometry();
335 Qt3DExtras::QPlaneGeometry *tileGeometry = qobject_cast<Qt3DExtras::QPlaneGeometry *>( geometry );
336 if ( tileGeometry ==
nullptr )
338 QgsDebugMsg(
"Qt3DExtras::QPlaneGeometry* is expected but something else was given" );
342 float scale = transform->scale();
343 QVector3D translation = transform->translation();
346 Qt3DRender::QAttribute *positionAttribute = tileGeometry->positionAttribute();
347 QByteArray verticesBytes =
getData( positionAttribute->buffer() );
348 QVector<float> positionBuffer = getAttributeData<float>( positionAttribute, verticesBytes );
351 Qt3DRender::QAttribute *indexAttribute = tileGeometry->indexAttribute();
352 QByteArray indexBytes =
getData( indexAttribute->buffer() );
353 QVector<uint> indexesBuffer =
getIndexData( indexAttribute, indexBytes );
355 QString objectNamePrefix = layerName;
356 if ( objectNamePrefix != QString() ) objectNamePrefix += QString();
359 mObjects.push_back(
object );
361 object->setSmoothEdges( mSmoothEdges );
362 object->setupPositionCoordinates( positionBuffer,
scale, translation );
363 object->setupFaces( indexesBuffer );
365 if ( mExportNormals )
368 QVector<float> normalsBuffer;
369 for (
int i = 0; i < positionBuffer.size(); i += 3 ) normalsBuffer << 0.0f << 1.0f << 0.0f;
370 object->setupNormalCoordinates( normalsBuffer );
373 Qt3DRender::QAttribute *texCoordsAttribute = tileGeometry->texCoordAttribute();
374 if ( mExportTextures && texCoordsAttribute !=
nullptr )
377 QVector<float> texCoords = getAttributeData<float>( texCoordsAttribute, verticesBytes );
378 object->setupTextureCoordinates( texCoords );
380 QgsTerrainTextureImage *textureImage = tileEntity->textureImage();
381 QImage img = textureImage->getImage();
382 object->setTextureImage( img );
386 void Qgs3DSceneExporter::parseDemTile( QgsTerrainTileEntity *tileEntity,
const QString &layerName )
388 Qt3DRender::QGeometryRenderer *mesh = findTypedComponent<Qt3DRender::QGeometryRenderer>( tileEntity );
389 Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( tileEntity );
391 Qt3DRender::QGeometry *geometry = mesh->geometry();
392 DemTerrainTileGeometry *tileGeometry = qobject_cast<DemTerrainTileGeometry *>( geometry );
393 if ( tileGeometry ==
nullptr )
395 QgsDebugMsg(
"DemTerrainTileGeometry* is expected but something else was given" );
399 float scale = transform->scale();
400 QVector3D translation = transform->translation();
402 Qt3DRender::QAttribute *positionAttribute = tileGeometry->positionAttribute();
403 QByteArray positionBytes = positionAttribute->buffer()->data();
404 QVector<float> positionBuffer = getAttributeData<float>( positionAttribute, positionBytes );
406 Qt3DRender::QAttribute *indexAttribute = tileGeometry->indexAttribute();
407 QByteArray indexBytes = indexAttribute->buffer()->data();
408 QVector<unsigned int> indexBuffer =
getIndexData( indexAttribute, indexBytes );
410 QString objectNamePrefix = layerName;
411 if ( objectNamePrefix != QString() ) objectNamePrefix += QStringLiteral(
"_" );
414 mObjects.push_back(
object );
416 object->setSmoothEdges( mSmoothEdges );
417 object->setupPositionCoordinates( positionBuffer,
scale, translation );
418 object->setupFaces( indexBuffer );
420 Qt3DRender::QAttribute *normalsAttributes = tileGeometry->normalAttribute();
421 if ( mExportNormals && normalsAttributes !=
nullptr )
423 QByteArray normalsBytes = normalsAttributes->buffer()->data();
424 QVector<float> normalsBuffer = getAttributeData<float>( normalsAttributes, normalsBytes );
425 object->setupNormalCoordinates( normalsBuffer );
428 Qt3DRender::QAttribute *texCoordsAttribute = tileGeometry->texCoordsAttribute();
429 if ( mExportTextures && texCoordsAttribute !=
nullptr )
431 QByteArray texCoordsBytes = texCoordsAttribute->buffer()->data();
432 QVector<float> texCoordsBuffer = getAttributeData<float>( texCoordsAttribute, texCoordsBytes );
433 object->setupTextureCoordinates( texCoordsBuffer );
435 QgsTerrainTextureImage *textureImage = tileEntity->textureImage();
436 QImage img = textureImage->getImage();
437 object->setTextureImage( img );
441 void Qgs3DSceneExporter::parseMeshTile( QgsTerrainTileEntity *tileEntity,
const QString &layerName )
443 QString objectNamePrefix = layerName;
444 if ( objectNamePrefix != QString() ) objectNamePrefix += QStringLiteral(
"_" );
446 QList<Qt3DRender::QGeometryRenderer *> renderers = tileEntity->findChildren<Qt3DRender::QGeometryRenderer *>();
447 for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
450 if ( obj ==
nullptr )
continue;
455 QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processInstancedPointGeometry( Qt3DCore::QEntity *entity,
const QString &objectNamePrefix )
457 QVector<Qgs3DExportObject *> objects;
458 QList<Qt3DRender::QGeometry *> geometriesList = entity->findChildren<Qt3DRender::QGeometry *>();
459 for ( Qt3DRender::QGeometry *geometry : geometriesList )
461 Qt3DRender::QAttribute *positionAttribute =
findAttribute( geometry, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
462 Qt3DRender::QAttribute *indexAttribute =
nullptr;
463 for ( Qt3DRender::QAttribute *attribute : geometry->attributes() )
465 if ( attribute->attributeType() == Qt3DRender::QAttribute::IndexAttribute )
466 indexAttribute = attribute;
468 if ( positionAttribute ==
nullptr || indexAttribute ==
nullptr )
470 QByteArray vertexBytes =
getData( positionAttribute->buffer() );
471 QByteArray indexBytes =
getData( indexAttribute->buffer() );
472 QVector<float> positionData = getAttributeData<float>( positionAttribute, vertexBytes );
473 QVector<uint> indexData =
getIndexData( indexAttribute, indexBytes );
475 Qt3DRender::QAttribute *instanceDataAttribute =
findAttribute( geometry, QStringLiteral(
"pos" ), Qt3DRender::QAttribute::VertexAttribute );
476 QByteArray instancePositionBytes =
getData( instanceDataAttribute->buffer() );
477 QVector<float> instancePosition = getAttributeData<float>( instanceDataAttribute, instancePositionBytes );
478 for (
int i = 0; i < instancePosition.size(); i += 3 )
481 objects.push_back(
object );
482 object->setupPositionCoordinates( positionData, 1.0f, QVector3D( instancePosition[i], instancePosition[i + 1], instancePosition[i + 2] ) );
483 object->setupFaces( indexData );
485 object->setSmoothEdges( mSmoothEdges );
487 Qt3DRender::QAttribute *normalsAttribute =
findAttribute( geometry, Qt3DRender::QAttribute::defaultNormalAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
488 if ( mExportNormals && normalsAttribute !=
nullptr )
491 QVector<float> normalsData = getAttributeData<float>( normalsAttribute, vertexBytes );
492 object->setupNormalCoordinates( normalsData );
499 QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processSceneLoaderGeometries( Qt3DRender::QSceneLoader *sceneLoader,
const QString &objectNamePrefix )
501 QVector<Qgs3DExportObject *> objects;
502 Qt3DCore::QEntity *sceneLoaderParent = qobject_cast<Qt3DCore::QEntity *>( sceneLoader->parent() );
503 Qt3DCore::QTransform *entityTransform = findTypedComponent<Qt3DCore::QTransform>( sceneLoaderParent );
504 float sceneScale = 1.0f;
505 QVector3D sceneTranslation( 0.0f, 0.0f, 0.0f );
506 if ( entityTransform !=
nullptr )
508 sceneScale = entityTransform->scale();
509 sceneTranslation = entityTransform->translation();
511 for ( QString entityName : sceneLoader->entityNames() )
513 Qt3DRender::QGeometryRenderer *mesh = qobject_cast<Qt3DRender::QGeometryRenderer *>( sceneLoader->component( entityName, Qt3DRender::QSceneLoader::GeometryRendererComponent ) );
514 Qgs3DExportObject *
object = processGeometryRenderer( mesh, objectNamePrefix, sceneScale, sceneTranslation );
515 if (
object ==
nullptr )
continue;
516 objects.push_back(
object );
521 Qgs3DExportObject *Qgs3DSceneExporter::processGeometryRenderer( Qt3DRender::QGeometryRenderer *mesh,
const QString &objectNamePrefix,
float sceneScale, QVector3D sceneTranslation )
524 if ( mesh->primitiveType() != Qt3DRender::QGeometryRenderer::Triangles )
return nullptr;
527 QVector3D translation( 0.0f, 0.0f, 0.0f );
528 QObject *parent = mesh->parent();
529 while ( parent !=
nullptr )
531 Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( parent );
532 Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( entity );
533 if ( transform !=
nullptr )
535 scale *= transform->scale();
536 translation += transform->translation();
538 parent = parent->parent();
541 Qt3DRender::QGeometry *geometry = mesh->geometry();
543 Qt3DRender::QAttribute *positionAttribute =
findAttribute( geometry, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
544 Qt3DRender::QAttribute *indexAttribute =
nullptr;
545 QByteArray indexBytes, vertexBytes;
546 QVector<uint> indexData;
547 QVector<float> positionData;
548 for ( Qt3DRender::QAttribute *attribute : geometry->attributes() )
550 if ( attribute->attributeType() == Qt3DRender::QAttribute::IndexAttribute )
551 indexAttribute = attribute;
554 if ( indexAttribute !=
nullptr )
556 indexBytes =
getData( indexAttribute->buffer() );
560 if ( positionAttribute !=
nullptr )
562 vertexBytes =
getData( positionAttribute->buffer() );
563 positionData = getAttributeData<float>( positionAttribute, vertexBytes );
567 if ( positionAttribute !=
nullptr && indexAttribute ==
nullptr )
569 for (
int i = 0; i < positionData.size() / 3; ++i )
570 indexData.push_back( i );
573 if ( positionAttribute ==
nullptr )
575 QgsDebugMsg(
"Geometry renderer with null data was being processed" );
580 object->setupPositionCoordinates( positionData,
scale * sceneScale, translation + sceneTranslation );
581 object->setupFaces( indexData );
583 Qt3DRender::QAttribute *normalsAttribute =
findAttribute( geometry, Qt3DRender::QAttribute::defaultNormalAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
584 if ( mExportNormals && normalsAttribute !=
nullptr )
587 QVector<float> normalsData = getAttributeData<float>( normalsAttribute, vertexBytes );
588 object->setupNormalCoordinates( normalsData );
591 Qt3DRender::QAttribute *texCoordsAttribute =
findAttribute( geometry, Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
592 if ( mExportTextures && texCoordsAttribute !=
nullptr )
595 QVector<float> texCoordsData = getAttributeData<float>( texCoordsAttribute, vertexBytes );
596 object->setupTextureCoordinates( texCoordsData );
602 QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processLines( Qt3DCore::QEntity *entity,
const QString &objectNamePrefix )
604 QVector<Qgs3DExportObject *> objs;
605 QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
606 for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
608 if ( renderer->primitiveType() != Qt3DRender::QGeometryRenderer::LineStripAdjacency )
continue;
609 Qt3DRender::QGeometry *geom = renderer->geometry();
610 Qt3DRender::QAttribute *positionAttribute =
findAttribute( geom, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
611 Qt3DRender::QAttribute *indexAttribute =
nullptr;
612 for ( Qt3DRender::QAttribute *attribute : geom->attributes() )
614 if ( attribute->attributeType() == Qt3DRender::QAttribute::IndexAttribute )
616 indexAttribute = attribute;
620 if ( positionAttribute ==
nullptr || indexAttribute ==
nullptr )
622 QgsDebugMsg(
"Position or index attribute was not found" );
626 QByteArray vertexBytes =
getData( positionAttribute->buffer() );
627 QByteArray indexBytes =
getData( indexAttribute->buffer() );
628 QVector<float> positionData = getAttributeData<float>( positionAttribute, vertexBytes );
629 QVector<uint> indexData =
getIndexData( indexAttribute, indexBytes );
636 objs.push_back( exportObject );
641 Qgs3DExportObject *Qgs3DSceneExporter::processPoints( Qt3DCore::QEntity *entity,
const QString &objectNamePrefix )
643 QVector<float> points;
644 QList<Qt3DRender::QGeometryRenderer *> renderers = entity->findChildren<Qt3DRender::QGeometryRenderer *>();
645 for ( Qt3DRender::QGeometryRenderer *renderer : renderers )
647 Qt3DRender::QGeometry *geometry = qobject_cast<QgsBillboardGeometry *>( renderer->geometry() );
648 if ( geometry ==
nullptr )
650 Qt3DRender::QAttribute *positionAttribute =
findAttribute( geometry, Qt3DRender::QAttribute::defaultPositionAttributeName(), Qt3DRender::QAttribute::VertexAttribute );
651 QByteArray positionBytes =
getData( positionAttribute->buffer() );
652 if ( positionBytes.size() == 0 )
654 QVector<float> positions = getAttributeData<float>( positionAttribute, positionBytes );
665 QString objFilePath = QDir( sceneFolderPath ).filePath( sceneName + QStringLiteral(
".obj" ) );
666 QString mtlFilePath = QDir( sceneFolderPath ).filePath( sceneName + QStringLiteral(
".mtl" ) );
668 QFile file( objFilePath );
669 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
671 QFile mtlFile( mtlFilePath );
672 if ( !mtlFile.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
675 float maxfloat = std::numeric_limits<float>::max(), minFloat = std::numeric_limits<float>::lowest();
676 float minX = maxfloat, minY = maxfloat, minZ = maxfloat, maxX = minFloat, maxY = minFloat, maxZ = minFloat;
679 float diffX = 1.0f, diffY = 1.0f, diffZ = 1.0f;
684 float centerX = ( minX + maxX ) / 2.0f;
685 float centerY = ( minY + maxY ) / 2.0f;
686 float centerZ = ( minZ + maxZ ) / 2.0f;
688 float scale = std::max( diffX, std::max( diffY, diffZ ) );
690 QTextStream out( &file );
692 QString mtlLibName = sceneName +
".mtl";
693 out <<
"mtllib " << mtlLibName <<
"\n";
695 QTextStream mtlOut( &mtlFile );
698 if ( obj ==
nullptr )
continue;
700 QString material = obj->
saveMaterial( mtlOut, sceneFolderPath );
701 out <<
"o " << obj->
name() <<
"\n";
702 if ( material != QString() )
703 out <<
"usemtl " << material <<
"\n";
704 obj->
saveTo( out,
scale / mScale, QVector3D( centerX, centerY, centerZ ) );
708 QString Qgs3DSceneExporter::getObjectName(
const QString &name )
711 if ( usedObjectNamesCounter.contains( name ) )
713 ret = QStringLiteral(
"%1%2" ).arg( name ).arg( usedObjectNamesCounter[name] );
714 usedObjectNamesCounter[name]++;
717 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)