23 #include <QDomDocument>    24 #include <Qt3DRender/QCamera>    25 #include <Qt3DRender/QObjectPicker>    26 #include <Qt3DRender/QPickEvent>    32   , mMouseDevice( new 
Qt3DInput::QMouseDevice() )
    33   , mKeyboardDevice( new 
Qt3DInput::QKeyboardDevice() )
    34   , mMouseHandler( new 
Qt3DInput::QMouseHandler )
    35   , mKeyboardHandler( new 
Qt3DInput::QKeyboardHandler )
    38   mMouseHandler->setSourceDevice( mMouseDevice );
    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( mKeyboardDevice );
    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::QMouseHandler::setEnabled );
    68   connect( te->terrainPicker(), &Qt3DRender::QObjectPicker::pressed, 
this, &QgsCameraController::onPickerMousePressed );
    73   if ( mCamera == camera )
    86   if ( mViewport == viewport )
    94 static QVector3D unproject( QVector3D v, 
const QMatrix4x4 &modelView, 
const QMatrix4x4 &projection, QRect 
viewport )
   101   QMatrix4x4 inverse = QMatrix4x4( projection * modelView ).inverted();
   103   QVector4D tmp( v, 1.0f );
   104   tmp.setX( ( tmp.x() - float( viewport.x() ) ) / float( viewport.width() ) );
   105   tmp.setY( ( tmp.y() - float( viewport.y() ) ) / float( viewport.height() ) );
   106   tmp = tmp * 2.0f - QVector4D( 1.0f, 1.0f, 1.0f, 1.0f );
   108   QVector4D obj = inverse * tmp;
   112   return obj.toVector3D();
   120   float k = ( y - y0 ) / d_y; 
   127   QVector3D l0 = unproject( QVector3D( pt.x(), viewport.height() - pt.y(), 0 ), camera->viewMatrix(), camera->projectionMatrix(), 
viewport );
   128   QVector3D l1 = unproject( QVector3D( pt.x(), viewport.height() - pt.y(), 1 ), camera->viewMatrix(), camera->projectionMatrix(), 
viewport );
   130   QVector3D p0( 0, y, 0 ); 
   131   QVector3D n( 0, 1, 0 ); 
   132   QVector3D l = l1 - l0; 
   133   float d = QVector3D::dotProduct( p0 - l0, n ) / QVector3D::dotProduct( l, n );
   134   QVector3D p = d * l + l0;
   136   return QPointF( p.x(), p.z() );
   140 void QgsCameraController::rotateCamera( 
float diffPitch, 
float diffYaw )
   145   if ( pitch + diffPitch > 180 )
   146     diffPitch = 180 - 
pitch;  
   147   if ( pitch + diffPitch < 0 )
   148     diffPitch = 0 - 
pitch;   
   155   QQuaternion q = QQuaternion::fromEulerAngles( pitch + diffPitch, yaw + diffYaw, 0 ) *
   156                   QQuaternion::fromEulerAngles( pitch, yaw, 0 ).conjugated();
   159   QVector3D position = mCamera->position();
   160   QVector3D viewCenter = mCamera->viewCenter();
   161   QVector3D viewVector = viewCenter - position;
   162   QVector3D cameraToCenter = q * viewVector;
   163   viewCenter = position + cameraToCenter;
   189   mCamera->setNearPlane( distance / 2 );
   190   mCamera->setFarPlane( distance * 2 );
   212   if ( camPose == mCameraPose )
   215   mCameraPose = camPose;
   225   QDomElement elemCamera = doc.createElement( QStringLiteral( 
"camera" ) );
   226   elemCamera.setAttribute( QStringLiteral( 
"x" ), mCameraPose.
centerPoint().
x() );
   227   elemCamera.setAttribute( QStringLiteral( 
"y" ), mCameraPose.
centerPoint().
z() );
   228   elemCamera.setAttribute( QStringLiteral( 
"elev" ), mCameraPose.
centerPoint().
y() );
   230   elemCamera.setAttribute( QStringLiteral( 
"pitch" ), mCameraPose.
pitchAngle() );
   231   elemCamera.setAttribute( QStringLiteral( 
"yaw" ), mCameraPose.
headingAngle() );
   237   float x = elem.attribute( QStringLiteral( 
"x" ) ).toFloat();
   238   float y = elem.attribute( QStringLiteral( 
"y" ) ).toFloat();
   239   float elev = elem.attribute( QStringLiteral( 
"elev" ) ).toFloat();
   240   float dist = elem.attribute( QStringLiteral( 
"dist" ) ).toFloat();
   241   float pitch = elem.attribute( QStringLiteral( 
"pitch" ) ).toFloat();
   242   float yaw = elem.attribute( QStringLiteral( 
"yaw" ) ).toFloat();
   246 void QgsCameraController::updateCameraFromPose( 
bool centerPointChanged )
   251     qDebug() << 
