23#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
24#include <Qt3DRender/QAttribute>
25#include <Qt3DRender/QBuffer>
29#include <Qt3DCore/QAttribute>
30#include <Qt3DCore/QBuffer>
39void Qgs3DExportObject::setupPositionCoordinates(
const QVector<float> &positionsBuffer,
const QMatrix4x4 &transform )
41 mVertexPosition.clear();
42 for (
int i = 0; i < positionsBuffer.size(); i += 3 )
44 const QVector3D position( positionsBuffer[i], positionsBuffer[i + 1], positionsBuffer[i + 2] );
45 const QVector3D positionFinal = transform.map( position );
46 mVertexPosition << positionFinal.x() << positionFinal.y() << positionFinal.z();
53 setupPositionCoordinates( positionsBuffer, transform );
57 for (
int i = 0; i < facesIndexes.size(); i += 3 )
59 if ( i + 2 >= facesIndexes.size() )
62 if ( facesIndexes[i] == facesIndexes[i + 1] || facesIndexes[i + 1] == facesIndexes[i + 2] || facesIndexes[i] == facesIndexes[i + 2] )
64 for (
int j = 0; j < 3; ++j )
65 mIndexes << facesIndexes[i + j];
72 setupPositionCoordinates( positionsBuffer );
76 for (
int i = 0; i < mVertexPosition.size(); i += 3 )
77 mIndexes << i / 3 + 1;
83 setupPositionCoordinates( positionsBuffer );
91 QMatrix3x3 normal3x3 = transform.normalMatrix();
92 QMatrix4x4 normal4x4( normal3x3( 0, 0 ), normal3x3( 0, 1 ), normal3x3( 0, 2 ), 0, normal3x3( 1, 0 ), normal3x3( 1, 1 ), normal3x3( 1, 2 ), 0, normal3x3( 2, 0 ), normal3x3( 2, 1 ), normal3x3( 2, 2 ), 0, 0, 0, 0, 1 );
94 for (
int i = 0; i < normalsBuffer.size(); i += 3 )
96 const QVector3D normalVector( normalsBuffer[i], normalsBuffer[i + 1], normalsBuffer[i + 2] );
97 QVector3D v = normal4x4.mapVector( normalVector );
105 mNormals << v.x() << v.y() << v.z();
112 mTexturesUV << texturesBuffer;
117 mMaterialParameters.clear();
119 for (
auto it = parameters.begin(); it != parameters.end(); ++it )
121 mMaterialParameters[it.key()] = it.value();
129 for (
const unsigned int vertice : qAsConst( mIndexes ) )
131 const int heightIndex =
static_cast<int>( vertice ) * 3 + 1;
132 minX = std::min( minX, mVertexPosition[heightIndex - 1] );
133 maxX = std::max( maxX, mVertexPosition[heightIndex - 1] );
134 minY = std::min( minY, mVertexPosition[heightIndex] );
135 maxY = std::max( maxY, mVertexPosition[heightIndex] );
136 minZ = std::min( minZ, mVertexPosition[heightIndex + 1] );
137 maxZ = std::max( maxZ, mVertexPosition[heightIndex + 1] );
145 out << qSetRealNumberPrecision( precision );
156 for (
const unsigned int vertice : qAsConst( mIndexes ) )
158 const int i =
static_cast<int>( vertice * 3 );
161 out << ( mVertexPosition[i] - center.x() ) / scale <<
" ";
162 out << ( mVertexPosition[i + 1] - center.y() ) / scale <<
" ";
163 out << ( mVertexPosition[i + 2] - center.z() ) / scale <<
"\n";
164 if ( i + 3 <= mNormals.size() )
166 out <<
"vn " << mNormals[i] <<
" " << mNormals[i + 1] <<
" " << mNormals[i + 2] <<
"\n";
168 const int u_index = i / 3 * 2;
169 if ( u_index + 1 < mTexturesUV.size() )
172 out <<
"vt " << mTexturesUV[u_index] <<
" " << 1.0f - mTexturesUV[u_index + 1] <<
"\n";
176 bool hasTextures = mTexturesUV.size() == mVertexPosition.size() / 3 * 2;
178 bool hasNormals = mNormals.size() == mVertexPosition.size();
180 if ( !hasNormals && !mNormals.empty() )
182 QgsDebugError(
"Vertex normals count and vertex positions count are different" );
184 const int verticesCount = mIndexes.size();
188 auto getVertexIndex = [&](
unsigned int i ) -> QString {
189 const int negativeIndex =
static_cast<int>( i - verticesCount );
190 if ( hasNormals && !hasTextures )
191 return QStringLiteral(
"%1//%2" ).arg( negativeIndex ).arg( negativeIndex );
192 if ( !hasNormals && hasTextures )
193 return QStringLiteral(
"%1/%2" ).arg( negativeIndex ).arg( negativeIndex );
194 if ( hasNormals && hasTextures )
195 return QStringLiteral(
"%1/%2/%3" ).arg( negativeIndex ).arg( negativeIndex ).arg( negativeIndex );
196 return QString::number( negativeIndex );
204 for (
int i = 0; i < mIndexes.size(); i += 3 )
206 out <<
"f " << getVertexIndex( i );
207 out <<
" " << getVertexIndex( i + 1 );
208 out <<
" " << getVertexIndex( i + 2 );
215 for (
const unsigned int i : qAsConst( mIndexes ) )
216 out <<
" " << getVertexIndex( i );
219 else if ( mType ==
Points )
222 for (
const unsigned int i : qAsConst( mIndexes ) )
223 out <<
" " << getVertexIndex( i );
230 QString materialName = mName +
"_material";
231 if ( mMaterialParameters.size() == 0 && ( mTexturesUV.size() == 0 || mTextureImage.isNull() ) )
233 mtlOut <<
"newmtl " << materialName <<
"\n";
234 if ( mTexturesUV.size() != 0 && !mTextureImage.isNull() )
236 const QString filePath = QDir( folderPath ).filePath( materialName +
".jpg" );
237 mTextureImage.save( filePath,
"JPG" );
238 mtlOut <<
"\tmap_Kd " << materialName <<
".jpg" <<
"\n";
240 for (
auto it = mMaterialParameters.constBegin(); it != mMaterialParameters.constEnd(); it++ )
242 mtlOut <<
"\t" << it.key() <<
" " << it.value() <<
"\n";
244 mtlOut <<
"\tillum 2\n";
void setupPoint(const QVector< float > &positionsBuffer)
sets point positions coordinates
QString saveMaterial(QTextStream &mtlOut, const QString &folder) const
saves the texture of the object and material information
void setupMaterial(QgsAbstractMaterialSettings *material)
Sets the material parameters (diffuse color, shininess...) to be exported in the ....
void setupTriangle(const QVector< float > &positionsBuffer, const QVector< uint > &facesIndexes, const QMatrix4x4 &transform)
sets triangle indexes and positions coordinates
void setupNormalCoordinates(const QVector< float > &normalsBuffer, const QMatrix4x4 &transform)
Sets normal coordinates for each vertex.
void saveTo(QTextStream &out, float scale, const QVector3D ¢er, int precision=6) const
Saves the current object to the output stream while scaling the object and centering it to be visible...
void objectBounds(float &minX, float &minY, float &minZ, float &maxX, float &maxY, float &maxZ) const
Updates the box bounds explained with the current object bounds This expands the bounding box if the ...
void setupLine(const QVector< float > &positionsBuffer)
sets line indexes and positions coordinates
void setupTextureCoordinates(const QVector< float > &texturesBuffer)
Sets texture coordinates for each vertex.
Abstract base class for material settings.
virtual QMap< QString, QString > toExportParameters() const =0
Returns the parameters to be exported to .mtl file.
bool qgsFloatNear(float a, float b, float epsilon=4 *FLT_EPSILON)
Compare two floats (but allow some difference).
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer
#define QgsDebugError(str)