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)