Skip to content

Commit 255aa9e

Browse files
committed
Fix issues with camera view center adjustments + option to show the center
1 parent 8a15cef commit 255aa9e

10 files changed

+112
-26
lines changed

src/3d/qgs3dmapscene.cpp

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <Qt3DExtras/QForwardRenderer>
2424
#include <Qt3DExtras/QPhongMaterial>
2525
#include <Qt3DExtras/QSkyboxEntity>
26+
#include <Qt3DExtras/QSphereMesh>
2627
#include <Qt3DLogic/QFrameAction>
2728

2829
#include <QTimer>
@@ -34,7 +35,6 @@
3435
#include "qgscameracontroller.h"
3536
#include "qgschunkedentity_p.h"
3637
#include "qgschunknode_p.h"
37-
#include "qgsraycastingutils_p.h"
3838
#include "qgsterrainentity_p.h"
3939
#include "qgsterraingenerator.h"
4040
#include "qgsvectorlayer.h"
@@ -74,6 +74,8 @@ Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, Qt3DExtras::QForwardR
7474
mCameraController->setCamera( camera );
7575
mCameraController->resetView( 1000 );
7676

77+
addCameraViewCenterEntity( camera );
78+
7779
// create terrain entity
7880

7981
createTerrain();
@@ -255,21 +257,6 @@ void Qgs3DMapScene::onCameraChanged()
255257
camera->setFarPlane( ffar * 2 );
256258
camera->setNearPlane( fnear / 2 );
257259

258-
// figure out our distance from terrain and update the camera's view center
259-
// so that camera tilting and rotation is around a point on terrain, not an point at fixed elevation
260-
QVector3D intersectionPoint;
261-
QgsRayCastingUtils::Ray3D ray = QgsRayCastingUtils::rayForViewportAndCamera(
262-
mCameraController->viewport().size(),
263-
mCameraController->viewport().center(),
264-
QRectF( 0.0, 0.0, 1.0, 1.0 ),
265-
mCameraController->camera() );
266-
if ( mTerrain->rayIntersection( ray, intersectionPoint ) )
267-
{
268-
float dist = ( intersectionPoint - mCameraController->camera()->position() ).length();
269-
mCameraController->blockSignals( true );
270-
mCameraController->setLookingAtPoint( QgsVector3D( intersectionPoint.x(), intersectionPoint.y(), intersectionPoint.z() ), dist );
271-
mCameraController->blockSignals( false );
272-
}
273260
}
274261
else
275262
qDebug() << "no terrain - not setting near/far plane";
@@ -321,7 +308,7 @@ void Qgs3DMapScene::createTerrainDeferred()
321308
if ( mMap.showTerrainBoundingBoxes() )
322309
mTerrain->setShowBoundingBoxes( true );
323310

324-
mCameraController->addTerrainPicker( mTerrain->terrainPicker() );
311+
mCameraController->setTerrainEntity( mTerrain );
325312

326313
mChunkEntities << mTerrain;
327314

@@ -435,3 +422,31 @@ void Qgs3DMapScene::removeLayerEntity( QgsMapLayer *layer )
435422
disconnect( vlayer, &QgsVectorLayer::selectionChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
436423
}
437424
}
425+
426+
void Qgs3DMapScene::addCameraViewCenterEntity( Qt3DRender::QCamera *camera )
427+
{
428+
mEntityCameraViewCenter = new Qt3DCore::QEntity;
429+
430+
Qt3DCore::QTransform *trCameraViewCenter = new Qt3DCore::QTransform;
431+
mEntityCameraViewCenter->addComponent( trCameraViewCenter );
432+
connect( camera, &Qt3DRender::QCamera::viewCenterChanged, this, [trCameraViewCenter, camera]
433+
{
434+
trCameraViewCenter->setTranslation( camera->viewCenter() );
435+
} );
436+
437+
Qt3DExtras::QPhongMaterial *materialCameraViewCenter = new Qt3DExtras::QPhongMaterial;
438+
materialCameraViewCenter->setAmbient( Qt::red );
439+
mEntityCameraViewCenter->addComponent( materialCameraViewCenter );
440+
441+
Qt3DExtras::QSphereMesh *rendererCameraViewCenter = new Qt3DExtras::QSphereMesh;
442+
rendererCameraViewCenter->setRadius( 10 );
443+
mEntityCameraViewCenter->addComponent( rendererCameraViewCenter );
444+
445+
mEntityCameraViewCenter->setEnabled( mMap.showCameraViewCenter() );
446+
mEntityCameraViewCenter->setParent( this );
447+
448+
connect( &mMap, &Qgs3DMapSettings::showCameraViewCenterChanged, this, [this]
449+
{
450+
mEntityCameraViewCenter->setEnabled( mMap.showCameraViewCenter() );
451+
} );
452+
}

