Skip to content

Commit

Permalink
initial implementation of the scene exporter class
Browse files Browse the repository at this point in the history
  • Loading branch information
NEDJIMAbelgacem committed Jun 28, 2020
1 parent 9b8e983 commit 273b8f3
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/3d/CMakeLists.txt
Expand Up @@ -68,6 +68,7 @@ SET(QGIS_3D_SRCS
mesh/qgsmesh3dentity_p.cpp
mesh/qgsmesh3dmaterial_p.cpp
mesh/qgsmeshterraingenerator.cpp
qgs3dsceneexporter.cpp

)

Expand Down Expand Up @@ -110,6 +111,7 @@ SET(QGIS_3D_HDRS
chunks/qgschunkloader_p.h
chunks/qgschunkqueuejob_p.h
mesh/qgsmeshterraingenerator.h
qgs3dsceneexporter.h
)

SET(QGIS_3D_PRIVATE_HDRS
Expand Down
14 changes: 14 additions & 0 deletions src/3d/qgs3dmapscene.cpp
Expand Up @@ -57,6 +57,8 @@
#include "qgsmaplayertemporalproperties.h"

#include "qgslinematerial_p.h"
#include "qgs3dsceneexporter.h"
#include "qgsabstract3drenderer.h"

Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine *engine )
: mMap( map )
Expand Down Expand Up @@ -763,3 +765,15 @@ void Qgs3DMapScene::updateSceneState()

setSceneState( Ready );
}

void Qgs3DMapScene::exportScene(const QString& sceneName, const QString& sceneDir) {
Qgs3DSceneExporter exporter;

for ( QgsMapLayer * layer : mLayerEntities.keys() ) {
exporter.parseEntity(mLayerEntities[layer]);
}
QString filePath = sceneDir;
if (!filePath.endsWith('/')) filePath.push_back('/');
filePath += sceneName + ".obj";
exporter.saveToFile(filePath);
}
1 change: 1 addition & 0 deletions src/3d/qgs3dmapscene.h
Expand Up @@ -102,6 +102,7 @@ class _3D_EXPORT Qgs3DMapScene : public Qt3DCore::QEntity
*/
float worldSpaceError( float epsilon, float distance );

void exportScene(const QString& sceneName, const QString& sceneDir);
signals:
//! Emitted when the current terrain entity is replaced by a new one
void terrainEntityChanged();
Expand Down
111 changes: 111 additions & 0 deletions src/3d/qgs3dsceneexporter.cpp
@@ -0,0 +1,111 @@
#include "qgs3dsceneexporter.h"

#include <QDebug>
#include <QVector>
#include <Qt3DCore/QEntity>
#include <Qt3DCore/QComponent>
#include <Qt3DCore/QNode>
#include <Qt3DRender/QGeometry>
#include <Qt3DRender/QAttribute>
#include <Qt3DRender/QBuffer>
#include <Qt3DRender/QGeometryRenderer>
#include <qgstessellatedpolygongeometry.h>
#include <qgs3dmapscene.h>
#include <QByteArray>
#include <QFile>
#include <QTextStream>
#include <QtMath>

Qgs3DSceneExporter::Qgs3DSceneExporter( )
: mVertices(QVector<float>())
{

}


void Qgs3DSceneExporter::parseEntity(Qt3DCore::QEntity* entity) {
if (entity == nullptr) return;
for (Qt3DCore::QComponent *c : entity->components()) {
Qt3DRender::QGeometryRenderer* comp = qobject_cast<Qt3DRender::QGeometryRenderer*>(c);
if (comp == nullptr) continue;
Qt3DRender::QGeometry* geom = comp->geometry();
QgsTessellatedPolygonGeometry* polygonGeometry = qobject_cast<QgsTessellatedPolygonGeometry*>(geom);
if (geom == nullptr) continue;
if (polygonGeometry != nullptr) processGeometry(polygonGeometry);
// for (Qt3DRender::QAttribute* attribute : geom->attributes()) {
// processAttribute(attribute);
// }
}
for (QObject* child : entity->children()) {
Qt3DCore::QEntity* childEntity = qobject_cast<Qt3DCore::QEntity*>( child );
if (childEntity != nullptr) parseEntity(childEntity);
}
}

void Qgs3DSceneExporter::processAttribute(Qt3DRender::QAttribute* attribute) {
qDebug() << __PRETTY_FUNCTION__;
Qt3DRender::QBuffer* buffer = attribute->buffer();
QByteArray bufferData = buffer->data();
uint bytesOffset = attribute->byteOffset();
uint bytesStride = attribute->byteStride();
uint verticesCount = attribute->count();
uint vertexSize = attribute->vertexSize();

QDataStream stream(bufferData);

for (int offset = bytesOffset; offset < vertexSize * verticesCount * bytesStride; offset += bytesStride) {
QVector<float> verticeData;
for (int i = 0; i < vertexSize; ++i) {
float v;
stream >> v;
if (qIsInf(v)) break;
verticeData.push_back(v);
}
if (verticeData.size() == vertexSize) {
mVertices.append(verticeData);
qDebug() << "v" << verticeData[0] << verticeData[1] << verticeData[2];
}
}
}

