summaryrefslogtreecommitdiff
path: root/src/location/maps
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli.qt@gmail.com>2019-11-27 15:37:07 +0100
committerpaolo <paolo.angelelli.qt@gmail.com>2020-02-11 11:46:08 +0100
commitd055098540df99a5d426360e9322c659e678e5ee (patch)
treee7e43a057b7e06814e2ef11eeddc52a4aac06cdb /src/location/maps
parent614d67be158e3ef8443c1b7f3126303cfcf4becc (diff)
downloadqtlocation-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.cpp7
-rw-r--r--src/location/maps/qgeomap_p.h3
-rw-r--r--src/location/maps/qgeoprojection.cpp72
-rw-r--r--src/location/maps/qgeoprojection_p.h25
-rw-r--r--src/location/maps/qgeotiledmap.cpp4
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