Skip to content
Permalink
Browse files

Added normals export

  • Loading branch information
NEDJIMAbelgacem committed Jul 6, 2020
1 parent b3a2a3c commit ed2ebeb27e75422360cd4bf81ddb0cdcdc45d829
@@ -16,6 +16,7 @@
#include "qgs3dexportobject.h"

#include <QVector3D>
#include <QDebug>

Qgs3DExportObject::Qgs3DExportObject( const QString &name, const QString &parentName, QObject *parent )
: QObject( parent )
@@ -54,11 +55,17 @@ void Qgs3DExportObject::setupPositionCoordinates( const QVector<float> &position

for ( int i = 0; i < faceIndex.size(); i += 3 )
{
// skip invalid triangles
if ( faceIndex[i] == faceIndex[i + 1] && faceIndex[i + 1] == faceIndex[i + 2] ) continue;
for ( int j = 0; j < 3; ++j ) mIndexes << faceIndex[i + j] + 1;
}
}

void Qgs3DExportObject::setupNormalCoordinates( const QVector<float> &normalsBuffer )
{
mNormals << normalsBuffer;
}

void Qgs3DExportObject::objectBounds( float &minX, float &minY, float &minZ, float &maxX, float &maxY, float &maxZ )
{
for ( int vertice : mIndexes )
@@ -94,13 +101,37 @@ void Qgs3DExportObject::saveTo( QTextStream &out, int scale, const QVector3D &ce
out << ( mVertxPosition[i] - center.x() ) / scale << " ";
out << ( mVertxPosition[i + 1] - center.y() ) / scale << " ";
out << ( mVertxPosition[i + 2] - center.z() ) / scale << "\n";
if ( i + 3 <= mNormals.size() )
{
out << "vn " << mNormals[i] << " " << mNormals[i + 1] << " " << mNormals[i + 2] << "\n";
}
}

// Construct faces
bool hasTextures = false;
// if the object has normals then the normals and positions buffers should be the same size
bool hasNormals = mNormals.size() == mVertxPosition.size();
if ( !hasNormals && !mNormals.empty() )
{
qDebug() << "WARNING: vertex normals count and vertex positions count are different";
}
int verticesCount = mVertxPosition.size() / 3;

auto getVertexIndex = [&]( int i ) -> QString
{
int negativeIndex = -1 - ( verticesCount - i );
if ( !hasNormals && !hasTextures ) return QString( "%1" ).arg( negativeIndex );
if ( hasNormals && !hasTextures ) return QString( "%1//%2" ).arg( negativeIndex ).arg( negativeIndex );
// TODO: handle other cases
return QString( "%1" ).arg( negativeIndex );
};

// Construct faces
for ( int i = 0; i < mIndexes.size(); i += 3 )
{
if ( mIndexes[i] == mIndexes[i + 1] && mIndexes[i + 1] == mIndexes[i + 2] ) continue;
out << "f " << -1 - ( verticesCount - mIndexes[i] ) << " " << -1 - ( verticesCount - mIndexes[i + 1] ) << " " << -1 - ( verticesCount - mIndexes[i + 2] ) << "\n";
out << "f " << getVertexIndex( mIndexes[i] );
out << " " << getVertexIndex( mIndexes[i + 1] );
out << " " << getVertexIndex( mIndexes[i + 2] );
out << "\n";
}
}
@@ -54,6 +54,9 @@ class Qgs3DExportObject : public QObject
//! Sets positions coordinates from just one positions buffer and indexes buffer and does the translation and scaling
void setupPositionCoordinates( const QVector<float> &positionsBuffer, const QVector<unsigned int> &facesIndexes, float scale = 1.0f, const QVector3D translation = QVector3D( 0, 0, 0 ) );

//! setss normal coordinates for each vertex
void setupNormalCoordinates( const QVector<float> &normalsBuffer );

