Skip to content

Commit

Permalink
[FEATURE][3d] Orthographic projection support for 3D scenes
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvn committed Nov 19, 2020
1 parent f3f0522 commit 9dee613
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 1 deletion.
9 changes: 9 additions & 0 deletions python/3d/auto_generated/qgs3dmapsettings.sip.in
Expand Up @@ -552,6 +552,8 @@ Sets the camera lens' field of view
.. versionadded:: 3.8
%End



void setOutputDpi( const double dpi );
%Docstring
Sets DPI used for conversion between real world units (e.g. mm) and pixels
Expand Down Expand Up @@ -757,6 +759,13 @@ Emitted when the list of directional lights changes
Emitted when the camera lens field of view changes

.. versionadded:: 3.8
%End

void projectionTypeChanged();
%Docstring
Emitted when the camera lens projection type changes

.. versionadded:: 3.18
%End

void skyboxSettingsChanged();
Expand Down
10 changes: 10 additions & 0 deletions src/3d/qgs3dmapscene.cpp
Expand Up @@ -128,6 +128,7 @@ Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine *
connect( &map, &Qgs3DMapSettings::directionalLightsChanged, this, &Qgs3DMapScene::updateLights );
connect( &map, &Qgs3DMapSettings::showLightSourceOriginsChanged, this, &Qgs3DMapScene::updateLights );
connect( &map, &Qgs3DMapSettings::fieldOfViewChanged, this, &Qgs3DMapScene::updateCameraLens );
connect( &map, &Qgs3DMapSettings::projectionTypeChanged, this, &Qgs3DMapScene::updateCameraLens );
connect( &map, &Qgs3DMapSettings::renderersChanged, this, &Qgs3DMapScene::onRenderersChanged );
connect( &map, &Qgs3DMapSettings::skyboxSettingsChanged, this, &Qgs3DMapScene::onSkyboxSettingsChanged );
connect( &map, &Qgs3DMapSettings::shadowSettingsChanged, this, &Qgs3DMapScene::onShadowSettingsChanged );
Expand Down Expand Up @@ -320,6 +321,14 @@ QgsChunkedEntity::SceneState _sceneState( QgsCameraController *cameraController

void Qgs3DMapScene::onCameraChanged()
{
if ( mMap.projectionType() == Qt3DRender::QCameraLens::OrthographicProjection )
{
QRect viewportRect( QPoint( 0, 0 ), mEngine->size() );
const float viewWidthFromCenter = mEngine->camera()->position().distanceToPoint( mEngine->camera()->viewCenter() );
const float viewHeightFromCenter = viewportRect.height() * viewWidthFromCenter / viewportRect.width();
mEngine->camera()->lens()->setOrthographicProjection( -viewWidthFromCenter, viewWidthFromCenter, -viewHeightFromCenter, viewHeightFromCenter, 1.0f, 10000.0f );
}

updateScene();
bool changedCameraPlanes = updateCameraNearFarPlanes();

Expand Down Expand Up @@ -623,6 +632,7 @@ void Qgs3DMapScene::updateLights()
void Qgs3DMapScene::updateCameraLens()
{
mEngine->camera()->lens()->setFieldOfView( mMap.fieldOfView() );
mEngine->camera()->lens()->setProjectionType( mMap.projectionType() );
onCameraChanged();
}

Expand Down
12 changes: 12 additions & 0 deletions src/3d/qgs3dmapsettings.cpp
Expand Up @@ -54,6 +54,7 @@ Qgs3DMapSettings::Qgs3DMapSettings( const Qgs3DMapSettings &other )
, mPointLights( other.mPointLights )
, mDirectionalLights( other.mDirectionalLights )
, mFieldOfView( other.mFieldOfView )
, mProjectionType( other.mProjectionType )
, mLayers( other.mLayers )
, mTerrainLayers( other.mTerrainLayers )
, mRenderers() // initialized in body
Expand Down Expand Up @@ -96,6 +97,7 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte
if ( !elemCamera.isNull() )
{
mFieldOfView = elemCamera.attribute( QStringLiteral( "field-of-view" ), QStringLiteral( "45" ) ).toFloat();
mProjectionType = static_cast< Qt3DRender::QCameraLens::ProjectionType >( elemCamera.attribute( QStringLiteral( "projection-type" ), QStringLiteral( "1" ) ).toInt() );
}

QDomElement elemColor = elem.firstChildElement( QStringLiteral( "color" ) );
Expand Down Expand Up @@ -287,6 +289,7 @@ QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteCon

QDomElement elemCamera = doc.createElement( QStringLiteral( "camera" ) );
elemCamera.setAttribute( QStringLiteral( "field-of-view" ), mFieldOfView );
elemCamera.setAttribute( QStringLiteral( "projection-type" ), static_cast< int >( mProjectionType ) );
elem.appendChild( elemCamera );

QDomElement elemColor = doc.createElement( QStringLiteral( "color" ) );
Expand Down Expand Up @@ -734,6 +737,15 @@ void Qgs3DMapSettings::setFieldOfView( const float fieldOfView )
emit fieldOfViewChanged();
}

void Qgs3DMapSettings::setProjectionType( const Qt3DRender::QCameraLens::ProjectionType projectionType )
{
if ( mProjectionType == projectionType )
return;

mProjectionType = projectionType;
emit projectionTypeChanged();
}

void Qgs3DMapSettings::setSkyboxSettings( const QgsSkyboxSettings &skyboxSettings )
{
mSkyboxSettings = skyboxSettings;
Expand Down
20 changes: 20 additions & 0 deletions src/3d/qgs3dmapsettings.h
Expand Up @@ -21,6 +21,7 @@
#include <memory>
#include <QColor>
#include <QMatrix4x4>
#include <Qt3DRender/QCamera>

#include "qgscoordinatereferencesystem.h"
#include "qgsmaplayerref.h"
Expand Down Expand Up @@ -463,6 +464,18 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
*/
void setFieldOfView( const float fieldOfView );

/**
* Returns the camera lens' projection type
* \since QGIS 3.18
*/
Qt3DRender::QCameraLens::ProjectionType projectionType() const SIP_SKIP { return mProjectionType; }

/**
* Sets the camera lens' projection type
* \since QGIS 3.18
*/
void setProjectionType( const Qt3DRender::QCameraLens::ProjectionType projectionType ) SIP_SKIP;

/**
* Sets DPI used for conversion between real world units (e.g. mm) and pixels
* \param dpi the number of dot per inch
Expand Down Expand Up @@ -645,6 +658,12 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
*/
void fieldOfViewChanged();

/**
* Emitted when the camera lens projection type changes
* \since QGIS 3.18
*/
void projectionTypeChanged();

/**
* Emitted when skybox settings are changed
* \since QGIS 3.16
Expand Down Expand Up @@ -685,6 +704,7 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject, public QgsTemporalRangeObjec
QList<QgsPointLightSettings> mPointLights; //!< List of point lights defined for the scene
QList<QgsDirectionalLightSettings> mDirectionalLights; //!< List of directional lights defined for the scene
float mFieldOfView = 45.0f; //<! Camera lens field of view value
Qt3DRender::QCameraLens::ProjectionType mProjectionType = Qt3DRender::QCameraLens::PerspectiveProjection; //<! Camera lens projection type
QList<QgsMapLayerRef> mLayers; //!< Layers to be rendered
QList<QgsMapLayerRef> mTerrainLayers; //!< Terrain layers to be rendered
QList<QgsAbstract3DRenderer *> mRenderers; //!< Extra stuff to render as 3D object
Expand Down
9 changes: 9 additions & 0 deletions src/app/3d/qgs3dmapconfigwidget.cpp
Expand Up @@ -68,6 +68,13 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas
mMeshSymbolWidget = new QgsMesh3dSymbolWidget( nullptr, groupMeshTerrainShading );
mMeshSymbolWidget->configureForTerrain();

cboCameraProjectionType->addItem( tr( "Perspective projection" ), Qt3DRender::QCameraLens::PerspectiveProjection );
cboCameraProjectionType->addItem( tr( "Orthogonal projection" ), Qt3DRender::QCameraLens::OrthographicProjection );
connect( cboCameraProjectionType, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, [ = ]()
{
spinCameraFieldOfView->setEnabled( cboCameraProjectionType->currentIndex() == cboCameraProjectionType->findData( Qt3DRender::QCameraLens::PerspectiveProjection ) );
} );

spinCameraFieldOfView->setClearValue( 45.0 );
spinTerrainScale->setClearValue( 1.0 );
spinTerrainResolution->setClearValue( 16 );
Expand Down Expand Up @@ -125,6 +132,7 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas
}

spinCameraFieldOfView->setValue( mMap->fieldOfView() );
cboCameraProjectionType->setCurrentIndex( cboCameraProjectionType->findData( mMap->projectionType() ) );
spinTerrainScale->setValue( mMap->terrainVerticalScale() );
spinMapResolution->setValue( mMap->mapTileResolution() );
spinScreenError->setValue( mMap->maxTerrainScreenError() );
Expand Down Expand Up @@ -293,6 +301,7 @@ void Qgs3DMapConfigWidget::apply()
}

mMap->setFieldOfView( spinCameraFieldOfView->value() );
mMap->setProjectionType( cboCameraProjectionType->currentData().value< Qt3DRender::QCameraLens::ProjectionType >() );
mMap->setTerrainVerticalScale( spinTerrainScale->value() );
mMap->setMapTileResolution( spinMapResolution->value() );
mMap->setMaxTerrainScreenError( spinScreenError->value() );
Expand Down
12 changes: 11 additions & 1 deletion src/ui/3d/map3dconfigwidget.ui
Expand Up @@ -608,13 +608,23 @@
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="labelCameraProjectionType">
<property name="text">
<string>Projection type</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="cboCameraProjectionType"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Field of View</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<item row="2" column="1" colspan="2">
<widget class="QgsSpinBox" name="spinCameraFieldOfView">
<property name="suffix">
<string>°</string>
Expand Down

0 comments on commit 9dee613

Please sign in to comment.