Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flip axes of the 3D world coordinates #59272

Merged
merged 11 commits into from
Nov 6, 2024
2 changes: 1 addition & 1 deletion src/3d/lights/qgsdirectionallightsettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class _3D_EXPORT QgsDirectionalLightSettings : public QgsLightSource
bool operator==( const QgsDirectionalLightSettings &other );

private:
QgsVector3D mDirection { -0.32, -0.91, -0.27 };
QgsVector3D mDirection { -0.32, 0.27, -0.91 };
QColor mColor = Qt::white;
float mIntensity = 1.0;
};
Expand Down
2 changes: 1 addition & 1 deletion src/3d/lights/qgspointlightsettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class _3D_EXPORT QgsPointLightSettings : public QgsLightSource
bool operator==( const QgsPointLightSettings &other );

private:
QgsVector3D mPosition { 0, 1000, 0 };
QgsVector3D mPosition { 0, 0, 1000 };
QColor mColor = Qt::white;
float mIntensity = 1.0;
float mConstantAttenuation = 1.0f;
Expand Down
12 changes: 6 additions & 6 deletions src/3d/mesh/qgsmesh3dgeometry_p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,16 @@ static QByteArray createTerrainVertexData(
{
const QgsMeshVertex &vert = mesh.vertices().at( i );
*fptr++ = float( vert.x() - origin.x() );
*fptr++ = float( vert.y() - origin.y() );
*fptr++ = float( vert.z() - origin.z() ) * vertScale ;
*fptr++ = float( -vert.y() + origin.y() );

QVector3D normal = normals.at( i );
normal = QVector3D( normal.x() * vertScale, -normal.y() * vertScale, normal.z() );
normal = QVector3D( normal.x(), normal.y(), normal.z() / vertScale ); // TODO: correct?
normal.normalize();

*fptr++ = normal.x();
*fptr++ = normal.z();
*fptr++ = normal.y();
*fptr++ = normal.z();
}

return bufferBytes;
Expand Down Expand Up @@ -115,16 +115,16 @@ static QByteArray createDatasetVertexData(
vertMag += vert.z();

*fptr++ = float( vert.x() - origin.x() );
*fptr++ = float( vert.y() - origin.y() );
*fptr++ = float( vertMag - origin.z() ) * vertScale ;
*fptr++ = float( -vert.y() + origin.y() );

QVector3D normal = normals.at( i );
normal = QVector3D( normal.x() * vertScale, -normal.y() * vertScale, normal.z() );
normal = QVector3D( normal.x(), normal.y(), normal.z() / vertScale ); // TODO: correct?
normal.normalize();

*fptr++ = normal.x();
*fptr++ = normal.z();
*fptr++ = normal.y();
*fptr++ = normal.z();

*fptr++ = float( scalarMag );
}
Expand Down
25 changes: 8 additions & 17 deletions src/3d/qgs3daxis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ Qt3DRender::QViewport *Qgs3DAxis::constructAxisScene( Qt3DCore::QEntity *parent3
mAxisCamera->setProjectionType( mCameraController->camera()->projectionType() );
mAxisCamera->lens()->setFieldOfView( mCameraController->camera()->lens()->fieldOfView() * 0.5f );

mAxisCamera->setUpVector( QVector3D( 0.0f, 0.0f, 1.0f ) );
mAxisCamera->setUpVector( QVector3D( 0.0f, 1.0f, 0.0f ) );
mAxisCamera->setViewCenter( QVector3D( 0.0f, 0.0f, 0.0f ) );
// position will be set later

Expand Down Expand Up @@ -747,15 +747,15 @@ void Qgs3DAxis::onCameraViewChange( float pitch, float yaw )
const QVector<QgsRayCastingUtils::RayHit> hits = mMapScene->terrainEntity()->rayIntersection( ray, QgsRayCastingUtils::RayCastContext() );
if ( !hits.isEmpty() )
{
elevation = hits.at( 0 ).pos.y();
elevation = hits.at( 0 ).pos.z();
QgsDebugMsgLevel( QString( "Computed elevation from terrain: %1" ).arg( elevation ), 2 );
}
else
{
QgsDebugMsgLevel( "Unable to obtain elevation from terrain", 2 );
}
}
pos.set( pos.x(), elevation + mMapSettings->terrainElevationOffset(), pos.z() );
pos.set( pos.x(), pos.y(), elevation + mMapSettings->terrainElevationOffset() );

mCameraController->setLookingAtPoint( pos, ( mCameraController->camera()->position() - pos.toVector3D() ).length(),
pitch, yaw );
Expand Down Expand Up @@ -946,7 +946,8 @@ void Qgs3DAxis::createAxis( Qt::Axis axisType )
mTextTransformY = new Qt3DCore::QTransform();
mTextCoordY = QVector3D( 0.0f, mCylinderLength + coneLength / 2.0f, 0.0f );

rotation = QQuaternion::fromAxisAndAngle( QVector3D( 0.0f, 0.0f, 0.0f ), 0.0f );
// no rotation

color = Qt::green;
text = mTextY;
textTransform = mTextTransformY;
Expand Down Expand Up @@ -1149,20 +1150,10 @@ void Qgs3DAxis::onCameraUpdate( )
&& !std::isnan( parentCamera->viewVector().z() ) )
{
mPreviousVector = parentCamera->viewVector();
QVector3D mainCameraShift = parentCamera->viewVector().normalized();
float zy_swap = mainCameraShift.y();
mainCameraShift.setY( mainCameraShift.z() );
mainCameraShift.setZ( -zy_swap );
mainCameraShift.setX( -mainCameraShift.x() );

if ( mAxisCamera->projectionType() == Qt3DRender::QCameraLens::ProjectionType::OrthographicProjection )
{
mAxisCamera->setPosition( mainCameraShift );
}
else
{
mAxisCamera->setPosition( mainCameraShift * mCylinderLength * 9.0 );
}
QQuaternion q = QQuaternion::fromDirection( -parentCamera->viewVector(), parentCamera->upVector() );
mAxisCamera->setPosition( q.rotatedVector( QVector3D( 0, 0, mCylinderLength * 9.0f ) ) );
mAxisCamera->setUpVector( q.rotatedVector( QVector3D( 0, 1, 0 ) ) );

if ( mAxisRoot->isEnabled() )
{
Expand Down
30 changes: 23 additions & 7 deletions src/3d/qgs3dexportobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <QVector3D>
#include <QDir>
#include <QImage>
#include <QMatrix4x4>

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <Qt3DRender/QAttribute>
Expand Down Expand Up @@ -49,14 +50,13 @@ void insertIndexData( QVector<uint> &vertexIndex, const QVector<T> &faceIndex )
}
}

