24#include <QDomDocument> 
   25#include <Qt3DRender/QCamera> 
   33  , mCamera( scene->engine()->camera() )
 
   35  , mMouseHandler( new 
Qt3DInput::QMouseHandler )
 
   36  , mKeyboardHandler( new 
Qt3DInput::QKeyboardHandler )
 
   38  mMouseHandler->setSourceDevice( 
new Qt3DInput::QMouseDevice() );
 
   39  connect( mMouseHandler, &Qt3DInput::QMouseHandler::positionChanged,
 
   40           this, &QgsCameraController::onPositionChanged );
 
   41  connect( mMouseHandler, &Qt3DInput::QMouseHandler::wheel,
 
   42           this, &QgsCameraController::onWheel );
 
   43  connect( mMouseHandler, &Qt3DInput::QMouseHandler::pressed,
 
   44           this, &QgsCameraController::onMousePressed );
 
   45  connect( mMouseHandler, &Qt3DInput::QMouseHandler::released,
 
   46           this, &QgsCameraController::onMouseReleased );
 
   47  addComponent( mMouseHandler );
 
   49  mKeyboardHandler->setSourceDevice( 
new Qt3DInput::QKeyboardDevice() );
 
   50  connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::pressed,
 
   51           this, &QgsCameraController::onKeyPressed );
 
   52  connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::released,
 
   53           this, &QgsCameraController::onKeyReleased );
 
   54  addComponent( mKeyboardHandler );
 
   57  connect( 
this, &Qt3DCore::QEntity::enabledChanged,
 
   58           mMouseHandler, &Qt3DInput::QMouseHandler::setEnabled );
 
   59  connect( 
this, &Qt3DCore::QEntity::enabledChanged,
 
   60           mKeyboardHandler, &Qt3DInput::QKeyboardHandler::setEnabled );
 
   62  mFpsNavTimer = 
new QTimer( 
this );
 
   63  mFpsNavTimer->setInterval( 10 );
 
   64  connect( mFpsNavTimer, &QTimer::timeout, 
this, &QgsCameraController::applyFlyModeKeyMovements );
 
   65  mFpsNavTimer->start();
 
 
   70QWindow *QgsCameraController::window()
 const 
   73  return windowEngine ? windowEngine->
window() : 
nullptr;
 
   78  if ( navigationMode == mCameraNavigationMode )
 
   81  mCameraNavigationMode = navigationMode;
 
   82  mIgnoreNextMouseMove = 
true;
 
 
   88  if ( movementSpeed == mCameraMovementSpeed )
 
   93  mCameraMovementSpeed = std::clamp( movementSpeed, 0.05, 150.0 );
 
 
   99  mVerticalAxisInversion = inversion;
 
 
  107  if ( 
pitch + diffPitch > 180 )
 
  108    diffPitch = 180 - 
pitch;  
 
  109  if ( 
pitch + diffPitch < 0 )
 
  110    diffPitch = 0 - 
