17#include "moc_qgscameracontroller.cpp"
25#include <QDomDocument>
26#include <Qt3DRender/QCamera>
34 , mCamera( scene->engine()->camera() )
36 , mMouseHandler( new
Qt3DInput::QMouseHandler )
37 , mKeyboardHandler( new
Qt3DInput::QKeyboardHandler )
38 , mOrigin( scene->mapSettings()->origin() )
40 mMouseHandler->setSourceDevice(
new Qt3DInput::QMouseDevice() );
41 connect( mMouseHandler, &Qt3DInput::QMouseHandler::positionChanged,
this, &QgsCameraController::onPositionChanged );
42 connect( mMouseHandler, &Qt3DInput::QMouseHandler::wheel,
this, &QgsCameraController::onWheel );
43 connect( mMouseHandler, &Qt3DInput::QMouseHandler::pressed,
this, &QgsCameraController::onMousePressed );
44 connect( mMouseHandler, &Qt3DInput::QMouseHandler::released,
this, &QgsCameraController::onMouseReleased );
45 addComponent( mMouseHandler );
47 mKeyboardHandler->setSourceDevice(
new Qt3DInput::QKeyboardDevice() );
48 connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::pressed,
this, &QgsCameraController::onKeyPressed );
49 connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::released,
this, &QgsCameraController::onKeyReleased );
50 addComponent( mKeyboardHandler );
53 connect(
this, &Qt3DCore::QEntity::enabledChanged, mMouseHandler, &Qt3DInput::QMouseHandler::setEnabled );
54 connect(
this, &Qt3DCore::QEntity::enabledChanged, mKeyboardHandler, &Qt3DInput::QKeyboardHandler::setEnabled );
56 mFpsNavTimer =
new QTimer(
this );
57 mFpsNavTimer->setInterval( 10 );
58 connect( mFpsNavTimer, &QTimer::timeout,
this, &QgsCameraController::applyFlyModeKeyMovements );
59 mFpsNavTimer->start();
64QWindow *QgsCameraController::window()
const
67 return windowEngine ? windowEngine->
window() :
nullptr;
72 if ( navigationMode == mCameraNavigationMode )
75 mCameraNavigationMode = navigationMode;
76 mIgnoreNextMouseMove =
true;
82 if ( movementSpeed == mCameraMovementSpeed )
87 mCameraMovementSpeed = std::clamp( movementSpeed, 0.05, 150.0 );
93 mVerticalAxisInversion = inversion;
101 if (
pitch + diffPitch > 180 )
102 diffPitch = 180 -
pitch;
103 if (
pitch + diffPitch < 0 )
104 diffPitch = 0 -
pitch;
112 const QQuaternion q1 = QQuaternion::fromEulerAngles( 0, 0,
yaw + diffYaw ) * QQuaternion::fromEulerAngles(
pitch + diffPitch, 0, 0 );
113 const QQuaternion q2 = QQuaternion::fromEulerAngles( 0, 0,
yaw ) * QQuaternion::fromEulerAngles(
pitch, 0, 0 );
114 const QQuaternion q = q1 * q2.conjugated();
117 const QVector3D position = mCamera->position();
118 QVector3D viewCenter = mCamera->viewCenter();
119 const QVector3D viewVector = viewCenter - position;
120 const QVector3D cameraToCenter = q * viewVector;
121 viewCenter = position + cameraToCenter;
126 updateCameraFromPose();
152 mCamera->setNearPlane(
distance / 2 );
153 mCamera->setFarPlane(
distance * 2 );
175 if ( camPose == mCameraPose )
178 mCameraPose = camPose;
179 updateCameraFromPose();
184 QDomElement elemCamera = doc.createElement( QStringLiteral(
"camera" ) );
185 elemCamera.setAttribute( QStringLiteral(
"x" ), mCameraPose.
centerPoint().
x() );
186 elemCamera.setAttribute( QStringLiteral(
"y" ), mCameraPose.
centerPoint().
z() );
187 elemCamera.setAttribute( QStringLiteral(
"elev" ), mCameraPose.
centerPoint().
y() );
189 elemCamera.setAttribute( QStringLiteral(
"pitch" ), mCameraPose.
pitchAngle() );
190 elemCamera.setAttribute( QStringLiteral(
"yaw" ), mCameraPose.
headingAngle() );
196 const float x = elem.attribute( QStringLiteral(
"x" ) ).toFloat();
197 const float y = elem.attribute( QStringLiteral(
"y" ) ).toFloat();
198 const float elev = elem.attribute( QStringLiteral(
"elev" ) ).toFloat();
199 const float dist = elem.attribute( QStringLiteral(
"dist" ) ).toFloat();
200 const float pitch = elem.attribute( QStringLiteral(
"pitch" ) ).toFloat();
201 const float yaw = elem.attribute( QStringLiteral(
"yaw" ) ).toFloat();
205double QgsCameraController::sampleDepthBuffer(
const QImage &buffer,
int px,
int py )
210 for (
int x = px - 3; x <= px + 3; ++x )
212 for (
int y = py - 3; y <= py + 3; ++y )
214 if ( buffer.valid( x, y ) )
226 int samplesCount = 0;
227 for (
int x = 0; x < buffer.width(); ++x )
229 for (
int y = 0; y < buffer.height(); ++y )
241 if ( samplesCount == 0 )
244 depth /= samplesCount;
249void QgsCameraController::updateCameraFromPose()
257void QgsCameraController::moveCameraPositionBy(
const QVector3D &posDiff )
260 updateCameraFromPose();
263void QgsCameraController::onPositionChanged( Qt3DInput::QMouseEvent *mouse )
265 switch ( mCameraNavigationMode )
268 onPositionChangedTerrainNavigation( mouse );
272 onPositionChangedFlyNavigation( mouse );
277bool QgsCameraController::screenPointToWorldPos( QPoint position, Qt3DRender::QCamera *mCameraBefore,
double &depth, QVector3D &worldPosition )
279 depth = sampleDepthBuffer( mDepthBufferImage, position.x(), position.y() );
280 if ( !std::isfinite( depth ) )
282 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: depth is NaN or Inf. This should not happen." ), 2 );
288 if ( !std::isfinite( worldPosition.x() ) || !std::isfinite( worldPosition.y() ) || !std::isfinite( worldPosition.z() ) )
290 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: position is NaN or Inf. This should not happen." ), 2 );
300void QgsCameraController::onPositionChangedTerrainNavigation( Qt3DInput::QMouseEvent *mouse )
302 if ( mIgnoreNextMouseMove )
304 mIgnoreNextMouseMove =
false;
305 mMousePos = QPoint( mouse->x(), mouse->y() );
309 const int dx = mouse->x() - mMousePos.x();
310 const int dy = mouse->y() - mMousePos.y();
312 const bool hasShift = ( mouse->modifiers() & Qt::ShiftModifier );
313 const bool hasCtrl = ( mouse->modifiers() & Qt::ControlModifier );
314 const bool hasLeftButton = ( mouse->buttons() & Qt::LeftButton );
315 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
316 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
318 if ( ( hasLeftButton && hasShift && !hasCtrl ) || ( hasMiddleButton && !hasShift && !hasCtrl ) )
321 setMouseParameters( MouseOperation::RotationCenter, mMousePos );
323 float scale =
static_cast<float>( std::max( mScene->
engine()->
size().width(), mScene->
engine()->
size().height() ) );
324 float pitchDiff = 180.0f *
static_cast<float>( mouse->y() - mClickPoint.y() ) / scale;
325 float yawDiff = -180.0f *
static_cast<float>( mouse->x() - mClickPoint.x() ) / scale;
327 if ( !mDepthBufferIsReady )
330 if ( !mRotationCenterCalculated )
333 QVector3D worldPosition;
334 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
336 mRotationCenter = worldPosition;
337 mRotationDistanceFromCenter = ( mRotationCenter - mCameraBefore->position() ).length();
339 mRotationCenterCalculated =
true;
345 QVector3D shiftVector = mRotationCenter - mCamera->viewCenter();
347 QVector3D newViewCenterWorld =
camera()->viewCenter() + shiftVector;
348 QVector3D newCameraPosition =
camera()->position() + shiftVector;
354 updateCameraFromPose();
362 QVector3D clickedPositionWorld = ray.
origin() + mRotationDistanceFromCenter * ray.
direction();
364 QVector3D shiftVector = clickedPositionWorld - mCamera->viewCenter();
366 QVector3D newViewCenterWorld =
camera()->viewCenter() - shiftVector;
367 QVector3D newCameraPosition =
camera()->position() - shiftVector;
371 updateCameraFromPose();
374 else if ( hasLeftButton && hasCtrl && !hasShift )
376 setMouseParameters( MouseOperation::RotationCamera );
378 const float diffPitch = 0.2f * dy;
379 const float diffYaw = -0.2f * dx;
382 else if ( hasLeftButton && !hasShift && !hasCtrl )
385 setMouseParameters( MouseOperation::Translation, mMousePos );
387 if ( !mDepthBufferIsReady )
390 if ( !mDragPointCalculated )
393 QVector3D worldPosition;
394 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
397 mDragPoint = worldPosition;
398 mDragPointCalculated =
true;
402 QVector3D cameraBeforeDragPos = mCameraBefore->position();
405 QVector3D cameraBeforeToMoveToPos = ( moveToPosition - mCameraBefore->position() ).normalized();
406 QVector3D cameraBeforeToDragPointPos = ( mDragPoint - mCameraBefore->position() ).normalized();
409 if ( cameraBeforeToMoveToPos.z() == 0 )
411 cameraBeforeToMoveToPos.setZ( 0.01 );
412 cameraBeforeToMoveToPos = cameraBeforeToMoveToPos.normalized();
415 if ( cameraBeforeToDragPointPos.z() == 0 )
417 cameraBeforeToDragPointPos.setZ( 0.01 );
418 cameraBeforeToDragPointPos = cameraBeforeToDragPointPos.normalized();
421 double d1 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToMoveToPos.z();
422 double d2 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToDragPointPos.z();
424 QVector3D from = cameraBeforeDragPos + d1 * cameraBeforeToMoveToPos;
425 QVector3D to = cameraBeforeDragPos + d2 * cameraBeforeToDragPointPos;
427 QVector3D shiftVector = to - from;
429 mCameraPose.
setCenterPoint( mCameraBefore->viewCenter() + shiftVector );
430 updateCameraFromPose();
432 else if ( hasLeftButton && hasShift && hasCtrl )
436 double tElev = mMousePos.y() - mouse->y();
437 center.
set( center.
x(), center.
y(), center.
z() + tElev * 0.5 );
439 updateCameraFromPose();
441 else if ( hasRightButton && !hasShift && !hasCtrl )
443 setMouseParameters( MouseOperation::Zoom, mMousePos );
444 if ( !mDepthBufferIsReady )
447 if ( !mDragPointCalculated )
450 QVector3D worldPosition;
451 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
453 mDragPoint = worldPosition;
454 mDragPointCalculated =
true;
458 float dist = ( mCameraBefore->position() - mDragPoint ).length();
461 int screenHeight = mScene->
engine()->
size().height();
462 QWindow *win = window();
465 yOffset = win->mapToGlobal( QPoint( 0, 0 ) ).y();
466 screenHeight = win->screen()->size().height();
470 if ( mMousePos.y() > mClickPoint.y() )
472 double f = ( double ) ( mMousePos.y() - mClickPoint.y() ) / (
double ) ( screenHeight - mClickPoint.y() - yOffset );
473 f = std::max( 0.0, std::min( 1.0, f ) );
474 f = 1 - ( std::expm1( -2 * f ) ) / ( std::expm1( -2 ) );
479 double f = 1 - ( double ) ( mMousePos.y() + yOffset ) / (
double ) ( mClickPoint.y() + yOffset );
480 f = std::max( 0.0, std::min( 1.0, f ) );
481 f = ( std::expm1( 2 * f ) ) / ( std::expm1( 2 ) );
482 dist = dist + 2 * dist * f;
487 QVector3D shiftVector = mDragPoint - mCamera->viewCenter();
489 QVector3D newViewCenterWorld =
camera()->viewCenter() + shiftVector;
493 updateCameraFromPose();
499 QVector3D clickedPositionWorld = ray.
origin() + dist * ray.
direction();
501 QVector3D shiftVector = clickedPositionWorld - mCamera->viewCenter();
503 QVector3D newViewCenterWorld =
camera()->viewCenter() - shiftVector;
504 QVector3D newCameraPosition =
camera()->position() - shiftVector;
508 updateCameraFromPose();
512 mMousePos = QPoint( mouse->x(), mouse->y() );
519 dist -= dist * factor * 0.01f;
521 updateCameraFromPose();
524void QgsCameraController::handleTerrainNavigationWheelZoom()
526 if ( !mDepthBufferIsReady )
529 if ( !mZoomPointCalculated )
532 QVector3D worldPosition;
533 if ( screenPointToWorldPos( mMousePos, mCameraBefore.get(), depth, worldPosition ) )
535 mZoomPoint = worldPosition;
536 mZoomPointCalculated =
true;
540 float f = mCumulatedWheelY / ( 120.0 * 24.0 );
542 double dist = ( mZoomPoint - mCameraBefore->position() ).length();
547 QVector3D shiftVector = mZoomPoint - mCamera->viewCenter();
549 QVector3D newViewCenterWorld =
camera()->viewCenter() + shiftVector;
553 updateCameraFromPose();
559 QVector3D clickedPositionWorld = ray.
origin() + dist * ray.
direction();
561 QVector3D shiftVector = clickedPositionWorld - mCamera->viewCenter();
563 QVector3D newViewCenterWorld =
camera()->viewCenter() - shiftVector;
564 QVector3D newCameraPosition =
camera()->position() - shiftVector;
568 updateCameraFromPose();
570 mCumulatedWheelY = 0;
571 setMouseParameters( MouseOperation::None );
574void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel )
576 switch ( mCameraNavigationMode )
580 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.1f : 1.0f ) / 1000.f;
581 setCameraMovementSpeed( mCameraMovementSpeed + mCameraMovementSpeed * scaling * wheel->angleDelta().y() );
587 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.5f : 5.f );
591 mCumulatedWheelY += scaling * wheel->angleDelta().y();
593 if ( mCurrentOperation != MouseOperation::ZoomWheel )
595 setMouseParameters( MouseOperation::ZoomWheel );
599 handleTerrainNavigationWheelZoom();
606void QgsCameraController::onMousePressed( Qt3DInput::QMouseEvent *mouse )
608 mKeyboardHandler->setFocus(
true );
610 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 ) )
612 mMousePos = QPoint( mouse->x(), mouse->y() );
614 if ( mCaptureFpsMouseMovements )
615 mIgnoreNextMouseMove =
true;
617 const MouseOperation operation {
618 ( mouse->modifiers() & Qt::ControlModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ? MouseOperation::RotationCamera : MouseOperation::RotationCenter
620 setMouseParameters( operation, mMousePos );
623 else if ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton || mouse->button() == Qt3DInput::QMouseEvent::RightButton )
625 mMousePos = QPoint( mouse->x(), mouse->y() );
627 if ( mCaptureFpsMouseMovements )
628 mIgnoreNextMouseMove =
true;
630 const MouseOperation operation = ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) ? MouseOperation::Translation : MouseOperation::Zoom;
631 setMouseParameters( operation, mMousePos );
635void QgsCameraController::onMouseReleased( Qt3DInput::QMouseEvent *mouse )
639 setMouseParameters( MouseOperation::None );
642void QgsCameraController::onKeyPressed( Qt3DInput::QKeyEvent *event )
644 if ( event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_QuoteLeft )
647 switch ( mCameraNavigationMode )
659 switch ( mCameraNavigationMode )
663 onKeyPressedFlyNavigation( event );
669 onKeyPressedTerrainNavigation( event );
675void QgsCameraController::onKeyPressedTerrainNavigation( Qt3DInput::QKeyEvent *event )
677 const bool hasShift = (
event->modifiers() & Qt::ShiftModifier );
678 const bool hasCtrl = (
event->modifiers() & Qt::ControlModifier );
680 int tx = 0, ty = 0, tElev = 0;
681 switch ( event->key() )
697 case Qt::Key_PageDown:
707 if ( !hasShift && !hasCtrl )
711 else if ( hasShift && !hasCtrl )
717 else if ( hasCtrl && !hasShift )
720 const float diffPitch = ty;
721 const float diffYaw = -tx;
729 center.
set( center.
x(), center.
y(), center.
z() + tElev * 10 );
731 updateCameraFromPose();
735void QgsCameraController::onKeyPressedFlyNavigation( Qt3DInput::QKeyEvent *event )
737 switch ( event->key() )
739 case Qt::Key_QuoteLeft:
742 mCaptureFpsMouseMovements = !mCaptureFpsMouseMovements;
743 mIgnoreNextMouseMove =
true;
744 if ( mCaptureFpsMouseMovements )
746 qApp->setOverrideCursor( QCursor( Qt::BlankCursor ) );
750 qApp->restoreOverrideCursor();
758 if ( mCaptureFpsMouseMovements )
760 mCaptureFpsMouseMovements =
false;
761 mIgnoreNextMouseMove =
true;
762 qApp->restoreOverrideCursor();
772 if ( event->isAutoRepeat() )
775 mDepressedKeys.insert( event->key() );
780 const QVector3D cameraUp = mCamera->upVector().normalized();
782 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
784 QVector3D cameraPosDiff( 0.0f, 0.0f, 0.0f );
788 cameraPosDiff +=
static_cast<float>( tx ) * cameraFront;
792 cameraPosDiff +=
static_cast<float>( ty ) * cameraLeft;
796 cameraPosDiff +=
static_cast<float>( tz ) * QVector3D( 0.0f, 0.0f, 1.0f );
799 moveCameraPositionBy( cameraPosDiff );
802void QgsCameraController::applyFlyModeKeyMovements()
805 const bool shiftPressed = mDepressedKeys.contains( Qt::Key_Shift );
806 const bool ctrlPressed = mDepressedKeys.contains( Qt::Key_Control );
808 const double movementSpeed = mCameraMovementSpeed * ( shiftPressed ? 2 : 1 ) * ( ctrlPressed ? 0.1 : 1 );
810 bool changed =
false;
814 if ( mDepressedKeys.contains( Qt::Key_Left ) || mDepressedKeys.contains( Qt::Key_A ) )
820 if ( mDepressedKeys.contains( Qt::Key_Right ) || mDepressedKeys.contains( Qt::Key_D ) )
826 if ( mDepressedKeys.contains( Qt::Key_Up ) || mDepressedKeys.contains( Qt::Key_W ) )
832 if ( mDepressedKeys.contains( Qt::Key_Down ) || mDepressedKeys.contains( Qt::Key_S ) )
840 static constexpr double ELEVATION_MOVEMENT_SCALE = 0.5;
841 if ( mDepressedKeys.contains( Qt::Key_PageUp ) || mDepressedKeys.contains( Qt::Key_E ) )
844 z += ELEVATION_MOVEMENT_SCALE * movementSpeed;
847 if ( mDepressedKeys.contains( Qt::Key_PageDown ) || mDepressedKeys.contains( Qt::Key_Q ) )
850 z -= ELEVATION_MOVEMENT_SCALE * movementSpeed;
857void QgsCameraController::onPositionChangedFlyNavigation( Qt3DInput::QMouseEvent *mouse )
859 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
860 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
862 const double dx = mCaptureFpsMouseMovements ? QCursor::pos().x() - mMousePos.x() : mouse->x() - mMousePos.x();
863 const double dy = mCaptureFpsMouseMovements ? QCursor::pos().y() - mMousePos.y() : mouse->y() - mMousePos.y();
864 mMousePos = mCaptureFpsMouseMovements ? QCursor::pos() : QPoint( mouse->x(), mouse->y() );
866 if ( mIgnoreNextMouseMove )
868 mIgnoreNextMouseMove =
false;
872 if ( hasMiddleButton )
875 const QVector3D cameraUp = mCamera->upVector().normalized();
877 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
878 const QVector3D cameraPosDiff = -dx * cameraLeft - dy * cameraUp;
879 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 10.0 );
881 else if ( hasRightButton )
885 const QVector3D cameraPosDiff = dy * cameraFront;
886 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 5.0 );
890 if ( mCaptureFpsMouseMovements )
892 float diffPitch = -0.2f * dy;
893 switch ( mVerticalAxisInversion )
904 const float diffYaw = -0.2f * dx;
907 else if ( mouse->buttons() & Qt::LeftButton )
909 float diffPitch = -0.2f * dy;
910 switch ( mVerticalAxisInversion )
920 const float diffYaw = -0.2f * dx;
925 if ( mCaptureFpsMouseMovements )
927 mIgnoreNextMouseMove =
true;
934void QgsCameraController::onKeyReleased( Qt3DInput::QKeyEvent *event )
936 if ( event->isAutoRepeat() )
939 mDepressedKeys.remove( event->key() );
948 updateCameraFromPose();
957 updateCameraFromPose();
963 updateCameraFromPose();
970 const float x = tx * dist * 0.02f;
971 const float y = -ty * dist * 0.02f;
974 const float t = sqrt( x * x + y * y );
975 const float a = atan2( y, x ) -
yaw * M_PI / 180;
976 const float dx = cos( a ) * t;
977 const float dy = sin( a ) * t;
980 center.
set( center.
x() + dx, center.
y() - dy, center.
z() );
982 updateCameraFromPose();
987 if ( event->key() == Qt::Key_QuoteLeft )
990 switch ( mCameraNavigationMode )
994 switch ( event->key() )
1004 case Qt::Key_PageUp:
1006 case Qt::Key_PageDown:
1010 case Qt::Key_Escape:
1011 if ( mCaptureFpsMouseMovements )
1023 switch ( event->key() )
1027 case Qt::Key_PageUp:
1028 case Qt::Key_PageDown:
1042 mDepthBufferImage = depthImage;
1043 mDepthBufferIsReady =
true;
1045 if ( mCurrentOperation == MouseOperation::ZoomWheel )
1047 handleTerrainNavigationWheelZoom();
1051bool QgsCameraController::isATranslationRotationSequence( MouseOperation newOperation )
const
1053 return std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), newOperation ) != std::end( mTranslateOrRotate ) && std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), mCurrentOperation ) != std::end( mTranslateOrRotate );
1056void QgsCameraController::setMouseParameters(
const MouseOperation &newOperation,
const QPoint &clickPoint )
1058 if ( newOperation == mCurrentOperation )
1063 if ( newOperation == MouseOperation::None )
1065 mClickPoint = QPoint();
1073 else if ( mClickPoint.isNull() || isATranslationRotationSequence( newOperation ) )
1075 mClickPoint = clickPoint;
1079 mCurrentOperation = newOperation;
1080 mDepthBufferIsReady =
false;
1081 mRotationCenterCalculated =
false;
1082 mDragPointCalculated =
false;
1083 mZoomPointCalculated =
false;
1085 if ( mCurrentOperation != MouseOperation::None && mCurrentOperation != MouseOperation::RotationCamera )
1089 mCameraBefore->setProjectionMatrix( mCamera->projectionMatrix() );
1090 mCameraBefore->setNearPlane( mCamera->nearPlane() );
1091 mCameraBefore->setFarPlane( mCamera->farPlane() );
1092 mCameraBefore->setAspectRatio( mCamera->aspectRatio() );
1093 mCameraBefore->setFieldOfView( mCamera->fieldOfView() );
1104 mCameraBefore->setPosition( (
QgsVector3D( mCameraBefore->position() ) - diff ).toVector3D() );
1105 mCameraBefore->setViewCenter( (
QgsVector3D( mCameraBefore->viewCenter() ) - diff ).toVector3D() );
1106 mDragPoint = (
QgsVector3D( mDragPoint ) - diff ).toVector3D();
1107 mRotationCenter = (
QgsVector3D( mRotationCenter ) - diff ).toVector3D();
1111 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 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.
static QgsRay3D rayFromScreenPoint(const QPoint &point, const QSize &windowSize, Qt3DRender::QCamera *camera)
Convert from clicked point on the screen to a ray in 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).
Qt3DRender::QCamera * camera() const
Returns camera that is being controlled.
~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 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 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 representation of a ray in 3D.
QVector3D origin() const
Returns the origin of the ray.
QVector3D direction() const
Returns the direction of the ray see setDirection()
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)