void Qgs3DExportObject::setupPositionCoordinates( const QVector<float> &positionsBuffer, float scale, const QVector3D &translation )
void Qgs3DExportObject::setupPositionCoordinates( const QVector<float> &positionsBuffer, const QMatrix4x4 &transform )
{
for ( int i = 0; i < positionsBuffer.size(); i += 3 )
{
for ( int j = 0; j < 3; ++j )
{
mVertexPosition << positionsBuffer[i + j] * scale + translation[j];
}
const QVector3D position( positionsBuffer[i], positionsBuffer[i + 1], positionsBuffer[i + 2] );
const QVector3D positionFinal = transform.map( position );
mVertexPosition << positionFinal.x() << positionFinal.y() << positionFinal.z();
}
}

Expand All @@ -71,9 +71,25 @@ void Qgs3DExportObject::setupLine( const QVector<uint> &lineIndexes )
for ( int i = 0; i < mVertexPosition.size(); i += 3 ) mIndexes << i / 3 + 1;
}

void Qgs3DExportObject::setupNormalCoordinates( const QVector<float> &normalsBuffer )
void Qgs3DExportObject::setupNormalCoordinates( const QVector<float> &normalsBuffer, const QMatrix4x4 &transform )
{
mNormals << normalsBuffer;
// Qt does not provide QMatrix3x3 * QVector3D multiplication so we use QMatrix4x4
QMatrix3x3 normal3x3 = transform.normalMatrix();
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 );

for ( int i = 0; i < normalsBuffer.size(); i += 3 )
{
const QVector3D normalVector( normalsBuffer[i], normalsBuffer[i + 1], normalsBuffer[i + 2] );
QVector3D v = normal4x4.mapVector( normalVector );
// round numbers very close to zero to avoid tiny numbers like 6e-8 in export
if ( qgsFloatNear( v.x(), 0 ) ) v.setX( 0 );
if ( qgsFloatNear( v.y(), 0 ) ) v.setY( 0 );
if ( qgsFloatNear( v.z(), 0 ) ) v.setZ( 0 );
mNormals << v.x() << v.y() << v.z();
}
}

