Skip to content
Permalink
Browse files

[FEATURE][3d] Add camera lens field of view settings

  • Loading branch information
nirvn authored and nyalldawson committed Feb 3, 2019
1 parent 9983961 commit 3433c9cc88bfec8a6661ab05b697cc59c2a662b5
@@ -71,7 +71,7 @@ Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine *

// Camera
float aspectRatio = ( float )viewportRect.width() / viewportRect.height();
mEngine->camera()->lens()->setPerspectiveProjection( 45.0f, aspectRatio, 10.f, 10000.0f );
mEngine->camera()->lens()->setPerspectiveProjection( mMap.fieldOfView(), aspectRatio, 10.f, 10000.0f );

mFrameAction = new Qt3DLogic::QFrameAction();
connect( mFrameAction, &Qt3DLogic::QFrameAction::triggered,
@@ -96,6 +96,7 @@ Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine *
connect( &map, &Qgs3DMapSettings::maxTerrainGroundErrorChanged, this, &Qgs3DMapScene::createTerrain );
connect( &map, &Qgs3DMapSettings::terrainShadingChanged, this, &Qgs3DMapScene::createTerrain );
connect( &map, &Qgs3DMapSettings::pointLightsChanged, this, &Qgs3DMapScene::updateLights );
connect( &map, &Qgs3DMapSettings::fieldOfViewChanged, this, &Qgs3DMapScene::updateCameraLens );

// create entities of renderers

@@ -486,6 +487,12 @@ void Qgs3DMapScene::updateLights()
}
}

void Qgs3DMapScene::updateCameraLens()
{
mEngine->camera()->lens()->setFieldOfView( mMap.fieldOfView() );
onCameraChanged();
}

void Qgs3DMapScene::onLayerRenderer3DChanged()
{
QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
@@ -107,7 +107,7 @@ class _3D_EXPORT Qgs3DMapScene : public Qt3DCore::QEntity
void onBackgroundColorChanged();
void onLayerEntityPickEvent( Qt3DRender::QPickEvent *event );
void updateLights();

void updateCameraLens();
private:
void addLayerEntity( QgsMapLayer *layer );
void removeLayerEntity( QgsMapLayer *layer );
@@ -46,6 +46,7 @@ Qgs3DMapSettings::Qgs3DMapSettings( const Qgs3DMapSettings &other )
, mShowCameraViewCenter( other.mShowCameraViewCenter )
, mShowLabels( other.mShowLabels )
, mPointLights( other.mPointLights )
, mFieldOfView( other.mFieldOfView )
, mLayers( other.mLayers )
, mSkyboxEnabled( other.mSkyboxEnabled )
, mSkyboxFileBase( other.mSkyboxFileBase )
@@ -73,6 +74,12 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte
elemOrigin.attribute( QStringLiteral( "y" ) ).toDouble(),
elemOrigin.attribute( QStringLiteral( "z" ) ).toDouble() );

QDomElement elemCamera = elem.firstChildElement( QStringLiteral( "camera" ) );
if ( !elemCamera.isNull() )
{
mFieldOfView = elemCamera.attribute( QStringLiteral( "field-of-view" ), QStringLiteral( "45" ) ).toFloat();
}

