Skip to content
Permalink
Browse files

inital terrain elevation offset implementation

  • Loading branch information
NEDJIMAbelgacem committed Nov 8, 2020
1 parent 7d012ee commit 23b723e5a0032b9ea351c750bdf425b41c4b3777
@@ -294,6 +294,20 @@ This value tells that when the given ground error is reached (e.g. 10 meters), i
to further split terrain tiles into finer ones because they will not add extra details anymore.
%End

void setTerrainElevationOffset( float offset );
%Docstring
Sets the terrain elevation offset (used to move the terrain up or down)

.. seealso:: :py:func:`terrainElevationOffset`

.. versionadded:: 3.18
%End

float terrainElevationOffset() const;
%Docstring
Returns the elevation offset of the terrain (used to move the terrain up or down)
%End


void setTerrainShadingEnabled( bool enabled );
%Docstring
@@ -631,6 +645,13 @@ Emitted when the maximum terrain screen error has changed
void maxTerrainGroundErrorChanged();
%Docstring
Emitted when the maximum terrain ground error has changed
%End

void terrainElevationOffsetChanged();
%Docstring
Emitted when the terrain elevation offset is changed

.. versionadded:: 3.16
%End

void terrainShadingChanged();
@@ -104,6 +104,8 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte
mMaxTerrainScreenError = elemTerrain.attribute( QStringLiteral( "max-terrain-error" ), QStringLiteral( "3" ) ).toFloat();
mMaxTerrainGroundError = elemTerrain.attribute( QStringLiteral( "max-ground-error" ), QStringLiteral( "1" ) ).toFloat();
mTerrainShadingEnabled = elemTerrain.attribute( QStringLiteral( "shading-enabled" ), QStringLiteral( "0" ) ).toInt();
mTerrainElevationOffset = elemTerrain.attribute( QStringLiteral( "elevation-offset" ), QStringLiteral( "0.0" ) ).toFloat();

QDomElement elemTerrainShadingMaterial = elemTerrain.firstChildElement( QStringLiteral( "shading-material" ) );
if ( !elemTerrainShadingMaterial.isNull() )
mTerrainShadingMaterial.readXml( elemTerrainShadingMaterial, context );
@@ -292,6 +294,8 @@ QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteCon
elemTerrain.setAttribute( QStringLiteral( "max-terrain-error" ), QString::number( mMaxTerrainScreenError ) );
elemTerrain.setAttribute( QStringLiteral( "max-ground-error" ), QString::number( mMaxTerrainGroundError ) );
elemTerrain.setAttribute( QStringLiteral( "shading-enabled" ), mTerrainShadingEnabled ? 1 : 0 );
elemTerrain.setAttribute( QStringLiteral( "elevation-offset" ), mTerrainElevationOffset );

QDomElement elemTerrainShadingMaterial = doc.createElement( QStringLiteral( "shading-material" ) );
mTerrainShadingMaterial.writeXml( elemTerrainShadingMaterial, context );
elemTerrain.appendChild( elemTerrainShadingMaterial );
@@ -411,12 +415,12 @@ void Qgs3DMapSettings::resolveReferences( const QgsProject &project )

QgsVector3D Qgs3DMapSettings::mapToWorldCoordinates( const QgsVector3D &mapCoords ) const
{
return Qgs3DUtils::mapToWorldCoordinates( mapCoords, mOrigin );
return Qgs3DUtils::mapToWorldCoordinates( mapCoords, mOrigin ) + QgsVector3D( 0.0f, mTerrainElevationOffset, 0.0f );
}

QgsVector3D Qgs3DMapSettings::worldToMapCoordinates( const QgsVector3D &worldCoords ) const
{
return Qgs3DUtils::worldToMapCoordinates( worldCoords, mOrigin );
return Qgs3DUtils::worldToMapCoordinates( worldCoords - QgsVector3D( 0.0f, mTerrainElevationOffset, 0.0f ), mOrigin );
}

void Qgs3DMapSettings::setCrs( const QgsCoordinateReferenceSystem &crs )
@@ -569,6 +573,14 @@ void Qgs3DMapSettings::setMaxTerrainGroundError( float error )
emit maxTerrainGroundErrorChanged();
}

void Qgs3DMapSettings::setTerrainElevationOffset( float offset )
{
if ( mTerrainElevationOffset == offset )
return;
mTerrainElevationOffset = offset;
emit terrainElevationOffsetChanged();
}

