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 );
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 );