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 switch ( mCameraNavigationMode )
299 onPositionChangedTerrainNavigation( mouse );
303 onPositionChangedFlyNavigation( mouse );
308bool QgsCameraController::screenPointToWorldPos( QPoint position, Qt3DRender::QCamera *mCameraBefore,
double &depth, QVector3D &worldPosition )
310 depth = sampleDepthBuffer( mDepthBufferImage, position.x(), position.y() );
311 if ( !std::isfinite( depth ) )
313 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: depth is NaN or Inf. This should not happen." ), 2 );
319 if ( !std::isfinite( worldPosition.x() ) || !std::isfinite( worldPosition.y() ) || !std::isfinite( worldPosition.z() ) )
321 QgsDebugMsgLevel( QStringLiteral(
"screenPointToWorldPos: position is NaN or Inf. This should not happen." ), 2 );
331void QgsCameraController::onPositionChangedTerrainNavigation( Qt3DInput::QMouseEvent *mouse )
333 if ( mIgnoreNextMouseMove )
335 mIgnoreNextMouseMove =
false;
336 mMousePos = QPoint( mouse->x(), mouse->y() );
340 const int dx = mouse->x() - mMousePos.x();
341 const int dy = mouse->y() - mMousePos.y();
343 const bool hasShift = ( mouse->modifiers() & Qt::ShiftModifier );
344 const bool hasCtrl = ( mouse->modifiers() & Qt::ControlModifier );
345 const bool hasLeftButton = ( mouse->buttons() & Qt::LeftButton );
346 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
347 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
349 if ( ( hasLeftButton && hasShift && !hasCtrl ) || ( hasMiddleButton && !hasShift && !hasCtrl ) )
352 setMouseParameters( MouseOperation::RotationCenter, mMousePos );
354 float scale =
static_cast<float>( std::max( mScene->
engine()->
size().width(), mScene->
engine()->
size().height() ) );
355 float pitchDiff = 180.0f *
static_cast<float>( mouse->y() - mClickPoint.y() ) / scale;
356 float yawDiff = -180.0f *
static_cast<float>( mouse->x() - mClickPoint.x() ) / scale;
358 if ( !mDepthBufferIsReady )
361 if ( !mRotationCenterCalculated )
364 QVector3D worldPosition;
365 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
367 mRotationCenter = worldPosition;
368 mRotationDistanceFromCenter = ( mRotationCenter - mCameraBefore->position() ).length();
370 mRotationCenterCalculated =
true;
376 else if ( hasLeftButton && hasCtrl && !hasShift )
378 setMouseParameters( MouseOperation::RotationCamera );
380 const float diffPitch = 0.2f * dy;
381 const float diffYaw = -0.2f * dx;
384 else if ( hasLeftButton && !hasShift && !hasCtrl )
387 setMouseParameters( MouseOperation::Translation, mMousePos );
389 if ( !mDepthBufferIsReady )
392 if ( !mDragPointCalculated )
395 QVector3D worldPosition;
396 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
399 mDragPoint = worldPosition;
400 mDragPointCalculated =
true;
404 QVector3D cameraBeforeDragPos = mCameraBefore->position();
407 QVector3D cameraBeforeToMoveToPos = ( moveToPosition - mCameraBefore->position() ).normalized();
408 QVector3D cameraBeforeToDragPointPos = ( mDragPoint - mCameraBefore->position() ).normalized();
411 if ( cameraBeforeToMoveToPos.z() == 0 )
413 cameraBeforeToMoveToPos.setZ( 0.01 );
414 cameraBeforeToMoveToPos = cameraBeforeToMoveToPos.normalized();
417 if ( cameraBeforeToDragPointPos.z() == 0 )
419 cameraBeforeToDragPointPos.setZ( 0.01 );
420 cameraBeforeToDragPointPos = cameraBeforeToDragPointPos.normalized();
423 double d1 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToMoveToPos.z();
424 double d2 = ( mDragPoint.z() - cameraBeforeDragPos.z() ) / cameraBeforeToDragPointPos.z();
426 QVector3D from = cameraBeforeDragPos + d1 * cameraBeforeToMoveToPos;
427 QVector3D to = cameraBeforeDragPos + d2 * cameraBeforeToDragPointPos;
429 QVector3D shiftVector = to - from;
431 mCameraPose.
setCenterPoint( mCameraBefore->viewCenter() + shiftVector );
432 updateCameraFromPose();
434 else if ( hasLeftButton && hasShift && hasCtrl )
438 double tElev = mMousePos.y() - mouse->y();
439 center.
set( center.
x(), center.
y(), center.
z() + tElev * 0.5 );
441 updateCameraFromPose();
443 else if ( hasRightButton && !hasShift && !hasCtrl )
445 setMouseParameters( MouseOperation::Zoom, mMousePos );
446 if ( !mDepthBufferIsReady )
449 if ( !mDragPointCalculated )
452 QVector3D worldPosition;
453 if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
455 mDragPoint = worldPosition;
456 mDragPointCalculated =
true;
460 float oldDist = ( mCameraBefore->position() - mDragPoint ).length();
461 float newDist = oldDist;
464 int screenHeight = mScene->
engine()->
size().height();
465 QWindow *win = window();
468 yOffset = win->mapToGlobal( QPoint( 0, 0 ) ).y();
469 screenHeight = win->screen()->size().height();
473 if ( mMousePos.y() > mClickPoint.y() )
475 double f = ( double ) ( mMousePos.y() - mClickPoint.y() ) / (
double ) ( screenHeight - mClickPoint.y() - yOffset );
476 f = std::max( 0.0, std::min( 1.0, f ) );
477 f = 1 - ( std::expm1( -2 * f ) ) / ( std::expm1( -2 ) );
478 newDist = newDist * f;
482 double f = 1 - ( double ) ( mMousePos.y() + yOffset ) / (
double ) ( mClickPoint.y() + yOffset );
483 f = std::max( 0.0, std::min( 1.0, f ) );
484 f = ( std::expm1( 2 * f ) ) / ( std::expm1( 2 ) );
485 newDist = newDist + 2 * newDist * f;
488 double zoomFactor = newDist / oldDist;
492 mMousePos = QPoint( mouse->x(), mouse->y() );
499 dist -= dist * factor * 0.01f;
501 updateCameraFromPose();
504void QgsCameraController::handleTerrainNavigationWheelZoom()
506 if ( !mDepthBufferIsReady )
509 if ( !mZoomPointCalculated )
512 QVector3D worldPosition;
513 if ( screenPointToWorldPos( mMousePos, mCameraBefore.get(), depth, worldPosition ) )
515 mZoomPoint = worldPosition;
516 mZoomPointCalculated =
true;
520 float f = mCumulatedWheelY / ( 120.0 * 24.0 );
522 double oldDist = ( mZoomPoint - mCameraBefore->position() ).length();
523 double newDist = ( 1 - f ) * oldDist;
524 double zoomFactor = newDist / oldDist;
528 mCumulatedWheelY = 0;
529 setMouseParameters( MouseOperation::None );
532void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel )
534 switch ( mCameraNavigationMode )
538 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.1f : 1.0f ) / 1000.f;
539 setCameraMovementSpeed( mCameraMovementSpeed + mCameraMovementSpeed * scaling * wheel->angleDelta().y() );
545 const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.5f : 5.f );
549 mCumulatedWheelY += scaling * wheel->angleDelta().y();
551 if ( mCurrentOperation != MouseOperation::ZoomWheel )
553 setMouseParameters( MouseOperation::ZoomWheel );
557 handleTerrainNavigationWheelZoom();
564void QgsCameraController::onMousePressed( Qt3DInput::QMouseEvent *mouse )
566 mKeyboardHandler->setFocus(
true );
568 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 ) )
570 mMousePos = QPoint( mouse->x(), mouse->y() );
572 if ( mCaptureFpsMouseMovements )
573 mIgnoreNextMouseMove =
true;
575 const MouseOperation operation {
576 ( mouse->modifiers() & Qt::ControlModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ? MouseOperation::RotationCamera : MouseOperation::RotationCenter
578 setMouseParameters( operation, mMousePos );
581 else if ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton || mouse->button() == Qt3DInput::QMouseEvent::RightButton )
583 mMousePos = QPoint( mouse->x(), mouse->y() );
585 if ( mCaptureFpsMouseMovements )
586 mIgnoreNextMouseMove =
true;
588 const MouseOperation operation = ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) ? MouseOperation::Translation : MouseOperation::Zoom;
589 setMouseParameters( operation, mMousePos );
593void QgsCameraController::onMouseReleased( Qt3DInput::QMouseEvent *mouse )
597 setMouseParameters( MouseOperation::None );
600void QgsCameraController::onKeyPressed( Qt3DInput::QKeyEvent *event )
602 if ( event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_QuoteLeft )
605 switch ( mCameraNavigationMode )
617 switch ( mCameraNavigationMode )
621 onKeyPressedFlyNavigation( event );
627 onKeyPressedTerrainNavigation( event );
633void QgsCameraController::onKeyPressedTerrainNavigation( Qt3DInput::QKeyEvent *event )
635 const bool hasShift = (
event->modifiers() & Qt::ShiftModifier );
636 const bool hasCtrl = (
event->modifiers() & Qt::ControlModifier );
638 int tx = 0, ty = 0, tElev = 0;
639 switch ( event->key() )
655 case Qt::Key_PageDown:
665 if ( !hasShift && !hasCtrl )
669 else if ( hasShift && !hasCtrl )
675 else if ( hasCtrl && !hasShift )
678 const float diffPitch = ty;
679 const float diffYaw = -tx;
687 center.
set( center.
x(), center.
y(), center.
z() + tElev * 10 );
689 updateCameraFromPose();
693void QgsCameraController::onKeyPressedFlyNavigation( Qt3DInput::QKeyEvent *event )
695 switch ( event->key() )
697 case Qt::Key_QuoteLeft:
700 mCaptureFpsMouseMovements = !mCaptureFpsMouseMovements;
701 mIgnoreNextMouseMove =
true;
702 if ( mCaptureFpsMouseMovements )
704 qApp->setOverrideCursor( QCursor( Qt::BlankCursor ) );
708 qApp->restoreOverrideCursor();
716 if ( mCaptureFpsMouseMovements )
718 mCaptureFpsMouseMovements =
false;
719 mIgnoreNextMouseMove =
true;
720 qApp->restoreOverrideCursor();
730 if ( event->isAutoRepeat() )
733 mDepressedKeys.insert( event->key() );
738 const QVector3D cameraUp = mCamera->upVector().normalized();
740 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
742 QVector3D cameraPosDiff( 0.0f, 0.0f, 0.0f );
746 cameraPosDiff +=
static_cast<float>( tx ) * cameraFront;
750 cameraPosDiff +=
static_cast<float>( ty ) * cameraLeft;
754 cameraPosDiff +=
static_cast<float>( tz ) * QVector3D( 0.0f, 0.0f, 1.0f );
757 moveCameraPositionBy( cameraPosDiff );
760void QgsCameraController::applyFlyModeKeyMovements()
763 const bool shiftPressed = mDepressedKeys.contains( Qt::Key_Shift );
764 const bool ctrlPressed = mDepressedKeys.contains( Qt::Key_Control );
766 const double movementSpeed = mCameraMovementSpeed * ( shiftPressed ? 2 : 1 ) * ( ctrlPressed ? 0.1 : 1 );
768 bool changed =
false;
772 if ( mDepressedKeys.contains( Qt::Key_Left ) || mDepressedKeys.contains( Qt::Key_A ) )
778 if ( mDepressedKeys.contains( Qt::Key_Right ) || mDepressedKeys.contains( Qt::Key_D ) )
784 if ( mDepressedKeys.contains( Qt::Key_Up ) || mDepressedKeys.contains( Qt::Key_W ) )
790 if ( mDepressedKeys.contains( Qt::Key_Down ) || mDepressedKeys.contains( Qt::Key_S ) )
798 static constexpr double ELEVATION_MOVEMENT_SCALE = 0.5;
799 if ( mDepressedKeys.contains( Qt::Key_PageUp ) || mDepressedKeys.contains( Qt::Key_E ) )
802 z += ELEVATION_MOVEMENT_SCALE * movementSpeed;
805 if ( mDepressedKeys.contains( Qt::Key_PageDown ) || mDepressedKeys.contains( Qt::Key_Q ) )
808 z -= ELEVATION_MOVEMENT_SCALE * movementSpeed;
815void QgsCameraController::onPositionChangedFlyNavigation( Qt3DInput::QMouseEvent *mouse )
817 const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
818 const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
820 const double dx = mCaptureFpsMouseMovements ? QCursor::pos().x() - mMousePos.x() : mouse->x() - mMousePos.x();
821 const double dy = mCaptureFpsMouseMovements ? QCursor::pos().y() - mMousePos.y() : mouse->y() - mMousePos.y();
822 mMousePos = mCaptureFpsMouseMovements ? QCursor::pos() : QPoint( mouse->x(), mouse->y() );
824 if ( mIgnoreNextMouseMove )
826 mIgnoreNextMouseMove =
false;
830 if ( hasMiddleButton )
833 const QVector3D cameraUp = mCamera->upVector().normalized();
835 const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
836 const QVector3D cameraPosDiff = -dx * cameraLeft - dy * cameraUp;
837 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 10.0 );
839 else if ( hasRightButton )
843 const QVector3D cameraPosDiff = dy * cameraFront;
844 moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 5.0 );
848 if ( mCaptureFpsMouseMovements )
850 float diffPitch = -0.2f * dy;
851 switch ( mVerticalAxisInversion )
862 const float diffYaw = -0.2f * dx;
865 else if ( mouse->buttons() & Qt::LeftButton )
867 float diffPitch = -0.2f * dy;
868 switch ( mVerticalAxisInversion )
878 const float diffYaw = -0.2f * dx;
883 if ( mCaptureFpsMouseMovements )
885 mIgnoreNextMouseMove =
true;
892void QgsCameraController::onKeyReleased( Qt3DInput::QKeyEvent *event )
894 if ( event->isAutoRepeat() )
897 mDepressedKeys.remove( event->key() );
906 updateCameraFromPose();
915 updateCameraFromPose();
921 updateCameraFromPose();
928 const float x = tx * dist * 0.02f;
929 const float y = -ty * dist * 0.02f;
932 const float t = sqrt( x * x + y * y );
933 const float a = atan2( y, x ) -
yaw * M_PI / 180;
934 const float dx = cos( a ) * t;
935 const float dy = sin( a ) * t;
938 center.
set( center.
x() + dx, center.
y() - dy, center.
z() );
940 updateCameraFromPose();
945 if ( event->key() == Qt::Key_QuoteLeft )
948 switch ( mCameraNavigationMode )
952 switch ( event->key() )
964 case Qt::Key_PageDown:
969 if ( mCaptureFpsMouseMovements )
981 switch ( event->key() )
986 case Qt::Key_PageDown:
1000 mDepthBufferImage = depthImage;
1001 mDepthBufferIsReady =
true;
1003 if ( mCurrentOperation == MouseOperation::ZoomWheel )
1005 handleTerrainNavigationWheelZoom();
1009bool QgsCameraController::isATranslationRotationSequence( MouseOperation newOperation )
const
1011 return std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), newOperation ) != std::end( mTranslateOrRotate ) && std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), mCurrentOperation ) != std::end( mTranslateOrRotate );
1014void QgsCameraController::setMouseParameters(
const MouseOperation &newOperation,
const QPoint &clickPoint )
1016 if ( newOperation == mCurrentOperation )
1021 if ( newOperation == MouseOperation::None )
1023 mClickPoint = QPoint();
1031 else if ( mClickPoint.isNull() || isATranslationRotationSequence( newOperation ) )
1033 mClickPoint = clickPoint;
1037 mCurrentOperation = newOperation;
1038 mDepthBufferIsReady =
false;
1039 mRotationCenterCalculated =
false;
1040 mDragPointCalculated =
false;
1041 mZoomPointCalculated =
false;
1043 if ( mCurrentOperation != MouseOperation::None && mCurrentOperation != MouseOperation::RotationCamera )
1047 mCameraBefore->setProjectionMatrix( mCamera->projectionMatrix() );
1048 mCameraBefore->setNearPlane( mCamera->nearPlane() );
1049 mCameraBefore->setFarPlane( mCamera->farPlane() );
1050 mCameraBefore->setAspectRatio( mCamera->aspectRatio() );
1051 mCameraBefore->setFieldOfView( mCamera->fieldOfView() );
1062 mCameraBefore->setPosition( (
QgsVector3D( mCameraBefore->position() ) - diff ).toVector3D() );
1063 mCameraBefore->setViewCenter( (
QgsVector3D( mCameraBefore->viewCenter() ) - diff ).toVector3D() );
1064 mDragPoint = (
QgsVector3D( mDragPoint ) - diff ).toVector3D();
1065 mRotationCenter = (
QgsVector3D( mRotationCenter ) - diff ).toVector3D();
1069 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)