pitch;   
 
  117  const QQuaternion q = QQuaternion::fromEulerAngles( 
pitch + diffPitch, 
yaw + diffYaw, 0 ) *
 
  118                        QQuaternion::fromEulerAngles( 
pitch, 
yaw, 0 ).conjugated();
 
  121  const QVector3D position = mCamera->position();
 
  122  QVector3D viewCenter = mCamera->viewCenter();
 
  123  const QVector3D viewVector = viewCenter - position;
 
  124  const QVector3D cameraToCenter = q * viewVector;
 
  125  viewCenter = position + cameraToCenter;
 
  130  updateCameraFromPose();
 
 
  156  mCamera->setNearPlane( 
distance / 2 );
 
  157  mCamera->setFarPlane( 
distance * 2 );
 
 
  179  if ( camPose == mCameraPose )
 
  182  mCameraPose = camPose;
 
  183  updateCameraFromPose();
 
 
  188  QDomElement elemCamera = doc.createElement( QStringLiteral( 
"camera" ) );
 
  189  elemCamera.setAttribute( QStringLiteral( 
"x" ), mCameraPose.
centerPoint().
x() );
 
  190  elemCamera.setAttribute( QStringLiteral( 
"y" ), mCameraPose.
centerPoint().
z() );
 
  191  elemCamera.setAttribute( QStringLiteral( 
"elev" ), mCameraPose.
centerPoint().
y() );
 
  193  elemCamera.setAttribute( QStringLiteral( 
"pitch" ), mCameraPose.
pitchAngle() );
 
  194  elemCamera.setAttribute( QStringLiteral( 
"yaw" ), mCameraPose.
headingAngle() );
 
 
  200  const float x = elem.attribute( QStringLiteral( 
"x" ) ).toFloat();
 
  201  const float y = elem.attribute( QStringLiteral( 
"y" ) ).toFloat();
 
  202  const float elev = elem.attribute( QStringLiteral( 
"elev" ) ).toFloat();
 
  203  const float dist = elem.attribute( QStringLiteral( 
"dist" ) ).toFloat();
 
  204  const float pitch = elem.attribute( QStringLiteral( 
"pitch" ) ).toFloat();
 
  205  const float yaw = elem.attribute( QStringLiteral( 
"yaw" ) ).toFloat();
 
 
  209double QgsCameraController::sampleDepthBuffer( 
const QImage &buffer, 
int px, 
int py )
 
  214  for ( 
int x = px - 3; x <= px + 3; ++x )
 
  216    for ( 
int y = py - 3; y <= py + 3; ++y )
 
  218      if ( buffer.valid( x, y ) )
 
  230  int samplesCount = 0;
 
  231  for ( 
int x = 0; x < buffer.width(); ++x )
 
  233    for ( 
int y = 0; y < buffer.height(); ++y )
 
  245  if ( samplesCount == 0 )
 
  248    depth /= samplesCount;
 
  253void QgsCameraController::updateCameraFromPose()
 
  261void QgsCameraController::moveCameraPositionBy( 
const QVector3D &posDiff )
 
  264  updateCameraFromPose();
 
  267void QgsCameraController::onPositionChanged( Qt3DInput::QMouseEvent *mouse )
 
  269  switch ( mCameraNavigationMode )
 
  272      onPositionChangedTerrainNavigation( mouse );
 
  276      onPositionChangedFlyNavigation( mouse );
 
  281bool QgsCameraController::screenPointToWorldPos( QPoint position, Qt3DRender::QCamera *mCameraBefore, 
double &depth, QVector3D &worldPosition )
 
  283  depth = sampleDepthBuffer( mDepthBufferImage, position.x(), position.y() );
 
  284  if ( !std::isfinite( depth ) )
 
  286    QgsDebugMsgLevel( QStringLiteral( 
"screenPointToWorldPos: depth is NaN or Inf. This should not happen." ), 2 );
 
  292    if ( !std::isfinite( worldPosition.x() ) || !std::isfinite( worldPosition.y() ) || !std::isfinite( worldPosition.z() ) )
 
  294      QgsDebugMsgLevel( QStringLiteral( 
"screenPointToWorldPos: position is NaN or Inf. This should not happen." ), 2 );
 
  304void QgsCameraController::onPositionChangedTerrainNavigation( Qt3DInput::QMouseEvent *mouse )
 
  306  if ( mIgnoreNextMouseMove )
 
  308    mIgnoreNextMouseMove = 
false;
 
  309    mMousePos = QPoint( mouse->x(), mouse->y() );
 
  313  const int dx = mouse->x() - mMousePos.x();
 
  314  const int dy = mouse->y() - mMousePos.y();
 
  316  const bool hasShift = ( mouse->modifiers() & Qt::ShiftModifier );
 
  317  const bool hasCtrl = ( mouse->modifiers() & Qt::ControlModifier );
 
  318  const bool hasLeftButton = ( mouse->buttons() & Qt::LeftButton );
 
  319  const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
 
  320  const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
 
  322  if ( ( hasLeftButton && hasShift && !hasCtrl ) || ( hasMiddleButton && !hasShift && !hasCtrl ) )
 
  325    setMouseParameters( MouseOperation::RotationCenter, mMousePos );
 
  327    float scale = 
static_cast<float>( std::max( mScene->
engine()->
size().width(), mScene->
engine()->
size().height() ) );
 
  328    float pitchDiff = 180.0f * 
static_cast<float>( mouse->y() - mClickPoint.y() ) / scale;
 
  329    float yawDiff = -180.0f * 
static_cast<float>( mouse->x() - mClickPoint.x() ) / scale;
 
  331    if ( !mDepthBufferIsReady )
 
  334    if ( !mRotationCenterCalculated )
 
  337      QVector3D worldPosition;
 
  338      if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
 
  340        mRotationCenter = worldPosition;
 
  341        mRotationDistanceFromCenter = ( mRotationCenter - mCameraBefore->position() ).length();
 
  343        mRotationCenterCalculated = 