"camera position got NaN!";
   265   if ( mCamera && mTerrainEntity && centerPointChanged )
   269     QVector3D intersectionPoint;
   270     QgsRayCastingUtils::Ray3D ray = QgsRayCastingUtils::rayForCameraCenter( mCamera );
   271     if ( mTerrainEntity->rayIntersection( ray, intersectionPoint ) )
   273       float dist = ( intersectionPoint - mCamera->position() ).length();
   283 void QgsCameraController::onPositionChanged( Qt3DInput::QMouseEvent *mouse )
   285   int dx = mouse->x() - mMousePos.x();
   286   int dy = mouse->y() - mMousePos.y();
   288   bool hasShift = ( mouse->modifiers() & Qt::ShiftModifier );
   289   bool hasCtrl = ( mouse->modifiers() & Qt::ControlModifier );
   290   bool hasLeftButton = ( mouse->buttons() & Qt::LeftButton );
   291   bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
   292   bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
   294   if ( ( hasLeftButton && hasShift && !hasCtrl ) || ( hasMiddleButton && !hasShift && !hasCtrl ) )
   303     updateCameraFromPose();
   305   else if ( hasLeftButton && hasCtrl && !hasShift )
   308     float diffPitch = 0.2f * dy;
   309     float diffYaw = 0.2f * -dx / 2;
   310     rotateCamera( diffPitch, diffYaw );
   311     updateCameraFromPose( 
true );
   313   else if ( hasLeftButton && !hasShift && !hasCtrl )
   319     float z = mLastPressedHeight;
   324     center.
set( center.
x() - ( p2.x() - p1.x() ), center.
y(), center.
z() - ( p2.y() - p1.y() ) );
   326     updateCameraFromPose( 
true );
   328   else if ( hasRightButton && !hasShift && !hasCtrl )
   333   mMousePos = QPoint( mouse->x(), mouse->y() );
   340   dist -= dist * factor * 0.01f;
   342   updateCameraFromPose();
   345 void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel )
   347   float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) ? 0.1f : 1.0f ) / 1000.f;
   349   dist -= dist * scaling * wheel->angleDelta().y();
   351   updateCameraFromPose();
   354 void QgsCameraController::onMousePressed( Qt3DInput::QMouseEvent *mouse )
   357   mKeyboardHandler->setFocus( 
true );
   360 void QgsCameraController::onMouseReleased( Qt3DInput::QMouseEvent *mouse )
   365 void QgsCameraController::onKeyPressed( Qt3DInput::QKeyEvent *event )
   367   bool hasShift = ( 
event->modifiers() & Qt::ShiftModifier );
   368   bool hasCtrl = ( 
event->modifiers() & Qt::ControlModifier );
   370   int tx = 0, ty = 0, tElev = 0;
   371   switch ( event->key() )
   387     case Qt::Key_PageDown:
   397     if ( !hasShift && !hasCtrl )
   401     else if ( hasShift && !hasCtrl )
   407     else if ( hasCtrl && !hasShift )
   410       float diffPitch = ty;   
   412       rotateCamera( diffPitch, diffYaw );
   413       updateCameraFromPose( 
true );
   420     center.
set( center.
x(), center.
y() + tElev * 10, center.
z() );
   422     updateCameraFromPose( 
true );
   426 void QgsCameraController::onKeyReleased( Qt3DInput::QKeyEvent *event )
   431 void QgsCameraController::onPickerMousePressed( Qt3DRender::QPickEvent *pick )
   433   mLastPressedHeight = pick->worldIntersection().y();
   442   updateCameraFromPose();
   451   updateCameraFromPose();
   452   qInfo() << 
