Skip to content

Commit 3433c9c

Browse files
nirvnnyalldawson
authored andcommitted
[FEATURE][3d] Add camera lens field of view settings
1 parent 9983961 commit 3433c9c

File tree

9 files changed

+85
-3
lines changed

9 files changed

+85
-3
lines changed

src/3d/qgs3dmapscene.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine *
7171

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

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

100101
// create entities of renderers
101102

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

490+
void Qgs3DMapScene::updateCameraLens()
491+
{
492+
mEngine->camera()->lens()->setFieldOfView( mMap.fieldOfView() );
493+
onCameraChanged();
494+
}
495+
489496
void Qgs3DMapScene::onLayerRenderer3DChanged()
490497
{
491498
QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );

src/3d/qgs3dmapscene.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class _3D_EXPORT Qgs3DMapScene : public Qt3DCore::QEntity
107107
void onBackgroundColorChanged();
108108
void onLayerEntityPickEvent( Qt3DRender::QPickEvent *event );
109109
void updateLights();
110-
110+
void updateCameraLens();
111111
private:
112112
void addLayerEntity( QgsMapLayer *layer );
113113
void removeLayerEntity( QgsMapLayer *layer );

src/3d/qgs3dmapsettings.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Qgs3DMapSettings::Qgs3DMapSettings( const Qgs3DMapSettings &other )
4646
, mShowCameraViewCenter( other.mShowCameraViewCenter )
4747
, mShowLabels( other.mShowLabels )
4848
, mPointLights( other.mPointLights )
49+
, mFieldOfView( other.mFieldOfView )
4950
, mLayers( other.mLayers )
5051
, mSkyboxEnabled( other.mSkyboxEnabled )
5152
, mSkyboxFileBase( other.mSkyboxFileBase )
@@ -73,6 +74,12 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte
7374
elemOrigin.attribute( QStringLiteral( "y" ) ).toDouble(),
7475
elemOrigin.attribute( QStringLiteral( "z" ) ).toDouble() );
7576