true;
 
  349      QVector3D shiftVector = mRotationCenter - mCamera->viewCenter();
 
  351      QVector3D newViewCenterWorld = 
camera()->viewCenter() + shiftVector;
 
  352      QVector3D newCameraPosition = 
camera()->position() + shiftVector;
 
  358      updateCameraFromPose();
 
  366      QVector3D clickedPositionWorld = ray.
origin() + mRotationDistanceFromCenter * ray.
direction();
 
  368      QVector3D shiftVector = clickedPositionWorld - mCamera->viewCenter();
 
  370      QVector3D newViewCenterWorld = 
camera()->viewCenter() - shiftVector;
 
  371      QVector3D newCameraPosition = 
camera()->position() - shiftVector;
 
  375      updateCameraFromPose();
 
  378  else if ( hasLeftButton && hasCtrl && !hasShift )
 
  380    setMouseParameters( MouseOperation::RotationCamera );
 
  382    const float diffPitch = 0.2f * dy;
 
  383    const float diffYaw = - 0.2f * dx;
 
  386  else if ( hasLeftButton && !hasShift && !hasCtrl )
 
  389    setMouseParameters( MouseOperation::Translation, mMousePos );
 
  391    if ( !mDepthBufferIsReady )
 
  394    if ( !mDragPointCalculated )
 
  397      QVector3D worldPosition;
 
  398      if ( screenPointToWorldPos( mClickPoint, mCameraBefore.get(), depth, worldPosition ) )
 
  401        mDragPoint = worldPosition;
 
  402        mDragPointCalculated = 
true;
 
  407    QVector3D cameraBeforeDragPos = mCameraBefore->position();
 
  410    QVector3D cameraBeforeToMoveToPos = ( moveToPosition - mCameraBefore->position() ).normalized();
 
  411    QVector3D cameraBeforeToDragPointPos = ( mDragPoint - mCameraBefore->position() ).normalized();
 
  414    if ( cameraBeforeToMoveToPos.y() == 0 )
 
  416      cameraBeforeToMoveToPos.setY( 0.01 );
 
  417      cameraBeforeToMoveToPos = cameraBeforeToMoveToPos.normalized();
 
  420    if ( cameraBeforeToDragPointPos.y() == 0 )
 
  422      cameraBeforeToDragPointPos.setY( 0.01 );
 
  423      cameraBeforeToDragPointPos = cameraBeforeToDragPointPos.normalized();
 
  426    double d1 = ( mDragPoint.y() - cameraBeforeDragPos.y() ) / cameraBeforeToMoveToPos.y();
 
  427    double d2 = ( mDragPoint.y() - cameraBeforeDragPos.y() ) / cameraBeforeToDragPointPos.y();
 
  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() + tElev * 0.5, center.
z() );
 
  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 dist = ( mCameraBefore->position() - mDragPoint ).length();
 
  466    int screenHeight = mScene->
engine()->
size().height();
 
  467    QWindow *win = window();
 
  470      yOffset = win->mapToGlobal( QPoint( 0, 0 ) ).y();
 
  471      screenHeight = win->screen()->size().height();
 
  475    if ( mMousePos.y() > mClickPoint.y() ) 
 
  477      double f = ( double )( mMousePos.y() - mClickPoint.y() ) / ( 
double )( screenHeight - mClickPoint.y() - yOffset );
 
  478      f = std::max( 0.0, std::min( 1.0, f ) );
 
  479      f = 1 - ( std::expm1( -2 * f ) ) / ( std::expm1( -2 ) );
 
  484      double f = 1 - ( double )( mMousePos.y() + yOffset ) / ( 
double )( mClickPoint.y() + yOffset );
 
  485      f = std::max( 0.0, std::min( 1.0, f ) );
 
  486      f = ( std::expm1( 2 * f ) ) / ( std::expm1( 2 ) );
 
  487      dist = dist + 2 * dist * f;
 
  492      QVector3D shiftVector = mDragPoint - mCamera->viewCenter();
 
  494      QVector3D newViewCenterWorld = 
camera()->viewCenter() + shiftVector;
 
  498      updateCameraFromPose();
 
  504      QVector3D clickedPositionWorld = ray.
origin() + dist * ray.
direction();
 
  506      QVector3D shiftVector = clickedPositionWorld - mCamera->viewCenter();
 
  508      QVector3D newViewCenterWorld = 