src/3d/qgs3dmapscene.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class _3D_EXPORT Qgs3DMapScene : public Qt3DCore::QEntity
8383
private:
8484
void addLayerEntity( QgsMapLayer *layer );
8585
void removeLayerEntity( QgsMapLayer *layer );
86+
void addCameraViewCenterEntity( Qt3DRender::QCamera *camera );
8687

8788
private:
8889
const Qgs3DMapSettings &mMap;
@@ -93,6 +94,8 @@ class _3D_EXPORT Qgs3DMapScene : public Qt3DCore::QEntity
9394
//! Forward renderer provided by 3D window
9495
Qt3DExtras::QForwardRenderer *mForwardRenderer = nullptr;
9596
QList<QgsChunkedEntity *> mChunkEntities;
97+
//! Entity that shows view center - useful for debugging camera issues
98+
Qt3DCore::QEntity *mEntityCameraViewCenter = nullptr;
9699
//! Keeps track of entities that belong to a particular layer
97100
QMap<QgsMapLayer *, Qt3DCore::QEntity *> mLayerEntities;
98101
bool mTerrainUpdateScheduled = false;

src/3d/qgs3dmapsettings.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Qgs3DMapSettings::Qgs3DMapSettings( const Qgs3DMapSettings &other )
3838
, mMaxTerrainGroundError( other.mMaxTerrainGroundError )
3939
, mShowTerrainBoundingBoxes( other.mShowTerrainBoundingBoxes )
4040
, mShowTerrainTileInfo( other.mShowTerrainTileInfo )
41+
, mShowCameraViewCenter( other.mShowCameraViewCenter )
4142
, mLayers( other.mLayers )
4243
, mSkyboxEnabled( other.mSkyboxEnabled )
4344
, mSkyboxFileBase( other.mSkyboxFileBase )
@@ -133,6 +134,7 @@ void Qgs3DMapSettings::readXml( const QDomElement &elem, const QgsReadWriteConte
133134
QDomElement elemDebug = elem.firstChildElement( "debug" );
134135
mShowTerrainBoundingBoxes = elemDebug.attribute( "bounding-boxes", "0" ).toInt();
135136
mShowTerrainTileInfo = elemDebug.attribute( "terrain-tile-info", "0" ).toInt();
137+
mShowCameraViewCenter = elemDebug.attribute( "camera-view-center", "0" ).toInt();
136138
}
137139

138140
QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
@@ -189,6 +191,7 @@ QDomElement Qgs3DMapSettings::writeXml( QDomDocument &doc, const QgsReadWriteCon
189191
QDomElement elemDebug = doc.createElement( "debug" );
190192
elemDebug.setAttribute( "bounding-boxes", mShowTerrainBoundingBoxes ? 1 : 0 );
191193
elemDebug.setAttribute( "terrain-tile-info", mShowTerrainTileInfo ? 1 : 0 );
194+
elemDebug.setAttribute( "camera-view-center", mShowCameraViewCenter ? 1 : 0 );
192195
elem.appendChild( elemDebug );
193196

194197
return elem;
@@ -377,6 +380,15 @@ void Qgs3DMapSettings::setShowTerrainTilesInfo( bool enabled )
377380
emit showTerrainTilesInfoChanged();
378381
}
379382