77+
QDomElement elemCamera = elem.firstChildElement( QStringLiteral( "camera" ) );
78+
if ( !elemCamera.isNull() )
79+
{
80+
mFieldOfView = elemCamera.attribute( QStringLiteral( "field-of-view" ), QStringLiteral( "45" ) ).toFloat();
81+
}
82+
7683
QDomElement elemColor = elem.firstChildElement( QStringLiteral( "color" ) );
7784
if ( !elemColor.isNull() )
7885
{
@@ -196,6 +203,10 @@ QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteCon
196203
elemOrigin.setAttribute( QStringLiteral( "z" ), QString::number( mOrigin.z() ) );
197204
elem.appendChild( elemOrigin );
198205

206+
QDomElement elemCamera = doc.createElement( QStringLiteral( "camera" ) );
207+
elemCamera.setAttribute( QStringLiteral( "field-of-view" ), mFieldOfView );
208+
elem.appendChild( elemCamera );
209+
199210
QDomElement elemColor = doc.createElement( QStringLiteral( "color" ) );
200211
elemColor.setAttribute( QStringLiteral( "background" ), QgsSymbolLayerUtils::encodeColor( mBackgroundColor ) );
201212
elemColor.setAttribute( QStringLiteral( "selection" ), QgsSymbolLayerUtils::encodeColor( mSelectionColor ) );
@@ -501,3 +512,12 @@ void Qgs3DMapSettings::setPointLights( const QList<QgsPointLightSettings> &point
501512
mPointLights = pointLights;
502513
emit pointLightsChanged();
503514
}
515+
516+
void Qgs3DMapSettings::setFieldOfView( const float fieldOfView )
517+
{
518+
if ( mFieldOfView == fieldOfView )
519+
return;
520+
521+
mFieldOfView = fieldOfView;
522+
emit fieldOfViewChanged();
523+
}

src/3d/qgs3dmapsettings.h

+19
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,18 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
328328
*/
329329
void setPointLights( const QList<QgsPointLightSettings> &pointLights );
330330

331+
/**
332+
* Returns the camera lens' field of view
333+
* \since QGIS 3.8
334+
*/
335+
float fieldOfView() const { return mFieldOfView; }
336+
337+
/**
338+
* Sets the camera lens' field of view
339+
* \since QGIS 3.8
340+
*/
341+
void setFieldOfView( const float fieldOfView );
342+
331343
signals:
332344
//! Emitted when the background color has changed
333345
void backgroundColorChanged();
@@ -376,6 +388,12 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
376388
*/
377389
void pointLightsChanged();
378390

391+
/**
392+
* Emitted when the camer lens field of view changes
393+
* \since QGIS 3.8
394+
*/
395+
void fieldOfViewChanged();
396+
379397
private:
380398
//! Offset in map CRS coordinates at which our 3D world has origin (0,0,0)
381399
QgsVector3D mOrigin;
@@ -395,6 +413,7 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
395413
bool mShowCameraViewCenter = false; //!< Whether to show camera view center as a sphere - useful for debugging
396414
bool mShowLabels = false; //!< Whether to display labels on terrain tiles
397415
QList<QgsPointLightSettings> mPointLights; //!< List of lights defined for the scene
416+
float mFieldOfView = 45.0f; //<! Camera lens field of view value
398417
QList<QgsMapLayerRef> mLayers; //!< Layers to be rendered
399418
QList<QgsAbstract3DRenderer *> mRenderers; //!< Extra stuff to render as 3D object
400419
bool mSkyboxEnabled = false; //!< Whether to render skybox

src/3d/qgslayoutitem3dmap.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ void QgsLayoutItem3DMap::draw( QgsLayoutItemRenderContext &context )
142142
connect( mEngine.get(), &QgsAbstract3DEngine::imageCaptured, this, &QgsLayoutItem3DMap::onImageCaptured );
143143

144144
mEngine->setSize( sizePixelsInt );
145-
146145
mScene = new Qgs3DMapScene( *mSettings, mEngine.get() );
147146
connect( mScene, &Qgs3DMapScene::sceneStateChanged, this, &QgsLayoutItem3DMap::onSceneStateChanged );
148147

src/app/3d/qgs3dmapconfigwidget.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas
3535
Q_ASSERT( map );
3636
Q_ASSERT( mainCanvas );
3737

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

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

146+
mMap->setFieldOfView( spinCameraFieldOfView->value() );
144147
mMap->setTerrainVerticalScale( spinTerrainScale->value() );
145148
mMap->setMapTileResolution( spinMapResolution->value() );
146149
mMap->setMaxTerrainScreenError( spinScreenError->value() );

src/ui/3d/map3dconfigwidget.ui

+29
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,35 @@
2929
</rect>
3030
</property>
3131
<layout class="QVBoxLayout" name="verticalInnerLayout">
32+
<item>
33+
<widget class="QgsCollapsibleGroupBox" name="cameraTerrain">
34+
<property name="title">
35+
<string>Camera</string>
36+
</property>
37+
<layout class="QGridLayout" name="gridLayout">
38+
<item row="1" column="0">
39+
<widget class="QLabel" name="label_3">
40+
<property name="text">
41+
<string>Field of View</string>
42+
</property>
43+
</widget>
44+
</item>
45+
<item row="1" column="1" colspan="2">
46+
<widget class="QgsSpinBox" name="spinCameraFieldOfView">
47+
<property name="suffix">
48+
<string>°</string>
49+
</property>
50+
<property name="maximum">
51+
<number>0</number>
52+
</property>
53+
<property name="maximum">
54+
<number>180</number>
55+
</property>
56+
</widget>
57+
</item>
58+
</layout>
59+
</widget>
60+
</item>
3261
<item>
3362
<widget class="QgsCollapsibleGroupBox" name="groupTerrain">
3463
<property name="title">

tests/src/3d/testqgs3drendering.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ void TestQgs3DRendering::testFlatTerrain()
210210
scene->cameraController()->setLookingAtPoint( QgsVector3D( 0, 0, 0 ), 2500, 60, 45 );
211211
QImage img3 = Qgs3DUtils::captureSceneImage( engine, scene );
212212
QVERIFY( renderCheck( "flat_terrain_3", img3, 40 ) );
213+
214+
// change camera lens field of view
215+
map->setFieldOfView( 85.0f );
216+
QImage img4 = Qgs3DUtils::captureSceneImage( engine, scene );
217+
QVERIFY( renderCheck( "flat_terrain_4", img4, 40 ) );
213218
}
214219

215220
void TestQgs3DRendering::testDemTerrain()
Loading

0 commit comments

Comments
 (0)