25#include <QDomDocument>
26#include <Qt3DRender/QCamera>
27#include <Qt3DRender/QObjectPicker>
28#include <Qt3DRender/QPickEvent>
35 , mCameraBeforeRotation( new
Qt3DRender::QCamera )
38 , mMouseDevice( new
Qt3DInput::QMouseDevice() )
39 , mKeyboardDevice( new
Qt3DInput::QKeyboardDevice() )
40 , mMouseHandler( new
Qt3DInput::QMouseHandler )
41 , mKeyboardHandler( new
Qt3DInput::QKeyboardHandler )
43 mMouseHandler->setSourceDevice( mMouseDevice );
44 connect( mMouseHandler, &Qt3DInput::QMouseHandler::positionChanged,
45 this, &QgsCameraController::onPositionChanged );
46 connect( mMouseHandler, &Qt3DInput::QMouseHandler::wheel,
47 this, &QgsCameraController::onWheel );
48 connect( mMouseHandler, &Qt3DInput::QMouseHandler::pressed,
49 this, &QgsCameraController::onMousePressed );
50 connect( mMouseHandler, &Qt3DInput::QMouseHandler::released,
51 this, &QgsCameraController::onMouseReleased );
52 addComponent( mMouseHandler );
54 mKeyboardHandler->setSourceDevice( mKeyboardDevice );
55 connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::pressed,
56 this, &QgsCameraController::onKeyPressed );
57 connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::released,
58 this, &QgsCameraController::onKeyReleased );
59 addComponent( mKeyboardHandler );
62 connect(
this, &Qt3DCore::QEntity::enabledChanged,
63 mMouseHandler, &Qt3DInput::QMouseHandler::setEnabled );
64 connect(
this, &Qt3DCore::QEntity::enabledChanged,
65 mKeyboardHandler, &Qt3DInput::QKeyboardHandler::setEnabled );
67 mFpsNavTimer =
new QTimer(
this );
68 mFpsNavTimer->setInterval( 10 );
69 connect( mFpsNavTimer, &QTimer::timeout,
this, &QgsCameraController::applyFlyModeKeyMovements );
70 mFpsNavTimer->start();
75 if ( navigationMode == mCameraNavigationMode )
78 mCameraNavigationMode = navigationMode;
79 mIgnoreNextMouseMove =
true;
85 if ( movementSpeed == mCameraMovementSpeed )
88 mCameraMovementSpeed = movementSpeed;
94 mVerticalAxisInversion = inversion;
101 if ( mTerrainEntity )
102 connect( te->terrainPicker(), &Qt3DRender::QObjectPicker::pressed,
this, &QgsCameraController::onPickerMousePressed );
127void QgsCameraController::rotateCamera(
float diffPitch,
float diffYaw )
132 if (
pitch + diffPitch > 180 )
133 diffPitch = 180 -
pitch;
134 if (
pitch + diffPitch < 0 )
135 diffPitch = 0 -
pitch;
142 const QQuaternion q = QQuaternion::fromEulerAngles(
pitch + diffPitch,
yaw + diffYaw, 0 ) *
143 QQuaternion::fromEulerAngles(
pitch,
yaw, 0 ).conjugated();
146 const QVector3D position = mCamera->position();
147 QVector3D viewCenter = mCamera->viewCenter();
148 const QVector3D viewVector = viewCenter - position;
149 const QVector3D cameraToCenter = q * viewVector;
150 viewCenter = position + cameraToCenter;
155 updateCameraFromPose();
172 if ( mTerrainEntity )
180 mCamera->setNearPlane(
distance / 2 );
181 mCamera->setFarPlane(
distance * 2 );
203 if ( camPose == mCameraPose )
206 mCameraPose = camPose;
216 QDomElement elemCamera = doc.createElement( QStringLiteral(
"camera" ) );
217 elemCamera.setAttribute( QStringLiteral(
"x" ), mCameraPose.
centerPoint().
x() );
218 elemCamera.setAttribute( QStringLiteral(
"y" ), mCameraPose.
centerPoint().
z() );
219 elemCamera.setAttribute( QStringLiteral(
"elev" ), mCameraPose.
centerPoint().
y() );
221 elemCamera.setAttribute( QStringLiteral(
"pitch" ), mCameraPose.
pitchAngle() );
222 elemCamera.setAttribute( QStringLiteral(
"yaw" ), mCameraPose.
headingAngle() );
228 const float x = elem.attribute( QStringLiteral(
"x" ) ).toFloat();
229 const float y = elem.attribute( QStringLiteral(
"y" ) ).toFloat();
230 const float elev = elem.attribute( QStringLiteral(
"elev" ) ).toFloat();
231 const float dist = elem.attribute( QStringLiteral(
"dist" ) ).toFloat();
232 const float pitch = elem.attribute( QStringLiteral(
"pitch" ) ).toFloat();
233 const float yaw = elem.attribute( QStringLiteral(
"yaw" ) ).toFloat();
237double QgsCameraController::sampleDepthBuffer(
const QImage &buffer,
int px,
int py )
242 for (
int x = px - 3; x <= px + 3; ++x )
244 for (
int y = py - 3; y <= py + 3; ++y )
246 if ( buffer.valid( x, y ) )
258 int samplesCount = 0;
259 for (
int x = 0; x < mDepthBufferImage.width(); ++x )
261 for (
int y = 0; y < mDepthBufferImage.height(); ++y )
273 if ( samplesCount == 0 )
276 depth /= samplesCount;
281void QgsCameraController::updateCameraFromPose()
288void QgsCameraController::moveCameraPositionBy(
const QVector3D &posDiff )
291 updateCameraFromPose();
294void QgsCameraController::onPositionChanged( Qt3DInput::QMouseEvent *mouse )
296 mIsInZoomInState =
false;
297 mCumulatedWheelY = 0;
298 switch ( mCameraNavigationMode )
301 onPositionChangedTerrainNavigation( mouse );
305 onPositionChangedFlyNavigation( mouse );
310bool QgsCameraController::screenPointToWorldPos( QPoint position, Qt3DRender::QCamera *cameraBefore,
double &depth, QVector3D &worldPosition )
312 depth = sampleDepthBuffer( mDepthBufferImage, position.x(), position.y() );
313 if ( !std::isfinite( depth ) )
315 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: depth is NaN or Inf. This should not happen." ), 2 );
321 if ( !std::isfinite( worldPosition.x() ) || !std::isfinite( worldPosition.y() ) || !std::isfinite( worldPosition.z() ) )
323 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: position is NaN or Inf. This should not happen." ), 2 );
333void QgsCameraController::onPositionChangedTerrainNavigation( Qt3DInput::QMouseEvent *mouse )
335 if ( mIgnoreNextMouseMove )
337 mIgnoreNextMouseMove =
false;
338 mMousePos = QPoint( mouse->x(), mouse->y() );
342 const int dx = mouse->x() - mMousePos.x();
343 const int dy = mouse->y() - mMousePos.y();
345 const bool hasShift = ( mouse->modifiers() & Qt::ShiftModifier );
346 const bool hasCtrl = ( mouse->modifiers() & Qt::ControlModifier );
347 const bool hasLeftButton = ( mouse->buttons() & Qt::LeftButton );
348 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
349 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
351 if ( ( hasLeftButton && hasShift && !hasCtrl ) || ( hasMiddleButton && !hasShift && !hasCtrl ) )
355 double scale = std::max( mViewport.width(), mViewport.height() );
356 float pitchDiff = 180 * ( mouse->y() - mMiddleButtonClickPos.y() ) / scale;
357 float yawDiff = -180 * ( mouse->x() - mMiddleButtonClickPos.x() ) / scale;
359 if ( !mDepthBufferIsReady )
362 if ( !mRotationCenterCalculated )
365 QVector3D worldPosition;
366 if ( screenPointToWorldPos( mMiddleButtonClickPos, mCameraBeforeRotation.get(), depth, worldPosition ) )
368 mRotationCenter = worldPosition;
369 mRotationDistanceFromCenter = ( mRotationCenter - mCameraBeforeRotation->position() ).length();
371 mRotationCenterCalculated =
true;
377 QVector3D shiftVector = mRotationCenter - mCamera->viewCenter();
379 QVector3D newViewCenterWorld =
camera()->viewCenter() + shiftVector;
380 QVector3D newCameraPosition =
camera()->position() + shiftVector;
386 updateCameraFromPose();
394 QVector3D clickedPositionWorld = ray.
origin() + mRotationDistanceFromCenter * ray.
direction();
396 QVector3D shiftVector = clickedPositionWorld - mCamera->viewCenter();
398 QVector3D newViewCenterWorld =
camera()->viewCenter() - shiftVector;
399 QVector3D newCameraPosition =
camera()->position() - shiftVector;
403 updateCameraFromPose();
406 else if ( hasLeftButton && hasCtrl && !hasShift )
409 const float diffPitch = 0.2f * dy;
410 const float diffYaw = - 0.2f * dx;
411 rotateCamera( diffPitch, diffYaw );
413 else if ( hasLeftButton && !hasShift && !hasCtrl )
417 if ( !mDepthBufferIsReady )
420 if ( !mDragPointCalculated )
423 QVector3D worldPosition;
424 if ( screenPointToWorldPos( mDragButtonClickPos, mCameraBeforeDrag.get(), depth, worldPosition ) )
427 mDragPoint = worldPosition;
428 mDragPointCalculated =
true;
433 QVector3D cameraBeforeDragPos = mCameraBeforeDrag->position();
436 QVector3D cameraBeforeToMoveToPos = ( moveToPosition - mCameraBeforeDrag->position() ).normalized();
437 QVector3D cameraBeforeToDragPointPos = ( mDragPoint - mCameraBeforeDrag->position() ).normalized();
440 if ( cameraBeforeToMoveToPos.y() == 0 )
442 cameraBeforeToMoveToPos.setY( 0.01 );
443 cameraBeforeToMoveToPos = cameraBeforeToMoveToPos.normalized();
446 if ( cameraBeforeToDragPointPos.y() == 0 )
448 cameraBeforeToDragPointPos.setY( 0.01 );
449 cameraBeforeToDragPointPos = cameraBeforeToDragPointPos.normalized();
452 double d1 = ( mDragPoint.y() - cameraBeforeDragPos.y() ) / cameraBeforeToMoveToPos.y();
453 double d2 = ( mDragPoint.y() - cameraBeforeDragPos.y() ) / cameraBeforeToDragPointPos.y();
455 QVector3D from = cameraBeforeDragPos + d1 * cameraBeforeToMoveToPos;
456 QVector3D to = cameraBeforeDragPos + d2 * cameraBeforeToDragPointPos;
458 QVector3D shiftVector = to - from;
460 mCameraPose.
setCenterPoint( mCameraBeforeDrag->viewCenter() + shiftVector );
461 updateCameraFromPose();
463 else if ( hasRightButton && !hasShift && !hasCtrl )
465 if ( !mDepthBufferIsReady )
468 if ( !mDragPointCalculated )
471 QVector3D worldPosition;
472 if ( screenPointToWorldPos( mDragButtonClickPos, mCameraBeforeDrag.get(), depth, worldPosition ) )
474 mDragPoint = worldPosition;
475 mDragPointCalculated =
true;
479 float dist = ( mCameraBeforeDrag->position() - mDragPoint ).length();
482 if ( mMousePos.y() > mDragButtonClickPos.y() )
484 double f = ( double )( mMousePos.y() - mDragButtonClickPos.y() ) / (
double )( mViewport.height() - mDragButtonClickPos.y() );
485 f = std::max( 0.0, std::min( 1.0, f ) );
486 f = 1 - ( std::expm1( -2 * f ) ) / ( std::expm1( -2 ) );
491 double f = 1 - ( double )( mMousePos.y() ) / (
double )( mDragButtonClickPos.y() );
492 f = std::max( 0.0, std::min( 1.0, f ) );
493 f = ( std::expm1( 2 * f ) ) / ( std::expm1( 2 ) );
494 dist = dist + 2 * dist * f;
499 QVector3D shiftVector = mDragPoint - mCamera->viewCenter();
501 QVector3D newViewCenterWorld =
camera()->viewCenter() + shiftVector;
505 updateCameraFromPose();
511 QVector3D clickedPositionWorld = ray.
origin() + dist * ray.
direction();
513 QVector3D shiftVector = clickedPositionWorld - mCamera->viewCenter();
515 QVector3D newViewCenterWorld =
camera()->viewCenter() - shiftVector;
516 QVector3D newCameraPosition =
camera()->position() - shiftVector;
520 updateCameraFromPose();
524 mMousePos = QPoint( mouse->x(), mouse->y() );
531 dist -= dist * factor * 0.01f;
533 updateCameraFromPose();
536void QgsCameraController::handleTerrainNavigationWheelZoom()
538 if ( !mDepthBufferIsReady )
541 if ( !mZoomPointCalculated )
544 QVector3D worldPosition;
545 if ( screenPointToWorldPos( mMousePos, mCameraBeforeZoom.get(), depth, worldPosition ) )
547 mZoomPoint = worldPosition;
548 mZoomPointCalculated =
true;
552 float f = mCumulatedWheelY / ( 120.0 * 24.0 );
554 double dist = ( mZoomPoint - mCameraBeforeZoom->position() ).length();
559 QVector3D shiftVector = mZoomPoint - mCamera->viewCenter();
561 QVector3D newViewCenterWorld =
camera()->viewCenter() + shiftVector;
565 updateCameraFromPose();
571 QVector3D clickedPositionWorld = ray.
origin() + dist * ray.
direction();
573 QVector3D shiftVector = clickedPositionWorld - mCamera->viewCenter();
575 QVector3D newViewCenterWorld =
camera()->viewCenter() - shiftVector;
576 QVector3D newCameraPosition =
camera()->position() - shiftVector;
580 updateCameraFromPose();
582 mIsInZoomInState =
false;
583 mCumulatedWheelY = 0;
586void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel )
588 switch ( mCameraNavigationMode )
592 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.1f : 1.0f ) / 1000.f;
593 setCameraMovementSpeed( mCameraMovementSpeed + mCameraMovementSpeed * scaling * wheel->angleDelta().y() );
600 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.5f : 5.f );
604 mCumulatedWheelY += scaling * wheel->angleDelta().y();
606 if ( !mIsInZoomInState )
610 mCameraBeforeZoom->setProjectionMatrix( mCamera->projectionMatrix() );
611 mCameraBeforeZoom->setNearPlane( mCamera->nearPlane() );
612 mCameraBeforeZoom->setFarPlane( mCamera->farPlane() );
613 mCameraBeforeZoom->setAspectRatio( mCamera->aspectRatio() );
614 mCameraBeforeZoom->setFieldOfView( mCamera->fieldOfView() );
616 mZoomPointCalculated =
false;
617 mIsInZoomInState =
true;
618 mDepthBufferIsReady =
false;
622 handleTerrainNavigationWheelZoom();
629void QgsCameraController::onMousePressed( Qt3DInput::QMouseEvent *mouse )
631 mKeyboardHandler->setFocus(
true );
632 if ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton || mouse->button() == Qt3DInput::QMouseEvent::RightButton )
634 mMousePos = QPoint( mouse->x(), mouse->y() );
635 mDragButtonClickPos = QPoint( mouse->x(), mouse->y() );
636 mPressedButton = mouse->button();
637 mMousePressed =
true;
639 if ( mCaptureFpsMouseMovements )
640 mIgnoreNextMouseMove =
true;
644 mCameraBeforeDrag->setProjectionMatrix( mCamera->projectionMatrix() );
645 mCameraBeforeDrag->setNearPlane( mCamera->nearPlane() );
646 mCameraBeforeDrag->setFarPlane( mCamera->farPlane() );
647 mCameraBeforeDrag->setAspectRatio( mCamera->aspectRatio() );
648 mCameraBeforeDrag->setFieldOfView( mCamera->fieldOfView() );
650 mDepthBufferIsReady =
false;
651 mDragPointCalculated =
false;
656 if ( mouse->button() == Qt3DInput::QMouseEvent::MiddleButton || ( ( mouse->modifiers() & Qt::ShiftModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) )
658 mMousePos = QPoint( mouse->x(), mouse->y() );
659 mMiddleButtonClickPos = QPoint( mouse->x(), mouse->y() );
660 mPressedButton = mouse->button();
661 mMousePressed =
true;
662 if ( mCaptureFpsMouseMovements )
663 mIgnoreNextMouseMove =
true;
664 mDepthBufferIsReady =
false;
665 mRotationCenterCalculated =
false;
670 mCameraPose.
updateCamera( mCameraBeforeRotation.get() );
672 mCameraBeforeRotation->setProjectionMatrix( mCamera->projectionMatrix() );
673 mCameraBeforeRotation->setNearPlane( mCamera->nearPlane() );
674 mCameraBeforeRotation->setFarPlane( mCamera->farPlane() );
675 mCameraBeforeRotation->setAspectRatio( mCamera->aspectRatio() );
676 mCameraBeforeRotation->setFieldOfView( mCamera->fieldOfView() );
682void QgsCameraController::onMouseReleased( Qt3DInput::QMouseEvent *mouse )
685 mPressedButton = Qt3DInput::QMouseEvent::NoButton;
686 mMousePressed =
false;
688 mDragPointCalculated =
false;
689 mRotationCenterCalculated =
false;
692void QgsCameraController::onKeyPressed( Qt3DInput::QKeyEvent *event )
694 if ( event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_QuoteLeft )
697 switch ( mCameraNavigationMode )
699 case NavigationMode::WalkNavigation:
702 case NavigationMode::TerrainBasedNavigation:
709 switch ( mCameraNavigationMode )
713 onKeyPressedFlyNavigation( event );
719 onKeyPressedTerrainNavigation( event );
725void QgsCameraController::onKeyPressedTerrainNavigation( Qt3DInput::QKeyEvent *event )
727 const bool hasShift = (
event->modifiers() & Qt::ShiftModifier );
728 const bool hasCtrl = (
event->modifiers() & Qt::ControlModifier );
730 int tx = 0, ty = 0, tElev = 0;
731 switch ( event->key() )
747 case Qt::Key_PageDown:
757 if ( !hasShift && !hasCtrl )
761 else if ( hasShift && !hasCtrl )
767 else if ( hasCtrl && !hasShift )
770 const float diffPitch = ty;
771 const float diffYaw = -tx;
772 rotateCamera( diffPitch, diffYaw );
779 center.
set( center.
x(), center.
y() + tElev * 10, center.
z() );
781 updateCameraFromPose();
785void QgsCameraController::onKeyPressedFlyNavigation( Qt3DInput::QKeyEvent *event )
787 switch ( event->key() )
789 case Qt::Key_QuoteLeft:
792 mCaptureFpsMouseMovements = !mCaptureFpsMouseMovements;
793 mIgnoreNextMouseMove =
true;
794 if ( mCaptureFpsMouseMovements )
796 qApp->setOverrideCursor( QCursor( Qt::BlankCursor ) );
800 qApp->restoreOverrideCursor();
808 if ( mCaptureFpsMouseMovements )
810 mCaptureFpsMouseMovements =
false;
811 mIgnoreNextMouseMove =
true;
812 qApp->restoreOverrideCursor();
822 if ( event->isAutoRepeat() )
825 mDepressedKeys.insert( event->key() );
828void QgsCameraController::applyFlyModeKeyMovements()
830 const QVector3D cameraUp = mCamera->upVector().normalized();
832 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
834 QVector3D cameraPosDiff( 0.0f, 0.0f, 0.0f );
837 const bool shiftPressed = mDepressedKeys.contains( Qt::Key_Shift );
838 const bool ctrlPressed = mDepressedKeys.contains( Qt::Key_Control );
840 const double movementSpeed = mCameraMovementSpeed * ( shiftPressed ? 2 : 1 ) * ( ctrlPressed ? 0.1 : 1 );
842 bool changed =
false;
843 if ( mDepressedKeys.contains( Qt::Key_Left ) || mDepressedKeys.contains( Qt::Key_A ) )
846 cameraPosDiff += movementSpeed * cameraLeft;
849 if ( mDepressedKeys.contains( Qt::Key_Right ) || mDepressedKeys.contains( Qt::Key_D ) )
852 cameraPosDiff += - movementSpeed * cameraLeft;
855 if ( mDepressedKeys.contains( Qt::Key_Up ) || mDepressedKeys.contains( Qt::Key_W ) )
858 cameraPosDiff += movementSpeed * cameraFront;
861 if ( mDepressedKeys.contains( Qt::Key_Down ) || mDepressedKeys.contains( Qt::Key_S ) )
864 cameraPosDiff += - movementSpeed * cameraFront;
869 static constexpr double ELEVATION_MOVEMENT_SCALE = 0.5;
870 if ( mDepressedKeys.contains( Qt::Key_PageUp ) || mDepressedKeys.contains( Qt::Key_E ) )
873 cameraPosDiff += ELEVATION_MOVEMENT_SCALE * movementSpeed * QVector3D( 0.0f, 1.0f, 0.0f );
876 if ( mDepressedKeys.contains( Qt::Key_PageDown ) || mDepressedKeys.contains( Qt::Key_Q ) )
879 cameraPosDiff += ELEVATION_MOVEMENT_SCALE * - movementSpeed * QVector3D( 0.0f, 1.0f, 0.0f );
883 moveCameraPositionBy( cameraPosDiff );
886void QgsCameraController::onPositionChangedFlyNavigation( Qt3DInput::QMouseEvent *mouse )
888 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
889 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
891 const double dx = mCaptureFpsMouseMovements ? QCursor::pos().x() - mMousePos.x() : mouse->x() - mMousePos.x();
892 const double dy = mCaptureFpsMouseMovements ? QCursor::pos().y() - mMousePos.y() : mouse->y() - mMousePos.y();
893 mMousePos = mCaptureFpsMouseMovements ? QCursor::pos() : QPoint( mouse->x(), mouse->y() );
895 if ( mIgnoreNextMouseMove )
897 mIgnoreNextMouseMove =
false;
901 if ( hasMiddleButton )
904 const QVector3D cameraUp = mCamera->upVector().normalized();
906 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
907 const QVector3D cameraPosDiff = -dx * cameraLeft - dy * cameraUp;
908 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 10.0 );
910 else if ( hasRightButton )
914 const QVector3D cameraPosDiff = dy * cameraFront;
915 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 5.0 );
919 if ( mCaptureFpsMouseMovements )
921 float diffPitch = -0.2f * dy;
922 switch ( mVerticalAxisInversion )
933 const float diffYaw = - 0.2f * dx;
934 rotateCamera( diffPitch, diffYaw );
936 else if ( mouse->buttons() & Qt::LeftButton )
938 float diffPitch = -0.2f * dy;
939 switch ( mVerticalAxisInversion )
949 const float diffYaw = - 0.2f * dx;
950 rotateCamera( diffPitch, diffYaw );
954 if ( mCaptureFpsMouseMovements )
956 mIgnoreNextMouseMove =
true;
959 emit
setCursorPosition( QPoint( mViewport.width() / 2, mViewport.height() / 2 ) );
963void QgsCameraController::onKeyReleased( Qt3DInput::QKeyEvent *event )
965 if ( event->isAutoRepeat() )
968 mDepressedKeys.remove( event->key() );
971void QgsCameraController::onPickerMousePressed( Qt3DRender::QPickEvent *pick )
973 mLastPressedHeight = pick->worldIntersection().y();
983 updateCameraFromPose();
992 updateCameraFromPose();
998 updateCameraFromPose();
1005 const float x = tx * dist * 0.02f;
1006 const float y = -ty * dist * 0.02f;
1009 const float t = sqrt( x * x + y * y );
1010 const float a = atan2( y, x ) -
yaw * M_PI / 180;
1011 const float dx = cos( a ) * t;
1012 const float dy = sin( a ) * t;
1015 center.
set( center.
x() + dx, center.
y(), center.
z() + dy );
1017 updateCameraFromPose();
1022 if ( event->key() == Qt::Key_QuoteLeft )
1025 switch ( mCameraNavigationMode )
1029 switch ( event->key() )
1039 case Qt::Key_PageUp:
1041 case Qt::Key_PageDown:
1045 case Qt::Key_Escape:
1046 if ( mCaptureFpsMouseMovements )
1058 switch ( event->key() )
1062 case Qt::Key_PageUp:
1063 case Qt::Key_PageDown:
1077 mDepthBufferImage = depthImage;
1078 mDepthBufferIsReady =
true;
1080 if ( mIsInZoomInState )
1081 handleTerrainNavigationWheelZoom();
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.
void setViewport(QRect viewport)
Sets viewport rectangle. Called internally from 3D canvas. Allows conversion of mouse coordinates.
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).
float yaw() const
Returns yaw angle in degrees.
void requestDepthBufferCapture()
Emitted to ask for the depth buffer image.
void setCameraNavigationMode(QgsCameraController::NavigationMode navigationMode)
Sets the navigation mode used by the camera controller.
void tiltUpAroundViewCenter(float deltaPitch)
Tilt up the view by deltaPitch around the view center (camera moves)
void navigationModeChanged(QgsCameraController::NavigationMode mode)
Emitted when the navigation mode is changed using the hotkey ctrl + ~.
bool willHandleKeyEvent(QKeyEvent *event)
Returns true if the camera controller will handle the specified key event, preventing it from being i...
Qt3DRender::QCamera * camera
void setVerticalAxisInversion(QgsCameraController::VerticalAxisInversion inversion)
Sets the vertical axis inversion behavior.
float distance() const
Returns distance of the camera from the point it is looking at.
void setCamera(Qt3DRender::QCamera *camera)
Assigns camera that should be controlled by this class. Called internally from 3D scene.
VerticalAxisInversion
Vertical axis inversion options.
@ WhenDragging
Invert vertical axis movements when dragging in first person modes.
@ Always
Always invert vertical axis movements.
@ Never
Never invert vertical axis movements.
void cameraChanged()
Emitted when camera has been updated.
void cameraMovementSpeedChanged(double speed)
Emitted whenever the camera movement speed is changed by the controller.
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...
NavigationMode
The navigation mode used by the camera.
@ WalkNavigation
Uses WASD keys or arrows to navigate in walking (first person) manner.
@ TerrainBasedNavigation
The default navigation based on the terrain.
void zoom(float factor)
Zoom the map by factor.
void setTerrainEntity(QgsTerrainEntity *te)
Connects to object picker attached to terrain entity.
void rotateAroundViewCenter(float deltaYaw)
Rotate clockwise the view by deltaYaw around the view center (camera moves)
QgsCameraController(Qt3DCore::QNode *parent=nullptr)
Constructs the camera controller with optional parent node that will take ownership.
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 viewportChanged()
Emitted when viewport rectangle has been updated.
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()
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.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
#define QgsDebugMsgLevel(str, level)