17#include "moc_qgscameracontroller.cpp"
26#include <QDomDocument>
27#include <Qt3DRender/QCamera>
35 , mCamera( scene->engine()->camera() )
37 , mMouseHandler( new
Qt3DInput::QMouseHandler )
38 , mKeyboardHandler( new
Qt3DInput::QKeyboardHandler )
39 , mOrigin( scene->mapSettings()->origin() )
41 mMouseHandler->setSourceDevice(
new Qt3DInput::QMouseDevice() );
42 connect( mMouseHandler, &Qt3DInput::QMouseHandler::positionChanged,
this, &QgsCameraController::onPositionChanged );
43 connect( mMouseHandler, &Qt3DInput::QMouseHandler::wheel,
this, &QgsCameraController::onWheel );
44 connect( mMouseHandler, &Qt3DInput::QMouseHandler::pressed,
this, &QgsCameraController::onMousePressed );
45 connect( mMouseHandler, &Qt3DInput::QMouseHandler::released,
this, &QgsCameraController::onMouseReleased );
46 addComponent( mMouseHandler );
48 mKeyboardHandler->setSourceDevice(
new Qt3DInput::QKeyboardDevice() );
49 connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::pressed,
this, &QgsCameraController::onKeyPressed );
50 connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::released,
this, &QgsCameraController::onKeyReleased );
51 addComponent( mKeyboardHandler );
54 connect(
this, &Qt3DCore::QEntity::enabledChanged, mMouseHandler, &Qt3DInput::QMouseHandler::setEnabled );
55 connect(
this, &Qt3DCore::QEntity::enabledChanged, mKeyboardHandler, &Qt3DInput::QKeyboardHandler::setEnabled );
57 mFpsNavTimer =
new QTimer(
this );
58 mFpsNavTimer->setInterval( 10 );
59 connect( mFpsNavTimer, &QTimer::timeout,
this, &QgsCameraController::applyFlyModeKeyMovements );
60 mFpsNavTimer->start();
65QWindow *QgsCameraController::window()
const
68 return windowEngine ? windowEngine->
window() :
nullptr;
73 if ( navigationMode == mCameraNavigationMode )
76 mCameraNavigationMode = navigationMode;
77 mIgnoreNextMouseMove =
true;
83 if ( movementSpeed == mCameraMovementSpeed )
88 mCameraMovementSpeed = std::clamp( movementSpeed, 0.05, 150.0 );
94 mVerticalAxisInversion = inversion;
99 const float oldPitch = mCameraPose.
pitchAngle();
101 float newPitch = oldPitch + diffPitch;
102 float newHeading = oldHeading + diffHeading;
104 newPitch = std::clamp( newPitch, 0.f, 180.f );
110 const QQuaternion q = qNew * qOld.conjugated();
113 const QVector3D position = mCamera->position();
114 QVector3D viewCenter = mCamera->viewCenter();
115 const QVector3D viewVector = viewCenter - position;
116 const QVector3D cameraToCenter = q * viewVector;
117 viewCenter = position + cameraToCenter;
122 updateCameraFromPose();
127 const float oldPitch = mCameraPose.
pitchAngle();
130 newPitch = std::clamp( newPitch, 0.f, 180.f );
136 const QQuaternion q = qNew * qOld.conjugated();
138 const QVector3D newViewCenter = q * ( mCamera->viewCenter() - pivotPoint ) + pivotPoint;
143 updateCameraFromPose();
149 QVector3D newCamPosition = pivotPoint + ( oldCameraPosition - pivotPoint ) * zoomFactor;
154 QVector3D cameraToCenter = q * QVector3D( 0, 0, -newDistance );
155 QVector3D newViewCenter = newCamPosition + cameraToCenter;
159 updateCameraFromPose();
166 if ( mCameraChanged )
169 mCameraChanged =
false;
190 mCamera->setNearPlane(
distance / 2 );
191 mCamera->setFarPlane(
distance * 2 );
213 if ( camPose == mCameraPose )
216 mCameraPose = camPose;
217 updateCameraFromPose();
222 QDomElement elemCamera = doc.createElement( QStringLiteral(
"camera" ) );
223 elemCamera.setAttribute( QStringLiteral(
"x" ), mCameraPose.
centerPoint().
x() );
224 elemCamera.setAttribute( QStringLiteral(
"y" ), mCameraPose.
centerPoint().
z() );
225 elemCamera.setAttribute( QStringLiteral(
"elev" ), mCameraPose.
centerPoint().
y() );
227 elemCamera.setAttribute( QStringLiteral(
"pitch" ), mCameraPose.
pitchAngle() );
228 elemCamera.setAttribute( QStringLiteral(
"yaw" ), mCameraPose.
headingAngle() );
234 const float x = elem.attribute( QStringLiteral(
"x" ) ).toFloat();
235 const float y = elem.attribute( QStringLiteral(
"y" ) ).toFloat();
236 const float elev = elem.attribute( QStringLiteral(
"elev" ) ).toFloat();
237 const float dist = elem.attribute( QStringLiteral(
"dist" ) ).toFloat();
238 const float pitch = elem.attribute( QStringLiteral(
"pitch" ) ).toFloat();
239 const float yaw = elem.attribute( QStringLiteral(
"yaw" ) ).toFloat();
243double QgsCameraController::sampleDepthBuffer(
int px,
int py )
248 for (
int x = px - 3; x <= px + 3; ++x )
250 for (
int y = py - 3; y <= py + 3; ++y )
252 if ( mDepthBufferImage.valid( x, y ) )
263 if ( mDepthBufferNonVoidAverage != -1 )
264 return mDepthBufferNonVoidAverage;
268 int samplesCount = 0;
270 Q_ASSERT( mDepthBufferImage.format() == QImage::Format_RGB32 );
271 for (
int y = 0; y < mDepthBufferImage.height(); ++y )
273 const QRgb *line =
reinterpret_cast<const QRgb *
>( mDepthBufferImage.constScanLine( y ) );
274 for (
int x = 0; x < mDepthBufferImage.width(); ++x )
286 if ( samplesCount == 0 )
289 depth /= samplesCount;
291 mDepthBufferNonVoidAverage = depth;
296void QgsCameraController::updateCameraFromPose()
301 mCameraChanged =
true;
304void QgsCameraController::moveCameraPositionBy(
const QVector3D &posDiff )
307 updateCameraFromPose();
310void QgsCameraController::onPositionChanged( Qt3DInput::QMouseEvent *mouse )
312 if ( !mInputHandlersEnabled )
315 QgsEventTracing::ScopedEvent traceEvent( QStringLiteral(
"3D" ), QStringLiteral(
"QgsCameraController::onPositionChanged" ) );
317 switch ( mCameraNavigationMode )
320 onPositionChangedTerrainNavigation( mouse );
324 onPositionChangedFlyNavigation( mouse );
329bool QgsCameraController::screenPointToWorldPos( QPoint position, Qt3DRender::QCamera *mCameraBefore,
double &depth, QVector3D &worldPosition )
331 depth = sampleDepthBuffer( position.x(), position.y() );
332 if ( !std::isfinite( depth ) )
334 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: depth is NaN or Inf. This should not happen." ), 2 );
340 if ( !std::isfinite( worldPosition.x() ) || !std::isfinite( worldPosition.y() ) || !std::isfinite( worldPosition.z() ) )
342 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: position is NaN or Inf. This should not happen." ), 2 );
352void QgsCameraController::onPositionChangedTerrainNavigation( Qt3DInput::QMouseEvent *mouse )
354 if ( mIgnoreNextMouseMove )
356 mIgnoreNextMouseMove =
false;
357 mMousePos = QPoint( mouse->x(), mouse->y() );
361 const int dx = mouse->x() - mMousePos.x();
362 const int dy = mouse->y() - mMousePos.y();
364 const bool hasShift = ( mouse->modifiers() & Qt::ShiftModifier );
365 const bool hasCtrl = ( mouse->modifiers() & Qt::ControlModifier );
366 const bool hasLeftButton = ( mouse->buttons() & Qt::LeftButton );
367 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
368 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
370 if ( ( hasLeftButton && hasShift && !hasCtrl ) || ( hasMiddleButton && !hasShift && !hasCtrl ) )
373 setMouseParameters( MouseOperation::RotationCenter, mMousePos );
375 float scale =
static_cast<float>( std::max( mScene->
engine()->
size().width(), mScene->
engine()->
size().height() ) );
376 float pitchDiff = 180.0f *
static_cast<float>( mouse->y() - mClickPoint.y() ) / scale;
377 float yawDiff = -180.0f *
static_cast<float>( mouse->x() - mClickPoint.x() ) / scale;
379 if ( !mDepthBufferIsReady )
382 if ( !mRotationCenterCalculated )
385 QVector3D worldPosition;
386 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
388 mRotationCenter = worldPosition;
389 mRotationDistanceFromCenter = ( mRotationCenter - mCameraBefore->position() ).length();
391 mRotationCenterCalculated =
true;
397 else if ( hasLeftButton && hasCtrl && !hasShift )
399 setMouseParameters( MouseOperation::RotationCamera );
401 const float diffPitch = 0.2f * dy;
402 const float diffYaw = -0.2f * dx;
405 else if ( hasLeftButton && !hasShift && !hasCtrl )
408 setMouseParameters( MouseOperation::Translation, mMousePos );
410 if ( !mDepthBufferIsReady )
413 if ( !mDragPointCalculated )
416 QVector3D worldPosition;
417 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
420 mDragPoint = worldPosition;
421 mDragPointCalculated =
true;
425 QVector3D cameraBeforeDragPos = mCameraBefore->position();
428 QVector3D cameraBeforeToMoveToPos = ( moveToPosition - mCameraBefore->position() ).normalized();
429 QVector3D cameraBeforeToDragPointPos = ( mDragPoint - mCameraBefore->position() ).normalized();
432 if ( cameraBeforeToMoveToPos.z() == 0 )
434 cameraBeforeToMoveToPos.setZ( 0.01 );
435 cameraBeforeToMoveToPos = cameraBeforeToMoveToPos.normalized();
438 if ( cameraBeforeToDragPointPos.z() == 0 )
440 cameraBeforeToDragPointPos.setZ( 0.01 );
441 cameraBeforeToDragPointPos = cameraBeforeToDragPointPos.normalized();
444 double d1 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToMoveToPos.z();
445 double d2 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToDragPointPos.z();
447 QVector3D from = cameraBeforeDragPos + d1 * cameraBeforeToMoveToPos;
448 QVector3D to = cameraBeforeDragPos + d2 * cameraBeforeToDragPointPos;
450 QVector3D shiftVector = to - from;
452 mCameraPose.
setCenterPoint( mCameraBefore->viewCenter() + shiftVector );
453 updateCameraFromPose();
455 else if ( hasLeftButton && hasShift && hasCtrl )
459 double tElev = mMousePos.y() - mouse->y();
460 center.
set( center.
x(), center.
y(), center.
z() + tElev * 0.5 );
462 updateCameraFromPose();
464 else if ( hasRightButton && !hasShift && !hasCtrl )
466 setMouseParameters( MouseOperation::Zoom, mMousePos );
467 if ( !mDepthBufferIsReady )
470 if ( !mDragPointCalculated )
473 QVector3D worldPosition;
474 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
476 mDragPoint = worldPosition;
477 mDragPointCalculated =
true;
481 float oldDist = ( mCameraBefore->position() - mDragPoint ).length();
482 float newDist = oldDist;
485 int screenHeight = mScene->
engine()->
size().height();
486 QWindow *win = window();
489 yOffset = win->mapToGlobal( QPoint( 0, 0 ) ).y();
490 screenHeight = win->screen()->size().height();
494 if ( mMousePos.y() > mClickPoint.y() )
496 double f = ( double ) ( mMousePos.y() - mClickPoint.y() ) / (
double ) ( screenHeight - mClickPoint.y() - yOffset );
497 f = std::max( 0.0, std::min( 1.0, f ) );
498 f = 1 - ( std::expm1( -2 * f ) ) / ( std::expm1( -2 ) );
499 newDist = newDist * f;
503 double f = 1 - ( double ) ( mMousePos.y() + yOffset ) / (
double ) ( mClickPoint.y() + yOffset );
504 f = std::max( 0.0, std::min( 1.0, f ) );
505 f = ( std::expm1( 2 * f ) ) / ( std::expm1( 2 ) );
506 newDist = newDist + 2 * newDist * f;
509 double zoomFactor = newDist / oldDist;
513 mMousePos = QPoint( mouse->x(), mouse->y() );
520 dist -= dist * factor * 0.01f;
522 updateCameraFromPose();
525void QgsCameraController::handleTerrainNavigationWheelZoom()
527 if ( !mDepthBufferIsReady )
530 if ( !mZoomPointCalculated )
533 QVector3D worldPosition;
534 if ( screenPointToWorldPos( mMousePos, mCameraBefore.get(), depth, worldPosition ) )
536 mZoomPoint = worldPosition;
537 mZoomPointCalculated =
true;
541 float f = mCumulatedWheelY / ( 120.0 * 24.0 );
543 double oldDist = ( mZoomPoint - mCameraBefore->position() ).length();
544 double newDist = ( 1 - f ) * oldDist;
545 double zoomFactor = newDist / oldDist;
549 mCumulatedWheelY = 0;
550 setMouseParameters( MouseOperation::None );
553void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel )
555 if ( !mInputHandlersEnabled )
558 switch ( mCameraNavigationMode )
562 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.1f : 1.0f ) / 1000.f;
563 setCameraMovementSpeed( mCameraMovementSpeed + mCameraMovementSpeed * scaling * wheel->angleDelta().y() );
569 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.5f : 5.f );
573 mCumulatedWheelY += scaling * wheel->angleDelta().y();
575 if ( mCurrentOperation != MouseOperation::ZoomWheel )
577 setMouseParameters( MouseOperation::ZoomWheel );
582 handleTerrainNavigationWheelZoom();
589void QgsCameraController::onMousePressed( Qt3DInput::QMouseEvent *mouse )
591 if ( !mInputHandlersEnabled )
594 mKeyboardHandler->setFocus(
true );
596 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 ) )
598 mMousePos = QPoint( mouse->x(), mouse->y() );
600 if ( mCaptureFpsMouseMovements )
601 mIgnoreNextMouseMove =
true;
603 const MouseOperation operation {
604 ( mouse->modifiers() & Qt::ControlModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ? MouseOperation::RotationCamera : MouseOperation::RotationCenter
606 setMouseParameters( operation, mMousePos );
609 else if ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton || mouse->button() == Qt3DInput::QMouseEvent::RightButton )
611 mMousePos = QPoint( mouse->x(), mouse->y() );
613 if ( mCaptureFpsMouseMovements )
614 mIgnoreNextMouseMove =
true;
616 const MouseOperation operation = ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) ? MouseOperation::Translation : MouseOperation::Zoom;
617 setMouseParameters( operation, mMousePos );
621void QgsCameraController::onMouseReleased( Qt3DInput::QMouseEvent *mouse )
624 if ( !mInputHandlersEnabled )
628 setMouseParameters( MouseOperation::None );
631void QgsCameraController::onKeyPressed( Qt3DInput::QKeyEvent *event )
633 if ( !mInputHandlersEnabled )
636 if ( event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_QuoteLeft )
639 switch ( mCameraNavigationMode )
651 switch ( mCameraNavigationMode )
655 onKeyPressedFlyNavigation( event );
661 onKeyPressedTerrainNavigation( event );
667void QgsCameraController::onKeyPressedTerrainNavigation( Qt3DInput::QKeyEvent *event )
669 const bool hasShift = (
event->modifiers() & Qt::ShiftModifier );
670 const bool hasCtrl = (
event->modifiers() & Qt::ControlModifier );
672 int tx = 0, ty = 0, tElev = 0;
673 switch ( event->key() )
689 case Qt::Key_PageDown:
699 if ( !hasShift && !hasCtrl )
703 else if ( hasShift && !hasCtrl )
709 else if ( hasCtrl && !hasShift )
712 const float diffPitch = ty;
713 const float diffYaw = -tx;
721 center.
set( center.
x(), center.
y(), center.
z() + tElev * 10 );
723 updateCameraFromPose();
727void QgsCameraController::onKeyPressedFlyNavigation( Qt3DInput::QKeyEvent *event )
729 switch ( event->key() )
731 case Qt::Key_QuoteLeft:
734 mCaptureFpsMouseMovements = !mCaptureFpsMouseMovements;
735 mIgnoreNextMouseMove =
true;
736 if ( mCaptureFpsMouseMovements )
738 qApp->setOverrideCursor( QCursor( Qt::BlankCursor ) );
742 qApp->restoreOverrideCursor();
750 if ( mCaptureFpsMouseMovements )
752 mCaptureFpsMouseMovements =
false;
753 mIgnoreNextMouseMove =
true;
754 qApp->restoreOverrideCursor();
764 if ( event->isAutoRepeat() )
767 mDepressedKeys.insert( event->key() );
772 const QVector3D cameraUp = mCamera->upVector().normalized();
774 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
776 QVector3D cameraPosDiff( 0.0f, 0.0f, 0.0f );
780 cameraPosDiff +=
static_cast<float>( tx ) * cameraFront;
784 cameraPosDiff +=
static_cast<float>( ty ) * cameraLeft;
788 cameraPosDiff +=
static_cast<float>( tz ) * QVector3D( 0.0f, 0.0f, 1.0f );
791 moveCameraPositionBy( cameraPosDiff );
794void QgsCameraController::applyFlyModeKeyMovements()
797 const bool shiftPressed = mDepressedKeys.contains( Qt::Key_Shift );
798 const bool ctrlPressed = mDepressedKeys.contains( Qt::Key_Control );
800 const double movementSpeed = mCameraMovementSpeed * ( shiftPressed ? 2 : 1 ) * ( ctrlPressed ? 0.1 : 1 );
802 bool changed =
false;
806 if ( mDepressedKeys.contains( Qt::Key_Left ) || mDepressedKeys.contains( Qt::Key_A ) )
812 if ( mDepressedKeys.contains( Qt::Key_Right ) || mDepressedKeys.contains( Qt::Key_D ) )
818 if ( mDepressedKeys.contains( Qt::Key_Up ) || mDepressedKeys.contains( Qt::Key_W ) )
824 if ( mDepressedKeys.contains( Qt::Key_Down ) || mDepressedKeys.contains( Qt::Key_S ) )
832 static constexpr double ELEVATION_MOVEMENT_SCALE = 0.5;
833 if ( mDepressedKeys.contains( Qt::Key_PageUp ) || mDepressedKeys.contains( Qt::Key_E ) )
836 z += ELEVATION_MOVEMENT_SCALE * movementSpeed;
839 if ( mDepressedKeys.contains( Qt::Key_PageDown ) || mDepressedKeys.contains( Qt::Key_Q ) )
842 z -= ELEVATION_MOVEMENT_SCALE * movementSpeed;
849void QgsCameraController::onPositionChangedFlyNavigation( Qt3DInput::QMouseEvent *mouse )
851 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
852 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
854 const double dx = mCaptureFpsMouseMovements ? QCursor::pos().x() - mMousePos.x() : mouse->x() - mMousePos.x();
855 const double dy = mCaptureFpsMouseMovements ? QCursor::pos().y() - mMousePos.y() : mouse->y() - mMousePos.y();
856 mMousePos = mCaptureFpsMouseMovements ? QCursor::pos() : QPoint( mouse->x(), mouse->y() );
858 if ( mIgnoreNextMouseMove )
860 mIgnoreNextMouseMove =
false;
864 if ( hasMiddleButton )
867 const QVector3D cameraUp = mCamera->upVector().normalized();
869 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
870 const QVector3D cameraPosDiff = -dx * cameraLeft - dy * cameraUp;
871 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 10.0 );
873 else if ( hasRightButton )
877 const QVector3D cameraPosDiff = dy * cameraFront;
878 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 5.0 );
882 if ( mCaptureFpsMouseMovements )
884 float diffPitch = -0.2f * dy;
885 switch ( mVerticalAxisInversion )
896 const float diffYaw = -0.2f * dx;
899 else if ( mouse->buttons() & Qt::LeftButton )
901 float diffPitch = -0.2f * dy;
902 switch ( mVerticalAxisInversion )
912 const float diffYaw = -0.2f * dx;
917 if ( mCaptureFpsMouseMovements )
919 mIgnoreNextMouseMove =
true;
926void QgsCameraController::onKeyReleased( Qt3DInput::QKeyEvent *event )
928 if ( !mInputHandlersEnabled )
931 if ( event->isAutoRepeat() )
934 mDepressedKeys.remove( event->key() );
943 updateCameraFromPose();
952 updateCameraFromPose();
958 updateCameraFromPose();
965 const float x = tx * dist * 0.02f;
966 const float y = -ty * dist * 0.02f;
969 const float t = sqrt( x * x + y * y );
970 const float a = atan2( y, x ) -
yaw * M_PI / 180;
971 const float dx = cos( a ) * t;
972 const float dy = sin( a ) * t;
975 center.
set( center.
x() + dx, center.
y() - dy, center.
z() );
977 updateCameraFromPose();
982 if ( event->key() == Qt::Key_QuoteLeft )
985 switch ( mCameraNavigationMode )
989 switch ( event->key() )
1001 case Qt::Key_PageDown:
1005 case Qt::Key_Escape:
1006 if ( mCaptureFpsMouseMovements )
1018 switch ( event->key() )
1022 case Qt::Key_PageUp:
1023 case Qt::Key_PageDown:
1037 mDepthBufferImage = depthImage;
1038 mDepthBufferIsReady =
true;
1039 mDepthBufferNonVoidAverage = -1;
1041 if ( mCurrentOperation == MouseOperation::ZoomWheel )
1043 handleTerrainNavigationWheelZoom();
1047bool QgsCameraController::isATranslationRotationSequence( MouseOperation newOperation )
const
1049 return std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), newOperation ) != std::end( mTranslateOrRotate ) && std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), mCurrentOperation ) != std::end( mTranslateOrRotate );
1052void QgsCameraController::setMouseParameters(
const MouseOperation &newOperation,
const QPoint &clickPoint )
1054 if ( newOperation == mCurrentOperation )
1059 if ( newOperation == MouseOperation::None )
1061 mClickPoint = QPoint();
1069 else if ( mClickPoint.isNull() || isATranslationRotationSequence( newOperation ) )
1071 mClickPoint = clickPoint;
1075 mCurrentOperation = newOperation;
1076 mDepthBufferIsReady =
false;
1077 mRotationCenterCalculated =
false;
1078 mDragPointCalculated =
false;
1079 mZoomPointCalculated =
false;
1081 if ( mCurrentOperation != MouseOperation::None && mCurrentOperation != MouseOperation::RotationCamera )
1085 mCameraBefore->setProjectionMatrix( mCamera->projectionMatrix() );
1086 mCameraBefore->setNearPlane( mCamera->nearPlane() );
1087 mCameraBefore->setFarPlane( mCamera->farPlane() );
1088 mCameraBefore->setAspectRatio( mCamera->aspectRatio() );
1089 mCameraBefore->setFieldOfView( mCamera->fieldOfView() );
1100 mCameraBefore->setPosition( (
QgsVector3D( mCameraBefore->position() ) - diff ).toVector3D() );
1101 mCameraBefore->setViewCenter( (
QgsVector3D( mCameraBefore->viewCenter() ) - diff ).toVector3D() );
1102 mDragPoint = (
QgsVector3D( mDragPoint ) - diff ).toVector3D();
1103 mRotationCenter = (
QgsVector3D( mRotationCenter ) - diff ).toVector3D();
1107 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 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 setCameraPose(const QgsCameraPose &camPose)
Sets camera pose.
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)