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;
98 const float oldPitch = mCameraPose.
pitchAngle();
100 float newPitch = oldPitch + diffPitch;
101 float newHeading = oldHeading + diffHeading;
103 newPitch = std::clamp( newPitch, 0.f, 180.f );
109 const QQuaternion q = qNew * qOld.conjugated();
112 const QVector3D position = mCamera->position();
113 QVector3D viewCenter = mCamera->viewCenter();
114 const QVector3D viewVector = viewCenter - position;
115 const QVector3D cameraToCenter = q * viewVector;
116 viewCenter = position + cameraToCenter;
121 updateCameraFromPose();
126 const float oldPitch = mCameraPose.
pitchAngle();
129 newPitch = std::clamp( newPitch, 0.f, 180.f );
135 const QQuaternion q = qNew * qOld.conjugated();
137 const QVector3D newViewCenter = q * ( mCamera->viewCenter() - pivotPoint ) + pivotPoint;
142 updateCameraFromPose();
148 QVector3D newCamPosition = pivotPoint + ( oldCameraPosition - pivotPoint ) * zoomFactor;
153 QVector3D cameraToCenter = q * QVector3D( 0, 0, -newDistance );
154 QVector3D newViewCenter = newCamPosition + cameraToCenter;
158 updateCameraFromPose();
183 mCamera->setNearPlane(
distance / 2 );
184 mCamera->setFarPlane(
distance * 2 );
206 if ( camPose == mCameraPose )
209 mCameraPose = camPose;
210 updateCameraFromPose();
215 QDomElement elemCamera = doc.createElement( QStringLiteral(
"camera" ) );
216 elemCamera.setAttribute( QStringLiteral(
"x" ), mCameraPose.
centerPoint().
x() );
217 elemCamera.setAttribute( QStringLiteral(
"y" ), mCameraPose.
centerPoint().
z() );
218 elemCamera.setAttribute( QStringLiteral(
"elev" ), mCameraPose.
centerPoint().
y() );
220 elemCamera.setAttribute( QStringLiteral(
"pitch" ), mCameraPose.
pitchAngle() );
221 elemCamera.setAttribute( QStringLiteral(
"yaw" ), mCameraPose.
headingAngle() );
227 const float x = elem.attribute( QStringLiteral(
"x" ) ).toFloat();
228 const float y = elem.attribute( QStringLiteral(
"y" ) ).toFloat();
229 const float elev = elem.attribute( QStringLiteral(
"elev" ) ).toFloat();
230 const float dist = elem.attribute( QStringLiteral(
"dist" ) ).toFloat();
231 const float pitch = elem.attribute( QStringLiteral(
"pitch" ) ).toFloat();
232 const float yaw = elem.attribute( QStringLiteral(
"yaw" ) ).toFloat();
236double QgsCameraController::sampleDepthBuffer(
const QImage &buffer,
int px,
int py )
241 for (
int x = px - 3; x <= px + 3; ++x )
243 for (
int y = py - 3; y <= py + 3; ++y )
245 if ( buffer.valid( x, y ) )
257 int samplesCount = 0;
258 for (
int x = 0; x < buffer.width(); ++x )
260 for (
int y = 0; y < buffer.height(); ++y )
272 if ( samplesCount == 0 )
275 depth /= samplesCount;
280void QgsCameraController::updateCameraFromPose()
288void QgsCameraController::moveCameraPositionBy(
const QVector3D &posDiff )
291 updateCameraFromPose();
294void QgsCameraController::onPositionChanged( Qt3DInput::QMouseEvent *mouse )
296 if ( !mInputHandlersEnabled )
299 switch ( mCameraNavigationMode )
302 onPositionChangedTerrainNavigation( mouse );
306 onPositionChangedFlyNavigation( mouse );
311bool QgsCameraController::screenPointToWorldPos( QPoint position, Qt3DRender::QCamera *mCameraBefore,
double &depth, QVector3D &worldPosition )
313 depth = sampleDepthBuffer( mDepthBufferImage, position.x(), position.y() );
314 if ( !std::isfinite( depth ) )
316 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: depth is NaN or Inf. This should not happen." ), 2 );
322 if ( !std::isfinite( worldPosition.x() ) || !std::isfinite( worldPosition.y() ) || !std::isfinite( worldPosition.z() ) )
324 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: position is NaN or Inf. This should not happen." ), 2 );
334void QgsCameraController::onPositionChangedTerrainNavigation( Qt3DInput::QMouseEvent *mouse )
336 if ( mIgnoreNextMouseMove )
338 mIgnoreNextMouseMove =
false;
339 mMousePos = QPoint( mouse->x(), mouse->y() );
343 const int dx = mouse->x() - mMousePos.x();
344 const int dy = mouse->y() - mMousePos.y();
346 const bool hasShift = ( mouse->modifiers() & Qt::ShiftModifier );
347 const bool hasCtrl = ( mouse->modifiers() & Qt::ControlModifier );
348 const bool hasLeftButton = ( mouse->buttons() & Qt::LeftButton );
349 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
350 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
352 if ( ( hasLeftButton && hasShift && !hasCtrl ) || ( hasMiddleButton && !hasShift && !hasCtrl ) )
355 setMouseParameters( MouseOperation::RotationCenter, mMousePos );
357 float scale =
static_cast<float>( std::max( mScene->
engine()->
size().width(), mScene->
engine()->
size().height() ) );
358 float pitchDiff = 180.0f *
static_cast<float>( mouse->y() - mClickPoint.y() ) / scale;
359 float yawDiff = -180.0f *
static_cast<float>( mouse->x() - mClickPoint.x() ) / scale;
361 if ( !mDepthBufferIsReady )
364 if ( !mRotationCenterCalculated )
367 QVector3D worldPosition;
368 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
370 mRotationCenter = worldPosition;
371 mRotationDistanceFromCenter = ( mRotationCenter - mCameraBefore->position() ).length();
373 mRotationCenterCalculated =
true;
379 else if ( hasLeftButton && hasCtrl && !hasShift )
381 setMouseParameters( MouseOperation::RotationCamera );
383 const float diffPitch = 0.2f * dy;
384 const float diffYaw = -0.2f * dx;
387 else if ( hasLeftButton && !hasShift && !hasCtrl )
390 setMouseParameters( MouseOperation::Translation, mMousePos );
392 if ( !mDepthBufferIsReady )
395 if ( !mDragPointCalculated )
398 QVector3D worldPosition;
399 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
402 mDragPoint = worldPosition;
403 mDragPointCalculated =
true;
407 QVector3D cameraBeforeDragPos = mCameraBefore->position();
410 QVector3D cameraBeforeToMoveToPos = ( moveToPosition - mCameraBefore->position() ).normalized();
411 QVector3D cameraBeforeToDragPointPos = ( mDragPoint - mCameraBefore->position() ).normalized();
414 if ( cameraBeforeToMoveToPos.z() == 0 )
416 cameraBeforeToMoveToPos.setZ( 0.01 );
417 cameraBeforeToMoveToPos = cameraBeforeToMoveToPos.normalized();
420 if ( cameraBeforeToDragPointPos.z() == 0 )
422 cameraBeforeToDragPointPos.setZ( 0.01 );
423 cameraBeforeToDragPointPos = cameraBeforeToDragPointPos.normalized();
426 double d1 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToMoveToPos.z();
427 double d2 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToDragPointPos.z();
429 QVector3D from = cameraBeforeDragPos + d1 * cameraBeforeToMoveToPos;
430 QVector3D to = cameraBeforeDragPos + d2 * cameraBeforeToDragPointPos;
432 QVector3D shiftVector = to - from;
434 mCameraPose.
setCenterPoint( mCameraBefore->viewCenter() + shiftVector );
435 updateCameraFromPose();
437 else if ( hasLeftButton && hasShift && hasCtrl )
441 double tElev = mMousePos.y() - mouse->y();
442 center.
set( center.
x(), center.
y(), center.
z() + tElev * 0.5 );
444 updateCameraFromPose();
446 else if ( hasRightButton && !hasShift && !hasCtrl )
448 setMouseParameters( MouseOperation::Zoom, mMousePos );
449 if ( !mDepthBufferIsReady )
452 if ( !mDragPointCalculated )
455 QVector3D worldPosition;
456 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
458 mDragPoint = worldPosition;
459 mDragPointCalculated =
true;
463 float oldDist = ( mCameraBefore->position() - mDragPoint ).length();
464 float newDist = oldDist;
467 int screenHeight = mScene->
engine()->
size().height();
468 QWindow *win = window();
471 yOffset = win->mapToGlobal( QPoint( 0, 0 ) ).y();
472 screenHeight = win->screen()->size().height();
476 if ( mMousePos.y() > mClickPoint.y() )
478 double f = ( double ) ( mMousePos.y() - mClickPoint.y() ) / (
double ) ( screenHeight - mClickPoint.y() - yOffset );
479 f = std::max( 0.0, std::min( 1.0, f ) );
480 f = 1 - ( std::expm1( -2 * f ) ) / ( std::expm1( -2 ) );
481 newDist = newDist * f;
485 double f = 1 - ( double ) ( mMousePos.y() + yOffset ) / (
double ) ( mClickPoint.y() + yOffset );
486 f = std::max( 0.0, std::min( 1.0, f ) );
487 f = ( std::expm1( 2 * f ) ) / ( std::expm1( 2 ) );
488 newDist = newDist + 2 * newDist * f;
491 double zoomFactor = newDist / oldDist;
495 mMousePos = QPoint( mouse->x(), mouse->y() );
502 dist -= dist * factor * 0.01f;
504 updateCameraFromPose();
507void QgsCameraController::handleTerrainNavigationWheelZoom()
509 if ( !mDepthBufferIsReady )
512 if ( !mZoomPointCalculated )
515 QVector3D worldPosition;
516 if ( screenPointToWorldPos( mMousePos, mCameraBefore.get(), depth, worldPosition ) )
518 mZoomPoint = worldPosition;
519 mZoomPointCalculated =
true;
523 float f = mCumulatedWheelY / ( 120.0 * 24.0 );
525 double oldDist = ( mZoomPoint - mCameraBefore->position() ).length();
526 double newDist = ( 1 - f ) * oldDist;
527 double zoomFactor = newDist / oldDist;
531 mCumulatedWheelY = 0;
532 setMouseParameters( MouseOperation::None );
535void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel )
537 if ( !mInputHandlersEnabled )
540 switch ( mCameraNavigationMode )
544 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.1f : 1.0f ) / 1000.f;
545 setCameraMovementSpeed( mCameraMovementSpeed + mCameraMovementSpeed * scaling * wheel->angleDelta().y() );
551 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.5f : 5.f );
555 mCumulatedWheelY += scaling * wheel->angleDelta().y();
557 if ( mCurrentOperation != MouseOperation::ZoomWheel )
559 setMouseParameters( MouseOperation::ZoomWheel );
563 handleTerrainNavigationWheelZoom();
570void QgsCameraController::onMousePressed( Qt3DInput::QMouseEvent *mouse )
572 if ( !mInputHandlersEnabled )
575 mKeyboardHandler->setFocus(
true );
577 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 ) )
579 mMousePos = QPoint( mouse->x(), mouse->y() );
581 if ( mCaptureFpsMouseMovements )
582 mIgnoreNextMouseMove =
true;
584 const MouseOperation operation {
585 ( mouse->modifiers() & Qt::ControlModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ? MouseOperation::RotationCamera : MouseOperation::RotationCenter
587 setMouseParameters( operation, mMousePos );
590 else if ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton || mouse->button() == Qt3DInput::QMouseEvent::RightButton )
592 mMousePos = QPoint( mouse->x(), mouse->y() );
594 if ( mCaptureFpsMouseMovements )
595 mIgnoreNextMouseMove =
true;
597 const MouseOperation operation = ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) ? MouseOperation::Translation : MouseOperation::Zoom;
598 setMouseParameters( operation, mMousePos );
602void QgsCameraController::onMouseReleased( Qt3DInput::QMouseEvent *mouse )
605 if ( !mInputHandlersEnabled )
609 setMouseParameters( MouseOperation::None );
612void QgsCameraController::onKeyPressed( Qt3DInput::QKeyEvent *event )
614 if ( !mInputHandlersEnabled )
617 if ( event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_QuoteLeft )
620 switch ( mCameraNavigationMode )
632 switch ( mCameraNavigationMode )
636 onKeyPressedFlyNavigation( event );
642 onKeyPressedTerrainNavigation( event );
648void QgsCameraController::onKeyPressedTerrainNavigation( Qt3DInput::QKeyEvent *event )
650 const bool hasShift = (
event->modifiers() & Qt::ShiftModifier );
651 const bool hasCtrl = (
event->modifiers() & Qt::ControlModifier );
653 int tx = 0, ty = 0, tElev = 0;
654 switch ( event->key() )
670 case Qt::Key_PageDown:
680 if ( !hasShift && !hasCtrl )
684 else if ( hasShift && !hasCtrl )
690 else if ( hasCtrl && !hasShift )
693 const float diffPitch = ty;
694 const float diffYaw = -tx;
702 center.
set( center.
x(), center.
y(), center.
z() + tElev * 10 );
704 updateCameraFromPose();
708void QgsCameraController::onKeyPressedFlyNavigation( Qt3DInput::QKeyEvent *event )
710 switch ( event->key() )
712 case Qt::Key_QuoteLeft:
715 mCaptureFpsMouseMovements = !mCaptureFpsMouseMovements;
716 mIgnoreNextMouseMove =
true;
717 if ( mCaptureFpsMouseMovements )
719 qApp->setOverrideCursor( QCursor( Qt::BlankCursor ) );
723 qApp->restoreOverrideCursor();
731 if ( mCaptureFpsMouseMovements )
733 mCaptureFpsMouseMovements =
false;
734 mIgnoreNextMouseMove =
true;
735 qApp->restoreOverrideCursor();
745 if ( event->isAutoRepeat() )
748 mDepressedKeys.insert( event->key() );
753 const QVector3D cameraUp = mCamera->upVector().normalized();
755 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
757 QVector3D cameraPosDiff( 0.0f, 0.0f, 0.0f );
761 cameraPosDiff +=
static_cast<float>( tx ) * cameraFront;
765 cameraPosDiff +=
static_cast<float>( ty ) * cameraLeft;
769 cameraPosDiff +=
static_cast<float>( tz ) * QVector3D( 0.0f, 0.0f, 1.0f );
772 moveCameraPositionBy( cameraPosDiff );
775void QgsCameraController::applyFlyModeKeyMovements()
778 const bool shiftPressed = mDepressedKeys.contains( Qt::Key_Shift );
779 const bool ctrlPressed = mDepressedKeys.contains( Qt::Key_Control );
781 const double movementSpeed = mCameraMovementSpeed * ( shiftPressed ? 2 : 1 ) * ( ctrlPressed ? 0.1 : 1 );
783 bool changed =
false;
787 if ( mDepressedKeys.contains( Qt::Key_Left ) || mDepressedKeys.contains( Qt::Key_A ) )
793 if ( mDepressedKeys.contains( Qt::Key_Right ) || mDepressedKeys.contains( Qt::Key_D ) )
799 if ( mDepressedKeys.contains( Qt::Key_Up ) || mDepressedKeys.contains( Qt::Key_W ) )
805 if ( mDepressedKeys.contains( Qt::Key_Down ) || mDepressedKeys.contains( Qt::Key_S ) )
813 static constexpr double ELEVATION_MOVEMENT_SCALE = 0.5;
814 if ( mDepressedKeys.contains( Qt::Key_PageUp ) || mDepressedKeys.contains( Qt::Key_E ) )
817 z += ELEVATION_MOVEMENT_SCALE * movementSpeed;
820 if ( mDepressedKeys.contains( Qt::Key_PageDown ) || mDepressedKeys.contains( Qt::Key_Q ) )
823 z -= ELEVATION_MOVEMENT_SCALE * movementSpeed;
830void QgsCameraController::onPositionChangedFlyNavigation( Qt3DInput::QMouseEvent *mouse )
832 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
833 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
835 const double dx = mCaptureFpsMouseMovements ? QCursor::pos().x() - mMousePos.x() : mouse->x() - mMousePos.x();
836 const double dy = mCaptureFpsMouseMovements ? QCursor::pos().y() - mMousePos.y() : mouse->y() - mMousePos.y();
837 mMousePos = mCaptureFpsMouseMovements ? QCursor::pos() : QPoint( mouse->x(), mouse->y() );
839 if ( mIgnoreNextMouseMove )
841 mIgnoreNextMouseMove =
false;
845 if ( hasMiddleButton )
848 const QVector3D cameraUp = mCamera->upVector().normalized();
850 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
851 const QVector3D cameraPosDiff = -dx * cameraLeft - dy * cameraUp;
852 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 10.0 );
854 else if ( hasRightButton )
858 const QVector3D cameraPosDiff = dy * cameraFront;
859 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 5.0 );
863 if ( mCaptureFpsMouseMovements )
865 float diffPitch = -0.2f * dy;
866 switch ( mVerticalAxisInversion )
877 const float diffYaw = -0.2f * dx;
880 else if ( mouse->buttons() & Qt::LeftButton )
882 float diffPitch = -0.2f * dy;
883 switch ( mVerticalAxisInversion )
893 const float diffYaw = -0.2f * dx;
898 if ( mCaptureFpsMouseMovements )
900 mIgnoreNextMouseMove =
true;
907void QgsCameraController::onKeyReleased( Qt3DInput::QKeyEvent *event )
909 if ( !mInputHandlersEnabled )
912 if ( event->isAutoRepeat() )
915 mDepressedKeys.remove( event->key() );
924 updateCameraFromPose();
933 updateCameraFromPose();
939 updateCameraFromPose();
946 const float x = tx * dist * 0.02f;
947 const float y = -ty * dist * 0.02f;
950 const float t = sqrt( x * x + y * y );
951 const float a = atan2( y, x ) -
yaw * M_PI / 180;
952 const float dx = cos( a ) * t;
953 const float dy = sin( a ) * t;
956 center.
set( center.
x() + dx, center.
y() - dy, center.
z() );
958 updateCameraFromPose();
963 if ( event->key() == Qt::Key_QuoteLeft )
966 switch ( mCameraNavigationMode )
970 switch ( event->key() )
982 case Qt::Key_PageDown:
987 if ( mCaptureFpsMouseMovements )
999 switch ( event->key() )
1003 case Qt::Key_PageUp:
1004 case Qt::Key_PageDown:
1018 mDepthBufferImage = depthImage;
1019 mDepthBufferIsReady =
true;
1021 if ( mCurrentOperation == MouseOperation::ZoomWheel )
1023 handleTerrainNavigationWheelZoom();
1027bool QgsCameraController::isATranslationRotationSequence( MouseOperation newOperation )
const
1029 return std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), newOperation ) != std::end( mTranslateOrRotate ) && std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), mCurrentOperation ) != std::end( mTranslateOrRotate );
1032void QgsCameraController::setMouseParameters(
const MouseOperation &newOperation,
const QPoint &clickPoint )
1034 if ( newOperation == mCurrentOperation )
1039 if ( newOperation == MouseOperation::None )
1041 mClickPoint = QPoint();
1049 else if ( mClickPoint.isNull() || isATranslationRotationSequence( newOperation ) )
1051 mClickPoint = clickPoint;
1055 mCurrentOperation = newOperation;
1056 mDepthBufferIsReady =
false;
1057 mRotationCenterCalculated =
false;
1058 mDragPointCalculated =
false;
1059 mZoomPointCalculated =
false;
1061 if ( mCurrentOperation != MouseOperation::None && mCurrentOperation != MouseOperation::RotationCamera )
1065 mCameraBefore->setProjectionMatrix( mCamera->projectionMatrix() );
1066 mCameraBefore->setNearPlane( mCamera->nearPlane() );
1067 mCameraBefore->setFarPlane( mCamera->farPlane() );
1068 mCameraBefore->setAspectRatio( mCamera->aspectRatio() );
1069 mCameraBefore->setFieldOfView( mCamera->fieldOfView() );
1080 mCameraBefore->setPosition( (
QgsVector3D( mCameraBefore->position() ) - diff ).toVector3D() );
1081 mCameraBefore->setViewCenter( (
QgsVector3D( mCameraBefore->viewCenter() ) - diff ).toVector3D() );
1082 mDragPoint = (
QgsVector3D( mDragPoint ) - diff ).toVector3D();
1083 mRotationCenter = (
QgsVector3D( mRotationCenter ) - diff ).toVector3D();
1087 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)