|
21 | 21 | #include "qgis.h"
|
22 | 22 |
|
23 | 23 | #include <QDomDocument>
|
| 24 | +#include <Qt3DRender/QCamera> |
24 | 25 | #include <Qt3DRender/QObjectPicker>
|
25 | 26 | #include <Qt3DRender/QPickEvent>
|
| 27 | +#include <Qt3DInput> |
26 | 28 |
|
27 | 29 |
|
28 | 30 | QgsCameraController::QgsCameraController( Qt3DCore::QNode *parent )
|
29 | 31 | : Qt3DCore::QEntity( parent )
|
30 | 32 | , mMouseDevice( new Qt3DInput::QMouseDevice() )
|
31 | 33 | , mKeyboardDevice( new Qt3DInput::QKeyboardDevice() )
|
32 | 34 | , mMouseHandler( new Qt3DInput::QMouseHandler )
|
33 |
| - , mLogicalDevice( new Qt3DInput::QLogicalDevice() ) |
34 |
| - , mLeftMouseButtonAction( new Qt3DInput::QAction() ) |
35 |
| - , mLeftMouseButtonInput( new Qt3DInput::QActionInput() ) |
36 |
| - , mMiddleMouseButtonAction( new Qt3DInput::QAction() ) |
37 |
| - , mMiddleMouseButtonInput( new Qt3DInput::QActionInput() ) |
38 |
| - , mRightMouseButtonAction( new Qt3DInput::QAction() ) |
39 |
| - , mRightMouseButtonInput( new Qt3DInput::QActionInput() ) |
40 |
| - , mShiftAction( new Qt3DInput::QAction() ) |
41 |
| - , mShiftInput( new Qt3DInput::QActionInput() ) |
42 |
| - , mCtrlAction( new Qt3DInput::QAction() ) |
43 |
| - , mCtrlInput( new Qt3DInput::QActionInput() ) |
44 |
| - , mWheelAxis( new Qt3DInput::QAxis() ) |
45 |
| - , mMouseWheelInput( new Qt3DInput::QAnalogAxisInput() ) |
46 |
| - , mTxAxis( new Qt3DInput::QAxis() ) |
47 |
| - , mTyAxis( new Qt3DInput::QAxis() ) |
48 |
| - , mKeyboardTxPosInput( new Qt3DInput::QButtonAxisInput() ) |
49 |
| - , mKeyboardTyPosInput( new Qt3DInput::QButtonAxisInput() ) |
50 |
| - , mKeyboardTxNegInput( new Qt3DInput::QButtonAxisInput() ) |
51 |
| - , mKeyboardTyNegInput( new Qt3DInput::QButtonAxisInput() ) |
52 |
| - , mTelevAxis( new Qt3DInput::QAxis() ) |
53 |
| - , mKeyboardTelevPosInput( new Qt3DInput::QButtonAxisInput() ) |
54 |
| - , mKeyboardTelevNegInput( new Qt3DInput::QButtonAxisInput() ) |
| 35 | + , mKeyboardHandler( new Qt3DInput::QKeyboardHandler ) |
55 | 36 | {
|
56 | 37 |
|
57 |
| - // not using QAxis + QAnalogAxisInput for mouse X,Y because |
58 |
| - // it is only in action when a mouse button is pressed. |
59 | 38 | mMouseHandler->setSourceDevice( mMouseDevice );
|
60 | 39 | connect( mMouseHandler, &Qt3DInput::QMouseHandler::positionChanged,
|
61 | 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 ); |
62 | 47 | addComponent( mMouseHandler );
|
63 | 48 |
|
64 |
| - // TODO: keep using QAxis and QAction approach or just switch to using QMouseHandler / QKeyboardHandler? |
65 |
| - // it does not feel like the former approach makes anything much simpler |
66 |
| - |
67 |
| - // left mouse button |
68 |
| - mLeftMouseButtonInput->setButtons( QVector<int>() << Qt::LeftButton ); |
69 |
| - mLeftMouseButtonInput->setSourceDevice( mMouseDevice ); |
70 |
| - mLeftMouseButtonAction->addInput( mLeftMouseButtonInput ); |
71 |
| - |
72 |
| - // middle mouse button |
73 |
| - mMiddleMouseButtonInput->setButtons( QVector<int>() << Qt::MiddleButton ); |
74 |
| - mMiddleMouseButtonInput->setSourceDevice( mMouseDevice ); |
75 |
| - mMiddleMouseButtonAction->addInput( mMiddleMouseButtonInput ); |
76 |
| - |
77 |
| - // right mouse button |
78 |
| - mRightMouseButtonInput->setButtons( QVector<int>() << Qt::RightButton ); |
79 |
| - mRightMouseButtonInput->setSourceDevice( mMouseDevice ); |
80 |
| - mRightMouseButtonAction->addInput( mRightMouseButtonInput ); |
81 |
| - |
82 |
| - // Mouse Wheel (Y) |
83 |
| - mMouseWheelInput->setAxis( Qt3DInput::QMouseDevice::WheelY ); |
84 |
| - mMouseWheelInput->setSourceDevice( mMouseDevice ); |
85 |
| - mWheelAxis->addInput( mMouseWheelInput ); |
86 |
| - |
87 |
| - // Keyboard shift |
88 |
| - mShiftInput->setButtons( QVector<int>() << Qt::Key_Shift ); |
89 |
| - mShiftInput->setSourceDevice( mKeyboardDevice ); |
90 |
| - mShiftAction->addInput( mShiftInput ); |
91 |
| - |
92 |
| - // Keyboard ctrl |
93 |
| - mCtrlInput->setButtons( QVector<int>() << Qt::Key_Control ); |
94 |
| - mCtrlInput->setSourceDevice( mKeyboardDevice ); |
95 |
| - mCtrlAction->addInput( mCtrlInput ); |
96 |
| - |
97 |
| - // Keyboard Pos Tx |
98 |
| - mKeyboardTxPosInput->setButtons( QVector<int>() << Qt::Key_Right ); |
99 |
| - mKeyboardTxPosInput->setScale( 1.0f ); |
100 |
| - mKeyboardTxPosInput->setSourceDevice( mKeyboardDevice ); |
101 |
| - mTxAxis->addInput( mKeyboardTxPosInput ); |
102 |
| - |
103 |
| - // Keyboard Pos Ty |
104 |
| - mKeyboardTyPosInput->setButtons( QVector<int>() << Qt::Key_Up ); |
105 |
| - mKeyboardTyPosInput->setScale( 1.0f ); |
106 |
| - mKeyboardTyPosInput->setSourceDevice( mKeyboardDevice ); |
107 |
| - mTyAxis->addInput( mKeyboardTyPosInput ); |
108 |
| - |
109 |
| - // Keyboard Neg Tx |
110 |
| - mKeyboardTxNegInput->setButtons( QVector<int>() << Qt::Key_Left ); |
111 |
| - mKeyboardTxNegInput->setScale( -1.0f ); |
112 |
| - mKeyboardTxNegInput->setSourceDevice( mKeyboardDevice ); |
113 |
| - mTxAxis->addInput( mKeyboardTxNegInput ); |
114 |
| - |
115 |
| - // Keyboard Neg Ty |
116 |
| - mKeyboardTyNegInput->setButtons( QVector<int>() << Qt::Key_Down ); |
117 |
| - mKeyboardTyNegInput->setScale( -1.0f ); |
118 |
| - mKeyboardTyNegInput->setSourceDevice( mKeyboardDevice ); |
119 |
| - mTyAxis->addInput( mKeyboardTyNegInput ); |
120 |
| - |
121 |
| - // Keyboard Neg Telev |
122 |
| - mKeyboardTelevNegInput->setButtons( QVector<int>() << Qt::Key_PageDown ); |
123 |
| - mKeyboardTelevNegInput->setScale( -1.0f ); |
124 |
| - mKeyboardTelevNegInput->setSourceDevice( mKeyboardDevice ); |
125 |
| - mTelevAxis->addInput( mKeyboardTelevNegInput ); |
126 |
| - |
127 |
| - // Keyboard Pos Telev |
128 |
| - mKeyboardTelevPosInput->setButtons( QVector<int>() << Qt::Key_PageUp ); |
129 |
| - mKeyboardTelevPosInput->setScale( 1.0f ); |
130 |
| - mKeyboardTelevPosInput->setSourceDevice( mKeyboardDevice ); |
131 |
| - mTelevAxis->addInput( mKeyboardTelevPosInput ); |
132 |
| - |
133 |
| - mLogicalDevice->addAction( mLeftMouseButtonAction ); |
134 |
| - mLogicalDevice->addAction( mMiddleMouseButtonAction ); |
135 |
| - mLogicalDevice->addAction( mRightMouseButtonAction ); |
136 |
| - mLogicalDevice->addAction( mShiftAction ); |
137 |
| - mLogicalDevice->addAction( mCtrlAction ); |
138 |
| - mLogicalDevice->addAxis( mWheelAxis ); |
139 |
| - mLogicalDevice->addAxis( mTxAxis ); |
140 |
| - mLogicalDevice->addAxis( mTyAxis ); |
141 |
| - mLogicalDevice->addAxis( mTelevAxis ); |
142 |
| - |
143 |
| - // Disable the logical device when the entity is disabled |
144 |
| - connect( this, &Qt3DCore::QEntity::enabledChanged, |
145 |
| - mLogicalDevice, &Qt3DInput::QLogicalDevice::setEnabled ); |
| 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 ); |
146 | 55 |
|
147 |
| - addComponent( mLogicalDevice ); |
| 56 | + // Disable the handlers when the entity is disabled |
| 57 | + connect( this, &Qt3DCore::QEntity::enabledChanged, |
| 58 | + mMouseHandler, &Qt3DInput::QMouseHandler::setEnabled ); |
| 59 | + connect( this, &Qt3DCore::QEntity::enabledChanged, |
| 60 | + mKeyboardHandler, &Qt3DInput::QMouseHandler::setEnabled ); |
148 | 61 | }
|
149 | 62 |
|
150 | 63 | void QgsCameraController::setTerrainEntity( QgsTerrainEntity *te )
|
@@ -257,130 +170,7 @@ void QgsCameraController::rotateCamera( float diffPitch, float diffYaw )
|
257 | 170 |
|
258 | 171 | void QgsCameraController::frameTriggered( float dt )
|
259 | 172 | {
|
260 |
| - if ( mCamera == nullptr ) |
261 |
| - return; |
262 |
| - |
263 |
| - QgsCameraPose oldCamPose = mCameraPose; |
264 |
| - float dist = mCameraPose.distanceFromCenterPoint(); |
265 |
| - float yaw = mCameraPose.headingAngle(); |
266 |
| - float pitch = mCameraPose.pitchAngle(); |
267 |
| - QgsVector3D center = mCameraPose.centerPoint(); |
268 |
| - |
269 |
| - int dx = mMousePos.x() - mLastMousePos.x(); |
270 |
| - int dy = mMousePos.y() - mLastMousePos.y(); |
271 |
| - mLastMousePos = mMousePos; |
272 |
| - |
273 |
| - double scaling = ( mCtrlAction->isActive() ? 0.1 : 1.0 ); |
274 |
| - dist -= scaling * dist * mWheelAxis->value() * 10 * dt; |
275 |
| - |
276 |
| - if ( mRightMouseButtonAction->isActive() ) |
277 |
| - { |
278 |
| - dist -= dist * dy * 0.01; |
279 |
| - } |
280 |
| - |
281 |
| - float tx = mTxAxis->value() * dt * dist * 1.5; |
282 |
| - float ty = -mTyAxis->value() * dt * dist * 1.5; |
283 |
| - float telev = mTelevAxis->value() * dt * 300; |
284 |
| - |
285 |
| - mCameraPose.setDistanceFromCenterPoint( dist ); |
286 |
| - |
287 |
| - if ( !mShiftAction->isActive() && !mCtrlAction->isActive() && ( tx || ty ) ) |
288 |
| - { |
289 |
| - // moving with keyboard - take into account yaw of camera |
290 |
| - float t = sqrt( tx * tx + ty * ty ); |
291 |
| - float a = atan2( ty, tx ) - yaw * M_PI / 180; |
292 |
| - float dx = cos( a ) * t; |
293 |
| - float dy = sin( a ) * t; |
294 |
| - center.set( center.x() + dx, center.y(), center.z() + dy ); |
295 |
| - mCameraPose.setCenterPoint( center ); |
296 |
| - } |
297 |
| - |
298 |
| - if ( ( mLeftMouseButtonAction->isActive() && mShiftAction->isActive() ) || mMiddleMouseButtonAction->isActive() ) |
299 |
| - { |
300 |
| - // rotate/tilt using mouse (camera moves as it rotates around its view center) |
301 |
| - pitch += dy; |
302 |
| - yaw -= dx / 2; |
303 |
| - mCameraPose.setPitchAngle( pitch ); |
304 |
| - mCameraPose.setHeadingAngle( yaw ); |
305 |
| - } |
306 |
| - else if ( mShiftAction->isActive() && ( mTxAxis->value() || mTyAxis->value() ) ) |
307 |
| - { |
308 |
| - // rotate/tilt using keyboard (camera moves as it rotates around its view center) |
309 |
| - pitch -= mTyAxis->value(); // down key = moving camera toward terrain |
310 |
| - yaw -= mTxAxis->value(); // right key = moving camera clockwise |
311 |
| - mCameraPose.setPitchAngle( pitch ); |
312 |
| - mCameraPose.setHeadingAngle( yaw ); |
313 |
| - } |
314 |
| - else if ( mCtrlAction->isActive() && mLeftMouseButtonAction->isActive() ) |
315 |
| - { |
316 |
| - // rotate/tilt using mouse (camera stays at one position as it rotates) |
317 |
| - float diffPitch = 0.2 * dy; |
318 |
| - float diffYaw = 0.2 * -dx / 2; |
319 |
| - rotateCamera( diffPitch, diffYaw ); |
320 |
| - } |
321 |
| - else if ( mCtrlAction->isActive() && ( mTxAxis->value() || mTyAxis->value() ) ) |
322 |
| - { |
323 |
| - // rotate/tilt using keyboard (camera stays at one position as it rotates) |
324 |
| - float diffPitch = mTyAxis->value(); // down key = rotating camera down |
325 |
| - float diffYaw = -mTxAxis->value(); // right key = rotating camera to the right |
326 |
| - rotateCamera( diffPitch, diffYaw ); |
327 |
| - } |
328 |
| - else if ( mLeftMouseButtonAction->isActive() && !mShiftAction->isActive() ) |
329 |
| - { |
330 |
| - // translation works as if one grabbed a point on the plane and dragged it |
331 |
| - // i.e. find out x,z of the previous mouse point, find out x,z of the current mouse point |
332 |
| - // and use the difference |
333 |
| - |
334 |
| - float z = mLastPressedHeight; |
335 |
| - QPointF p1 = screen_point_to_point_on_plane( QPointF( mMousePos - QPoint( dx, dy ) ), mViewport, mCamera, z ); |
336 |
| - QPointF p2 = screen_point_to_point_on_plane( QPointF( mMousePos ), mViewport, mCamera, z ); |
337 |
| - |
338 |
| - center.set( center.x() - ( p2.x() - p1.x() ), center.y(), center.z() - ( p2.y() - p1.y() ) ); |
339 |
| - mCameraPose.setCenterPoint( center ); |
340 |
| - } |
341 |
| - |
342 |
| - if ( telev != 0 ) |
343 |
| - { |
344 |
| - center.set( center.x(), center.y() + telev, center.z() ); |
345 |
| - mCameraPose.setCenterPoint( center ); |
346 |
| - } |
347 |
| - |
348 |
| - if ( std::isnan( mCameraPose.centerPoint().x() ) || std::isnan( mCameraPose.centerPoint().y() ) || std::isnan( mCameraPose.centerPoint().z() ) ) |
349 |
| - { |
350 |
| - // something went horribly wrong but we need to at least try to fix it somehow |
351 |
| - qDebug() << "camera position got NaN!"; |
352 |
| - center.set( 0, 0, 0 ); |
353 |
| - mCameraPose.setCenterPoint( center ); |
354 |
| - } |
355 |
| - |
356 |
| - if ( mCameraPose.pitchAngle() > 180 ) |
357 |
| - mCameraPose.setPitchAngle( 180 ); // prevent going over the head |
358 |
| - if ( mCameraPose.pitchAngle() < 0 ) |
359 |
| - mCameraPose.setPitchAngle( 0 ); // prevent going over the head |
360 |
| - if ( mCameraPose.distanceFromCenterPoint() < 10 ) |
361 |
| - mCameraPose.setDistanceFromCenterPoint( 10 ); |
362 |
| - |
363 |
| - if ( mCameraPose != oldCamPose ) |
364 |
| - { |
365 |
| - mCameraPose.updateCamera( mCamera ); |
366 |
| - |
367 |
| - if ( mTerrainEntity && mCameraPose.centerPoint() != oldCamPose.centerPoint() ) |
368 |
| - { |
369 |
| - // figure out our distance from terrain and update the camera's view center |
370 |
| - // so that camera tilting and rotation is around a point on terrain, not an point at fixed elevation |
371 |
| - QVector3D intersectionPoint; |
372 |
| - QgsRayCastingUtils::Ray3D ray = QgsRayCastingUtils::rayForCameraCenter( mCamera ); |
373 |
| - if ( mTerrainEntity->rayIntersection( ray, intersectionPoint ) ) |
374 |
| - { |
375 |
| - float dist = ( intersectionPoint - mCamera->position() ).length(); |
376 |
| - mCameraPose.setDistanceFromCenterPoint( dist ); |
377 |
| - mCameraPose.setCenterPoint( QgsVector3D( intersectionPoint ) ); |
378 |
| - mCameraPose.updateCamera( mCamera ); |
379 |
| - } |
380 |
| - } |
381 |
| - |
382 |
| - emit cameraChanged(); |
383 |
| - } |
| 173 | + Q_UNUSED( dt ); |
384 | 174 | }
|
385 | 175 |
|
386 | 176 | void QgsCameraController::resetView( float distance )
|
@@ -453,11 +243,205 @@ void QgsCameraController::readXml( const QDomElement &elem )
|
453 | 243 | setLookingAtPoint( QgsVector3D( x, elev, y ), dist, pitch, yaw );
|
454 | 244 | }
|
455 | 245 |
|
| 246 | +void QgsCameraController::updateCameraFromPose( bool centerPointChanged ) |
| 247 | +{ |
| 248 | + if ( std::isnan( mCameraPose.centerPoint().x() ) || std::isnan( mCameraPose.centerPoint().y() ) || std::isnan( mCameraPose.centerPoint().z() ) ) |
| 249 | + { |
| 250 | + // something went horribly wrong but we need to at least try to fix it somehow |
| 251 | + qDebug() << "camera position got NaN!"; |
| 252 | + mCameraPose.setCenterPoint( QgsVector3D( 0, 0, 0 ) ); |
| 253 | + } |
| 254 | + |
| 255 | + if ( mCameraPose.pitchAngle() > 180 ) |
| 256 | + mCameraPose.setPitchAngle( 180 ); // prevent going over the head |
| 257 | + if ( mCameraPose.pitchAngle() < 0 ) |
| 258 | + mCameraPose.setPitchAngle( 0 ); // prevent going over the head |
| 259 | + if ( mCameraPose.distanceFromCenterPoint() < 10 ) |
| 260 | + mCameraPose.setDistanceFromCenterPoint( 10 ); |
| 261 | + |
| 262 | + if ( mCamera ) |
| 263 | + mCameraPose.updateCamera( mCamera ); |
| 264 | + |
| 265 | + if ( mCamera && mTerrainEntity && centerPointChanged ) |
| 266 | + { |
| 267 | + // figure out our distance from terrain and update the camera's view center |
| 268 | + // so that camera tilting and rotation is around a point on terrain, not an point at fixed elevation |
| 269 | + QVector3D intersectionPoint; |
| 270 | + QgsRayCastingUtils::Ray3D ray = QgsRayCastingUtils::rayForCameraCenter( mCamera ); |
| 271 | + if ( mTerrainEntity->rayIntersection( ray, intersectionPoint ) ) |
| 272 | + { |
| 273 | + float dist = ( intersectionPoint - mCamera->position() ).length(); |
| 274 | + mCameraPose.setDistanceFromCenterPoint( dist ); |
| 275 | + mCameraPose.setCenterPoint( QgsVector3D( intersectionPoint ) ); |
| 276 | + mCameraPose.updateCamera( mCamera ); |
| 277 | + } |
| 278 | + } |
| 279 | + |
| 280 | + emit cameraChanged(); |
| 281 | +} |
| 282 | + |
456 | 283 | void QgsCameraController::onPositionChanged( Qt3DInput::QMouseEvent *mouse )
|
457 | 284 | {
|
| 285 | + int dx = mouse->x() - mMousePos.x(); |
| 286 | + int dy = mouse->y() - mMousePos.y(); |
| 287 | + |
| 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 ); |
| 293 | + |
| 294 | + if ( ( hasLeftButton && hasShift && !hasCtrl ) || ( hasMiddleButton && !hasShift && !hasCtrl ) ) |
| 295 | + { |
| 296 | + // rotate/tilt using mouse (camera moves as it rotates around its view center) |
| 297 | + float pitch = mCameraPose.pitchAngle(); |
| 298 | + float yaw = mCameraPose.headingAngle(); |
| 299 | + pitch += dy; |
| 300 | + yaw -= dx / 2; |
| 301 | + mCameraPose.setPitchAngle( pitch ); |
| 302 | + mCameraPose.setHeadingAngle( yaw ); |
| 303 | + updateCameraFromPose(); |
| 304 | + } |
| 305 | + else if ( hasLeftButton && hasCtrl && !hasShift ) |
| 306 | + { |
| 307 | + // rotate/tilt using mouse (camera stays at one position as it rotates) |
| 308 | + float diffPitch = 0.2f * dy; |
| 309 | + float diffYaw = 0.2f * -dx / 2; |
| 310 | + rotateCamera( diffPitch, diffYaw ); |
| 311 | + updateCameraFromPose( true ); |
| 312 | + } |
| 313 | + else if ( hasLeftButton && !hasShift && !hasCtrl ) |
| 314 | + { |
| 315 | + // translation works as if one grabbed a point on the plane and dragged it |
| 316 | + // i.e. find out x,z of the previous mouse point, find out x,z of the current mouse point |
| 317 | + // and use the difference |
| 318 | + |
| 319 | + float z = mLastPressedHeight; |
| 320 | + QPointF p1 = screen_point_to_point_on_plane( QPointF( mMousePos.x(), mMousePos.y() ), mViewport, mCamera, z ); |
| 321 | + QPointF p2 = screen_point_to_point_on_plane( QPointF( mouse->x(), mouse->y() ), mViewport, mCamera, z ); |
| 322 | + |
| 323 | + QgsVector3D center = mCameraPose.centerPoint(); |
| 324 | + center.set( center.x() - ( p2.x() - p1.x() ), center.y(), center.z() - ( p2.y() - p1.y() ) ); |
| 325 | + mCameraPose.setCenterPoint( center ); |
| 326 | + updateCameraFromPose( true ); |
| 327 | + } |
| 328 | + else if ( hasRightButton && !hasShift && !hasCtrl ) |
| 329 | + { |
| 330 | + // zoom in/out |
| 331 | + float dist = mCameraPose.distanceFromCenterPoint(); |
| 332 | + dist -= dist * dy * 0.01f; |
| 333 | + mCameraPose.setDistanceFromCenterPoint( dist ); |
| 334 | + updateCameraFromPose(); |
| 335 | + } |
| 336 | + |
458 | 337 | mMousePos = QPoint( mouse->x(), mouse->y() );
|
459 | 338 | }
|
460 | 339 |
|
| 340 | +void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel ) |
| 341 | +{ |
| 342 | + float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) ? 0.1f : 1.0f ) / 1000.f; |
| 343 | + float dist = mCameraPose.distanceFromCenterPoint(); |
| 344 | + dist -= dist * scaling * wheel->angleDelta().y(); |
| 345 | + mCameraPose.setDistanceFromCenterPoint( dist ); |
| 346 | + updateCameraFromPose(); |
| 347 | +} |
| 348 | + |
| 349 | +void QgsCameraController::onMousePressed( Qt3DInput::QMouseEvent *mouse ) |
| 350 | +{ |
| 351 | + Q_UNUSED( mouse ); |
| 352 | + mKeyboardHandler->setFocus( true ); |
| 353 | +} |
| 354 | + |
| 355 | +void QgsCameraController::onMouseReleased( Qt3DInput::QMouseEvent *mouse ) |
| 356 | +{ |
| 357 | + Q_UNUSED( mouse ); |
| 358 | +} |
| 359 | + |
| 360 | +void QgsCameraController::onKeyPressed( Qt3DInput::QKeyEvent *event ) |
| 361 | +{ |
| 362 | + bool hasShift = ( event->modifiers() & Qt::ShiftModifier ); |
| 363 | + bool hasCtrl = ( event->modifiers() & Qt::ControlModifier ); |
| 364 | + |
| 365 | + int tx = 0, ty = 0, tElev = 0; |
| 366 | + switch ( event->key() ) |
| 367 | + { |
| 368 | + case Qt::Key_Left: |
| 369 | + tx -= 1; |
| 370 | + break; |
| 371 | + case Qt::Key_Right: |
| 372 | + tx += 1; |
| 373 | + break; |
| 374 | + |
| 375 | + case Qt::Key_Up: |
| 376 | + ty += 1; |
| 377 | + break; |
| 378 | + case Qt::Key_Down: |
| 379 | + ty -= 1; |
| 380 | + break; |
| 381 | + |
| 382 | + case Qt::Key_PageDown: |
| 383 | + tElev -= 1; |
| 384 | + break; |
| 385 | + case Qt::Key_PageUp: |
| 386 | + tElev += 1; |
| 387 | + break; |
| 388 | + } |
| 389 | + |
| 390 | + if ( tx || ty ) |
| 391 | + { |
| 392 | + if ( !hasShift && !hasCtrl ) |
| 393 | + { |
| 394 | + float yaw = mCameraPose.headingAngle(); |
| 395 | + float dist = mCameraPose.distanceFromCenterPoint(); |
| 396 | + float x = tx * dist * 0.02f; |
| 397 | + float y = -ty * dist * 0.02f; |
| 398 | + |
| 399 | + // moving with keyboard - take into account yaw of camera |
| 400 | + float t = sqrt( x * x + y * y ); |
| 401 | + float a = atan2( y, x ) - yaw * M_PI / 180; |
| 402 | + float dx = cos( a ) * t; |
| 403 | + float dy = sin( a ) * t; |
| 404 | + |
| 405 | + QgsVector3D center = mCameraPose.centerPoint(); |
| 406 | + center.set( center.x() + dx, center.y(), center.z() + dy ); |
| 407 | + mCameraPose.setCenterPoint( center ); |
| 408 | + updateCameraFromPose( true ); |
| 409 | + } |
| 410 | + else if ( hasShift && !hasCtrl ) |
| 411 | + { |
| 412 | + // rotate/tilt using keyboard (camera moves as it rotates around its view center) |
| 413 | + float pitch = mCameraPose.pitchAngle(); |
| 414 | + float yaw = mCameraPose.headingAngle(); |
| 415 | + pitch -= ty; // down key = moving camera toward terrain |
| 416 | + yaw -= tx; // right key = moving camera clockwise |
| 417 | + mCameraPose.setPitchAngle( pitch ); |
| 418 | + mCameraPose.setHeadingAngle( yaw ); |
| 419 | + updateCameraFromPose(); |
| 420 | + } |
| 421 | + else if ( hasCtrl && !hasShift ) |
| 422 | + { |
| 423 | + // rotate/tilt using keyboard (camera stays at one position as it rotates) |
| 424 | + float diffPitch = ty; // down key = rotating camera down |
| 425 | + float diffYaw = -tx; // right key = rotating camera to the right |
| 426 | + rotateCamera( diffPitch, diffYaw ); |
| 427 | + updateCameraFromPose( true ); |
| 428 | + } |
| 429 | + } |
| 430 | + |
| 431 | + if ( tElev ) |
| 432 | + { |
| 433 | + QgsVector3D center = mCameraPose.centerPoint(); |
| 434 | + center.set( center.x(), center.y() + tElev * 10, center.z() ); |
| 435 | + mCameraPose.setCenterPoint( center ); |
| 436 | + updateCameraFromPose( true ); |
| 437 | + } |
| 438 | +} |
| 439 | + |
| 440 | +void QgsCameraController::onKeyReleased( Qt3DInput::QKeyEvent *event ) |
| 441 | +{ |
| 442 | + Q_UNUSED( event ); |
| 443 | +} |
| 444 | + |
461 | 445 | void QgsCameraController::onPickerMousePressed( Qt3DRender::QPickEvent *pick )
|
462 | 446 | {
|
463 | 447 | mLastPressedHeight = pick->worldIntersection().y();
|
|
0 commit comments