383+
void Qgs3DMapSettings::setShowCameraViewCenter( bool enabled )
384+
{
385+
if ( mShowCameraViewCenter == enabled )
386+
return;
387+
388+
mShowCameraViewCenter = enabled;
389+
emit showCameraViewCenterChanged();
390+
}
391+
380392
void Qgs3DMapSettings::setShowLabels( bool enabled )
381393
{
382394
if ( mShowLabels == enabled )

src/3d/qgs3dmapsettings.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,18 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
227227
void setShowTerrainTilesInfo( bool enabled );
228228
//! Returns whether to display extra tile info on top of terrain tiles (for debugging)
229229
bool showTerrainTilesInfo() const { return mShowTerrainTileInfo; }
230+
231+
/**
232+
* Sets whether to show camera's view center as a sphere (for debugging)
233+
* \since QGIS 3.4
234+
*/
235+
void setShowCameraViewCenter( bool enabled );
236+
237+
/**
238+
* Returns whether to show camera's view center as a sphere (for debugging)
239+
* \since QGIS 3.4
240+
*/
241+
bool showCameraViewCenter() const { return mShowCameraViewCenter; }
230242
//! Sets whether to display labels on terrain tiles
231243
void setShowLabels( bool enabled );
232244
//! Returns whether to display labels on terrain tiles
@@ -253,6 +265,12 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
253265
void showTerrainBoundingBoxesChanged();
254266
//! Emitted when the flag whether terrain's tile info is shown has changed
255267
void showTerrainTilesInfoChanged();
268+
269+
/**
270+
* Emitted when the flag whether camera's view center is shown has changed
271+
* \since QGIS 3.4
272+
*/
273+
void showCameraViewCenterChanged();
256274
//! Emitted when the flag whether labels are displayed on terrain tiles has changed
257275
void showLabelsChanged();
258276

@@ -269,6 +287,7 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
269287
float mMaxTerrainGroundError = 1.f; //!< Maximum allowed horizontal map error in map units (determines how many zoom levels will be used)
270288
bool mShowTerrainBoundingBoxes = false; //!< Whether to show bounding boxes of entities - useful for debugging
271289
bool mShowTerrainTileInfo = false; //!< Whether to draw extra information about terrain tiles to the textures - useful for debugging
290+
bool mShowCameraViewCenter = false; //!< Whether to show camera view center as a sphere - useful for debugging
272291
bool mShowLabels = false; //!< Whether to display labels on terrain tiles
273292
QList<QgsMapLayerRef> mLayers; //!< Layers to be rendered
274293
QList<QgsAbstract3DRenderer *> mRenderers; //!< Extra stuff to render as 3D object

src/3d/qgscameracontroller.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
***************************************************************************/
1515

1616
#include "qgscameracontroller.h"
17+
#include "qgsraycastingutils_p.h"
18+
#include "qgsterrainentity_p.h"
1719
#include "qgsvector3d.h"
1820

1921
#include "qgis.h"
@@ -129,10 +131,12 @@ QgsCameraController::QgsCameraController( Qt3DCore::QNode *parent )
129131
addComponent( mLogicalDevice );
130132
}
131133

132-
void QgsCameraController::addTerrainPicker( Qt3DRender::QObjectPicker *picker )
134+
void QgsCameraController::setTerrainEntity( QgsTerrainEntity *te )
133135
{
136+
mTerrainEntity = te;
137+
134138
// object picker for terrain for correct map panning
135-
connect( picker, &Qt3DRender::QObjectPicker::pressed, this, &QgsCameraController::onPickerMousePressed );
139+
connect( te->terrainPicker(), &Qt3DRender::QObjectPicker::pressed, this, &QgsCameraController::onPickerMousePressed );
136140
}
137141

138142
void QgsCameraController::setCamera( Qt3DRender::QCamera *camera )
@@ -295,6 +299,25 @@ void QgsCameraController::frameTriggered( float dt )
295299
if ( mCameraData != oldCamData )
296300
{
297301
mCameraData.setCamera( mCamera );
302+
303+
bool viewCenterChanged = ( mCameraData.x != oldCamData.x || mCameraData.y != oldCamData.y || mCameraData.elev != oldCamData.elev );
304+
if ( mTerrainEntity && viewCenterChanged )
305+
{
306+
// figure out our distance from terrain and update the camera's view center
307+
// so that camera tilting and rotation is around a point on terrain, not an point at fixed elevation
308+
QVector3D intersectionPoint;
309+
QgsRayCastingUtils::Ray3D ray = QgsRayCastingUtils::rayForViewportAndCamera( mViewport.size(), QPointF( mViewport.width() / 2., mViewport.height() / 2. ), QRectF( 0.0, 0.0, 1.0, 1.0 ), mCamera );
310+
if ( mTerrainEntity->rayIntersection( ray, intersectionPoint ) )
311+
{
312+
float dist = ( intersectionPoint - mCamera->position() ).length();
313+
mCameraData.dist = dist;
314+
mCameraData.x = intersectionPoint.x();
315+
mCameraData.y = intersectionPoint.z();
316+
mCameraData.elev = intersectionPoint.y();
317+
mCameraData.setCamera( mCamera );
318+
}
319+
}
320+
298321
emit cameraChanged();
299322
}
300323
}

src/3d/qgscameracontroller.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
class QDomDocument;
2626
class QDomElement;
2727

28+
class QgsTerrainEntity;
2829
class QgsVector3D;
2930

3031
/**
@@ -48,9 +49,11 @@ class _3D_EXPORT QgsCameraController : public Qt3DCore::QEntity
4849

4950
/**
5051
* Connects to object picker attached to terrain entity. Called internally from 3D scene.
51-
* This allows camera controller understand how far from the camera is the terrain under mouse cursor
52+
* This allows camera controller understand how far from the camera is the terrain under mouse cursor.
53+
* Also it allows adjustment of camera's view center to a point on terrain.
5254
*/
53-
void addTerrainPicker( Qt3DRender::QObjectPicker *picker );
55+
void setTerrainEntity( QgsTerrainEntity *te );
56+
5457
//! Assigns camera that should be controlled by this class. Called internally from 3D scene.
5558
void setCamera( Qt3DRender::QCamera *camera );
5659
//! Sets viewport rectangle. Called internally from 3D canvas. Allows conversion of mouse coordinates.
@@ -95,6 +98,8 @@ class _3D_EXPORT QgsCameraController : public Qt3DCore::QEntity
9598
//! height of terrain when mouse button was last pressed - for camera control
9699
float mLastPressedHeight = 0;
97100