camera()->viewCenter() - shiftVector;
 
  509      QVector3D newCameraPosition = 
camera()->position() - shiftVector;
 
  513      updateCameraFromPose();
 
  517  mMousePos = QPoint( mouse->x(), mouse->y() );
 
  524  dist -= dist * factor * 0.01f;
 
  526  updateCameraFromPose();
 
 
  529void QgsCameraController::handleTerrainNavigationWheelZoom()
 
  531  if ( !mDepthBufferIsReady )
 
  534  if ( !mZoomPointCalculated )
 
  537    QVector3D worldPosition;
 
  538    if ( screenPointToWorldPos( mMousePos, mCameraBefore.get(), depth, worldPosition ) )
 
  540      mZoomPoint = worldPosition;
 
  541      mZoomPointCalculated = 
true;
 
  545  float f = mCumulatedWheelY / ( 120.0 * 24.0 );
 
  547  double dist = ( mZoomPoint - mCameraBefore->position() ).length();
 
  552    QVector3D shiftVector = mZoomPoint - mCamera->viewCenter();
 
  554    QVector3D newViewCenterWorld = 
camera()->viewCenter() + shiftVector;
 
  558    updateCameraFromPose();
 
  564    QVector3D clickedPositionWorld = ray.
origin() + dist * ray.
direction();
 
  566    QVector3D shiftVector = clickedPositionWorld - mCamera->viewCenter();
 
  568    QVector3D newViewCenterWorld = 
camera()->viewCenter() - shiftVector;
 
  569    QVector3D newCameraPosition = 
camera()->position() - shiftVector;
 
  573    updateCameraFromPose();
 
  575  mCumulatedWheelY = 0;
 
  576  setMouseParameters( MouseOperation::None );
 
  579void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel )
 
  581  switch ( mCameraNavigationMode )
 
  585      const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.1f : 1.0f ) / 1000.f;
 
  586      setCameraMovementSpeed( mCameraMovementSpeed + mCameraMovementSpeed * scaling * wheel->angleDelta().y() );
 
  593      const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) != 0 ? 0.5f : 5.f );
 
  597      mCumulatedWheelY += scaling * wheel->angleDelta().y();
 
  599      if ( mCurrentOperation != MouseOperation::ZoomWheel )
 
  601        setMouseParameters( MouseOperation::ZoomWheel );
 
  605        handleTerrainNavigationWheelZoom();
 
  612void QgsCameraController::onMousePressed( Qt3DInput::QMouseEvent *mouse )
 
  614  mKeyboardHandler->setFocus( 
true );
 
  616  if ( mouse->button() == Qt3DInput::QMouseEvent::MiddleButton ||
 
  617       ( ( mouse->modifiers() & Qt::ShiftModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) ||
 
  618       ( ( mouse->modifiers() & Qt::ControlModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) )
 
  620    mMousePos = QPoint( mouse->x(), mouse->y() );
 
  622    if ( mCaptureFpsMouseMovements )
 
  623      mIgnoreNextMouseMove = 
true;
 
  625    const MouseOperation operation
 
  627      ( mouse->modifiers() & Qt::ControlModifier ) != 0 && mouse->button() == Qt3DInput::QMouseEvent::LeftButton  ?
 
  628      MouseOperation::RotationCamera :
 
  629      MouseOperation::RotationCenter
 
  631    setMouseParameters( operation, mMousePos );
 
  634  else if ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton || mouse->button() == Qt3DInput::QMouseEvent::RightButton )
 
  636    mMousePos = QPoint( mouse->x(), mouse->y() );
 
  638    if ( mCaptureFpsMouseMovements )
 
  639      mIgnoreNextMouseMove = 
true;
 
  641    const MouseOperation operation = ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton ) ? MouseOperation::Translation : MouseOperation::Zoom;
 
  642    setMouseParameters( operation, mMousePos );
 
  646void QgsCameraController::onMouseReleased( Qt3DInput::QMouseEvent *mouse )
 
  650  setMouseParameters( MouseOperation::None );
 
  653void QgsCameraController::onKeyPressed( Qt3DInput::QKeyEvent *event )
 
  655  if ( event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_QuoteLeft )
 
  658    switch ( mCameraNavigationMode )
 
  670  switch ( mCameraNavigationMode )
 
  674      onKeyPressedFlyNavigation( event );
 
  680      onKeyPressedTerrainNavigation( event );
 
  686void QgsCameraController::onKeyPressedTerrainNavigation( Qt3DInput::QKeyEvent *event )
 
  688  const bool hasShift = ( 
event->modifiers() & Qt::ShiftModifier );
 
  689  const bool hasCtrl = ( 
event->modifiers() & Qt::ControlModifier );
 
  691  int tx = 0, ty = 0, tElev = 0;
 
  692  switch ( event->key() )
 
  708    case Qt::Key_PageDown:
 
  718    if ( !hasShift && !hasCtrl )
 
  722    else if ( hasShift && !hasCtrl )
 
  728    else if ( hasCtrl && !hasShift )
 
  731      const float diffPitch = ty;   
 
  732      const float diffYaw = -tx;    
 
  740    center.
