diff options
author | Paolo Angelelli <paolo.angelelli.qt@gmail.com> | 2019-11-27 15:37:07 +0100 |
---|---|---|
committer | paolo <paolo.angelelli.qt@gmail.com> | 2020-02-11 11:46:08 +0100 |
commit | d055098540df99a5d426360e9322c659e678e5ee (patch) | |
tree | e7e43a057b7e06814e2ef11eeddc52a4aac06cdb /src/location/maps | |
parent | 614d67be158e3ef8443c1b7f3126303cfcf4becc (diff) | |
download | qtlocation-d055098540df99a5d426360e9322c659e678e5ee.tar.gz |
Enable mercator-to-screen projection in GLSL
With this change, all the geo-to-screen conversion,
and the triangulation operations for geo polylines
and geo polygon are performed either at set time
or in the shader.
A separate bounding box geometry is processed
in the old way to provide a correct QtQuick Item
geometry, that can be used for nesting mouse areas,
performing translations, input event delivery, etc.
With this approach, performance are improved by more
than one order of magnitude in average, but complex
geometries will of course benefit more.
It also adds correct rendering support for polygons
with holes, previously only rendered correctly
by the MapboxGL plugin.
The polyline shader has basic miter joins. The miter is
skipped if the angle is too sharp to avoid complicating
the implementation.
This shader introduces some glitches when the polyline
is minified, for which the real fix is to
have LOD for the geometry, and render simplified
geometries at low zoom levels (added in a subsequent patch).
Note: this approach, at least in its current implementation,
does not support enabling layers on individual items, only
on the Map element.
Task-number: QTBUG-49303
Task-number: QTBUG-38459
Change-Id: I0c2dc0bf364d32f74ca7c4014f6d66e6219c8ae4
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'src/location/maps')
-rw-r--r-- | src/location/maps/qgeomap.cpp | 7 | ||||
-rw-r--r-- | src/location/maps/qgeomap_p.h | 3 | ||||
-rw-r--r-- | src/location/maps/qgeoprojection.cpp | 72 | ||||
-rw-r--r-- | src/location/maps/qgeoprojection_p.h | 25 | ||||
-rw-r--r-- | src/location/maps/qgeotiledmap.cpp | 4 |
5 files changed, 100 insertions, 11 deletions
diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp index dc8aa2c8..51af9199 100644 --- a/src/location/maps/qgeomap.cpp +++ b/src/location/maps/qgeomap.cpp @@ -41,6 +41,7 @@ #include "qdeclarativegeomapitembase_p.h" #include "qgeomapobject_p.h" #include "qgeomapobject_p_p.h" +#include <QtQuick/private/qquickitem_p.h> #include <QDebug> #include <QRectF> @@ -310,6 +311,12 @@ QList<QObject *> QGeoMap::mapObjectsAt(const QGeoCoordinate &/*coordinate*/) con return QList<QObject *>(); } +void QGeoMap::setItemToWindowTransform(const QTransform &itemToWindowTransform) +{ + Q_D(QGeoMap); + d->m_geoProjection->setItemToWindowTransform(itemToWindowTransform); +} + void QGeoMap::setVisibleArea(const QRectF &visibleArea) { Q_D(QGeoMap); diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h index 216c8b64..e955b513 100644 --- a/src/location/maps/qgeomap_p.h +++ b/src/location/maps/qgeomap_p.h @@ -55,6 +55,7 @@ #include <QtPositioning/private/qdoublevector2d_p.h> #include <QtLocation/private/qgeoprojection_p.h> #include <QtLocation/qgeoroute.h> +#include <QTransform> QT_BEGIN_NAMESPACE @@ -67,6 +68,7 @@ class QQuickWindow; class QGeoMapParameter; class QDeclarativeGeoMapItemBase; class QGeoMapObject; +class QDeclarativeGeoMap; class Q_LOCATION_PRIVATE_EXPORT QGeoMap : public QObject { @@ -155,6 +157,7 @@ public: virtual void setCopyrightVisible(bool visible); virtual void removeMapObject(QGeoMapObject *obj); virtual QList<QObject *> mapObjectsAt(const QGeoCoordinate &coordinate) const; + virtual void setItemToWindowTransform(const QTransform &itemToWindowTransform); void setVisibleArea(const QRectF &visibleArea); QRectF visibleArea() const; diff --git a/src/location/maps/qgeoprojection.cpp b/src/location/maps/qgeoprojection.cpp index f64060e2..ff6a0b77 100644 --- a/src/location/maps/qgeoprojection.cpp +++ b/src/location/maps/qgeoprojection.cpp @@ -118,6 +118,19 @@ bool QGeoProjection::setBearing(qreal bearing, const QGeoCoordinate &coordinate) return false; } +void QGeoProjection::setItemToWindowTransform(const QTransform &itemToWindowTransform) +{ + if (m_itemToWindowTransform == itemToWindowTransform) + return; + m_qsgTransformDirty = true; + m_itemToWindowTransform = itemToWindowTransform; +} + +QTransform QGeoProjection::itemToWindowTransform() const +{ + return m_itemToWindowTransform; +} + /* * QGeoProjectionWebMercator implementation @@ -188,6 +201,31 @@ double QGeoProjectionWebMercator::minimumZoom() const return m_minimumZoom; } +QMatrix4x4 QGeoProjectionWebMercator::projectionTransformation() const +{ + return toMatrix4x4(m_transformation); +} + +QMatrix4x4 QGeoProjectionWebMercator::projectionTransformation_centered() const +{ + return toMatrix4x4(m_transformation0); +} + +const QMatrix4x4 &QGeoProjectionWebMercator::qsgTransform() const +{ + if (m_qsgTransformDirty) { + m_qsgTransformDirty = false; + m_qsgTransform = QMatrix4x4(m_itemToWindowTransform) * toMatrix4x4(m_transformation0); +// qDebug() << "QGeoProjectionWebMercator::qsgTransform" << m_itemToWindowTransform << toMatrix4x4(m_transformation0); + } + return m_qsgTransform; +} + +QDoubleVector3D QGeoProjectionWebMercator::centerMercator() const +{ + return geoToMapProjection(m_cameraData.center()).toVector3D(); +} + // This method recalculates the "no-trespassing" limits for the map center. // This has to be used when: // 1) the map is resized, because the meters per pixel remain the same, but @@ -273,19 +311,23 @@ QGeoCoordinate QGeoProjectionWebMercator::mapProjectionToGeo(const QDoubleVector return QWebMercator::mercatorToCoord(projection); } -//wraps around center -QDoubleVector2D QGeoProjectionWebMercator::wrapMapProjection(const QDoubleVector2D &projection) const +int QGeoProjectionWebMercator::projectionWrapFactor(const QDoubleVector2D &projection) const { - double x = projection.x(); + const double &x = projection.x(); if (m_cameraCenterXMercator < 0.5) { if (x - m_cameraCenterXMercator > 0.5 ) - x -= 1.0; + return -1; } else if (m_cameraCenterXMercator > 0.5) { if (x - m_cameraCenterXMercator < -0.5 ) - x += 1.0; + return 1; } + return 0; +} - return QDoubleVector2D(x, projection.y()); +//wraps around center +QDoubleVector2D QGeoProjectionWebMercator::wrapMapProjection(const QDoubleVector2D &projection) const +{ + return QDoubleVector2D(projection.x() + double(projectionWrapFactor(projection)), projection.y()); } QDoubleVector2D QGeoProjectionWebMercator::unwrapMapProjection(const QDoubleVector2D &wrappedProjection) const @@ -547,6 +589,7 @@ QGeoProjection::ProjectionType QGeoProjectionWebMercator::projectionType() const void QGeoProjectionWebMercator::setupCamera() { + m_qsgTransformDirty = true; m_centerMercator = geoToMapProjection(m_cameraData.center()); m_cameraCenterXMercator = m_centerMercator.x(); m_cameraCenterYMercator = m_centerMercator.y(); @@ -571,6 +614,10 @@ void QGeoProjectionWebMercator::setupCamera() // And in mercator space m_eyeMercator = m_centerMercator; m_eyeMercator.setZ(altitude_mercator / m_aperture); + m_eyeMercator0 = QDoubleVector3D(0,0,0); + m_eyeMercator0.setZ(altitude_mercator / m_aperture); + QDoubleVector3D eye0(0,0,0); + eye0.setZ(altitude * defaultTileSize / m_aperture); m_view = m_eye - m_center; QDoubleVector3D side = QDoubleVector3D::normal(m_view, QDoubleVector3D(0.0, 1.0, 0.0)); @@ -599,11 +646,13 @@ void QGeoProjectionWebMercator::setupCamera() QDoubleMatrix4x4 mTilt; mTilt.rotate(-m_cameraData.tilt(), m_side); m_eye = mTilt * m_view + m_center; + eye0 = mTilt * m_view; // In mercator space too QDoubleMatrix4x4 mTiltMercator; mTiltMercator.rotate(-m_cameraData.tilt(), m_sideMercator); m_eyeMercator = mTiltMercator * m_viewMercator + m_centerMercator; + m_eyeMercator0 = mTiltMercator * m_viewMercator; } m_view = m_eye - m_center; // ToDo: this should be inverted (center - eye), and the rest should follow @@ -634,8 +683,10 @@ void QGeoProjectionWebMercator::setupCamera() double verticalHalfFOV = QLocationUtils::degrees(atan(m_aperture)); - QDoubleMatrix4x4 cameraMatrix; - cameraMatrix.lookAt(m_eye, m_center, m_up); + m_cameraMatrix.setToIdentity(); + m_cameraMatrix.lookAt(m_eye, m_center, m_up); + m_cameraMatrix0.setToIdentity(); + m_cameraMatrix0.lookAt(eye0, QDoubleVector3D(0,0,0), m_up); QDoubleMatrix4x4 projectionMatrix; projectionMatrix.frustum(-m_halfWidth, m_halfWidth, -m_halfHeight, m_halfHeight, m_nearPlane, m_farPlane); @@ -656,10 +707,13 @@ void QGeoProjectionWebMercator::setupCamera() matScreenTransformation(0,3) = (0.5 + offsetPct.x()) * m_viewportWidth; matScreenTransformation(1,3) = (0.5 + offsetPct.y()) * m_viewportHeight; - m_transformation = matScreenTransformation * projectionMatrix * cameraMatrix; + m_transformation = matScreenTransformation * projectionMatrix * m_cameraMatrix; m_quickItemTransformation = m_transformation; m_transformation.scale(m_sideLengthPixels, m_sideLengthPixels, 1.0); + m_transformation0 = matScreenTransformation * projectionMatrix * m_cameraMatrix0; + m_transformation0.scale(m_sideLengthPixels, m_sideLengthPixels, 1.0); + m_centerNearPlane = m_eye - m_viewNormalized; m_centerNearPlaneMercator = m_eyeMercator - m_viewNormalized * m_nearPlaneMercator; diff --git a/src/location/maps/qgeoprojection_p.h b/src/location/maps/qgeoprojection_p.h index 2e1af8c5..9a75246a 100644 --- a/src/location/maps/qgeoprojection_p.h +++ b/src/location/maps/qgeoprojection_p.h @@ -52,6 +52,8 @@ #include <QtLocation/private/qgeocameradata_p.h> #include <QtPositioning/private/qdoublematrix4x4_p.h> #include <QtPositioning/QGeoShape> +#include <QMatrix4x4> +#include <QTransform> QT_BEGIN_NAMESPACE @@ -107,6 +109,17 @@ public: virtual QGeoShape visibleRegion() const; virtual bool setBearing(qreal bearing, const QGeoCoordinate &coordinate); + virtual QMatrix4x4 projectionTransformation() const = 0; // This brings a mercator coord into the correct viewport coordinate. + virtual QMatrix4x4 projectionTransformation_centered() const = 0; // Same as projectionTransformation, but the center of the camera is around 0,0. + // Requires subsequent shifting of the geometry to fit such camera. + virtual const QMatrix4x4 &qsgTransform() const = 0; + virtual QDoubleVector3D centerMercator() const = 0; + + void setItemToWindowTransform(const QTransform &itemToWindowTransform); + virtual QTransform itemToWindowTransform() const; + + QTransform m_itemToWindowTransform; + mutable bool m_qsgTransformDirty = true; }; class Q_LOCATION_PRIVATE_EXPORT QGeoProjectionWebMercator : public QGeoProjection @@ -117,6 +130,11 @@ public: // From QGeoProjection double minimumZoom() const override; + QMatrix4x4 projectionTransformation() const override; + QMatrix4x4 projectionTransformation_centered() const override; + const QMatrix4x4 &qsgTransform() const override; + QDoubleVector3D centerMercator() const override; + double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const override; double minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const override; @@ -144,6 +162,7 @@ public: QDoubleVector2D geoToMapProjection(const QGeoCoordinate &coordinate) const; QGeoCoordinate mapProjectionToGeo(const QDoubleVector2D &projection) const; + int projectionWrapFactor(const QDoubleVector2D &projection) const; QDoubleVector2D wrapMapProjection(const QDoubleVector2D &projection) const; QDoubleVector2D unwrapMapProjection(const QDoubleVector2D &wrappedProjection) const; @@ -213,7 +232,10 @@ protected: double m_1_viewportWidth; double m_1_viewportHeight; + QDoubleMatrix4x4 m_cameraMatrix; + QDoubleMatrix4x4 m_cameraMatrix0; QDoubleMatrix4x4 m_transformation; + QDoubleMatrix4x4 m_transformation0; QDoubleMatrix4x4 m_quickItemTransformation; QDoubleVector3D m_eye; QDoubleVector3D m_up; @@ -234,6 +256,7 @@ protected: // For the clipping region QDoubleVector3D m_centerMercator; QDoubleVector3D m_eyeMercator; + QDoubleVector3D m_eyeMercator0; QDoubleVector3D m_viewMercator; QDoubleVector3D m_upMercator; QDoubleVector3D m_sideMercator; @@ -245,6 +268,8 @@ protected: QList<QDoubleVector2D> m_visibleRegionExpanded; QList<QDoubleVector2D> m_projectableRegion; bool m_visibleRegionDirty; + + mutable QMatrix4x4 m_qsgTransform; QRectF m_visibleArea; Q_DISABLE_COPY(QGeoProjectionWebMercator) diff --git a/src/location/maps/qgeotiledmap.cpp b/src/location/maps/qgeotiledmap.cpp index 74346fdb..e6c91042 100644 --- a/src/location/maps/qgeotiledmap.cpp +++ b/src/location/maps/qgeotiledmap.cpp @@ -329,7 +329,7 @@ void QGeoTiledMapPrivate::changeCameraData(const QGeoCameraData &cameraData) m_mapScene->setCameraData(cam); updateScene(); - q->sgNodeChanged(); + q->sgNodeChanged(); // ToDo: explain why emitting twice } void QGeoTiledMapPrivate::updateScene() @@ -371,7 +371,7 @@ void QGeoTiledMapPrivate::setVisibleArea(const QRectF &visibleArea) if (m_copyrightVisible) q->evaluateCopyrights(m_mapScene->visibleTiles()); updateScene(); - q->sgNodeChanged(); + q->sgNodeChanged(); // ToDo: explain why emitting twice } QRectF QGeoTiledMapPrivate::visibleArea() const |