101+
QPointer<QgsTerrainEntity> mTerrainEntity;
102+
98103
struct CameraData
99104
{
100105
float x = 0, y = 0, elev = 0; // ground point towards which the camera is looking

src/3d/qgsraycastingutils_p.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ static QRect windowViewport( const QSize &area, const QRectF &relativeViewport )
302302
return relativeViewport.toRect();
303303
}
304304

305-
static QgsRayCastingUtils::Ray3D intersectionRay( const QPoint &pos, const QMatrix4x4 &viewMatrix,
305+
static QgsRayCastingUtils::Ray3D intersectionRay( const QPointF &pos, const QMatrix4x4 &viewMatrix,
306306
const QMatrix4x4 &projectionMatrix, const QRect &viewport )
307307
{
308308
QVector3D nearPos = QVector3D( pos.x(), pos.y(), 0.0f );
@@ -320,7 +320,7 @@ namespace QgsRayCastingUtils
320320
{
321321

322322
Ray3D rayForViewportAndCamera( const QSize &area,
323-
const QPoint &pos,
323+
const QPointF &pos,
324324
const QRectF &relativeViewport,
325325
const Qt3DRender::QCamera *camera )
326326
{
@@ -330,7 +330,7 @@ namespace QgsRayCastingUtils
330330
const QRect viewport = windowViewport( area, relativeViewport );
331331

332332
// In GL the y is inverted compared to Qt
333-
const QPoint glCorrectPos = QPoint( pos.x(), area.isValid() ? area.height() - pos.y() : pos.y() );
333+
const QPointF glCorrectPos = QPointF( pos.x(), area.isValid() ? area.height() - pos.y() : pos.y() );
334334
const auto ray = intersectionRay( glCorrectPos, viewMatrix, projectionMatrix, viewport );
335335
return ray;
336336
}

src/3d/qgsraycastingutils_p.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ namespace QgsRayCastingUtils
109109
* \since QGIS 3.4
110110
*/
111111
Ray3D rayForViewportAndCamera( const QSize &area,
112-
const QPoint &pos,
112+
const QPointF &pos,
113113
const QRectF &relativeViewport,
114114
const Qt3DRender::QCamera *camera );
115115
}

src/app/3d/qgs3dmapconfigwidget.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Qgs3DMapConfigWidget::Qgs3DMapConfigWidget( Qgs3DMapSettings *map, QgsMapCanvas
6060
chkShowLabels->setChecked( mMap->showLabels() );
6161
chkShowTileInfo->setChecked( mMap->showTerrainTilesInfo() );
6262
chkShowBoundingBoxes->setChecked( mMap->showTerrainBoundingBoxes() );
63+
chkShowCameraViewCenter->setChecked( mMap->showCameraViewCenter() );
6364

6465
connect( cboTerrainLayer, static_cast<void ( QComboBox::* )( int )>( &QgsMapLayerComboBox::currentIndexChanged ), this, &Qgs3DMapConfigWidget::onTerrainLayerChanged );
6566
connect( spinMapResolution, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ), this, &Qgs3DMapConfigWidget::updateMaxZoomLevel );
@@ -125,6 +126,7 @@ void Qgs3DMapConfigWidget::apply()
125126
mMap->setShowLabels( chkShowLabels->isChecked() );
126127
mMap->setShowTerrainTilesInfo( chkShowTileInfo->isChecked() );
127128
mMap->setShowTerrainBoundingBoxes( chkShowBoundingBoxes->isChecked() );
129+
mMap->setShowCameraViewCenter( chkShowCameraViewCenter->isChecked() );
128130
}
129131

130132
void Qgs3DMapConfigWidget::onTerrainLayerChanged()

src/ui/3d/map3dconfigwidget.ui

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<x>0</x>
88
<y>0</y>
99
<width>691</width>
10-
<height>775</height>
10+
<height>830</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
@@ -186,6 +186,13 @@
186186
</property>
187187
</widget>
188188
</item>
189+
<item>
190+
<widget class="QCheckBox" name="chkShowCameraViewCenter">
191+
<property name="text">
192+
<string>Show camera's view center</string>
193+
</property>
194+
</widget>
195+
</item>
189196
<item>
190197
<spacer name="verticalSpacer">
191198
<property name="orientation">

0 commit comments

Comments
 (0)