QDomElement elemColor = elem.firstChildElement( QStringLiteral( "color" ) );
if ( !elemColor.isNull() )
{
@@ -196,6 +203,10 @@ QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteCon
elemOrigin.setAttribute( QStringLiteral( "z" ), QString::number( mOrigin.z() ) );
elem.appendChild( elemOrigin );

QDomElement elemCamera = doc.createElement( QStringLiteral( "camera" ) );
elemCamera.setAttribute( QStringLiteral( "field-of-view" ), mFieldOfView );
elem.appendChild( elemCamera );

QDomElement elemColor = doc.createElement( QStringLiteral( "color" ) );
elemColor.setAttribute( QStringLiteral( "background" ), QgsSymbolLayerUtils::encodeColor( mBackgroundColor ) );
elemColor.setAttribute( QStringLiteral( "selection" ), QgsSymbolLayerUtils::encodeColor( mSelectionColor ) );
@@ -501,3 +512,12 @@ void Qgs3DMapSettings::setPointLights( const QList<QgsPointLightSettings> &point
mPointLights = pointLights;
emit pointLightsChanged();
}

void Qgs3DMapSettings::setFieldOfView( const float fieldOfView )
{
if ( mFieldOfView == fieldOfView )
return;

mFieldOfView = fieldOfView;
emit fieldOfViewChanged();
}
@@ -328,6 +328,18 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
*/
void setPointLights( const QList<QgsPointLightSettings> &pointLights );

/**
* Returns the camera lens' field of view
* \since QGIS 3.8
*/
float fieldOfView() const { return mFieldOfView; }

/**
* Sets the camera lens' field of view
* \since QGIS 3.8
*/
void setFieldOfView( const float fieldOfView );

signals:
//! Emitted when the background color has changed
void backgroundColorChanged();
@@ -376,6 +388,12 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
*/
void pointLightsChanged();

/**
* Emitted when the camer lens field of view changes
* \since QGIS 3.8
*/
void fieldOfViewChanged();

private:
//! Offset in map CRS coordinates at which our 3D world has origin (0,0,0)
QgsVector3D mOrigin;
@@ -395,6 +413,7 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
bool mShowCameraViewCenter = false; //!< Whether to show camera view center as a sphere - useful for debugging
bool mShowLabels = false; //!< Whether to display labels on terrain tiles
QList<QgsPointLightSettings> mPointLights; //!< List of lights defined for the scene
float mFieldOfView = 45.0f; //<! Camera lens field of view value
QList<QgsMapLayerRef> mLayers; //!< Layers to be rendered
QList<QgsAbstract3DRenderer *> mRenderers; //!< Extra stuff to render as 3D object
bool mSkyboxEnabled = false; //!< Whether to render skybox
@@ -142,7 +142,6 @@ void QgsLayoutItem3DMap::draw( QgsLayoutItemRenderContext &context )
connect( mEngine.get(), &QgsAbstract3DEngine::imageCaptured, this, &QgsLayoutItem3DMap::onImageCaptured );

mEngine->setSize( sizePixelsInt );

mScene = new Qgs3DMapScene( *mSettings, mEngine.get() );
connect( mScene, &Qgs3DMapScene::sceneStateChanged, this, &QgsLayoutItem3DMap::onSceneStateChanged );

@@ -35,6 +35,7 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas
Q_ASSERT( map );
Q_ASSERT( mainCanvas );

spinCameraFieldOfView->setClearValue( 45.0 );
spinTerrainScale->setClearValue( 1.0 );
spinTerrainResolution->setClearValue( 16 );
spinTerrainSkirtHeight->setClearValue( 10 );
@@ -61,6 +62,7 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas
spinTerrainSkirtHeight->setValue( 10 );
}

spinCameraFieldOfView->setValue( mMap->fieldOfView() );
spinTerrainScale->setValue( mMap->terrainVerticalScale() );
spinMapResolution->setValue( mMap->mapTileResolution() );
spinScreenError->setValue( mMap->maxTerrainScreenError() );
@@ -141,6 +143,7 @@ void Qgs3DMapConfigWidget::apply()
mMap->setOrigin( QgsVector3D( center.x(), center.y(), 0 ) );
}

mMap->setFieldOfView( spinCameraFieldOfView->value() );
mMap->setTerrainVerticalScale( spinTerrainScale->value() );
mMap->setMapTileResolution( spinMapResolution->value() );
mMap->setMaxTerrainScreenError( spinScreenError->value() );
@@ -29,6 +29,35 @@
</rect>
</property>
<layout class="QVBoxLayout" name="verticalInnerLayout">
<item>
<widget class="QgsCollapsibleGroupBox" name="cameraTerrain">
<property name="title">
<string>Camera</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" 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">
<widget class="QgsSpinBox" name="spinCameraFieldOfView">
<property name="suffix">
<string>°</string>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="maximum">
<number>180</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="groupTerrain">
<property name="title">
@@ -210,6 +210,11 @@ void TestQgs3DRendering::testFlatTerrain()
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 2500, 60, 45 );
QImage img3 = Qgs3DUtils::captureSceneImage( engine, scene );
QVERIFY( renderCheck( "flat_terrain_3", img3, 40 ) );

// change camera lens field of view
map->setFieldOfView( 85.0f );
QImage img4 = Qgs3DUtils::captureSceneImage( engine, scene );
QVERIFY( renderCheck( "flat_terrain_4", img4, 40 ) );
}

void TestQgs3DRendering::testDemTerrain()
Binary file not shown.

0 comments on commit 3433c9c

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