/**
* Updates the box bounds explained with the current object bounds
* This expands the bounding box if the current object outside the bounds of the already established bounds
@@ -66,6 +69,7 @@ class Qgs3DExportObject : public QObject
QString mName;
QString mParentName;
QVector<float> mVertxPosition;
QVector<float> mNormals;
QVector<int> mIndexes;

bool mSmoothEdges;
@@ -43,6 +43,8 @@ class _3D_EXPORT Qgs3DMapExportSettings : public QObject
int terrrainResolution() const { return mTerrainResolution; }
//! Returns whether triangles edges will look smooth
bool smoothEdges() const { return mSmoothEdges; }
//! Returns whether normals will be exported
bool exportNormals() const { return mExportNormals; }

//! Sets the scene name
void setSceneName( const QString &sceneName ) { mSceneName = sceneName; }
@@ -52,6 +54,8 @@ class _3D_EXPORT Qgs3DMapExportSettings : public QObject
void setTerrainResolution( int resolution ) { mTerrainResolution = resolution; }
//! Sets whether triangles edges will look smooth
void setSmoothEdges( bool smoothEdges ) { mSmoothEdges = smoothEdges; }
//! Sets whether normals should be exported
void setExportNormals( bool exportNormals ) { mExportNormals = exportNormals; }
//! Returns a path to a file that with the "name.extension" in the export folder
QString getFilePath( const QString &name, const QString &extension ) const
{
@@ -62,6 +66,7 @@ class _3D_EXPORT Qgs3DMapExportSettings : public QObject
QString mSceneFolderPath = QDir::homePath();
int mTerrainResolution = 128;
bool mSmoothEdges = false;
bool mExportNormals = true;
};

#endif // QGS3DMAPEXPORTSETTINGS_H
@@ -773,6 +773,7 @@ void Qgs3DMapScene::exportScene( const Qgs3DMapExportSettings &exportSettings )

exporter.setTerrainResolution( exportSettings.terrrainResolution() );
exporter.setSmoothEdges( exportSettings.smoothEdges() );
exporter.setExportNormals( exportSettings.exportNormals() );

for ( QgsMapLayer *layer : mLayerEntities.keys() )
{
@@ -55,12 +55,12 @@ QVector<T> getAttributeData( Qt3DRender::QAttribute *attribute )
QVector<T> result;
for ( int i = bytesOffset; i < data.size(); i += bytesStride )
{
for ( int j = 0; j < vertexSize * sizeof( T ); j += sizeof( T ) )
for ( unsigned int j = 0; j < vertexSize * sizeof( T ); j += sizeof( T ) )
{
// maybe a problem with indienness can happen?
T v;
char *vArr = ( char * )&v;
for ( int k = 0; k < sizeof( T ); ++k )
for ( unsigned int k = 0; k < sizeof( T ); ++k )
{
vArr[k] = data.at( i + j + k );
}
@@ -163,7 +163,8 @@ QVector<unsigned int> createPlaneIndexData( const QSize &resolution )
Qgs3DSceneExporter::Qgs3DSceneExporter( Qt3DCore::QNode *parent )
: Qt3DCore::QEntity( parent )
, mSmoothEdges( false )
, mTerrainResolution( 64 )
, mTerrainResolution( 128 )
, mExportNormals( true )
{

}
@@ -369,7 +370,6 @@ QgsTerrainTileEntity *Qgs3DSceneExporter::createDEMTileEntity( QgsTerrainEntity
return entity;
}


void Qgs3DSceneExporter::parseFlatTile( QgsTerrainTileEntity *tileEntity )
{
Qt3DRender::QGeometryRenderer *mesh = nullptr;
@@ -447,6 +447,12 @@ void Qgs3DSceneExporter::parseDemTile( QgsTerrainTileEntity *tileEntity )

object->setSmoothEdges( mSmoothEdges );
object->setupPositionCoordinates( positionBuffer, indexBuffer, scale, translation );

if ( mExportNormals )
{
QVector<float> normalsBuffer = getAttributeData<float>( tileGeometry->normalAttribute() );
object->setupNormalCoordinates( normalsBuffer );
}
}

void Qgs3DSceneExporter::processAttribute( Qt3DRender::QAttribute *attribute )
@@ -57,12 +57,17 @@ class Qgs3DSceneExporter : public Qt3DCore::QEntity
//! Sets whether the triangles will look smooth
void setSmoothEdges( bool smoothEdges ) { mSmoothEdges = smoothEdges; }
//! Returns whether the triangles will look smooth
bool smoothEdges() { return mSmoothEdges; }
bool smoothEdges() const { return mSmoothEdges; }

//! Sets whether the normals will be exported
void setExportNormals( bool exportNormals ) { mExportNormals = exportNormals; }
//! Returns whether the normals will be exported
bool exportNormals() const { return mExportNormals; }

//! Sets the terrian resolution
void setTerrainResolution( int resolution ) { mTerrainResolution = resolution; }
//! Returns the terrain resolution
int terrainResolution() { return mTerrainResolution; }
int terrainResolution() const { return mTerrainResolution; }

private:
//! Processes the attribute directly by taking a position buffer and converting it to Qgs3DExportObject
@@ -90,6 +95,7 @@ class Qgs3DSceneExporter : public Qt3DCore::QEntity

bool mSmoothEdges;
int mTerrainResolution;
bool mExportNormals;
};

#endif // QGS3DSCENEEXPORTER_H
@@ -68,6 +68,7 @@ class DemTerrainTileGeometry : public Qt3DRender::QGeometry
bool rayIntersection( const QgsRayCastingUtils::Ray3D &ray, const QMatrix4x4 &worldTransform, QVector3D &intersectionPoint );

Qt3DRender::QAttribute *positionAttribute() { return mPositionAttribute; }
Qt3DRender::QAttribute *normalAttribute() { return mNormalAttribute; }
Qt3DRender::QAttribute *indexAttribute() { return mIndexAttribute; }

private:
@@ -38,10 +38,16 @@ QgsMap3DExportWidget::QgsMap3DExportWidget( Qgs3DMapScene *scene, Qgs3DMapExport
QString initialPath = settings.value( QStringLiteral( "UI/last3DSceneExportDir" ), QDir::homePath() ).toString();
ui->selectFolderWidget->setDefaultRoot( initialPath );

ui->sceneNameLineEdit->setText( exportSettings->sceneName() );
ui->selectFolderWidget->setFilePath( exportSettings->sceneFolderPath() );
ui->terrainResolutionSpinBox->setValue( exportSettings->terrrainResolution() );
ui->smoothEdgesCheckBox->setChecked( exportSettings->smoothEdges() );

connect( ui->sceneNameLineEdit, &QLineEdit::textChanged, [ = ]( const QString & ) { settingsChanged(); } );
connect( ui->selectFolderWidget, &QgsFileWidget::fileChanged, [ = ]( const QString & ) { settingsChanged(); } );
connect( ui->smoothEdgesCheckBox, &QCheckBox::stateChanged, [ = ]( int ) { settingsChanged(); } );
connect( ui->terrainResolutionSpinBox, qgis::overload<int>::of( &QSpinBox::valueChanged ), [ = ]( int ) { settingsChanged(); } );
connect( ui->exportNormalsCheckBox, &QCheckBox::stateChanged, [ = ]( int ) { settingsChanged(); } );

// sets the export settings to whatever is on the scene
settingsChanged();
@@ -58,6 +64,7 @@ void QgsMap3DExportWidget::settingsChanged()
mExportSettings->setSceneFolderPath( ui->selectFolderWidget->filePath() );
mExportSettings->setTerrainResolution( ui->terrainResolutionSpinBox->value() );
mExportSettings->setSmoothEdges( ui->smoothEdgesCheckBox->isChecked() );
mExportSettings->setExportNormals( ui->exportNormalsCheckBox->isChecked() );
}

void QgsMap3DExportWidget::exportScene()
@@ -13,22 +13,22 @@
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0" colspan="3">
<widget class="QCheckBox" name="smoothEdgesCheckBox">
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Smooth Edges</string>
<string>Terrain resolution</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="folderLAbel">
<item row="0" column="0">
<widget class="QLabel" name="sceneNameLabel">
<property name="text">
<string>Folder</string>
<string>Scene name</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="sceneNameLineEdit"/>
<item row="1" column="1" colspan="2">
<widget class="QgsFileWidget" name="selectFolderWidget" native="true"/>
</item>
<item row="2" column="1" colspan="2">
<widget class="QSpinBox" name="terrainResolutionSpinBox">
@@ -43,7 +43,24 @@
</property>
</widget>
</item>
<item row="4" column="1">
<item row="3" column="0" colspan="3">
<widget class="QCheckBox" name="smoothEdgesCheckBox">
<property name="text">
<string>Smooth Edges</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="sceneNameLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="folderLAbel">
<property name="text">
<string>Folder</string>
</property>
</widget>
</item>
<item row="5" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -56,23 +73,19 @@
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<item row="4" column="0" colspan="3">
<widget class="QCheckBox" name="exportNormalsCheckBox">
<property name="text">
<string>Terrain resolution</string>
<string>Export Normals</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="sceneNameLabel">
<property name="text">
<string>Scene name</string>
<property name="checked">
<bool>true</bool>
</property>
<property name="autoRepeat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QgsFileWidget" name="selectFolderWidget" native="true"/>
</item>
</layout>
</item>
</layout>

0 comments on commit ed2ebeb

Please sign in to comment.
You can’t perform that action at this time.