"Delta yaw: " << deltaYaw;
   453   qInfo() << 
"Yaw: " << 
yaw;
   459   updateCameraFromPose();
   466   float x = tx * dist * 0.02f;
   467   float y = -ty * dist * 0.02f;
   470   float t = sqrt( x * x + y * y );
   471   float a = atan2( y, x ) - yaw * M_PI / 180;
   472   float dx = cos( a ) * t;
   473   float dy = sin( a ) * t;
   476   center.
set( center.
x() + dx, center.
y(), center.
z() + dy );
   478   updateCameraFromPose( 
true );
 3 Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double preci...
 
void cameraChanged()
Emitted when camera has been updated. 
 
QgsCameraController(Qt3DCore::QNode *parent=nullptr)
Constructs the camera controller with optional parent node that will take ownership. 
 
Qt3DRender::QCamera * camera() const
Returns camera that is being controlled. 
 
void frameTriggered(float dt)
Called internally from 3D scene when a new frame is generated. Updates camera according to keyboard/m...
 
void setCameraHeadingAngle(float angle)
Set camera heading to angle (used for rotating the view) 
 
float pitch() const
Returns pitch angle in degrees (0 = looking from the top, 90 = looking from the side). 
 
void tiltUpAroundViewCenter(float deltaPitch)
Tilt up the view by deltaPitch around the view center (camera moves) 
 
void setViewport(QRect viewport)
Sets viewport rectangle. Called internally from 3D canvas. Allows conversion of mouse coordinates...
 
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference) 
 
QgsVector3D centerPoint() const
Returns center point (towards which point the camera is looking) 
 
QRect viewport() const
Returns viewport rectangle. 
 
void resetView(float distance)
Move camera back to the initial position (looking down towards origin of world's coordinates) ...
 
double y() const
Returns Y coordinate. 
 
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) 
 
void set(double x, double y, double z)
Sets vector coordinates. 
 
3 Class that encapsulates camera pose in a 3D scene. 
 
float yaw() const
Returns yaw angle in degrees. 
 
double z() const
Returns Z coordinate. 
 
float find_x_on_line(float x0, float y0, float x1, float y1, float y)
 
void viewportChanged()
Emitted when viewport rectangle has been updated. 
 
void setPitchAngle(float pitch)
Sets pitch angle in degrees. 
 
float distanceFromCenterPoint() const
Returns distance of the camera from the center point. 
 
void readXml(const QDomElement &elem)
Reads camera configuration from the given DOM element. 
 
float headingAngle() const
Returns heading (yaw) angle in degrees. 
 
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...
 
QDomElement writeXml(QDomDocument &doc) const
Writes camera configuration to the given DOM element. 
 
void setCamera(Qt3DRender::QCamera *camera)
Assigns camera that should be controlled by this class. Called internally from 3D scene...
 
void updateCamera(Qt3DRender::QCamera *camera)
Update Qt3D camera view matrix based on the pose. 
 
QgsVector3D lookingAtPoint() const
Returns the point in the world coordinates towards which the camera is looking. 
 
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 moveView(float tx, float ty)
Move the map by tx and ty. 
 
void setHeadingAngle(float heading)
Sets heading (yaw) angle in degrees. 
 
QPointF screen_point_to_point_on_plane(QPointF pt, QRect viewport, Qt3DRender::QCamera *camera, float y)
 
void setCenterPoint(const QgsVector3D &point)
Sets center point (towards which point the camera is looking) 
 
float pitchAngle() const
Returns pitch angle in degrees. 
 
void setDistanceFromCenterPoint(float distance)
Sets distance of the camera from the center point. 
 
void setTerrainEntity(QgsTerrainEntity *te)
Connects to object picker attached to terrain entity. 
 
void setCameraPose(const QgsCameraPose &camPose)
Sets camera pose. 
 
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)...
 
float distance() const
Returns distance of the camera from the point it is looking at. 
 
double x() const
Returns X coordinate.