17#include "moc_qgscameracontroller.cpp"
26#include <QDomDocument>
27#include <Qt3DRender/QCamera>
36 , mCamera( scene->engine()->camera() )
38 , mMouseHandler( new
Qt3DInput::QMouseHandler )
39 , mKeyboardHandler( new
Qt3DInput::QKeyboardHandler )
40 , mOrigin( scene->mapSettings()->origin() )
42 mMouseHandler->setSourceDevice(
new Qt3DInput::QMouseDevice() );
43 connect( mMouseHandler, &Qt3DInput::QMouseHandler::positionChanged,
this, &QgsCameraController::onPositionChanged );
44 connect( mMouseHandler, &Qt3DInput::QMouseHandler::wheel,
this, &QgsCameraController::onWheel );
45 connect( mMouseHandler, &Qt3DInput::QMouseHandler::pressed,
this, &QgsCameraController::onMousePressed );
46 connect( mMouseHandler, &Qt3DInput::QMouseHandler::released,
this, &QgsCameraController::onMouseReleased );
47 addComponent( mMouseHandler );
49 mKeyboardHandler->setSourceDevice(
new Qt3DInput::QKeyboardDevice() );
50 connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::pressed,
this, &QgsCameraController::onKeyPressed );
51 connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::released,
this, &QgsCameraController::onKeyReleased );
52 addComponent( mKeyboardHandler );
55 connect(
this, &Qt3DCore::QEntity::enabledChanged, mMouseHandler, &Qt3DInput::QMouseHandler::setEnabled );
56 connect(
this, &Qt3DCore::QEntity::enabledChanged, mKeyboardHandler, &Qt3DInput::QKeyboardHandler::setEnabled );
58 mFpsNavTimer =
new QTimer(
this );
59 mFpsNavTimer->setInterval( 10 );
60 connect( mFpsNavTimer, &QTimer::timeout,
this, &QgsCameraController::applyFlyModeKeyMovements );
61 mFpsNavTimer->start();
66QWindow *QgsCameraController::window()
const
69 return windowEngine ? windowEngine->
window() :
nullptr;
74 if ( navigationMode == mCameraNavigationMode )
77 mCameraNavigationMode = navigationMode;
78 mIgnoreNextMouseMove =
true;
84 if ( movementSpeed == mCameraMovementSpeed )
89 mCameraMovementSpeed = std::clamp( movementSpeed, 0.05, 150.0 );
95 mVerticalAxisInversion = inversion;
100 const float oldPitch = mCameraPose.
pitchAngle();
102 float newPitch = oldPitch + diffPitch;
103 float newHeading = oldHeading + diffHeading;
105 newPitch = std::clamp( newPitch, 0.f, 180.f );
111 const QQuaternion q = qNew * qOld.conjugated();
114 const QVector3D position = mCamera->position();
115 QVector3D viewCenter = mCamera->viewCenter();
116 const QVector3D viewVector = viewCenter - position;
117 const QVector3D cameraToCenter = q * viewVector;
118 viewCenter = position + cameraToCenter;
123 updateCameraFromPose();
128 const float oldPitch = mCameraPose.
pitchAngle();
131 newPitch = std::clamp( newPitch, 0.f, 180.f );
137 const QQuaternion q = qNew * qOld.conjugated();
139 const QVector3D newViewCenter = q * ( mCamera->viewCenter() - pivotPoint ) + pivotPoint;
144 updateCameraFromPose();
150 QVector3D newCamPosition = pivotPoint + ( oldCameraPosition - pivotPoint ) * zoomFactor;
155 QVector3D cameraToCenter = q * QVector3D( 0, 0, -newDistance );
156 QVector3D newViewCenter = newCamPosition + cameraToCenter;
160 updateCameraFromPose();
167 if ( mCameraChanged )
170 mCameraChanged =
false;
185 const float terrainElevationOffset = terrain ? terrain->terrainElevationOffset() : 0.0f;
191 mCamera->setNearPlane(
distance / 2 );
192 mCamera->setFarPlane(
distance * 2 );
224 if ( camPose == mCameraPose && !force )
227 mCameraPose = camPose;
228 updateCameraFromPose();
233 QDomElement elemCamera = doc.createElement( QStringLiteral(
"camera" ) );
234 elemCamera.setAttribute( QStringLiteral(
"x" ), mCameraPose.
centerPoint().
x() );
235 elemCamera.setAttribute( QStringLiteral(
"y" ), mCameraPose.
centerPoint().
z() );
236 elemCamera.setAttribute( QStringLiteral(
"elev" ), mCameraPose.
centerPoint().
y() );
238 elemCamera.setAttribute( QStringLiteral(
"pitch" ), mCameraPose.
pitchAngle() );
239 elemCamera.setAttribute( QStringLiteral(
"yaw" ), mCameraPose.
headingAngle() );
245 const float x = elem.attribute( QStringLiteral(
"x" ) ).toFloat();
246 const float y = elem.attribute( QStringLiteral(
"y" ) ).toFloat();
247 const float elev = elem.attribute( QStringLiteral(
"elev" ) ).toFloat();
248 const float dist = elem.attribute( QStringLiteral(
"dist" ) ).toFloat();
249 const float pitch = elem.attribute( QStringLiteral(
"pitch" ) ).toFloat();
250 const float yaw = elem.attribute( QStringLiteral(
"yaw" ) ).toFloat();
254double QgsCameraController::sampleDepthBuffer(
int px,
int py )
259 for (
int x = px - 3; x <= px + 3; ++x )
261 for (
int y = py - 3; y <= py + 3; ++y )
263 if ( mDepthBufferImage.valid( x, y ) )
274 if ( mDepthBufferNonVoidAverage != -1 )
275 return mDepthBufferNonVoidAverage;
279 int samplesCount = 0;
281 Q_ASSERT( mDepthBufferImage.format() == QImage::Format_RGB32 );
282 for (
int y = 0; y < mDepthBufferImage.height(); ++y )
284 const QRgb *line =
reinterpret_cast<const QRgb *
>( mDepthBufferImage.constScanLine( y ) );
285 for (
int x = 0; x < mDepthBufferImage.width(); ++x )
297 if ( samplesCount == 0 )
300 depth /= samplesCount;
302 mDepthBufferNonVoidAverage = depth;
307void QgsCameraController::updateCameraFromPose()
312 mCameraChanged =
true;
316void QgsCameraController::moveCameraPositionBy(
const QVector3D &posDiff )
319 updateCameraFromPose();
322void QgsCameraController::onPositionChanged( Qt3DInput::QMouseEvent *mouse )
324 if ( !mInputHandlersEnabled )
327 QgsEventTracing::ScopedEvent traceEvent( QStringLiteral(
"3D" ), QStringLiteral(
"QgsCameraController::onPositionChanged" ) );
329 switch ( mCameraNavigationMode )
332 onPositionChangedTerrainNavigation( mouse );
336 onPositionChangedFlyNavigation( mouse );
341bool QgsCameraController::screenPointToWorldPos( QPoint position, Qt3DRender::QCamera *mCameraBefore,
double &depth, QVector3D &worldPosition )
343 depth = sampleDepthBuffer( position.x(), position.y() );
344 if ( !std::isfinite( depth ) )
346 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: depth is NaN or Inf. This should not happen." ), 2 );
352 if ( !std::isfinite( worldPosition.x() ) || !std::isfinite( worldPosition.y() ) || !std::isfinite( worldPosition.z() ) )
354 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: position is NaN or Inf. This should not happen." ), 2 );
364void QgsCameraController::onPositionChangedTerrainNavigation( Qt3DInput::QMouseEvent *mouse )
366 if ( mIgnoreNextMouseMove )
368 mIgnoreNextMouseMove =
false;
369 mMousePos = QPoint( mouse->x(), mouse->y() );
373 const int dx = mouse->x() - mMousePos.x();
374 const int dy = mouse->y() - mMousePos.y();
376 const bool hasShift = ( mouse->modifiers() & Qt::ShiftModifier );
377 const bool hasCtrl = ( mouse->modifiers() & Qt::ControlModifier );
378 const bool hasLeftButton = ( mouse->buttons() & Qt::LeftButton );
379 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
380 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
382 if ( ( hasLeftButton && hasShift && !hasCtrl ) || ( hasMiddleButton && !hasShift && !hasCtrl ) )
385 setMouseParameters( MouseOperation::RotationCenter, mMousePos );
387 float scale =
static_cast<float>( std::max( mScene->
engine()->
size().width(), mScene->
engine()->
size().height() ) );
388 float pitchDiff = 180.0f *
static_cast<float>( mouse->y() - mClickPoint.y() ) / scale;
389 float yawDiff = -180.0f *
static_cast<float>( mouse->x() - mClickPoint.x() ) / scale;
391 if ( !mDepthBufferIsReady )
394 if ( !mRotationCenterCalculated )
397 QVector3D worldPosition;
398 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
400 mRotationCenter = worldPosition;
401 mRotationDistanceFromCenter = ( mRotationCenter - mCameraBefore->position() ).length();
403 mRotationCenterCalculated =
true;
409 else if ( hasLeftButton && hasCtrl && !hasShift )
411 setMouseParameters( MouseOperation::RotationCamera );
413 const float diffPitch = 0.2f * dy;
414 const float diffYaw = -0.2f * dx;
417 else if ( hasLeftButton && !hasShift && !hasCtrl )
420 setMouseParameters( MouseOperation::Translation, mMousePos );
422 if ( !mDepthBufferIsReady )
425 if ( !mDragPointCalculated )
428 QVector3D worldPosition;
429 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
432 mDragPoint = worldPosition;
433 mDragPointCalculated =
true;
437 QVector3D cameraBeforeDragPos = mCameraBefore->position();
440 QVector3D cameraBeforeToMoveToPos = ( moveToPosition - mCameraBefore->position() ).normalized();
441 QVector3D cameraBeforeToDragPointPos = ( mDragPoint - mCameraBefore->position() ).normalized();
444 if ( cameraBeforeToMoveToPos.z() == 0 )
446 cameraBeforeToMoveToPos.setZ( 0.01 );
447 cameraBeforeToMoveToPos = cameraBeforeToMoveToPos.normalized();
450 if ( cameraBeforeToDragPointPos.z() == 0 )
452 cameraBeforeToDragPointPos.setZ( 0.01 );
453 cameraBeforeToDragPointPos = cameraBeforeToDragPointPos.normalized();
456 double d1 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToMoveToPos.z();
457 double d2 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToDragPointPos.z();
459 QVector3D from = cameraBeforeDragPos + d1 * cameraBeforeToMoveToPos;
460 QVector3D to = cameraBeforeDragPos + d2 * cameraBeforeToDragPointPos;
462 QVector3D shiftVector = to - from;
464 mCameraPose.
setCenterPoint( mCameraBefore->viewCenter() + shiftVector );
465 updateCameraFromPose();
467 else if ( hasLeftButton && hasShift && hasCtrl )
471 double tElev = mMousePos.y() - mouse->y();
472 center.
set( center.
x(), center.
y(), center.
z() + tElev * 0.5 );
474 updateCameraFromPose();
476 else if ( hasRightButton && !hasShift && !hasCtrl )
478 setMouseParameters( MouseOperation::Zoom, mMousePos );
479 if ( !mDepthBufferIsReady )
482 if ( !mDragPointCalculated )
485 QVector3D worldPosition;
486 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
488 mDragPoint = worldPosition;
489 mDragPointCalculated =
true;
493 float oldDist = ( mCameraBefore->position() - mDragPoint ).length();
494 float newDist = oldDist;
497 int screenHeight = mScene->
engine()->
size().height();
498 QWindow *win = window();
501 yOffset = win->mapToGlobal( QPoint( 0, 0 ) ).y();
502 screenHeight = win->screen()->size().height();
506 if ( mMousePos.y() > mClickPoint.y() )
508 double f = ( double ) ( mMousePos.y() - mClickPoint.y() ) / (
double ) ( screenHeight - mClickPoint.y() - yOffset );
509 f = std::max( 0.0, std::min( 1.0, f ) );
510 f = 1 - ( std::expm1( -2 * f ) ) / ( std::expm1( -2 ) );
511 newDist = newDist * f;
515 double f = 1 - ( double ) ( mMousePos.y() + yOffset ) / (
double ) ( mClickPoint.y() + yOffset );
516 f = std::max( 0.0, std::min( 1.0, f ) );
517 f = ( std::expm1( 2 * f ) ) / ( std::expm1( 2 ) );
518 newDist = newDist + 2 * newDist * f;
521 double zoomFactor = newDist / oldDist;
525 mMousePos = QPoint( mouse->x(), mouse->y() );
532 dist -= dist * factor * 0.01f;
534 updateCameraFromPose();
537void QgsCameraController::handleTerrainNavigationWheelZoom()
539 if ( !mDepthBufferIsReady )
542 if ( !mZoomPointCalculated )
545 QVector3D worldPosition;
546 if ( screenPointToWorldPos( mMousePos, mCameraBefore.get(), depth, worldPosition ) )
548 mZoomPoint = worldPosition;
549 mZoomPointCalculated =
true;
553 double oldDist = ( mZoomPoint - mCameraBefore->position() ).length();
555 double newDist = std::pow( 0.8, mCumulatedWheelY ) * oldDist;
557 newDist = std::max( newDist, 2.0 );
558 double zoomFactor = newDist / oldDist;
560 zoomFactor = std::clamp( zoomFactor, 0.01, 100.0 );
564 mCumulatedWheelY = 0;
565 setMouseParameters( MouseOperation::None );
568void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel )
570 if ( !mInputHandlersEnabled )
573 switch ( mCameraNavigationMode )
577 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.1f : 1.0f ) / 1000.f;
578 setCameraMovementSpeed( mCameraMovementSpeed + mCameraMovementSpeed * scaling * wheel->angleDelta().y() );
586 const double scaling = ( 1.0 / 120.0 ) * ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.1 : 1.0 );
590 mCumulatedWheelY += scaling * wheel->angleDelta().y();
592 if ( mCurrentOperation != MouseOperation::ZoomWheel )
594 setMouseParameters( MouseOperation::ZoomWheel );
599 handleTerrainNavigationWheelZoom();
606void QgsCameraController::onMousePressed( Qt3DInput::QMouseEvent *mouse )
608 if ( !mInputHandlersEnabled )
611 mKeyboardHandler->setFocus(
true );
613 if ( mouse->button() == Qt3DInput::QMouseEvent::MiddleButton || ( ( mouse->modifiers() & Qt::ShiftModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) || ( ( mouse->modifiers() & Qt::ControlModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) )
615 mMousePos = QPoint( mouse->x(), mouse->y() );
617 if ( mCaptureFpsMouseMovements )
618 mIgnoreNextMouseMove =
true;
620 const MouseOperation operation {
621 ( mouse->modifiers() & Qt::ControlModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ? MouseOperation::RotationCamera : MouseOperation::RotationCenter
623 setMouseParameters( operation, mMousePos );
626 else if ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton || mouse->button() == Qt3DInput::QMouseEvent::RightButton )
628 mMousePos = QPoint( mouse->x(), mouse->y() );
630 if ( mCaptureFpsMouseMovements )
631 mIgnoreNextMouseMove =
true;
633 const MouseOperation operation = ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) ? MouseOperation::Translation : MouseOperation::Zoom;
634 setMouseParameters( operation, mMousePos );
638void QgsCameraController::onMouseReleased( Qt3DInput::QMouseEvent *mouse )
641 if ( !mInputHandlersEnabled )
645 setMouseParameters( MouseOperation::None );
648void QgsCameraController::onKeyPressed( Qt3DInput::QKeyEvent *event )
650 if ( !mInputHandlersEnabled )
653 if ( event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_QuoteLeft )
656 switch ( mCameraNavigationMode )
668 switch ( mCameraNavigationMode )
672 onKeyPressedFlyNavigation( event );
678 onKeyPressedTerrainNavigation( event );
684void QgsCameraController::onKeyPressedTerrainNavigation( Qt3DInput::QKeyEvent *event )
686 const bool hasShift = (
event->modifiers() & Qt::ShiftModifier );
687 const bool hasCtrl = (
event->modifiers() & Qt::ControlModifier );
689 int tx = 0, ty = 0, tElev = 0;
690 switch ( event->key() )
706 case Qt::Key_PageDown:
716 if ( !hasShift && !hasCtrl )
720 else if ( hasShift && !hasCtrl )
726 else if ( hasCtrl && !hasShift )
729 const float diffPitch = ty;
730 const float diffYaw = -tx;
738 center.
set( center.
x(), center.
y(), center.
z() + tElev * 10 );
740 updateCameraFromPose();
744void QgsCameraController::onKeyPressedFlyNavigation( Qt3DInput::QKeyEvent *event )
746 switch ( event->key() )
748 case Qt::Key_QuoteLeft:
751 mCaptureFpsMouseMovements = !mCaptureFpsMouseMovements;
752 mIgnoreNextMouseMove =
true;
753 if ( mCaptureFpsMouseMovements )
755 qApp->setOverrideCursor( QCursor( Qt::BlankCursor ) );
759 qApp->restoreOverrideCursor();
767 if ( mCaptureFpsMouseMovements )
769 mCaptureFpsMouseMovements =
false;
770 mIgnoreNextMouseMove =
true;
771 qApp->restoreOverrideCursor();
781 if ( event->isAutoRepeat() )
784 mDepressedKeys.insert( event->key() );
789 const QVector3D cameraUp = mCamera->upVector().normalized();
791 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
793 QVector3D cameraPosDiff( 0.0f, 0.0f, 0.0f );
797 cameraPosDiff +=
static_cast<float>( tx ) * cameraFront;
801 cameraPosDiff +=
static_cast<float>( ty ) * cameraLeft;
805 cameraPosDiff +=
static_cast<float>( tz ) * QVector3D( 0.0f, 0.0f, 1.0f );
808 moveCameraPositionBy( cameraPosDiff );
811void QgsCameraController::applyFlyModeKeyMovements()
814 const bool shiftPressed = mDepressedKeys.contains( Qt::Key_Shift );
815 const bool ctrlPressed = mDepressedKeys.contains( Qt::Key_Control );
817 const double movementSpeed = mCameraMovementSpeed * ( shiftPressed ? 2 : 1 ) * ( ctrlPressed ? 0.1 : 1 );
819 bool changed =
false;
823 if ( mDepressedKeys.contains( Qt::Key_Left ) || mDepressedKeys.contains( Qt::Key_A ) )
829 if ( mDepressedKeys.contains( Qt::Key_Right ) || mDepressedKeys.contains( Qt::Key_D ) )
835 if ( mDepressedKeys.contains( Qt::Key_Up ) || mDepressedKeys.contains( Qt::Key_W ) )
841 if ( mDepressedKeys.contains( Qt::Key_Down ) || mDepressedKeys.contains( Qt::Key_S ) )
849 static constexpr double ELEVATION_MOVEMENT_SCALE = 0.5;
850 if ( mDepressedKeys.contains( Qt::Key_PageUp ) || mDepressedKeys.contains( Qt::Key_E ) )
853 z += ELEVATION_MOVEMENT_SCALE * movementSpeed;
856 if ( mDepressedKeys.contains( Qt::Key_PageDown ) || mDepressedKeys.contains( Qt::Key_Q ) )
859 z -= ELEVATION_MOVEMENT_SCALE * movementSpeed;
866void QgsCameraController::onPositionChangedFlyNavigation( Qt3DInput::QMouseEvent *mouse )
868 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
869 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
871 const double dx = mCaptureFpsMouseMovements ? QCursor::pos().x() - mMousePos.x() : mouse->x() - mMousePos.x();
872 const double dy = mCaptureFpsMouseMovements ? QCursor::pos().y() - mMousePos.y() : mouse->y() - mMousePos.y();
873 mMousePos = mCaptureFpsMouseMovements ? QCursor::pos() : QPoint( mouse->x(), mouse->y() );
875 if ( mIgnoreNextMouseMove )
877 mIgnoreNextMouseMove =
false;
881 if ( hasMiddleButton )
884 const QVector3D cameraUp = mCamera->upVector().normalized();
886 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
887 const QVector3D cameraPosDiff = -dx * cameraLeft - dy * cameraUp;
888 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 10.0 );
890 else if ( hasRightButton )
894 const QVector3D cameraPosDiff = dy * cameraFront;
895 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 5.0 );
899 if ( mCaptureFpsMouseMovements )
901 float diffPitch = -0.2f * dy;
902 switch ( mVerticalAxisInversion )
913 const float diffYaw = -0.2f * dx;
916 else if ( mouse->buttons() & Qt::LeftButton )
918 float diffPitch = -0.2f * dy;
919 switch ( mVerticalAxisInversion )
929 const float diffYaw = -0.2f * dx;
934 if ( mCaptureFpsMouseMovements )
936 mIgnoreNextMouseMove =
true;
943void QgsCameraController::onKeyReleased( Qt3DInput::QKeyEvent *event )
945 if ( !mInputHandlersEnabled )
948 if ( event->isAutoRepeat() )
951 mDepressedKeys.remove( event->key() );
960 updateCameraFromPose();
969 updateCameraFromPose();
975 updateCameraFromPose();
982 const float x = tx * dist * 0.02f;
983 const float y = -ty * dist * 0.02f;
986 const float t = sqrt( x * x + y * y );
987 const float a = atan2( y, x ) -
yaw * M_PI / 180;
988 const float dx = cos( a ) * t;
989 const float dy = sin( a ) * t;
992 center.
set( center.
x() + dx, center.
y() - dy, center.
z() );
994 updateCameraFromPose();
999 if ( event->key() == Qt::Key_QuoteLeft )
1002 switch ( mCameraNavigationMode )
1006 switch ( event->key() )
1016 case Qt::Key_PageUp:
1018 case Qt::Key_PageDown:
1022 case Qt::Key_Escape:
1023 if ( mCaptureFpsMouseMovements )
1035 switch ( event->key() )
1039 case Qt::Key_PageUp:
1040 case Qt::Key_PageDown:
1054 mDepthBufferImage = depthImage;
1055 mDepthBufferIsReady =
true;
1056 mDepthBufferNonVoidAverage = -1;
1058 if ( mCurrentOperation == MouseOperation::ZoomWheel )
1060 handleTerrainNavigationWheelZoom();
1064bool QgsCameraController::isATranslationRotationSequence( MouseOperation newOperation )
const
1066 return std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), newOperation ) != std::end( mTranslateOrRotate ) && std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), mCurrentOperation ) != std::end( mTranslateOrRotate );
1069void QgsCameraController::setMouseParameters(
const MouseOperation &newOperation,
const QPoint &clickPoint )
1071 if ( newOperation == mCurrentOperation )
1076 if ( newOperation == MouseOperation::None )
1078 mClickPoint = QPoint();
1086 else if ( mClickPoint.isNull() || isATranslationRotationSequence( newOperation ) )
1088 mClickPoint = clickPoint;
1092 mCurrentOperation = newOperation;
1093 mDepthBufferIsReady =
false;
1094 mRotationCenterCalculated =
false;
1095 mDragPointCalculated =
false;
1096 mZoomPointCalculated =
false;
1098 if ( mCurrentOperation != MouseOperation::None && mCurrentOperation != MouseOperation::RotationCamera )
1102 mCameraBefore->setProjectionMatrix( mCamera->projectionMatrix() );
1103 mCameraBefore->setNearPlane( mCamera->nearPlane() );
1104 mCameraBefore->setFarPlane( mCamera->farPlane() );
1105 mCameraBefore->setAspectRatio( mCamera->aspectRatio() );
1106 mCameraBefore->setFieldOfView( mCamera->fieldOfView() );
1117 mCameraBefore->setPosition( (
QgsVector3D( mCameraBefore->position() ) - diff ).toVector3D() );
1118 mCameraBefore->setViewCenter( (
QgsVector3D( mCameraBefore->viewCenter() ) - diff ).toVector3D() );
1119 mDragPoint = (
QgsVector3D( mDragPoint ) - diff ).toVector3D();
1120 mRotationCenter = (
QgsVector3D( mRotationCenter ) - diff ).toVector3D();
1124 updateCameraFromPose();
VerticalAxisInversion
Vertical axis inversion options for 3D views.
@ Always
Always invert vertical axis movements.
@ Never
Never invert vertical axis movements.
@ WhenDragging
Invert vertical axis movements when dragging in first person modes.
NavigationMode
The navigation mode used by 3D cameras.
@ TerrainBased
The default navigation based on the terrain.
@ Walk
Uses WASD keys or arrows to navigate in walking (first person) manner.
Qgs3DMapSettings * mapSettings() const
Returns the 3D map settings.
QgsAbstract3DEngine * engine() const
Returns the abstract 3D engine.
QgsTerrainEntity * terrainEntity()
Returns terrain entity (may be temporarily nullptr)
QgsRectangle extent() const
Returns the 3D scene's 2D extent in the 3D scene's CRS.
QgsVector3D origin() const
Returns coordinates in map CRS at which 3D scene has origin (0,0,0).
static QQuaternion rotationFromPitchHeadingAngles(float pitchAngle, float headingAngle)
Returns rotation quaternion that performs rotation around X axis by pitchAngle, followed by rotation ...
static double decodeDepth(const QRgb &pixel)
Decodes the depth value from the pixel's color value The depth value is encoded from OpenGL side (the...
static QVector3D screenPointToWorldPos(const QPoint &screenPoint, double depth, const QSize &screenSize, Qt3DRender::QCamera *camera)
Converts the clicked mouse position to the corresponding 3D world coordinates.
virtual QSize size() const =0
Returns size of the engine's rendering area in pixels.
void navigationModeChanged(Qgis::NavigationMode mode)
Emitted when the navigation mode is changed using the hotkey ctrl + ~.
void setLookingAtMapPoint(const QgsVector3D &point, float distance, float pitch, float yaw)
Sets camera configuration like setLookingAtPoint(), but the point is given in map coordinates.
void readXml(const QDomElement &elem)
Reads camera configuration from the given DOM element.
float pitch() const
Returns pitch angle in degrees (0 = looking from the top, 90 = looking from the side).
~QgsCameraController() override
float yaw() const
Returns yaw angle in degrees.
void requestDepthBufferCapture()
Emitted to ask for the depth buffer image.
void tiltUpAroundViewCenter(float deltaPitch)
Tilt up the view by deltaPitch around the view center (camera moves)
void setVerticalAxisInversion(Qgis::VerticalAxisInversion inversion)
Sets the vertical axis inversion behavior.
bool willHandleKeyEvent(QKeyEvent *event)
Returns true if the camera controller will handle the specified key event, preventing it from being i...
float distance() const
Returns distance of the camera from the point it is looking at.
void zoomCameraAroundPivot(const QVector3D &oldCameraPosition, double zoomFactor, const QVector3D &pivotPoint)
Zooms camera by given zoom factor (>1 one means zoom in) while keeping the pivot point (given in worl...
void rotateCamera(float diffPitch, float diffYaw)
Rotates the camera on itself.
void setCameraNavigationMode(Qgis::NavigationMode navigationMode)
Sets the navigation mode used by the camera controller.
void cameraChanged()
Emitted when camera has been updated.
void cameraMovementSpeedChanged(double speed)
Emitted whenever the camera movement speed is changed by the controller.
QgsCameraController(Qgs3DMapScene *scene)
Constructs the camera controller with optional parent node that will take ownership.
void frameTriggered(float dt)
Called internally from 3D scene when a new frame is generated. Updates camera according to keyboard/m...
void resetView(float distance)
Move camera back to the initial position (looking down towards origin of world's coordinates)
void setLookingAtPoint(const QgsVector3D &point, float distance, float pitch, float yaw)
Sets the complete camera configuration: the point towards it is looking (in 3D world coordinates),...
QgsVector3D lookingAtPoint() const
Returns the point in the world coordinates towards which the camera is looking.
QgsVector3D lookingAtMapPoint() const
Returns the point in the map coordinates towards which the camera is looking.
QDomElement writeXml(QDomDocument &doc) const
Writes camera configuration to the given DOM element.
void setViewFromTop(float worldX, float worldY, float distance, float yaw=0)
Sets camera to look down towards given point in world coordinate, in given distance from plane with z...
void zoom(float factor)
Zoom the map by factor.
void rotateAroundViewCenter(float deltaYaw)
Rotate clockwise the view by deltaYaw around the view center (camera moves)
void walkView(double tx, double ty, double tz)
Walks into the map by tx, ty, and tz.
void setCameraPose(const QgsCameraPose &camPose, bool force=false)
Sets camera pose.
void setOrigin(const QgsVector3D &origin)
Reacts to the shift of origin of the scene, updating camera pose and any other member variables so th...
void setCameraHeadingAngle(float angle)
Set camera heading to angle (used for rotating the view)
void setCameraMovementSpeed(double movementSpeed)
Sets the camera movement speed.
void rotateCameraAroundPivot(float newPitch, float newHeading, const QVector3D &pivotPoint)
Rotates the camera around the pivot point (in world coordinates) to the given new pitch and heading a...
void depthBufferCaptured(const QImage &depthImage)
Sets the depth buffer image used by the camera controller to calculate world position from a pixel's ...
void cameraRotationCenterChanged(QVector3D position)
Emitted when the camera rotation center changes.
void setCursorPosition(QPoint point)
Emitted when the mouse cursor position should be moved to the specified point on the map viewport.
void moveView(float tx, float ty)
Move the map by tx and ty.
float headingAngle() const
Returns heading (yaw) angle in degrees.
QgsVector3D centerPoint() const
Returns center point (towards which point the camera is looking)
float pitchAngle() const
Returns pitch angle in degrees.
float distanceFromCenterPoint() const
Returns distance of the camera from the center point.
void setPitchAngle(float pitch)
Sets pitch angle in degrees.
void setCenterPoint(const QgsVector3D &point)
Sets center point (towards which point the camera is looking)
void setHeadingAngle(float heading)
Sets heading (yaw) angle in degrees.
void setDistanceFromCenterPoint(float distance)
Sets distance of the camera from the center point.
void updateCamera(Qt3DRender::QCamera *camera)
Update Qt3D camera view matrix based on the pose.
A class to represent a 2D point.
Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double precisi...
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
double x() const
Returns X coordinate.
void set(double x, double y, double z)
Sets vector coordinates.
QWindow * window()
Returns the internal 3D window where all the rendered output is displayed.
#define QgsDebugMsgLevel(str, level)