void Qgs3DExportObject::setupTextureCoordinates( const QVector<float> &texturesBuffer )
Expand Down
6 changes: 3 additions & 3 deletions src/3d/qgs3dexportobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,15 @@ class _3D_EXPORT Qgs3DExportObject
//! Sets whether triangles edges will look smooth
void setSmoothEdges( bool smoothEdges ) { mSmoothEdges = smoothEdges; }

//! Sets positions coordinates and does the translation and scaling
void setupPositionCoordinates( const QVector<float> &positionsBuffer, float scale = 1.0f, const QVector3D &translation = QVector3D( 0, 0, 0 ) );
//! Sets positions coordinates and does the translation, rotation and scaling
void setupPositionCoordinates( const QVector<float> &positionsBuffer, const QMatrix4x4 &transform );
//! Sets the faces in facesIndexes to the faces in the object
void setupFaces( const QVector<uint> &facesIndexes );
//! sets line vertex indexes
void setupLine( const QVector<uint> &facesIndexes );

//! Sets normal coordinates for each vertex
void setupNormalCoordinates( const QVector<float> &normalsBuffer );
void setupNormalCoordinates( const QVector<float> &normalsBuffer, const QMatrix4x4 &transform );
//! Sets texture coordinates for each vertex
void setupTextureCoordinates( const QVector<float> &texturesBuffer );
//! Sets the material parameters (diffuse color, shininess...) from phong material
Expand Down
6 changes: 3 additions & 3 deletions src/3d/qgs3dmapscene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,9 @@ QVector<QgsPointXY> Qgs3DMapScene::viewFrustum2DExtent() const
const QPoint p( ( ( i >> 0 ) & 1 ) ? 0 : mEngine->size().width(), ( ( i >> 1 ) & 1 ) ? 0 : mEngine->size().height() );
QgsRay3D ray = Qgs3DUtils::rayFromScreenPoint( p, mEngine->size(), camera );
QVector3D dir = ray.direction();
if ( dir.y() == 0.0 )
dir.setY( 0.000001 );
double t = - ray.origin().y() / dir.y();
if ( dir.z() == 0.0 )
dir.setZ( 0.000001 );
double t = - ray.origin().z() / dir.z();
if ( t < 0 )
{
// If the projected point is on the back of the camera we choose the farthest point in the front
Expand Down
44 changes: 18 additions & 26 deletions src/3d/qgs3dsceneexporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,9 +350,6 @@ void Qgs3DSceneExporter::parseFlatTile( QgsTerrainTileEntity *tileEntity, const
return;
}

const float scale = transform->scale();
const QVector3D translation = transform->translation();

// Generate vertice data
Qt3DQAttribute *positionAttribute = tileGeometry->positionAttribute();
if ( !positionAttribute )
Expand Down Expand Up @@ -390,15 +387,15 @@ void Qgs3DSceneExporter::parseFlatTile( QgsTerrainTileEntity *tileEntity, const
mObjects.push_back( object );

object->setSmoothEdges( mSmoothEdges );
object->setupPositionCoordinates( positionBuffer, scale, translation );
object->setupPositionCoordinates( positionBuffer, transform->matrix() );
object->setupFaces( indexesBuffer );

if ( mExportNormals )
{
// Everts
QVector<float> normalsBuffer;
for ( int i = 0; i < positionBuffer.size(); i += 3 ) normalsBuffer << 0.0f << 1.0f << 0.0f;
object->setupNormalCoordinates( normalsBuffer );
object->setupNormalCoordinates( normalsBuffer, transform->matrix() );
}

Qt3DQAttribute *texCoordsAttribute = tileGeometry->texCoordAttribute();
Expand Down Expand Up @@ -427,9 +424,6 @@ void Qgs3DSceneExporter::parseDemTile( QgsTerrainTileEntity *tileEntity, const Q
return;
}

const float scale = transform->scale();
const QVector3D translation = transform->translation();

Qt3DQAttribute *positionAttribute = tileGeometry->positionAttribute();
const QByteArray positionBytes = positionAttribute->buffer()->data();
const QVector<float> positionBuffer = getAttributeData<float>( positionAttribute, positionBytes );
Expand All @@ -442,15 +436,15 @@ void Qgs3DSceneExporter::parseDemTile( QgsTerrainTileEntity *tileEntity, const Q
mObjects.push_back( object );

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

Qt3DQAttribute *normalsAttributes = tileGeometry->normalAttribute();
if ( mExportNormals && normalsAttributes )
{
const QByteArray normalsBytes = normalsAttributes->buffer()->data();
const QVector<float> normalsBuffer = getAttributeData<float>( normalsAttributes, normalsBytes );
object->setupNormalCoordinates( normalsBuffer );
object->setupNormalCoordinates( normalsBuffer, transform->matrix() );
}

Qt3DQAttribute *texCoordsAttribute = tileGeometry->texCoordsAttribute();
Expand Down Expand Up @@ -524,7 +518,9 @@ QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processInstancedPointGeometry(
{
Qgs3DExportObject *object = new Qgs3DExportObject( getObjectName( objectNamePrefix + QStringLiteral( "instance_point" ) ) );
objects.push_back( object );
object->setupPositionCoordinates( positionData, 1.0f, QVector3D( instancePosition[i], instancePosition[i + 1], instancePosition[i + 2] ) );
QMatrix4x4 instanceTransform;
instanceTransform.translate( instancePosition[i], instancePosition[i + 1], instancePosition[i + 2] );
object->setupPositionCoordinates( positionData, instanceTransform );
object->setupFaces( indexData );

object->setSmoothEdges( mSmoothEdges );
Expand All @@ -534,7 +530,7 @@ QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processInstancedPointGeometry(
{
// Reuse vertex bytes
const QVector<float> normalsData = getAttributeData<float>( normalsAttribute, vertexBytes );
object->setupNormalCoordinates( normalsData );
object->setupNormalCoordinates( normalsData, instanceTransform );
}
}
}
Expand All @@ -547,26 +543,24 @@ QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processSceneLoaderGeometries( Q
QVector<Qgs3DExportObject *> objects;
Qt3DCore::QEntity *sceneLoaderParent = qobject_cast<Qt3DCore::QEntity *>( sceneLoader->parent() );
Qt3DCore::QTransform *entityTransform = findTypedComponent<Qt3DCore::QTransform>( sceneLoaderParent );
float sceneScale = 1.0f;
QVector3D sceneTranslation( 0.0f, 0.0f, 0.0f );
QMatrix4x4 sceneTransform;
if ( entityTransform )
{
sceneScale = entityTransform->scale();
sceneTranslation = entityTransform->translation();
sceneTransform = entityTransform->matrix();
}
QStringList entityNames = sceneLoader->entityNames();
for ( const QString &entityName : entityNames )
{
Qt3DRender::QGeometryRenderer *mesh = qobject_cast<Qt3DRender::QGeometryRenderer *>( sceneLoader->component( entityName, Qt3DRender::QSceneLoader::GeometryRendererComponent ) );
Qgs3DExportObject *object = processGeometryRenderer( mesh, objectNamePrefix, sceneScale, sceneTranslation );
Qgs3DExportObject *object = processGeometryRenderer( mesh, objectNamePrefix, sceneTransform );
if ( !object )
continue;
objects.push_back( object );
}
return objects;
}

Qgs3DExportObject *Qgs3DSceneExporter::processGeometryRenderer( Qt3DRender::QGeometryRenderer *geomRenderer, const QString &objectNamePrefix, float sceneScale, QVector3D sceneTranslation )
Qgs3DExportObject *Qgs3DSceneExporter::processGeometryRenderer( Qt3DRender::QGeometryRenderer *geomRenderer, const QString &objectNamePrefix, const QMatrix4x4 &sceneTransform )
{
// We only export triangles for now
if ( geomRenderer->primitiveType() != Qt3DRender::QGeometryRenderer::Triangles )
Expand Down Expand Up @@ -618,17 +612,15 @@ Qgs3DExportObject *Qgs3DSceneExporter::processGeometryRenderer( Qt3DRender::QGeo
}

// === Compute inherited scale and translation from child entity to parent
float scale = 1.0f;
QVector3D translation( 0.0f, 0.0f, 0.0f );
QMatrix4x4 transformMatrix = sceneTransform;
QObject *parent = geomRenderer->parent();
while ( parent )
{
Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>( parent );
Qt3DCore::QTransform *transform = findTypedComponent<Qt3DCore::QTransform>( entity );
if ( transform )
{
scale *= transform->scale();
translation += transform->translation();
transformMatrix = transform->matrix() * transformMatrix;
}
parent = parent->parent();
}
Expand Down Expand Up @@ -721,15 +713,15 @@ Qgs3DExportObject *Qgs3DSceneExporter::processGeometryRenderer( Qt3DRender::QGeo

// === Create Qgs3DExportObject
Qgs3DExportObject *object = new Qgs3DExportObject( getObjectName( objectNamePrefix + QStringLiteral( "mesh_geometry" ) ) );
object->setupPositionCoordinates( positionData, scale * sceneScale, translation + sceneTranslation );
object->setupPositionCoordinates( positionData, transformMatrix );
object->setupFaces( indexData );

Qt3DQAttribute *normalsAttribute = findAttribute( geometry, Qt3DQAttribute::defaultNormalAttributeName(), Qt3DQAttribute::VertexAttribute );
if ( mExportNormals && normalsAttribute )
{
// Reuse vertex bytes
const QVector<float> normalsData = getAttributeData<float>( normalsAttribute, vertexBytes );
object->setupNormalCoordinates( normalsData );
object->setupNormalCoordinates( normalsData, transformMatrix );
}

Qt3DQAttribute *texCoordsAttribute = findAttribute( geometry, Qt3DQAttribute::defaultTextureCoordinateAttributeName(), Qt3DQAttribute::VertexAttribute );
Expand Down Expand Up @@ -771,7 +763,7 @@ QVector<Qgs3DExportObject *> Qgs3DSceneExporter::processLines( Qt3DCore::QEntity

Qgs3DExportObject *exportObject = new Qgs3DExportObject( getObjectName( objectNamePrefix + QStringLiteral( "line" ) ) );
exportObject->setType( Qgs3DExportObject::LineStrip );
exportObject->setupPositionCoordinates( positionData );
exportObject->setupPositionCoordinates( positionData, QMatrix4x4() );
exportObject->setupLine( indexData );

objs.push_back( exportObject );
Expand Down Expand Up @@ -805,7 +797,7 @@ Qgs3DExportObject *Qgs3DSceneExporter::processPoints( Qt3DCore::QEntity *entity,
}
Qgs3DExportObject *obj = new Qgs3DExportObject( getObjectName( objectNamePrefix + QStringLiteral( "points" ) ) );
obj->setType( Qgs3DExportObject::Points );
obj->setupPositionCoordinates( points );
obj->setupPositionCoordinates( points, QMatrix4x4() );
return obj;
}

Expand Down
3 changes: 2 additions & 1 deletion src/3d/qgs3dsceneexporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <QMap>
#include <QFile>
#include <QVector3D>
#include <QMatrix4x4>

#include "qgs3dexportobject.h"
#include "qgsfeatureid.h"
Expand Down Expand Up @@ -113,7 +114,7 @@ class _3D_EXPORT Qgs3DSceneExporter : public Qt3DCore::QEntity
//! Constructs Qgs3DExportObject from 3D models loaded using a scene loader
QVector<Qgs3DExportObject *> processSceneLoaderGeometries( Qt3DRender::QSceneLoader *sceneLoader, const QString &objectNamePrefix );
//! Constructs Qgs3DExportObject from geometry renderer
Qgs3DExportObject *processGeometryRenderer( Qt3DRender::QGeometryRenderer *mesh, const QString &objectNamePrefix, float sceneScale = 1.0f, QVector3D sceneTranslation = QVector3D( 0.0f, 0.0f, 0.0f ) );
Qgs3DExportObject *processGeometryRenderer( Qt3DRender::QGeometryRenderer *mesh, const QString &objectNamePrefix, const QMatrix4x4 &sceneTransform = QMatrix4x4() );
//! Extracts material information from geometry renderer and inserts it into the export object
void processEntityMaterial( Qt3DCore::QEntity *entity, Qgs3DExportObject *object );
//! Constricts Qgs3DExportObject from line entity
Expand Down
Loading
Loading