void Qgs3DSceneExporter::saveToFile(const QString& filePath) {
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return;

qDebug() << filePath;
QTextStream out(&file);

// Construct vertices
for (int i = 0; i < mVertices.size(); i += 3) {
out << "v " << mVertices[i] << " " << mVertices[i + 1] << " " << mVertices[i + 2] << "\n";
// qDebug() << "v " << mVertices[i] << " " << mVertices[i + 1] << " " << mVertices[i + 2] << "\n";

}
// Construct faces
for (int i = 0; i < mVertices.size() / 9; ++i) {
out << "f " << 3 * i + 1 << " " << 3 * i + 2 << " " << 3 * i + 3 << "\n";
// qDebug() << "f " << 3 * i << " " << 3 * i + 1 << " " << 3 * i + 2 << "\n";
}
}

void Qgs3DSceneExporter::processGeometry(QgsTessellatedPolygonGeometry* geom) {
QByteArray data = geom->mVertexBuffer->data();
Qt3DRender::QAttribute* attribute = geom->mPositionAttribute;
uint bytesOffset = attribute->byteOffset();
uint bytesStride = attribute->byteStride();
uint verticesCount = attribute->count();
uint vertexSize = attribute->vertexSize();

QVector<float> floatData;
QDataStream dataStream(data);
while (!dataStream.atEnd()) {
float f;
dataStream >> f;
floatData.push_back(f);
}

for (int i = 0; i < floatData.size(); i += bytesStride / sizeof(float)) {
mVertices << floatData[i] << floatData[i + 1] << floatData[i + 2];
}
}
26 changes: 26 additions & 0 deletions src/3d/qgs3dsceneexporter.h
@@ -0,0 +1,26 @@
#ifndef QGS3DSCENEEXPORTER_H
#define QGS3DSCENEEXPORTER_H

#include <Qt3DCore/QEntity>
#include <Qt3DRender/QGeometry>
#include <Qt3DRender/QAttribute>

class QgsTessellatedPolygonGeometry;
class Qgs3DMapSettings;

class Qgs3DSceneExporter
{

public:
Qgs3DSceneExporter( );

void parseEntity(Qt3DCore::QEntity* entity);
void saveToFile(const QString& filePath);
private:
void processAttribute(Qt3DRender::QAttribute* attribute);
void processGeometry(QgsTessellatedPolygonGeometry* geom);
private:
QVector<float> mVertices;
};

#endif // QGS3DSCENEEXPORTER_H
5 changes: 5 additions & 0 deletions src/3d/qgstessellatedpolygongeometry.h
Expand Up @@ -21,6 +21,8 @@

#include <Qt3DRender/QGeometry>

class Qgs3DSceneExporter;

namespace Qt3DRender
{
class QBuffer;
Expand Down Expand Up @@ -79,12 +81,15 @@ class QgsTessellatedPolygonGeometry : public Qt3DRender::QGeometry
*/
QgsFeatureId triangleIndexToFeatureId( uint triangleIndex ) const;

friend class Qgs3DSceneExporter;
private:

Qt3DRender::QAttribute *mPositionAttribute = nullptr;
Qt3DRender::QAttribute *mNormalAttribute = nullptr;
Qt3DRender::QBuffer *mVertexBuffer = nullptr;

QVector<float> mVertexData;

QVector<QgsFeatureId> mTriangleIndexFids;
QVector<uint> mTriangleIndexStartingIndices;

Expand Down
16 changes: 16 additions & 0 deletions src/app/3d/qgs3dmapcanvasdockwidget.cpp
Expand Up @@ -44,6 +44,8 @@
#include "qgs3dmaptoolmeasureline.h"
#include "qgs3dutils.h"

#include "qgs3dsceneexporter.h"
#include "qgsabstract3drenderer.h"


Qgs3DMapCanvasDockWidget::Qgs3DMapCanvasDockWidget( QWidget *parent )
Expand Down Expand Up @@ -99,6 +101,9 @@ Qgs3DMapCanvasDockWidget::Qgs3DMapCanvasDockWidget( QWidget *parent )
toolBar->addAction( QgsApplication::getThemeIcon( QStringLiteral( "mActionSaveMapAsImage.svg" ) ),
tr( "Save as Image…" ), this, &Qgs3DMapCanvasDockWidget::saveAsImage );

toolBar->addAction( QIcon( QgsApplication::iconPath( "mActionSaveMapAsImage.svg" ) ),
tr( "Export 3D Scene" ), this, &Qgs3DMapCanvasDockWidget::exportScene );

toolBar->addSeparator();

// Map Theme Menu
Expand Down Expand Up @@ -170,6 +175,17 @@ void Qgs3DMapCanvasDockWidget::saveAsImage()
}
}


void Qgs3DMapCanvasDockWidget::exportScene()
{

QgsSettings settings; // where we keep last used filter in persistent state
QString initialPath = settings.value( QStringLiteral( "UI/lastExportAsDir" ), QDir::homePath() ).toString();
QString outputDir = QFileDialog::getExistingDirectory(this, QString("Export scane"), initialPath);

mCanvas->scene()->exportScene("scene", outputDir);
}

void Qgs3DMapCanvasDockWidget::toggleAnimations()
{
if ( mAnimationWidget->isVisible() )
Expand Down
1 change: 1 addition & 0 deletions src/app/3d/qgs3dmapcanvasdockwidget.h
Expand Up @@ -59,6 +59,7 @@ class APP_EXPORT Qgs3DMapCanvasDockWidget : public QgsDockWidget
void cameraControl();
void identify();
void measureLine();
void exportScene();
void toggleNavigationWidget( bool visibility );

void onMainCanvasLayersChanged();
Expand Down

0 comments on commit 273b8f3

Please sign in to comment.