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 )
39 mMouseHandler->setSourceDevice(
new Qt3DInput::QMouseDevice() );
40 connect( mMouseHandler, &Qt3DInput::QMouseHandler::positionChanged,
41 this, &QgsCameraController::onPositionChanged );
42 connect( mMouseHandler, &Qt3DInput::QMouseHandler::wheel,
43 this, &QgsCameraController::onWheel );
44 connect( mMouseHandler, &Qt3DInput::QMouseHandler::pressed,
45 this, &QgsCameraController::onMousePressed );
46 connect( mMouseHandler, &Qt3DInput::QMouseHandler::released,
47 this, &QgsCameraController::onMouseReleased );
48 addComponent( mMouseHandler );
50 mKeyboardHandler->setSourceDevice(
new Qt3DInput::QKeyboardDevice() );
51 connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::pressed,
52 this, &QgsCameraController::onKeyPressed );
53 connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::released,
54 this, &QgsCameraController::onKeyReleased );
55 addComponent( mKeyboardHandler );
58 connect(
this, &Qt3DCore::QEntity::enabledChanged,
59 mMouseHandler, &Qt3DInput::QMouseHandler::setEnabled );
60 connect(
this, &Qt3DCore::QEntity::enabledChanged,
61 mKeyboardHandler, &Qt3DInput::QKeyboardHandler::setEnabled );
63 mFpsNavTimer =
new QTimer(
this );
64 mFpsNavTimer->setInterval( 10 );
65 connect( mFpsNavTimer, &QTimer::timeout,
this, &QgsCameraController::applyFlyModeKeyMovements );
66 mFpsNavTimer->start();
71QWindow *QgsCameraController::window()
const
74 return windowEngine ? windowEngine->
window() :
nullptr;
79 if ( navigationMode == mCameraNavigationMode )
82 mCameraNavigationMode = navigationMode;
83 mIgnoreNextMouseMove =
true;
89 if ( movementSpeed == mCameraMovementSpeed )
94 mCameraMovementSpeed = std::clamp( movementSpeed, 0.05, 150.0 );
100 mVerticalAxisInversion = inversion;
108 if (
pitch + diffPitch > 180 )
109 diffPitch = 180 -
pitch;
110 if (
pitch + diffPitch < 0 )
111 diffPitch = 0 -
pitch;
119 const QQuaternion q1 = QQuaternion::fromEulerAngles( 0, 0,
yaw + diffYaw ) *
120 QQuaternion::fromEulerAngles(
pitch + diffPitch, 0, 0 );
121 const QQuaternion q2 = QQuaternion::fromEulerAngles( 0, 0,
yaw ) *
122 QQuaternion::fromEulerAngles(
pitch, 0, 0 );
123 const QQuaternion q = q1 * q2.conjugated();
126 const QVector3D position = mCamera->position();
127 QVector3D viewCenter = mCamera->viewCenter();
128 const QVector3D viewVector = viewCenter - position;
129 const QVector3D cameraToCenter = q * viewVector;
130 viewCenter = position + cameraToCenter;
135 updateCameraFromPose();
161 mCamera->setNearPlane(
distance / 2 );
162 mCamera->setFarPlane(
distance * 2 );
184 if ( camPose == mCameraPose )
187 mCameraPose = camPose;
188 updateCameraFromPose();
193 QDomElement elemCamera = doc.createElement( QStringLiteral(
"camera" ) );
194 elemCamera.setAttribute( QStringLiteral(
"x" ), mCameraPose.
centerPoint().
x() );
195 elemCamera.setAttribute( QStringLiteral(
"y" ), mCameraPose.
centerPoint().
z() );
196 elemCamera.setAttribute( QStringLiteral(
"elev" ), mCameraPose.
centerPoint().
y() );
198 elemCamera.setAttribute( QStringLiteral(
"pitch" ), mCameraPose.
pitchAngle() );
199 elemCamera.setAttribute( QStringLiteral(
"yaw" ), mCameraPose.
headingAngle() );
205 const float x = elem.attribute( QStringLiteral(
"x" ) ).toFloat();
206 const float y = elem.attribute( QStringLiteral(
"y" ) ).toFloat();
207 const float elev = elem.attribute( QStringLiteral(
"elev" ) ).toFloat();
208 const float dist = elem.attribute( QStringLiteral(
"dist" ) ).toFloat();
209 const float pitch = elem.attribute( QStringLiteral(
"pitch" ) ).toFloat();
210 const float yaw = elem.attribute( QStringLiteral(
"yaw" ) ).toFloat();
214double QgsCameraController::sampleDepthBuffer(
const QImage &buffer,
int px,
int py )
219 for (
int x = px - 3; x <= px + 3; ++x )
221 for (
int y = py - 3; y <= py + 3; ++y )
223 if ( buffer.valid( x, y ) )
235 int samplesCount = 0;
236 for (
int x = 0; x < buffer.width(); ++x )
238 for (
int y = 0; y < buffer.height(); ++y )
250 if ( samplesCount == 0 )
253 depth /= samplesCount;
258void QgsCameraController::updateCameraFromPose()
266void QgsCameraController::moveCameraPositionBy(
const QVector3D &posDiff )
269 updateCameraFromPose();
272void QgsCameraController::onPositionChanged( Qt3DInput::QMouseEvent *mouse )
274 switch ( mCameraNavigationMode )
277 onPositionChangedTerrainNavigation( mouse );
281 onPositionChangedFlyNavigation( mouse );
286bool QgsCameraController::screenPointToWorldPos( QPoint position, Qt3DRender::QCamera *mCameraBefore,
double &depth, QVector3D &worldPosition )
288 depth = sampleDepthBuffer( mDepthBufferImage, position.x(), position.y() );
289 if ( !std::isfinite( depth ) )
291 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: depth is NaN or Inf. This should not happen." ), 2 );
297 if ( !std::isfinite( worldPosition.x() ) || !std::isfinite( worldPosition.y() ) || !std::isfinite( worldPosition.z() ) )
299 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: position is NaN or Inf. This should not happen." ), 2 );
309void QgsCameraController::onPositionChangedTerrainNavigation( Qt3DInput::QMouseEvent *mouse )
311 if ( mIgnoreNextMouseMove )
313 mIgnoreNextMouseMove =
false;
314 mMousePos = QPoint( mouse->x(), mouse->y() );
318 const int dx = mouse->x() - mMousePos.x();
319 const int dy = mouse->y() - mMousePos.y();
321 const bool hasShift = ( mouse->modifiers() & Qt::ShiftModifier );
322 const bool hasCtrl = ( mouse->modifiers() & Qt::ControlModifier );
323 const bool hasLeftButton = ( mouse->buttons() & Qt::LeftButton );
324 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
325 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
327 if ( ( hasLeftButton && hasShift && !hasCtrl ) || ( hasMiddleButton && !hasShift && !hasCtrl ) )
330 setMouseParameters( MouseOperation::RotationCenter, mMousePos );
332 float scale =
static_cast<float>( std::max( mScene->
engine()->
size().width(), mScene->
engine()->
size().height() ) );
333 float pitchDiff = 180.0f *
static_cast<float>( mouse->y() - mClickPoint.y() ) / scale;
334 float yawDiff = -180.0f *
static_cast<float>( mouse->x() - mClickPoint.x() ) / scale;
336 if ( !mDepthBufferIsReady )
339 if ( !mRotationCenterCalculated )
342 QVector3D worldPosition;
343 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
345 mRotationCenter = worldPosition;
346 mRotationDistanceFromCenter = ( mRotationCenter - mCameraBefore->position() ).length();
348 mRotationCenterCalculated =
true;
354 QVector3D shiftVector = mRotationCenter - mCamera->viewCenter();
356 QVector3D newViewCenterWorld =
camera()->viewCenter() + shiftVector;
357 QVector3D newCameraPosition =
camera()->position() + shiftVector;
363 updateCameraFromPose();
371 QVector3D clickedPositionWorld = ray.
origin() + mRotationDistanceFromCenter * ray.
direction();
373 QVector3D shiftVector = clickedPositionWorld - mCamera->viewCenter();
375 QVector3D newViewCenterWorld =
camera()->viewCenter() - shiftVector;
376 QVector3D newCameraPosition =
camera()->position() - shiftVector;
380 updateCameraFromPose();
383 else if ( hasLeftButton && hasCtrl && !hasShift )
385 setMouseParameters( MouseOperation::RotationCamera );
387 const float diffPitch = 0.2f * dy;
388 const float diffYaw = - 0.2f * dx;
391 else if ( hasLeftButton && !hasShift && !hasCtrl )
394 setMouseParameters( MouseOperation::Translation, mMousePos );
396 if ( !mDepthBufferIsReady )
399 if ( !mDragPointCalculated )
402 QVector3D worldPosition;
403 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
406 mDragPoint = worldPosition;
407 mDragPointCalculated =
true;
412 QVector3D cameraBeforeDragPos = mCameraBefore->position();
415 QVector3D cameraBeforeToMoveToPos = ( moveToPosition - mCameraBefore->position() ).normalized();
416 QVector3D cameraBeforeToDragPointPos = ( mDragPoint - mCameraBefore->position() ).normalized();
419 if ( cameraBeforeToMoveToPos.z() == 0 )
421 cameraBeforeToMoveToPos.setZ( 0.01 );
422 cameraBeforeToMoveToPos = cameraBeforeToMoveToPos.normalized();
425 if ( cameraBeforeToDragPointPos.z() == 0 )
427 cameraBeforeToDragPointPos.setZ( 0.01 );
428 cameraBeforeToDragPointPos = cameraBeforeToDragPointPos.normalized();
431 double d1 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToMoveToPos.z();
432 double d2 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToDragPointPos.z();
434 QVector3D from = cameraBeforeDragPos + d1 * cameraBeforeToMoveToPos;
435 QVector3D to = cameraBeforeDragPos + d2 * cameraBeforeToDragPointPos;
437 QVector3D shiftVector = to - from;
439 mCameraPose.
setCenterPoint( mCameraBefore->viewCenter() + shiftVector );
440 updateCameraFromPose();
442 else if ( hasLeftButton && hasShift && hasCtrl )
446 double tElev = mMousePos.y() - mouse->y();
447 center.
set( center.
x(), center.
y(), center.
z() + tElev * 0.5 );
449 updateCameraFromPose();
451 else if ( hasRightButton && !hasShift && !hasCtrl )
453 setMouseParameters( MouseOperation::Zoom, mMousePos );
454 if ( !mDepthBufferIsReady )
457 if ( !mDragPointCalculated )
460 QVector3D worldPosition;
461 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
463 mDragPoint = worldPosition;
464 mDragPointCalculated =
true;
468 float dist = ( mCameraBefore->position() - mDragPoint ).length();
471 int screenHeight = mScene->
engine()->
size().height();
472 QWindow *win = window();
475 yOffset = win->mapToGlobal( QPoint( 0, 0 ) ).y();
476 screenHeight = win->screen()->size().height();
480 if ( mMousePos.y() > mClickPoint.y() )
482 double f = ( double )( mMousePos.y() - mClickPoint.y() ) / (
double )( screenHeight - mClickPoint.y() - yOffset );
483 f = std::max( 0.0, std::min( 1.0, f ) );
484 f = 1 - ( std::expm1( -2 * f ) ) / ( std::expm1( -2 ) );
489 double f = 1 - ( double )( mMousePos.y() + yOffset ) / (
double )( mClickPoint.y() + yOffset );
490 f = std::max( 0.0, std::min( 1.0, f ) );
491 f = ( std::expm1( 2 * f ) ) / ( std::expm1( 2 ) );
492 dist = dist + 2 * dist * f;
497 QVector3D shiftVector = mDragPoint - mCamera->viewCenter();
499 QVector3D newViewCenterWorld =
camera()->viewCenter() + shiftVector;
503 updateCameraFromPose();
509 QVector3D clickedPositionWorld = ray.
origin() + dist * ray.
direction();
511 QVector3D shiftVector = clickedPositionWorld - mCamera->viewCenter();
513 QVector3D newViewCenterWorld =
camera()->viewCenter() - shiftVector;
514 QVector3D newCameraPosition =
camera()->position() - shiftVector;
518 updateCameraFromPose();
522 mMousePos = QPoint( mouse->x(), mouse->y() );
529 dist -= dist * factor * 0.01f;
531 updateCameraFromPose();
534void QgsCameraController::handleTerrainNavigationWheelZoom()
536 if ( !mDepthBufferIsReady )
539 if ( !mZoomPointCalculated )
542 QVector3D worldPosition;
543 if ( screenPointToWorldPos( mMousePos, mCameraBefore.get(), depth, worldPosition ) )
545 mZoomPoint = worldPosition;
546 mZoomPointCalculated =
true;
550 float f = mCumulatedWheelY / ( 120.0 * 24.0 );
552 double dist = ( mZoomPoint - mCameraBefore->position() ).length();
557 QVector3D shiftVector = mZoomPoint - mCamera->viewCenter();
559 QVector3D newViewCenterWorld =
camera()->viewCenter() + shiftVector;
563 updateCameraFromPose();
569 QVector3D clickedPositionWorld = ray.
origin() + dist * ray.
direction();
571 QVector3D shiftVector = clickedPositionWorld - mCamera->viewCenter();
573 QVector3D newViewCenterWorld =
camera()->viewCenter() - shiftVector;
574 QVector3D newCameraPosition =
camera()->position() - shiftVector;
578 updateCameraFromPose();
580 mCumulatedWheelY = 0;
581 setMouseParameters( MouseOperation::None );
584void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel )
586 switch ( mCameraNavigationMode )
590 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.1f : 1.0f ) / 1000.f;
591 setCameraMovementSpeed( mCameraMovementSpeed + mCameraMovementSpeed * scaling * wheel->angleDelta().y() );
598 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.5f : 5.f );
602 mCumulatedWheelY += scaling * wheel->angleDelta().y();
604 if ( mCurrentOperation != MouseOperation::ZoomWheel )
606 setMouseParameters( MouseOperation::ZoomWheel );
610 handleTerrainNavigationWheelZoom();
617void QgsCameraController::onMousePressed( Qt3DInput::QMouseEvent *mouse )
619 mKeyboardHandler->setFocus(
true );
621 if ( mouse->button() == Qt3DInput::QMouseEvent::MiddleButton ||
622 ( ( mouse->modifiers() & Qt::ShiftModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) ||
623 ( ( mouse->modifiers() & Qt::ControlModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) )
625 mMousePos = QPoint( mouse->x(), mouse->y() );
627 if ( mCaptureFpsMouseMovements )
628 mIgnoreNextMouseMove =
true;
630 const MouseOperation operation
632 ( mouse->modifiers() & Qt::ControlModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ?
633 MouseOperation::RotationCamera :
634 MouseOperation::RotationCenter
636 setMouseParameters( operation, mMousePos );
639 else if ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton || mouse->button() == Qt3DInput::QMouseEvent::RightButton )
641 mMousePos = QPoint( mouse->x(), mouse->y() );
643 if ( mCaptureFpsMouseMovements )
644 mIgnoreNextMouseMove =
true;
646 const MouseOperation operation = ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) ? MouseOperation::Translation : MouseOperation::Zoom;
647 setMouseParameters( operation, mMousePos );
651void QgsCameraController::onMouseReleased( Qt3DInput::QMouseEvent *mouse )
655 setMouseParameters( MouseOperation::None );
658void QgsCameraController::onKeyPressed( Qt3DInput::QKeyEvent *event )
660 if ( event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_QuoteLeft )
663 switch ( mCameraNavigationMode )
675 switch ( mCameraNavigationMode )
679 onKeyPressedFlyNavigation( event );
685 onKeyPressedTerrainNavigation( event );
691void QgsCameraController::onKeyPressedTerrainNavigation( Qt3DInput::QKeyEvent *event )
693 const bool hasShift = (
event->modifiers() & Qt::ShiftModifier );
694 const bool hasCtrl = (
event->modifiers() & Qt::ControlModifier );
696 int tx = 0, ty = 0, tElev = 0;
697 switch ( event->key() )
713 case Qt::Key_PageDown:
723 if ( !hasShift && !hasCtrl )
727 else if ( hasShift && !hasCtrl )
733 else if ( hasCtrl && !hasShift )
736 const float diffPitch = ty;
737 const float diffYaw = -tx;
745 center.
set( center.
x(), center.
y(), center.
z() + tElev * 10 );
747 updateCameraFromPose();
751void QgsCameraController::onKeyPressedFlyNavigation( Qt3DInput::QKeyEvent *event )
753 switch ( event->key() )
755 case Qt::Key_QuoteLeft:
758 mCaptureFpsMouseMovements = !mCaptureFpsMouseMovements;
759 mIgnoreNextMouseMove =
true;
760 if ( mCaptureFpsMouseMovements )
762 qApp->setOverrideCursor( QCursor( Qt::BlankCursor ) );
766 qApp->restoreOverrideCursor();
774 if ( mCaptureFpsMouseMovements )
776 mCaptureFpsMouseMovements =
false;
777 mIgnoreNextMouseMove =
true;
778 qApp->restoreOverrideCursor();
788 if ( event->isAutoRepeat() )
791 mDepressedKeys.insert( event->key() );
796 const QVector3D cameraUp = mCamera->upVector().normalized();
798 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
800 QVector3D cameraPosDiff( 0.0f, 0.0f, 0.0f );
804 cameraPosDiff +=
static_cast<float>( tx ) * cameraFront;
808 cameraPosDiff +=
static_cast<float>( ty ) * cameraLeft;
812 cameraPosDiff +=
static_cast<float>( tz ) * QVector3D( 0.0f, 0.0f, 1.0f );
815 moveCameraPositionBy( cameraPosDiff );
818void QgsCameraController::applyFlyModeKeyMovements()
821 const bool shiftPressed = mDepressedKeys.contains( Qt::Key_Shift );
822 const bool ctrlPressed = mDepressedKeys.contains( Qt::Key_Control );
824 const double movementSpeed = mCameraMovementSpeed * ( shiftPressed ? 2 : 1 ) * ( ctrlPressed ? 0.1 : 1 );
826 bool changed =
false;
830 if ( mDepressedKeys.contains( Qt::Key_Left ) || mDepressedKeys.contains( Qt::Key_A ) )
836 if ( mDepressedKeys.contains( Qt::Key_Right ) || mDepressedKeys.contains( Qt::Key_D ) )
842 if ( mDepressedKeys.contains( Qt::Key_Up ) || mDepressedKeys.contains( Qt::Key_W ) )
848 if ( mDepressedKeys.contains( Qt::Key_Down ) || mDepressedKeys.contains( Qt::Key_S ) )
856 static constexpr double ELEVATION_MOVEMENT_SCALE = 0.5;
857 if ( mDepressedKeys.contains( Qt::Key_PageUp ) || mDepressedKeys.contains( Qt::Key_E ) )
860 z += ELEVATION_MOVEMENT_SCALE * movementSpeed;
863 if ( mDepressedKeys.contains( Qt::Key_PageDown ) || mDepressedKeys.contains( Qt::Key_Q ) )
866 z -= ELEVATION_MOVEMENT_SCALE * movementSpeed;
873void QgsCameraController::onPositionChangedFlyNavigation( Qt3DInput::QMouseEvent *mouse )
875 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
876 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
878 const double dx = mCaptureFpsMouseMovements ? QCursor::pos().x() - mMousePos.x() : mouse->x() - mMousePos.x();
879 const double dy = mCaptureFpsMouseMovements ? QCursor::pos().y() - mMousePos.y() : mouse->y() - mMousePos.y();
880 mMousePos = mCaptureFpsMouseMovements ? QCursor::pos() : QPoint( mouse->x(), mouse->y() );
882 if ( mIgnoreNextMouseMove )
884 mIgnoreNextMouseMove =
false;
888 if ( hasMiddleButton )
891 const QVector3D cameraUp = mCamera->upVector().normalized();
893 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
894 const QVector3D cameraPosDiff = -dx * cameraLeft - dy * cameraUp;
895 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 10.0 );
897 else if ( hasRightButton )
901 const QVector3D cameraPosDiff = dy * cameraFront;
902 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 5.0 );
906 if ( mCaptureFpsMouseMovements )
908 float diffPitch = -0.2f * dy;
909 switch ( mVerticalAxisInversion )
920 const float diffYaw = - 0.2f * dx;
923 else if ( mouse->buttons() & Qt::LeftButton )
925 float diffPitch = -0.2f * dy;
926 switch ( mVerticalAxisInversion )
936 const float diffYaw = - 0.2f * dx;
941 if ( mCaptureFpsMouseMovements )
943 mIgnoreNextMouseMove =
true;
950void QgsCameraController::onKeyReleased( Qt3DInput::QKeyEvent *event )
952 if ( event->isAutoRepeat() )
955 mDepressedKeys.remove( event->key() );
964 updateCameraFromPose();
973 updateCameraFromPose();
979 updateCameraFromPose();
986 const float x = tx * dist * 0.02f;
987 const float y = -ty * dist * 0.02f;
990 const float t = sqrt( x * x + y * y );
991 const float a = atan2( y, x ) -
yaw * M_PI / 180;
992 const float dx = cos( a ) * t;
993 const float dy = sin( a ) * t;
996 center.
set( center.
x() + dx, center.
y() - dy, center.
z() );
998 updateCameraFromPose();
1003 if ( event->key() == Qt::Key_QuoteLeft )
1006 switch ( mCameraNavigationMode )
1010 switch ( event->key() )
1020 case Qt::Key_PageUp:
1022 case Qt::Key_PageDown:
1026 case Qt::Key_Escape:
1027 if ( mCaptureFpsMouseMovements )
1039 switch ( event->key() )
1043 case Qt::Key_PageUp:
1044 case Qt::Key_PageDown:
1058 mDepthBufferImage = depthImage;
1059 mDepthBufferIsReady =
true;
1061 if ( mCurrentOperation == MouseOperation::ZoomWheel )
1063 handleTerrainNavigationWheelZoom();
1067bool QgsCameraController::isATranslationRotationSequence( MouseOperation newOperation )
const
1069 return std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), newOperation ) != std::end( mTranslateOrRotate ) &&
1070 std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), mCurrentOperation ) != std::end( mTranslateOrRotate );
1073void QgsCameraController::setMouseParameters(
const MouseOperation &newOperation,
const QPoint &clickPoint )
1075 if ( newOperation == mCurrentOperation )
1080 if ( newOperation == MouseOperation::None )
1082 mClickPoint = QPoint();
1090 else if ( mClickPoint.isNull() || isATranslationRotationSequence( newOperation ) )
1092 mClickPoint = clickPoint;
1096 mCurrentOperation = newOperation;
1097 mDepthBufferIsReady =
false;
1098 mRotationCenterCalculated =
false;
1099 mDragPointCalculated =
false;
1100 mZoomPointCalculated =
false;
1102 if ( mCurrentOperation != MouseOperation::None && mCurrentOperation != MouseOperation::RotationCamera )
1106 mCameraBefore->setProjectionMatrix( mCamera->projectionMatrix() );
1107 mCameraBefore->setNearPlane( mCamera->nearPlane() );
1108 mCameraBefore->setFarPlane( mCamera->farPlane() );
1109 mCameraBefore->setAspectRatio( mCamera->aspectRatio() );
1110 mCameraBefore->setFieldOfView( mCamera->fieldOfView() );
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 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)