float Qgs3DMapSettings::maxTerrainGroundError() const
{
return mMaxTerrainGroundError;
@@ -263,6 +263,18 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
*/
float maxTerrainGroundError() const;

/**
* Sets the terrain elevation offset (used to move the terrain up or down)
* \see terrainElevationOffset()
* \since QGIS 3.18
*/
void setTerrainElevationOffset( float offset );

/**
* Returns the elevation offset of the terrain (used to move the terrain up or down)
*/
float terrainElevationOffset() const { return mTerrainElevationOffset; }

/**
* Sets terrain generator. It takes care of producing terrain tiles from the input data.
* Takes ownership of the generator
@@ -541,6 +553,12 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
//! Emitted when the maximum terrain ground error has changed
void maxTerrainGroundErrorChanged();

/**
* Emitted when the terrain elevation offset is changed
* \since QGIS 3.16
*/
void terrainElevationOffsetChanged();

/**
* Emitted when terrain shading enabled flag or terrain shading material has changed
* \since QGIS 3.6
@@ -655,6 +673,7 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
int mMapTileResolution = 512; //!< Size of map textures of tiles in pixels (width/height)
float mMaxTerrainScreenError = 3.f; //!< Maximum allowed terrain error in pixels (determines when tiles are switched to more detailed ones)
float mMaxTerrainGroundError = 1.f; //!< Maximum allowed horizontal map error in map units (determines how many zoom levels will be used)
float mTerrainElevationOffset = 0.0f; //!< Terrain elevation offset (used to adjust the position of the terrain and move it up and down)
bool mTerrainShadingEnabled = false; //!< Whether terrain should be shaded taking lights into account
QgsPhongMaterialSettings mTerrainShadingMaterial; //!< Material to use for the terrain (if shading is enabled). Diffuse color is ignored.
QString mTerrainMapTheme; //!< Name of map theme used for terrain's texture (empty means use the current map theme)
@@ -181,7 +181,10 @@ void QgsCameraController::resetView( float distance )
void QgsCameraController::setViewFromTop( float worldX, float worldY, float distance, float yaw )
{
QgsCameraPose camPose;
camPose.setCenterPoint( QgsVector3D( worldX, 0, worldY ) );
if ( mTerrainEntity != nullptr )
camPose.setCenterPoint( QgsVector3D( worldX, mTerrainEntity->terrainElevationOffset(), worldY ) );
else
camPose.setCenterPoint( QgsVector3D( worldX, 0.0f, worldY ) );
camPose.setDistanceFromCenterPoint( distance );
camPose.setHeadingAngle( yaw );

@@ -275,6 +278,12 @@ void QgsCameraController::updateCameraFromPose( bool centerPointChanged )
mCameraPose.setCenterPoint( QgsVector3D( intersectionPoint ) );
mCameraPose.updateCamera( mCamera );
}
else
{
QgsVector3D centerPoint = mCameraPose.centerPoint();
centerPoint.set( centerPoint.x(), mTerrainEntity->terrainElevationOffset(), centerPoint.z() );
mCameraPose.setCenterPoint( centerPoint );
}
}

emit cameraChanged();
@@ -70,6 +70,7 @@ QgsTerrainEntity::QgsTerrainEntity( const Qgs3DMapSettings &map, Qt3DCore::QNode
connect( &map, &Qgs3DMapSettings::terrainLayersChanged, this, &QgsTerrainEntity::onLayersChanged );
connect( &map, &Qgs3DMapSettings::backgroundColorChanged, this, &QgsTerrainEntity::invalidateMapImages );
connect( &map, &Qgs3DMapSettings::terrainMapThemeChanged, this, &QgsTerrainEntity::invalidateMapImages );
connect( &map, &Qgs3DMapSettings::terrainElevationOffsetChanged, this, &QgsTerrainEntity::onTerrainElevationOffsetChanged );

connectToLayersRepaintRequest();

@@ -83,6 +84,11 @@ QgsTerrainEntity::QgsTerrainEntity( const Qgs3DMapSettings &map, Qt3DCore::QNode
// add camera control's terrain picker as a component to be able to capture height where mouse was
// pressed in order to correctly pan camera when dragging mouse
addComponent( mTerrainPicker );

mTerrainTransform = new Qt3DCore::QTransform;
mTerrainTransform->setScale( 1.0f );
mTerrainTransform->setTranslation( QVector3D( 0.0f, map.terrainElevationOffset(), 0.0f ) );
addComponent( mTerrainTransform );
}

QgsTerrainEntity::~QgsTerrainEntity()
@@ -181,6 +187,16 @@ void QgsTerrainEntity::connectToLayersRepaintRequest()
}
}

void QgsTerrainEntity::onTerrainElevationOffsetChanged()
{
mTerrainTransform->setTranslation( QVector3D( 0.0f, mMap.terrainElevationOffset(), 0.0f ) );
}

float QgsTerrainEntity::terrainElevationOffset() const
{
return mMap.terrainElevationOffset();
}


// -----------

@@ -39,6 +39,11 @@ namespace Qt3DRender
class QObjectPicker;
}

namespace Qt3DCore
{
class QTransform;
}

namespace QgsRayCastingUtils
{
class Ray3D;
@@ -75,6 +80,10 @@ class QgsTerrainEntity : public QgsChunkedEntity

//! Returns object picker attached to the terrain entity - used by camera controller
Qt3DRender::QObjectPicker *terrainPicker() const { return mTerrainPicker; }
//! Returns the transform attached to the terrain entity
Qt3DCore::QTransform *transform() const { return mTerrainTransform; }
//! Returns the terrain elevation offset (adjusts the terrain position up and down)
float terrainElevationOffset() const;

//! Tests whether the ray intersects the terrain - if it does, it sets the intersection point (in world coordinates)
bool rayIntersection( const QgsRayCastingUtils::Ray3D &ray, QVector3D &intersectionPoint );
@@ -83,6 +92,7 @@ class QgsTerrainEntity : public QgsChunkedEntity
void onShowBoundingBoxesChanged();
void invalidateMapImages();
void onLayersChanged();
void onTerrainElevationOffsetChanged();

private:

@@ -93,6 +103,7 @@ class QgsTerrainEntity : public QgsChunkedEntity
Qt3DRender::QObjectPicker *mTerrainPicker = nullptr;
QgsTerrainTextureGenerator *mTextureGenerator = nullptr;
QgsCoordinateTransform *mTerrainToMapTransform = nullptr;
Qt3DCore::QTransform *mTerrainTransform = nullptr;

std::unique_ptr<TerrainMapUpdateJobFactory> mUpdateJobFactory;

@@ -75,6 +75,7 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas
spinMapResolution->setClearValue( 512 );
spinScreenError->setClearValue( 3 );
spinGroundError->setClearValue( 1 );
terrainElevationOffsetSpinBox->setClearValue( 0.0f );

cboTerrainLayer->setAllowEmptyLayer( true );
cboTerrainLayer->setFilters( QgsMapLayerProxyModel::RasterLayer );
@@ -124,6 +125,7 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas
spinMapResolution->setValue( mMap->mapTileResolution() );
spinScreenError->setValue( mMap->maxTerrainScreenError() );
spinGroundError->setValue( mMap->maxTerrainGroundError() );
terrainElevationOffsetSpinBox->setValue( mMap->terrainElevationOffset() );
chkShowLabels->setChecked( mMap->showLabels() );
chkShowTileInfo->setChecked( mMap->showTerrainTilesInfo() );
chkShowBoundingBoxes->setChecked( mMap->showTerrainBoundingBoxes() );
@@ -291,6 +293,7 @@ void Qgs3DMapConfigWidget::apply()
mMap->setMapTileResolution( spinMapResolution->value() );
mMap->setMaxTerrainScreenError( spinScreenError->value() );
mMap->setMaxTerrainGroundError( spinGroundError->value() );
mMap->setTerrainElevationOffset( terrainElevationOffsetSpinBox->value() );
mMap->setShowLabels( chkShowLabels->isChecked() );
mMap->setShowTerrainTilesInfo( chkShowTileInfo->isChecked() );
mMap->setShowTerrainBoundingBoxes( chkShowBoundingBoxes->isChecked() );
@@ -56,12 +56,6 @@ class Qgs3DMapConfigWidget : public QWidget, private Ui::Map3DConfigWidget
QgsMesh3dSymbolWidget *mMeshSymbolWidget = nullptr;
QgsSkyboxRenderingSettingsWidget *mSkyboxSettingsWidget = nullptr;
QgsShadowRenderingSettingsWidget *mShadowSetiingsWidget = nullptr;
bool mDebugShadowMapEnabled = false;
QString mDebugShadowMapCorner = "Top Left";
double mDebugShadowMapSize = 0.2;
bool mDebugDepthMapEnabled = false;
QString mDebugDepthMapCorner = "Top Right";
double mDebugDepthMapSize = 0.2;
};

#endif // QGS3DMAPCONFIGWIDGET_H

0 comments on commit 23b723e

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