set( center.
x(), center.
y() + tElev * 10, center.
z() );
 
  742    updateCameraFromPose();
 
  746void QgsCameraController::onKeyPressedFlyNavigation( Qt3DInput::QKeyEvent *event )
 
  748  switch ( event->key() )
 
  750    case Qt::Key_QuoteLeft:
 
  753      mCaptureFpsMouseMovements = !mCaptureFpsMouseMovements;
 
  754      mIgnoreNextMouseMove = 
true;
 
  755      if ( mCaptureFpsMouseMovements )
 
  757        qApp->setOverrideCursor( QCursor( Qt::BlankCursor ) );
 
  761        qApp->restoreOverrideCursor();
 
  769      if ( mCaptureFpsMouseMovements )
 
  771        mCaptureFpsMouseMovements = 
false;
 
  772        mIgnoreNextMouseMove = 
true;
 
  773        qApp->restoreOverrideCursor();
 
  783  if ( event->isAutoRepeat() )
 
  786  mDepressedKeys.insert( event->key() );
 
  791  const QVector3D cameraUp = mCamera->upVector().normalized();
 
  793  const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
 
  795  QVector3D cameraPosDiff( 0.0f, 0.0f, 0.0f );
 
  799    cameraPosDiff += tx * cameraFront;
 
  803    cameraPosDiff += ty * cameraLeft;
 
  807    cameraPosDiff += tz * QVector3D( 0.0f, 1.0f, 0.0f );
 
  810  moveCameraPositionBy( cameraPosDiff );
 
 
  813void QgsCameraController::applyFlyModeKeyMovements()
 
  816  const bool shiftPressed = mDepressedKeys.contains( Qt::Key_Shift );
 
  817  const bool ctrlPressed = mDepressedKeys.contains( Qt::Key_Control );
 
  819  const double movementSpeed = mCameraMovementSpeed * ( shiftPressed ? 2 : 1 ) * ( ctrlPressed ? 0.1 : 1 );
 
  821  bool changed = 
false;
 
  825  if ( mDepressedKeys.contains( Qt::Key_Left ) || mDepressedKeys.contains( Qt::Key_A ) )
 
  831  if ( mDepressedKeys.contains( Qt::Key_Right ) || mDepressedKeys.contains( Qt::Key_D ) )
 
  837  if ( mDepressedKeys.contains( Qt::Key_Up ) || mDepressedKeys.contains( Qt::Key_W ) )
 
  843  if ( mDepressedKeys.contains( Qt::Key_Down ) || mDepressedKeys.contains( Qt::Key_S ) )
 
  851  static constexpr double ELEVATION_MOVEMENT_SCALE = 0.5;
 
  852  if ( mDepressedKeys.contains( Qt::Key_PageUp ) || mDepressedKeys.contains( Qt::Key_E ) )
 
  855    z += ELEVATION_MOVEMENT_SCALE * movementSpeed;
 
  858  if ( mDepressedKeys.contains( Qt::Key_PageDown ) || mDepressedKeys.contains( Qt::Key_Q ) )
 
  861    z -= ELEVATION_MOVEMENT_SCALE * movementSpeed;
 
  868void QgsCameraController::onPositionChangedFlyNavigation( Qt3DInput::QMouseEvent *mouse )
 
  870  const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
 
  871  const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
 
  873  const double dx = mCaptureFpsMouseMovements ? QCursor::pos().x() - mMousePos.x() : mouse->x() - mMousePos.x();
 
  874  const double dy = mCaptureFpsMouseMovements ? QCursor::pos().y() - mMousePos.y() : mouse->y() - mMousePos.y();
 
  875  mMousePos = mCaptureFpsMouseMovements ? QCursor::pos() : QPoint( mouse->x(), mouse->y() );
 
  877  if ( mIgnoreNextMouseMove )
 
  879    mIgnoreNextMouseMove = 
