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;
191 mCamera->setNearPlane(
distance / 2 );
192 mCamera->setFarPlane(
distance * 2 );
214 if ( camPose == mCameraPose && !force )
217 mCameraPose = camPose;
218 updateCameraFromPose();
223 QDomElement elemCamera = doc.createElement( QStringLiteral(
"camera" ) );
224 elemCamera.setAttribute( QStringLiteral(
"x" ), mCameraPose.
centerPoint().
x() );
225 elemCamera.setAttribute( QStringLiteral(
"y" ), mCameraPose.
centerPoint().
z() );
226 elemCamera.setAttribute( QStringLiteral(
"elev" ), mCameraPose.
centerPoint().
y() );
228 elemCamera.setAttribute( QStringLiteral(
"pitch" ), mCameraPose.
pitchAngle() );
229 elemCamera.setAttribute( QStringLiteral(
"yaw" ), mCameraPose.
headingAngle() );
235 const float x = elem.attribute( QStringLiteral(
"x" ) ).toFloat();
236 const float y = elem.attribute( QStringLiteral(
"y" ) ).toFloat();
237 const float elev = elem.attribute( QStringLiteral(
"elev" ) ).toFloat();
238 const float dist = elem.attribute( QStringLiteral(
"dist" ) ).toFloat();
239 const float pitch = elem.attribute( QStringLiteral(
"pitch" ) ).toFloat();
240 const float yaw = elem.attribute( QStringLiteral(
"yaw" ) ).toFloat();
244double QgsCameraController::sampleDepthBuffer(
int px,
int py )
249 for (
int x = px - 3; x <= px + 3; ++x )
251 for (
int y = py - 3; y <= py + 3; ++y )
253 if ( mDepthBufferImage.valid( x, y ) )
264 if ( mDepthBufferNonVoidAverage != -1 )
265 return mDepthBufferNonVoidAverage;
269 int samplesCount = 0;
271 Q_ASSERT( mDepthBufferImage.format() == QImage::Format_RGB32 );
272 for (
int y = 0; y < mDepthBufferImage.height(); ++y )
274 const QRgb *line =
reinterpret_cast<const QRgb *
>( mDepthBufferImage.constScanLine( y ) );
275 for (
int x = 0; x < mDepthBufferImage.width(); ++x )
287 if ( samplesCount == 0 )
290 depth /= samplesCount;
292 mDepthBufferNonVoidAverage = depth;
297void QgsCameraController::updateCameraFromPose()
302 mCameraChanged =
true;
306void QgsCameraController::moveCameraPositionBy(
const QVector3D &posDiff )
309 updateCameraFromPose();
312void QgsCameraController::onPositionChanged( Qt3DInput::QMouseEvent *mouse )
314 if ( !mInputHandlersEnabled )
317 QgsEventTracing::ScopedEvent traceEvent( QStringLiteral(
"3D" ), QStringLiteral(
"QgsCameraController::onPositionChanged" ) );
319 switch ( mCameraNavigationMode )
322 onPositionChangedTerrainNavigation( mouse );
326 onPositionChangedFlyNavigation( mouse );
331bool QgsCameraController::screenPointToWorldPos( QPoint position, Qt3DRender::QCamera *mCameraBefore,
double &depth, QVector3D &worldPosition )
333 depth = sampleDepthBuffer( position.x(), position.y() );
334 if ( !std::isfinite( depth ) )
336 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: depth is NaN or Inf. This should not happen." ), 2 );
342 if ( !std::isfinite( worldPosition.x() ) || !std::isfinite( worldPosition.y() ) || !std::isfinite( worldPosition.z() ) )
344 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: position is NaN or Inf. This should not happen." ), 2 );
354void QgsCameraController::onPositionChangedTerrainNavigation( Qt3DInput::QMouseEvent *mouse )
356 if ( mIgnoreNextMouseMove )
358 mIgnoreNextMouseMove =
false;
359 mMousePos = QPoint( mouse->x(), mouse->y() );
363 const int dx = mouse->x() - mMousePos.x();
364 const int dy = mouse->y() - mMousePos.y();
366 const bool hasShift = ( mouse->modifiers() & Qt::ShiftModifier );
367 const bool hasCtrl = ( mouse->modifiers() & Qt::ControlModifier );
368 const bool hasLeftButton = ( mouse->buttons() & Qt::LeftButton );
369 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
370 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
372 if ( ( hasLeftButton && hasShift && !hasCtrl ) || ( hasMiddleButton && !hasShift && !hasCtrl ) )
375 setMouseParameters( MouseOperation::RotationCenter, mMousePos );
377 float scale =
static_cast<float>( std::max( mScene->
engine()->
size().width(), mScene->
engine()->
size().height() ) );
378 float pitchDiff = 180.0f *
static_cast<float>( mouse->y() - mClickPoint.y() ) / scale;
379 float yawDiff = -180.0f *
static_cast<float>( mouse->x() - mClickPoint.x() ) / scale;
381 if ( !mDepthBufferIsReady )
384 if ( !mRotationCenterCalculated )
387 QVector3D worldPosition;
388 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
390 mRotationCenter = worldPosition;
391 mRotationDistanceFromCenter = ( mRotationCenter - mCameraBefore->position() ).length();
393 mRotationCenterCalculated =
true;
399 else if ( hasLeftButton && hasCtrl && !hasShift )
401 setMouseParameters( MouseOperation::RotationCamera );
403 const float diffPitch = 0.2f * dy;
404 const float diffYaw = -0.2f * dx;
407 else if ( hasLeftButton && !hasShift && !hasCtrl )
410 setMouseParameters( MouseOperation::Translation, mMousePos );
412 if ( !mDepthBufferIsReady )
415 if ( !mDragPointCalculated )
418 QVector3D worldPosition;
419 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
422 mDragPoint = worldPosition;
423 mDragPointCalculated =
true;
427 QVector3D cameraBeforeDragPos = mCameraBefore->position();
430 QVector3D cameraBeforeToMoveToPos = ( moveToPosition - mCameraBefore->position() ).normalized();
431 QVector3D cameraBeforeToDragPointPos = ( mDragPoint - mCameraBefore->position() ).normalized();
434 if ( cameraBeforeToMoveToPos.z() == 0 )
436 cameraBeforeToMoveToPos.setZ( 0.01 );
437 cameraBeforeToMoveToPos = cameraBeforeToMoveToPos.normalized();
440 if ( cameraBeforeToDragPointPos.z() == 0 )
442 cameraBeforeToDragPointPos.setZ( 0.01 );
443 cameraBeforeToDragPointPos = cameraBeforeToDragPointPos.normalized();
446 double d1 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToMoveToPos.z();
447 double d2 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToDragPointPos.z();
449 QVector3D from = cameraBeforeDragPos + d1 * cameraBeforeToMoveToPos;
450 QVector3D to = cameraBeforeDragPos + d2 * cameraBeforeToDragPointPos;
452 QVector3D shiftVector = to - from;
454 mCameraPose.
setCenterPoint( mCameraBefore->viewCenter() + shiftVector );
455 updateCameraFromPose();
457 else if ( hasLeftButton && hasShift && hasCtrl )
461 double tElev = mMousePos.y() - mouse->y();
462 center.
set( center.
x(), center.
y(), center.
z() + tElev * 0.5 );
464 updateCameraFromPose();
466 else if ( hasRightButton && !hasShift && !hasCtrl )
468 setMouseParameters( MouseOperation::Zoom, mMousePos );
469 if ( !mDepthBufferIsReady )
472 if ( !mDragPointCalculated )
475 QVector3D worldPosition;
476 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
478 mDragPoint = worldPosition;
479 mDragPointCalculated =
true;
483 float oldDist = ( mCameraBefore->position() - mDragPoint ).length();
484 float newDist = oldDist;
487 int screenHeight = mScene->
engine()->
size().height();
488 QWindow *win = window();
491 yOffset = win->mapToGlobal( QPoint( 0, 0 ) ).y();
492 screenHeight = win->screen()->size().height();
496 if ( mMousePos.y() > mClickPoint.y() )
498 double f = ( double ) ( mMousePos.y() - mClickPoint.y() ) / (
double ) ( screenHeight - mClickPoint.y() - yOffset );
499 f = std::max( 0.0, std::min( 1.0, f ) );
500 f = 1 - ( std::expm1( -2 * f ) ) / ( std::expm1( -2 ) );
501 newDist = newDist * f;
505 double f = 1 - ( double ) ( mMousePos.y() + yOffset ) / (
double ) ( mClickPoint.y() + yOffset );
506 f = std::max( 0.0, std::min( 1.0, f ) );
507 f = ( std::expm1( 2 * f ) ) / ( std::expm1( 2 ) );
508 newDist = newDist + 2 * newDist * f;
511 double zoomFactor = newDist / oldDist;
515 mMousePos = QPoint( mouse->x(), mouse->y() );
522 dist -= dist * factor * 0.01f;
524 updateCameraFromPose();
527void QgsCameraController::handleTerrainNavigationWheelZoom()
529 if ( !mDepthBufferIsReady )
532 if ( !mZoomPointCalculated )
535 QVector3D worldPosition;
536 if ( screenPointToWorldPos( mMousePos, mCameraBefore.get(), depth, worldPosition ) )
538 mZoomPoint = worldPosition;
539 mZoomPointCalculated =
true;
543 double oldDist = ( mZoomPoint - mCameraBefore->position() ).length();
545 double newDist = std::pow( 0.8, mCumulatedWheelY ) * oldDist;
547 newDist = std::max( newDist, 2.0 );
548 double zoomFactor = newDist / oldDist;
550 zoomFactor = std::clamp( zoomFactor, 0.01, 100.0 );
554 mCumulatedWheelY = 0;
555 setMouseParameters( MouseOperation::None );
558void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel )
560 if ( !mInputHandlersEnabled )
563 switch ( mCameraNavigationMode )
567 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.1f : 1.0f ) / 1000.f;
568 setCameraMovementSpeed( mCameraMovementSpeed + mCameraMovementSpeed * scaling * wheel->angleDelta().y() );
576 const double scaling = ( 1.0 / 120.0 ) * ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.1 : 1.0 );
580 mCumulatedWheelY += scaling * wheel->angleDelta().y();
582 if ( mCurrentOperation != MouseOperation::ZoomWheel )
584 setMouseParameters( MouseOperation::ZoomWheel );
589 handleTerrainNavigationWheelZoom();
596void QgsCameraController::onMousePressed( Qt3DInput::QMouseEvent *mouse )
598 if ( !mInputHandlersEnabled )
601 mKeyboardHandler->setFocus(
true );
603 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 ) )
605 mMousePos = QPoint( mouse->x(), mouse->y() );
607 if ( mCaptureFpsMouseMovements )
608 mIgnoreNextMouseMove =
true;
610 const MouseOperation operation {
611 ( mouse->modifiers() & Qt::ControlModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ? MouseOperation::RotationCamera : MouseOperation::RotationCenter
613 setMouseParameters( operation, mMousePos );
616 else if ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton || mouse->button() == Qt3DInput::QMouseEvent::RightButton )
618 mMousePos = QPoint( mouse->x(), mouse->y() );
620 if ( mCaptureFpsMouseMovements )
621 mIgnoreNextMouseMove =
true;
623 const MouseOperation operation = ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) ? MouseOperation::Translation : MouseOperation::Zoom;
624 setMouseParameters( operation, mMousePos );
628void QgsCameraController::onMouseReleased( Qt3DInput::QMouseEvent *mouse )
631 if ( !mInputHandlersEnabled )
635 setMouseParameters( MouseOperation::None );
638void QgsCameraController::onKeyPressed( Qt3DInput::QKeyEvent *event )
640 if ( !mInputHandlersEnabled )
643 if ( event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_QuoteLeft )
646 switch ( mCameraNavigationMode )
658 switch ( mCameraNavigationMode )
662 onKeyPressedFlyNavigation( event );
668 onKeyPressedTerrainNavigation( event );
674void QgsCameraController::onKeyPressedTerrainNavigation( Qt3DInput::QKeyEvent *event )
676 const bool hasShift = (
event->modifiers() & Qt::ShiftModifier );
677 const bool hasCtrl = (
event->modifiers() & Qt::ControlModifier );
679 int tx = 0, ty = 0, tElev = 0;
680 switch ( event->key() )
696 case Qt::Key_PageDown:
706 if ( !hasShift && !hasCtrl )
710 else if ( hasShift && !hasCtrl )
716 else if ( hasCtrl && !hasShift )
719 const float diffPitch = ty;
720 const float diffYaw = -tx;
728 center.
set( center.
x(), center.
y(), center.
z() + tElev * 10 );
730 updateCameraFromPose();
734void QgsCameraController::onKeyPressedFlyNavigation( Qt3DInput::QKeyEvent *event )
736 switch ( event->key() )
738 case Qt::Key_QuoteLeft:
741 mCaptureFpsMouseMovements = !mCaptureFpsMouseMovements;
742 mIgnoreNextMouseMove =
true;
743 if ( mCaptureFpsMouseMovements )
745 qApp->setOverrideCursor( QCursor( Qt::BlankCursor ) );
749 qApp->restoreOverrideCursor();
757 if ( mCaptureFpsMouseMovements )
759 mCaptureFpsMouseMovements =
false;
760 mIgnoreNextMouseMove =
true;
761 qApp->restoreOverrideCursor();
771 if ( event->isAutoRepeat() )
774 mDepressedKeys.insert( event->key() );
779 const QVector3D cameraUp = mCamera->upVector().normalized();
781 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
783 QVector3D cameraPosDiff( 0.0f, 0.0f, 0.0f );
787 cameraPosDiff +=
static_cast<float>( tx ) * cameraFront;
791 cameraPosDiff +=
static_cast<float>( ty ) * cameraLeft;
795 cameraPosDiff +=
static_cast<float>( tz ) * QVector3D( 0.0f, 0.0f, 1.0f );
798 moveCameraPositionBy( cameraPosDiff );
801void QgsCameraController::applyFlyModeKeyMovements()
804 const bool shiftPressed = mDepressedKeys.contains( Qt::Key_Shift );
805 const bool ctrlPressed = mDepressedKeys.contains( Qt::Key_Control );
807 const double movementSpeed = mCameraMovementSpeed * ( shiftPressed ? 2 : 1 ) * ( ctrlPressed ? 0.1 : 1 );
809 bool changed =
false;
813 if ( mDepressedKeys.contains( Qt::Key_Left ) || mDepressedKeys.contains( Qt::Key_A ) )
819 if ( mDepressedKeys.contains( Qt::Key_Right ) || mDepressedKeys.contains( Qt::Key_D ) )
825 if ( mDepressedKeys.contains( Qt::Key_Up ) || mDepressedKeys.contains( Qt::Key_W ) )
831 if ( mDepressedKeys.contains( Qt::Key_Down ) || mDepressedKeys.contains( Qt::Key_S ) )
839 static constexpr double ELEVATION_MOVEMENT_SCALE = 0.5;
840 if ( mDepressedKeys.contains( Qt::Key_PageUp ) || mDepressedKeys.contains( Qt::Key_E ) )
843 z += ELEVATION_MOVEMENT_SCALE * movementSpeed;
846 if ( mDepressedKeys.contains( Qt::Key_PageDown ) || mDepressedKeys.contains( Qt::Key_Q ) )
849 z -= ELEVATION_MOVEMENT_SCALE * movementSpeed;
856void QgsCameraController::onPositionChangedFlyNavigation( Qt3DInput::QMouseEvent *mouse )
858 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
859 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
861 const double dx = mCaptureFpsMouseMovements ? QCursor::pos().x() - mMousePos.x() : mouse->x() - mMousePos.x();
862 const double dy = mCaptureFpsMouseMovements ? QCursor::pos().y() - mMousePos.y() : mouse->y() - mMousePos.y();
863 mMousePos = mCaptureFpsMouseMovements ? QCursor::pos() : QPoint( mouse->x(), mouse->y() );
865 if ( mIgnoreNextMouseMove )
867 mIgnoreNextMouseMove =
false;
871 if ( hasMiddleButton )
874 const QVector3D cameraUp = mCamera->upVector().normalized();
876 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
877 const QVector3D cameraPosDiff = -dx * cameraLeft - dy * cameraUp;
878 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 10.0 );
880 else if ( hasRightButton )
884 const QVector3D cameraPosDiff = dy * cameraFront;
885 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 5.0 );
889 if ( mCaptureFpsMouseMovements )
891 float diffPitch = -0.2f * dy;
892 switch ( mVerticalAxisInversion )
903 const float diffYaw = -0.2f * dx;
906 else if ( mouse->buttons() & Qt::LeftButton )
908 float diffPitch = -0.2f * dy;
909 switch ( mVerticalAxisInversion )
919 const float diffYaw = -0.2f * dx;
924 if ( mCaptureFpsMouseMovements )
926 mIgnoreNextMouseMove =
true;
933void QgsCameraController::onKeyReleased( Qt3DInput::QKeyEvent *event )
935 if ( !mInputHandlersEnabled )
938 if ( event->isAutoRepeat() )
941 mDepressedKeys.remove( event->key() );
950 updateCameraFromPose();
959 updateCameraFromPose();
965 updateCameraFromPose();
972 const float x = tx * dist * 0.02f;
973 const float y = -ty * dist * 0.02f;
976 const float t = sqrt( x * x + y * y );
977 const float a = atan2( y, x ) -
yaw * M_PI / 180;
978 const float dx = cos( a ) * t;
979 const float dy = sin( a ) * t;
982 center.
set( center.
x() + dx, center.
y() - dy, center.
z() );
984 updateCameraFromPose();
989 if ( event->key() == Qt::Key_QuoteLeft )
992 switch ( mCameraNavigationMode )
996 switch ( event->key() )
1006 case Qt::Key_PageUp:
1008 case Qt::Key_PageDown:
1012 case Qt::Key_Escape:
1013 if ( mCaptureFpsMouseMovements )
1025 switch ( event->key() )
1029 case Qt::Key_PageUp:
1030 case Qt::Key_PageDown:
1044 mDepthBufferImage = depthImage;
1045 mDepthBufferIsReady =
true;
1046 mDepthBufferNonVoidAverage = -1;
1048 if ( mCurrentOperation == MouseOperation::ZoomWheel )
1050 handleTerrainNavigationWheelZoom();
1054bool QgsCameraController::isATranslationRotationSequence( MouseOperation newOperation )
const
1056 return std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), newOperation ) != std::end( mTranslateOrRotate ) && std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), mCurrentOperation ) != std::end( mTranslateOrRotate );
1059void QgsCameraController::setMouseParameters(
const MouseOperation &newOperation,
const QPoint &clickPoint )
1061 if ( newOperation == mCurrentOperation )
1066 if ( newOperation == MouseOperation::None )
1068 mClickPoint = QPoint();
1076 else if ( mClickPoint.isNull() || isATranslationRotationSequence( newOperation ) )
1078 mClickPoint = clickPoint;
1082 mCurrentOperation = newOperation;
1083 mDepthBufferIsReady =
false;
1084 mRotationCenterCalculated =
false;
1085 mDragPointCalculated =
false;
1086 mZoomPointCalculated =
false;
1088 if ( mCurrentOperation != MouseOperation::None && mCurrentOperation != MouseOperation::RotationCamera )
1092 mCameraBefore->setProjectionMatrix( mCamera->projectionMatrix() );
1093 mCameraBefore->setNearPlane( mCamera->nearPlane() );
1094 mCameraBefore->setFarPlane( mCamera->farPlane() );
1095 mCameraBefore->setAspectRatio( mCamera->aspectRatio() );
1096 mCameraBefore->setFieldOfView( mCamera->fieldOfView() );
1107 mCameraBefore->setPosition( (
QgsVector3D( mCameraBefore->position() ) - diff ).toVector3D() );
1108 mCameraBefore->setViewCenter( (
QgsVector3D( mCameraBefore->viewCenter() ) - diff ).toVector3D() );
1109 mDragPoint = (
QgsVector3D( mDragPoint ) - diff ).toVector3D();
1110 mRotationCenter = (
QgsVector3D( mRotationCenter ) - diff ).toVector3D();
1114 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.
QgsAbstract3DEngine * engine() const
Returns the abstract 3D engine.
QgsTerrainEntity * terrainEntity()
Returns terrain entity (may be temporarily nullptr)
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 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.
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.
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)