|
27 | 27 | #include <Qt3DRender/QCamera>
|
28 | 28 | #include <Qt3DInput>
|
29 | 29 | #include <QStringLiteral>
|
| 30 | +#include <QQuaternion> |
30 | 31 | #include <cmath>
|
31 | 32 |
|
32 | 33 | #include "qgslogger.h"
|
@@ -104,30 +105,53 @@ void QgsCameraController::setVerticalAxisInversion( Qgis::VerticalAxisInversion
|
104 | 105 |
|
105 | 106 | void QgsCameraController::rotateCamera( float diffPitch, float diffHeading )
|
106 | 107 | {
|
107 |
| - const float oldPitch = mCameraPose.pitchAngle(); |
108 |
| - const float oldHeading = mCameraPose.headingAngle(); |
109 |
| - float newPitch = oldPitch + diffPitch; |
110 |
| - float newHeading = oldHeading + diffHeading; |
| 108 | + float newPitch = mCameraPose.pitchAngle() + diffPitch; |
| 109 | + float newHeading = mCameraPose.headingAngle() + diffHeading; |
111 | 110 |
|
112 | 111 | newPitch = std::clamp( newPitch, 0.f, 180.f ); // prevent going over the head
|
113 | 112 |
|
114 |
| - // First undo the previously applied rotation, then apply the new rotation |
115 |
| - // (We can't just apply our euler angles difference because the camera may be already rotated) |
116 |
| - const QQuaternion qNew = Qgs3DUtils::rotationFromPitchHeadingAngles( newPitch, newHeading ); |
117 |
| - const QQuaternion qOld = Qgs3DUtils::rotationFromPitchHeadingAngles( oldPitch, oldHeading ); |
118 |
| - const QQuaternion q = qNew * qOld.conjugated(); |
119 |
| - |
120 |
| - // get camera's view vector, rotate it to get new view center |
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; |
| 113 | + switch ( mScene->mapSettings()->sceneMode() ) |
| 114 | + { |
| 115 | + case Qgis::SceneMode::Globe: |
| 116 | + { |
| 117 | + // When on a globe, we need to calculate "where is up" (the normal of a tangent plane). |
| 118 | + // Also it uses different axes than the standard plane-based view. |
| 119 | + // See QgsCameraPose::updateCameraGlobe(), we basically want to make sure |
| 120 | + // that after an update, the camera stays in the same spot. |
| 121 | + QgsVector3D viewCenterLatLon; |
| 122 | + try |
| 123 | + { |
| 124 | + viewCenterLatLon = mGlobeCrsToLatLon.transform( mCameraPose.centerPoint() + mOrigin ); |
| 125 | + } |
| 126 | + catch ( const QgsCsException & ) |
| 127 | + { |
| 128 | + QgsDebugError( QStringLiteral( "rotateCamera: ECEF -> lat,lon transform failed!" ) ); |
| 129 | + return; |
| 130 | + } |
| 131 | + QQuaternion qLatLon = QQuaternion::fromAxisAndAngle( QVector3D( 0, 0, 1 ), static_cast<float>( viewCenterLatLon.x() ) ) |
| 132 | + * QQuaternion::fromAxisAndAngle( QVector3D( 0, -1, 0 ), static_cast<float>( viewCenterLatLon.y() ) ); |
| 133 | + QQuaternion qPitchHeading = QQuaternion::fromAxisAndAngle( QVector3D( 1, 0, 0 ), newHeading ) |
| 134 | + * QQuaternion::fromAxisAndAngle( QVector3D( 0, 1, 0 ), newPitch ); |
| 135 | + QVector3D newCameraToCenter = ( qLatLon * qPitchHeading * QVector3D( -1, 0, 0 ) ) * mCameraPose.distanceFromCenterPoint(); |
| 136 | + |
| 137 | + mCameraPose.setCenterPoint( mCamera->position() + newCameraToCenter ); |
| 138 | + mCameraPose.setPitchAngle( newPitch ); |
| 139 | + mCameraPose.setHeadingAngle( newHeading ); |
| 140 | + updateCameraFromPose(); |
| 141 | + return; |
| 142 | + } |
126 | 143 |
|
127 |
| - mCameraPose.setCenterPoint( viewCenter ); |
128 |
| - mCameraPose.setPitchAngle( newPitch ); |
129 |
| - mCameraPose.setHeadingAngle( newHeading ); |
130 |
| - updateCameraFromPose(); |
| 144 | + case Qgis::SceneMode::Local: |
| 145 | + { |
| 146 | + QQuaternion q = Qgs3DUtils::rotationFromPitchHeadingAngles( newPitch, newHeading ); |
| 147 | + QVector3D newCameraToCenter = q * QVector3D( 0, 0, -mCameraPose.distanceFromCenterPoint() ); |
| 148 | + mCameraPose.setCenterPoint( mCamera->position() + newCameraToCenter ); |
| 149 | + mCameraPose.setPitchAngle( newPitch ); |
| 150 | + mCameraPose.setHeadingAngle( newHeading ); |
| 151 | + updateCameraFromPose(); |
| 152 | + return; |
| 153 | + } |
| 154 | + } |
131 | 155 | }
|
132 | 156 |
|
133 | 157 | void QgsCameraController::rotateCameraAroundPivot( float newPitch, float newHeading, const QVector3D &pivotPoint )
|
|
0 commit comments