false;
 
  883  if ( hasMiddleButton )
 
  886    const QVector3D cameraUp = mCamera->upVector().normalized();
 
  888    const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
 
  889    const QVector3D cameraPosDiff = -dx * cameraLeft - dy * cameraUp;
 
  890    moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 10.0 );
 
  892  else if ( hasRightButton )
 
  896    const QVector3D cameraPosDiff = dy * cameraFront;
 
  897    moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 5.0 );
 
  901    if ( mCaptureFpsMouseMovements )
 
  903      float diffPitch = -0.2f * dy;
 
  904      switch ( mVerticalAxisInversion )
 
  915      const float diffYaw = - 0.2f * dx;
 
  918    else if ( mouse->buttons() & Qt::LeftButton )
 
  920      float diffPitch = -0.2f * dy;
 
  921      switch ( mVerticalAxisInversion )
 
  931      const float diffYaw = - 0.2f * dx;
 
  936  if ( mCaptureFpsMouseMovements )
 
  938    mIgnoreNextMouseMove = 
true;
 
  945void QgsCameraController::onKeyReleased( Qt3DInput::QKeyEvent *event )
 
  947  if ( event->isAutoRepeat() )
 
  950  mDepressedKeys.remove( event->key() );
 
  959  updateCameraFromPose();
 
 
  968  updateCameraFromPose();
 
 
  974  updateCameraFromPose();
 
 
  981  const float x = tx * dist * 0.02f;
 
  982  const float y = -ty * dist * 0.02f;
 
  985  const float t = sqrt( x * x + y * y );
 
  986  const float a = atan2( y, x ) - 
yaw * M_PI / 180;
 
  987  const float dx = cos( a ) * t;
 
  988  const float dy = sin( a ) * t;
 
  991  center.
set( center.
x() + dx, center.
y(), center.
z() + dy );
 
  993  updateCameraFromPose();
 
 
  998  if ( event->key() == Qt::Key_QuoteLeft )
 
 1001  switch ( mCameraNavigationMode )
 
 1005      switch ( event->key() )
 
 1015        case Qt::Key_PageUp:
 
 1017        case Qt::Key_PageDown:
 
 1021        case Qt::Key_Escape:
 
 1022          if ( mCaptureFpsMouseMovements )
 
 1034      switch ( event->key() )
 
 1038        case Qt::Key_PageUp:
 
 1039        case Qt::Key_PageDown:
 
 
 1053  mDepthBufferImage = depthImage;
 
 1054  mDepthBufferIsReady = 
true;
 
 1056  if ( mCurrentOperation == MouseOperation::ZoomWheel )
 
 1058    handleTerrainNavigationWheelZoom();
 
 
 1062bool QgsCameraController::isATranslationRotationSequence( MouseOperation newOperation )
 const 
 1064  return std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), newOperation ) != std::end( mTranslateOrRotate ) &&
 
 1065         std::find( mTranslateOrRotate.begin(), mTranslateOrRotate.end(), mCurrentOperation ) != std::end( mTranslateOrRotate );
 
 1068void QgsCameraController::setMouseParameters( 
const MouseOperation &newOperation, 
const QPoint &clickPoint )
 
 1070  if ( newOperation == mCurrentOperation )
 
 1075  if ( newOperation == MouseOperation::None )
 
 1077    mClickPoint = QPoint();
 
 1085  else if ( mClickPoint.isNull() || isATranslationRotationSequence( newOperation ) )
 
 1087    mClickPoint = clickPoint;
 
 1091  mCurrentOperation = newOperation;
 
 1092  mDepthBufferIsReady = 
false;
 
 1093  mRotationCenterCalculated = 
false;
 
 1094  mDragPointCalculated = 
false;
 
 1095  mZoomPointCalculated = 
false;
 
 1097  if ( mCurrentOperation != MouseOperation::None && mCurrentOperation != MouseOperation::RotationCamera )
 
 1101    mCameraBefore->setProjectionMatrix( mCamera->projectionMatrix() );
 
 1102    mCameraBefore->setNearPlane( mCamera->nearPlane() );
 
 1103    mCameraBefore->setFarPlane( mCamera->farPlane() );
 
 1104    mCameraBefore->setAspectRatio( mCamera->aspectRatio() );
 
 1105    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)