summaryrefslogtreecommitdiff
path: root/src/location/labs/qsg
diff options
context:
space:
mode:
Diffstat (limited to 'src/location/labs/qsg')
-rw-r--r--src/location/labs/qsg/qgeomapobjectqsgsupport.cpp2
-rw-r--r--src/location/labs/qsg/qmapcircleobjectqsg.cpp266
-rw-r--r--src/location/labs/qsg/qmapcircleobjectqsg_p_p.h40
-rw-r--r--src/location/labs/qsg/qmappolygonobjectqsg.cpp186
-rw-r--r--src/location/labs/qsg/qmappolygonobjectqsg_p_p.h11
-rw-r--r--src/location/labs/qsg/qmappolylineobjectqsg.cpp91
-rw-r--r--src/location/labs/qsg/qmappolylineobjectqsg_p_p.h7
7 files changed, 414 insertions, 189 deletions
diff --git a/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp b/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp
index 6cb2c44a..f965efb7 100644
--- a/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp
+++ b/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp
@@ -152,6 +152,7 @@ void QGeoMapObjectQSGSupport::removeMapObject(QGeoMapObject *obj)
}
}
+// called in the render thread
void QGeoMapObjectQSGSupport::updateMapObjects(QSGNode *root, QQuickWindow *window)
{
if (!m_mapObjectsRootNode) {
@@ -216,6 +217,7 @@ void QGeoMapObjectQSGSupport::updateMapObjects(QSGNode *root, QQuickWindow *wind
m_mapObjectsRootNode->setSubtreeBlocked(false);
}
+// called in GUI thread
void QGeoMapObjectQSGSupport::updateObjectsGeometry()
{
for (int i = 0; i < m_mapObjects.size(); ++i) {
diff --git a/src/location/labs/qsg/qmapcircleobjectqsg.cpp b/src/location/labs/qsg/qmapcircleobjectqsg.cpp
index 6c69ce5a..5b1f5361 100644
--- a/src/location/labs/qsg/qmapcircleobjectqsg.cpp
+++ b/src/location/labs/qsg/qmapcircleobjectqsg.cpp
@@ -41,16 +41,19 @@ QT_BEGIN_NAMESPACE
static const int CircleSamples = 128;
QMapCircleObjectPrivateQSG::QMapCircleObjectPrivateQSG(QGeoMapObject *q)
- : QMapCircleObjectPrivateDefault(q)
+ : QMapCircleObjectPrivateDefault(q), m_dataCPU(new CircleDataCPU)
{
}
QMapCircleObjectPrivateQSG::QMapCircleObjectPrivateQSG(const QMapCircleObjectPrivate &other)
- : QMapCircleObjectPrivateDefault(other)
+ : QMapCircleObjectPrivateDefault(other), m_dataCPU(new CircleDataCPU)
{
// Data already cloned by the *Default copy constructor, but necessary
// update operations triggered only by setters overrides
+ if (!QDeclarativeCircleMapItemPrivateCPU::crossEarthPole(center(), radius()))
+ switchToGL(); // this marks source dirty
+
updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
@@ -62,47 +65,54 @@ QMapCircleObjectPrivateQSG::~QMapCircleObjectPrivateQSG()
m_map->removeMapObject(q);
}
-void QMapCircleObjectPrivateQSG::updateCirclePath()
+void QMapCircleObjectPrivateQSG::updateGeometry()
+{
+ if (!m_dataGL.isNull())
+ updateGeometryGL();
+ else
+ updateGeometryCPU();
+}
+
+void QMapCircleObjectPrivateQSG::CircleDataCPU::updateCirclePath(const QGeoCoordinate &center, qreal radius, const QGeoProjectionWebMercator &p)
{
- const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
QList<QGeoCoordinate> path;
- QDeclarativeCircleMapItemPrivateCPU::calculatePeripheralPoints(path, center(), radius(), CircleSamples, m_leftBound);
+ QDeclarativeCircleMapItemPrivateCPU::calculatePeripheralPoints(path, center, radius, CircleSamples, m_leftBound);
m_circlePath.clear();
for (const QGeoCoordinate &c : path)
m_circlePath << p.geoToMapProjection(c);
}
-void QMapCircleObjectPrivateQSG::updateGeometry()
+void QMapCircleObjectPrivateQSG::updateGeometryCPU()
{
if (!m_map || m_map->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator
|| !qIsFinite(radius()) || !center().isValid())
return;
const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
- QScopedValueRollback<bool> rollback(m_updatingGeometry);
- m_updatingGeometry = true;
+ QScopedValueRollback<bool> rollback(m_dataCPU->m_updatingGeometry);
+ m_dataCPU->m_updatingGeometry = true;
- updateCirclePath();
- QList<QDoubleVector2D> circlePath = m_circlePath;
+ m_dataCPU->updateCirclePath(center(), radius(), p);
+ QList<QDoubleVector2D> circlePath = m_dataCPU->m_circlePath;
int pathCount = circlePath.size();
bool preserve = QDeclarativeCircleMapItemPrivateCPU::preserveCircleGeometry(circlePath, center(), radius(), p);
// using leftBound_ instead of the analytically calculated circle_.boundingGeoRectangle().topLeft());
// to fix QTBUG-62154
- m_geometry.markSourceDirty();
- m_geometry.setPreserveGeometry(true, m_leftBound); // to set the geoLeftBound_
- m_geometry.setPreserveGeometry(preserve, m_leftBound);
+ m_dataCPU->m_geometry.markSourceDirty();
+ m_dataCPU->m_geometry.setPreserveGeometry(true, m_dataCPU->m_leftBound); // to set the geoLeftBound_
+ m_dataCPU->m_geometry.setPreserveGeometry(preserve, m_dataCPU->m_leftBound);
bool invertedCircle = false;
if (QDeclarativeCircleMapItemPrivateCPU::crossEarthPole(center(), radius()) && circlePath.size() == pathCount) {
- m_geometry.updateScreenPointsInvert(circlePath, *m_map); // invert fill area for really huge circles
+ m_dataCPU->m_geometry.updateScreenPointsInvert(circlePath, *m_map); // invert fill area for really huge circles
invertedCircle = true;
} else {
- m_geometry.updateSourcePoints(*m_map, circlePath);
- m_geometry.updateScreenPoints(*m_map);
+ m_dataCPU->m_geometry.updateSourcePoints(*m_map, circlePath);
+ m_dataCPU->m_geometry.updateScreenPoints(*m_map);
}
- m_borderGeometry.clear();
+ m_dataCPU->m_borderGeometry.clear();
//if (borderColor() != Qt::transparent && borderWidth() > 0)
{
@@ -110,35 +120,76 @@ void QMapCircleObjectPrivateQSG::updateGeometry()
closedPath << closedPath.first();
if (invertedCircle) {
- closedPath = m_circlePath;
+ closedPath = m_dataCPU->m_circlePath;
closedPath << closedPath.first();
std::reverse(closedPath.begin(), closedPath.end());
}
- m_borderGeometry.markSourceDirty();
- m_borderGeometry.setPreserveGeometry(true, m_leftBound);
- m_borderGeometry.setPreserveGeometry(preserve, m_leftBound);
+ m_dataCPU->m_borderGeometry.markSourceDirty();
+ m_dataCPU->m_borderGeometry.setPreserveGeometry(true, m_dataCPU->m_leftBound);
+ m_dataCPU->m_borderGeometry.setPreserveGeometry(preserve, m_dataCPU->m_leftBound);
// Use srcOrigin_ from fill geometry after clipping to ensure that translateToCommonOrigin won't fail.
- const QGeoCoordinate &geometryOrigin = m_geometry.origin();
+ const QGeoCoordinate &geometryOrigin = m_dataCPU->m_geometry.origin();
- m_borderGeometry.clearSource();
+ m_dataCPU->m_borderGeometry.clearSource();
QDoubleVector2D borderLeftBoundWrapped;
QList<QList<QDoubleVector2D > > clippedPaths =
- m_borderGeometry.clipPath(*m_map, closedPath, borderLeftBoundWrapped);
+ m_dataCPU->m_borderGeometry.clipPath(*m_map, closedPath, borderLeftBoundWrapped);
if (clippedPaths.size()) {
borderLeftBoundWrapped = p.geoToWrappedMapProjection(geometryOrigin);
- m_borderGeometry.pathToScreen(*m_map, clippedPaths, borderLeftBoundWrapped);
- m_borderGeometry.updateScreenPoints(*m_map, borderWidth(), false);
+ m_dataCPU->m_borderGeometry.pathToScreen(*m_map, clippedPaths, borderLeftBoundWrapped);
+ m_dataCPU->m_borderGeometry.updateScreenPoints(*m_map, borderWidth(), false);
} else {
- m_borderGeometry.clear();
+ m_dataCPU->m_borderGeometry.clear();
}
}
- QPointF origin = m_map->geoProjection().coordinateToItemPosition(m_geometry.origin(), false).toPointF();
- m_geometry.translate(origin - m_geometry.firstPointOffset());
- m_borderGeometry.translate(origin - m_borderGeometry.firstPointOffset());
+ QPointF origin = m_map->geoProjection().coordinateToItemPosition(m_dataCPU->m_geometry.origin(), false).toPointF();
+ m_dataCPU->m_geometry.translate(origin - m_dataCPU->m_geometry.firstPointOffset());
+ m_dataCPU->m_borderGeometry.translate(origin - m_dataCPU->m_borderGeometry.firstPointOffset());
+}
+
+void QMapCircleObjectPrivateQSG::CircleDataGL::updateCirclePath(const QGeoCoordinate &center, qreal radius, const QGeoProjectionWebMercator &p)
+{
+ m_circlePath.clear();
+ if (radius < 0.001) // 1mm is small enough, probably already way too small.
+ return;
+ QDeclarativeCircleMapItemPrivate::calculatePeripheralPoints(m_circlePath,
+ center,
+ radius,
+ CircleSamples,
+ m_leftBound);
+
+ m_leftBoundMercator = p.geoToMapProjection(m_leftBound);
+ m_geometry.setPreserveGeometry(true, m_leftBound);
+ m_borderGeometry.setPreserveGeometry(true, m_leftBound);
+}
+
+void QMapCircleObjectPrivateQSG::updateGeometryGL()
+{
+ if (!m_map || m_map->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
+ return;
+
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
+ if (m_dataGL->m_geometry.isSourceDirty()
+ || m_dataGL->m_borderGeometry.isSourceDirty()) {
+ m_dataGL->updateCirclePath(center(), radius(), p);
+
+ if (m_dataGL->m_circlePath.length() == 0) { // Possibly cleared
+ m_dataGL->m_geometry.clear();
+ m_dataGL->m_borderGeometry.clear();
+ return;
+ }
+ m_dataGL->m_geometry.m_dataChanged = m_dataGL->m_borderGeometry.m_dataChanged = true;
+ m_dataGL->m_geometry.updateSourcePoints(*m_map, m_dataGL->m_circlePath);
+ m_dataGL->m_borderGeometry.updateSourcePoints(*m_map, QGeoCircle(center(), radius()));
+ m_dataGL->m_circlePath.clear(); // not needed anymore
+ }
+ m_dataGL->m_geometry.markScreenDirty(); // ToDo: this needs refactor. It's useless, remove screenDirty_ altogether.
+ m_dataGL->m_borderGeometry.markScreenDirty();
+ m_dataGL->m_borderGeometry.m_wrapOffset = m_dataGL->m_geometry.m_wrapOffset = p.projectionWrapFactor(m_dataGL->m_leftBoundMercator) + 1;
}
QGeoMapObjectPrivate *QMapCircleObjectPrivateQSG::clone()
@@ -146,45 +197,144 @@ QGeoMapObjectPrivate *QMapCircleObjectPrivateQSG::clone()
return new QMapCircleObjectPrivateQSG(static_cast<QMapCircleObjectPrivate &>(*this));
}
+void QMapCircleObjectPrivateQSG::switchToGL()
+{
+ if (!m_dataGL.isNull())
+ return;
+ QScopedPointer<CircleDataGL> data(new CircleDataGL);
+ m_dataGL.swap(data);
+ m_dataGL->markSourceDirty();
+ m_dataCPU.reset(nullptr);
+}
+
+void QMapCircleObjectPrivateQSG::switchToCPU()
+{
+ if (!m_dataCPU.isNull())
+ return;
+ QScopedPointer<CircleDataCPU> data(new CircleDataCPU);
+ m_dataCPU.swap(data);
+ m_dataGL.reset(nullptr);
+}
+
QSGNode *QMapCircleObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode,
VisibleNode **visibleNode,
QSGNode *root,
- QQuickWindow * /*window*/)
+ QQuickWindow * window)
{
-// Q_UNUSED(visibleNode); // coz of -Werror=unused-but-set-parameter
- MapPolygonNode *node = static_cast<MapPolygonNode *>(oldNode);
+ if (!m_dataGL.isNull())
+ return updateMapObjectNodeGL(oldNode, visibleNode, root, window);
+ else
+ return updateMapObjectNodeCPU(oldNode, visibleNode, root, window);
+}
- if (!node) {
- if (!m_geometry.size() && !m_borderGeometry.size()) {
- return nullptr;
- }
- node = new MapPolygonNode();
- *visibleNode = static_cast<VisibleNode *>(node);
+QSGNode *QMapCircleObjectPrivateQSG::updateMapObjectNodeCPU(QSGNode *oldNode,
+ VisibleNode **visibleNode,
+ QSGNode *root,
+ QQuickWindow */*window*/)
+{
+ if (!m_dataCPU->m_node || !oldNode) {
+ m_dataCPU->m_node = new MapPolygonNode();
+ *visibleNode = static_cast<VisibleNode *>(m_dataCPU->m_node);
+ if (oldNode)
+ delete oldNode;
+ } else {
+ m_dataCPU->m_node = static_cast<MapPolygonNode *>(oldNode);
+ }
+
+ if (!m_dataCPU->m_geometry.size() && !m_dataCPU->m_borderGeometry.size()) {
+ visibleNode = nullptr;
+ return nullptr;
}
//TODO: update only material
- if (m_geometry.isScreenDirty() || !m_borderGeometry.isScreenDirty() || !oldNode) {
+ if (m_dataCPU->m_geometry.isScreenDirty() || m_dataCPU->m_borderGeometry.isScreenDirty() || oldNode != m_dataCPU->m_node) {
//QMapPolygonObject *p = static_cast<QMapPolygonObject *>(q);
- node->update(color(), borderColor(), &m_geometry, &m_borderGeometry);
- m_geometry.setPreserveGeometry(false);
- m_borderGeometry.setPreserveGeometry(false);
- m_geometry.markClean();
- m_borderGeometry.markClean();
+ m_dataCPU->m_node->update(color(), borderColor(), &m_dataCPU->m_geometry, &m_dataCPU->m_borderGeometry);
+ m_dataCPU->m_geometry.setPreserveGeometry(false);
+ m_dataCPU->m_borderGeometry.setPreserveGeometry(false);
+ m_dataCPU->m_geometry.markClean();
+ m_dataCPU->m_borderGeometry.markClean();
}
- if (m_geometry.size() || m_borderGeometry.size()) {
- root->appendChildNode(node);
+ if (m_dataCPU->m_geometry.size() || m_dataCPU->m_borderGeometry.size()) {
+ root->appendChildNode(m_dataCPU->m_node);
} else {
- delete node;
+ delete m_dataCPU->m_node;
+ m_dataCPU->m_node = nullptr;
+ visibleNode = nullptr;
return nullptr;
}
- return node;
+ return m_dataCPU->m_node;
}
+QSGNode *QMapCircleObjectPrivateQSG::updateMapObjectNodeGL(QSGNode *oldNode,
+ VisibleNode **visibleNode,
+ QSGNode *root,
+ QQuickWindow */*window*/)
+{
+ if (!m_dataGL->m_rootNode || !oldNode) {
+ m_dataGL->m_rootNode = new QDeclarativePolygonMapItemPrivateOpenGL::RootNode();
+ m_dataGL->m_node = new MapPolygonNodeGL();
+ m_dataGL->m_rootNode->appendChildNode(m_dataGL->m_node);
+ m_dataGL->m_polylinenode = new MapPolylineNodeOpenGLExtruded();
+ m_dataGL->m_rootNode->appendChildNode(m_dataGL->m_polylinenode);
+ m_dataGL->m_rootNode->markDirty(QSGNode::DirtyNodeAdded);
+ *visibleNode = static_cast<VisibleNode *>(m_dataGL->m_rootNode);
+ if (oldNode)
+ delete oldNode;
+ } else {
+ m_dataGL->m_rootNode = static_cast<QDeclarativePolygonMapItemPrivateOpenGL::RootNode *>(oldNode);
+ }
+
+ const QMatrix4x4 &combinedMatrix = m_map->geoProjection().qsgTransform();
+ const QDoubleVector3D &cameraCenter = m_map->geoProjection().centerMercator();
+
+ if (m_dataGL->m_borderGeometry.isScreenDirty()) {
+ /* Do the border update first */
+ m_dataGL->m_polylinenode->update(borderColor(),
+ float(borderWidth()),
+ &m_dataGL->m_borderGeometry,
+ combinedMatrix,
+ cameraCenter,
+ Qt::SquareCap,
+ true);
+ m_dataGL->m_borderGeometry.setPreserveGeometry(false);
+ m_dataGL->m_borderGeometry.markClean();
+ }
+ if (m_dataGL->m_geometry.isScreenDirty()) {
+ m_dataGL->m_node->update(color(),
+ &m_dataGL->m_geometry,
+ combinedMatrix,
+ cameraCenter);
+ m_dataGL->m_geometry.setPreserveGeometry(false);
+ m_dataGL->m_geometry.markClean();
+ }
+
+ if (!m_dataGL->m_polylinenode->isSubtreeBlocked() || !m_dataGL->m_node->isSubtreeBlocked()) {
+ m_dataGL->m_rootNode->setSubtreeBlocked(false);
+ root->appendChildNode(m_dataGL->m_rootNode);
+ return m_dataGL->m_rootNode;
+ } else {
+ delete m_dataGL->m_rootNode;
+ m_dataGL->m_rootNode = nullptr;
+ m_dataGL->m_node = nullptr;
+ m_dataGL->m_polylinenode = nullptr;
+ *visibleNode = nullptr;
+ return nullptr;
+ }
+}
void QMapCircleObjectPrivateQSG::setCenter(const QGeoCoordinate &center)
{
QMapCircleObjectPrivateDefault::setCenter(center);
+ if (!QDeclarativeCircleMapItemPrivate::crossEarthPole(this->center(), this->radius())) // Switching implementation for circles crossing/not crossing poles
+ switchToGL();
+ else
+ switchToCPU();
+
+ if (!m_dataGL.isNull())
+ m_dataGL->markSourceDirty();
+
updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
@@ -193,6 +343,14 @@ void QMapCircleObjectPrivateQSG::setCenter(const QGeoCoordinate &center)
void QMapCircleObjectPrivateQSG::setRadius(qreal radius)
{
QMapCircleObjectPrivateDefault::setRadius(radius);
+ if (!QDeclarativeCircleMapItemPrivate::crossEarthPole(this->center(), this->radius())) // Switching implementation for circles crossing/not crossing poles
+ switchToGL();
+ else
+ switchToCPU();
+
+ if (!m_dataGL.isNull())
+ m_dataGL->markSourceDirty();
+
updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
@@ -201,7 +359,8 @@ void QMapCircleObjectPrivateQSG::setRadius(qreal radius)
void QMapCircleObjectPrivateQSG::setColor(const QColor &color)
{
QMapCircleObjectPrivateDefault::setColor(color);
- updateGeometry();
+ if (!m_dataCPU.isNull())
+ updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
}
@@ -209,7 +368,8 @@ void QMapCircleObjectPrivateQSG::setColor(const QColor &color)
void QMapCircleObjectPrivateQSG::setBorderColor(const QColor &color)
{
QMapCircleObjectPrivateDefault::setBorderColor(color);
- updateGeometry();
+ if (!m_dataCPU.isNull())
+ updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
}
@@ -217,10 +377,10 @@ void QMapCircleObjectPrivateQSG::setBorderColor(const QColor &color)
void QMapCircleObjectPrivateQSG::setBorderWidth(qreal width)
{
QMapCircleObjectPrivateDefault::setBorderWidth(width);
- updateGeometry();
+ if (!m_dataCPU.isNull())
+ updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
}
-
QT_END_NAMESPACE
diff --git a/src/location/labs/qsg/qmapcircleobjectqsg_p_p.h b/src/location/labs/qsg/qmapcircleobjectqsg_p_p.h
index 6bbeb397..dc057c0b 100644
--- a/src/location/labs/qsg/qmapcircleobjectqsg_p_p.h
+++ b/src/location/labs/qsg/qmapcircleobjectqsg_p_p.h
@@ -68,14 +68,22 @@ public:
QMapCircleObjectPrivateQSG(const QMapCircleObjectPrivate &other);
~QMapCircleObjectPrivateQSG() override;
- void updateCirclePath();
-
// QQSGMapObject
void updateGeometry() override;
+ void updateGeometryCPU();
+ void updateGeometryGL();
QSGNode *updateMapObjectNode(QSGNode *oldNode,
VisibleNode **visibleNode,
QSGNode *root,
QQuickWindow *window) override;
+ QSGNode *updateMapObjectNodeCPU(QSGNode *oldNode,
+ VisibleNode **visibleNode,
+ QSGNode *root,
+ QQuickWindow *window);
+ QSGNode *updateMapObjectNodeGL(QSGNode *oldNode,
+ VisibleNode **visibleNode,
+ QSGNode *root,
+ QQuickWindow *window);
// QGeoMapCirclePrivate interface
void setCenter(const QGeoCoordinate &center) override;
@@ -87,15 +95,43 @@ public:
// QGeoMapObjectPrivate
QGeoMapObjectPrivate *clone() override;
+ void switchToGL();
+ void switchToCPU();
+
public:
// Data Members
+struct CircleDataCPU {
+ MapPolygonNode *m_node = nullptr;
QList<QDoubleVector2D> m_circlePath;
QGeoCoordinate m_leftBound;
QGeoMapCircleGeometry m_geometry;
QGeoMapPolylineGeometry m_borderGeometry;
bool m_updatingGeometry = false;
+
+ void updateCirclePath(const QGeoCoordinate &center, qreal radius, const QGeoProjectionWebMercator &p);
+};
+struct CircleDataGL {
+ QList<QGeoCoordinate> m_circlePath;
+ QGeoCoordinate m_leftBound;
+ QDoubleVector2D m_leftBoundMercator;
+ QGeoMapPolygonGeometryOpenGL m_geometry;
+ QGeoMapPolylineGeometryOpenGL m_borderGeometry;
+ QDeclarativePolygonMapItemPrivateOpenGL::RootNode *m_rootNode = nullptr;
+ MapPolygonNodeGL *m_node = nullptr;
+ MapPolylineNodeOpenGLExtruded *m_polylinenode = nullptr;
+
+ void updateCirclePath(const QGeoCoordinate &center, qreal radius, const QGeoProjectionWebMercator &p);
+ void markSourceDirty()
+ {
+ m_geometry.markSourceDirty();
+ m_borderGeometry.markSourceDirty();
+ }
+};
+ QScopedPointer<CircleDataCPU> m_dataCPU;
+ QScopedPointer<CircleDataGL> m_dataGL;
};
QT_END_NAMESPACE
#endif // QMAPCIRCLEOBJECT_P_P_H
+
diff --git a/src/location/labs/qsg/qmappolygonobjectqsg.cpp b/src/location/labs/qsg/qmappolygonobjectqsg.cpp
index 25473478..a8a1cb4b 100644
--- a/src/location/labs/qsg/qmappolygonobjectqsg.cpp
+++ b/src/location/labs/qsg/qmappolygonobjectqsg.cpp
@@ -52,6 +52,7 @@ QMapPolygonObjectPrivateQSG::QMapPolygonObjectPrivateQSG(const QMapPolygonObject
{
// Data already cloned by the *Default copy constructor, but necessary
// update operations triggered only by setters overrides
+ markSourceDirty();
updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
@@ -63,67 +64,22 @@ QMapPolygonObjectPrivateQSG::~QMapPolygonObjectPrivateQSG()
m_map->removeMapObject(q);
}
-QList<QDoubleVector2D> QMapPolygonObjectPrivateQSG::projectPath()
+void QMapPolygonObjectPrivateQSG::setPath(const QList<QGeoCoordinate> &p)
{
- QList<QDoubleVector2D> geopathProjected_;
- if (!m_map || m_map->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
- return geopathProjected_;
-
- const QGeoProjectionWebMercator &p =
- static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
- geopathProjected_.reserve(m_path.path().size());
- for (const QGeoCoordinate &c : m_path.path())
- geopathProjected_ << p.geoToMapProjection(c);
- return geopathProjected_;
-}
-
-QSGNode *QMapPolygonObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode,
- VisibleNode **visibleNode,
- QSGNode *root,
- QQuickWindow * /*window*/)
-{
- Q_UNUSED(visibleNode);
- MapPolygonNode *node = static_cast<MapPolygonNode *>(oldNode);
-
- if (!node) {
- if (!m_geometry.size() && !m_borderGeometry.size()) {
- return nullptr;
- }
- node = new MapPolygonNode();
- *visibleNode = static_cast<VisibleNode *>(node);
- }
-
- //TODO: update only material
- if (m_geometry.isScreenDirty() || !m_borderGeometry.isScreenDirty() || !oldNode) {
- node->update(fillColor(), borderColor(), &m_geometry, &m_borderGeometry);
- m_geometry.setPreserveGeometry(false);
- m_borderGeometry.setPreserveGeometry(false);
- m_geometry.markClean();
- m_borderGeometry.markClean();
- }
-
- if (m_geometry.size() || m_borderGeometry.size()) {
- root->appendChildNode(node);
- } else {
- delete node;
- return nullptr;
- }
- return node;
-}
-
-void QMapPolygonObjectPrivateQSG::setPath(const QList<QGeoCoordinate> &path)
-{
- QMapPolygonObjectPrivateDefault::setPath(path);
+ if (p == path())
+ return;
+ QMapPolygonObjectPrivateDefault::setPath(p);
+ markSourceDirty();
updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
+ emit static_cast<QMapPolygonObject *>(q)->pathChanged();
}
void QMapPolygonObjectPrivateQSG::setFillColor(const QColor &color)
{
QMapPolygonObjectPrivateDefault::setFillColor(color);
- updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
@@ -132,7 +88,6 @@ void QMapPolygonObjectPrivateQSG::setFillColor(const QColor &color)
void QMapPolygonObjectPrivateQSG::setBorderColor(const QColor &color)
{
QMapPolygonObjectPrivateDefault::setBorderColor(color);
- updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
@@ -141,7 +96,6 @@ void QMapPolygonObjectPrivateQSG::setBorderColor(const QColor &color)
void QMapPolygonObjectPrivateQSG::setBorderWidth(qreal width)
{
QMapPolygonObjectPrivateDefault::setBorderWidth(width);
- updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
@@ -158,59 +112,111 @@ void QMapPolygonObjectPrivateQSG::setGeoShape(const QGeoShape &shape)
return;
m_path = QGeoPathEager(shape);
+ markSourceDirty();
updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
emit static_cast<QMapPolygonObject *>(q)->pathChanged();
}
+// This is called both when data changes and when viewport changes.
+// so handle both cases (sourceDirty, !sourceDirty)
void QMapPolygonObjectPrivateQSG::updateGeometry()
{
- if (!m_map || m_path.path().length() == 0
- || m_map->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
+ if (!m_map || m_map->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
return;
- QScopedValueRollback<bool> rollback(m_updatingGeometry);
- m_updatingGeometry = true;
-
- const QList<QDoubleVector2D> &geopathProjected = projectPath();
-
- m_geometry.markSourceDirty();
- m_geometry.setPreserveGeometry(true, m_path.boundingGeoRectangle().topLeft());
- m_geometry.updateSourcePoints(*m_map, geopathProjected);
- m_geometry.updateScreenPoints(*m_map);
-
- m_borderGeometry.clear();
-
- //if (border_.color() != Qt::transparent && border_.width() > 0)
- {
- const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
- QList<QDoubleVector2D> closedPath = geopathProjected;
- closedPath << closedPath.first();
-
- m_borderGeometry.markSourceDirty();
+ if (m_path.path().length() == 0) { // Possibly cleared
+ m_geometry.clear();
+ m_borderGeometry.clear();
+ return;
+ }
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
+ if (m_geometry.isSourceDirty() || m_borderGeometry.isSourceDirty()) {
+ // This works a bit differently than MapPolygon:
+ // the "screen bounds" aren't needed, so update only sources,
+ // regardless of the color, as color changes won't trigger polish(),
+ // and remember to flag m_dataChanged, that is in principle the same as
+ // sourceDirty_, but in practice is cleared in two different codepaths.
+ // sourceDirty_ is cleared in any case, dataChanged only if the primitive
+ // is effectively visible (e.g., not transparent or border not null)
+ m_geometry.setPreserveGeometry(true, m_path.boundingGeoRectangle().topLeft());
m_borderGeometry.setPreserveGeometry(true, m_path.boundingGeoRectangle().topLeft());
+ m_geometry.m_dataChanged = m_borderGeometry.m_dataChanged = true;
+ m_geometry.updateSourcePoints(*m_map, m_path);
+ m_borderGeometry.updateSourcePoints(*m_map, m_path);
+ m_leftBoundMercator = p.geoToMapProjection(m_geometry.origin());
+ }
+ m_geometry.markScreenDirty(); // ToDo: this needs refactor. It's useless, remove screenDirty_ altogether.
+ m_borderGeometry.markScreenDirty();
+ m_borderGeometry.m_wrapOffset = m_geometry.m_wrapOffset = p.projectionWrapFactor(m_leftBoundMercator) + 1;
+}
- const QGeoCoordinate &geometryOrigin = m_geometry.origin();
-
- m_borderGeometry.clearSource();
+QSGNode *QMapPolygonObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode,
+ VisibleNode **visibleNode,
+ QSGNode *root,
+ QQuickWindow * /*window*/)
+{
+ if (!m_rootNode || !oldNode) {
+ m_rootNode = new QDeclarativePolygonMapItemPrivateOpenGL::RootNode();
+ m_node = new MapPolygonNodeGL();
+ m_rootNode->appendChildNode(m_node);
+ m_polylinenode = new MapPolylineNodeOpenGLExtruded();
+ m_rootNode->appendChildNode(m_polylinenode);
+ m_rootNode->markDirty(QSGNode::DirtyNodeAdded);
+ *visibleNode = static_cast<VisibleNode *>(m_rootNode);
+ if (oldNode)
+ delete oldNode;
+ } else {
+ m_rootNode = static_cast<QDeclarativePolygonMapItemPrivateOpenGL::RootNode *>(oldNode);
+ }
- QDoubleVector2D borderLeftBoundWrapped;
- QList<QList<QDoubleVector2D > > clippedPaths =
- m_borderGeometry.clipPath(*m_map.data(), closedPath, borderLeftBoundWrapped);
+ const QMatrix4x4 &combinedMatrix = m_map->geoProjection().qsgTransform();
+ const QDoubleVector3D &cameraCenter = m_map->geoProjection().centerMercator();
+
+ if (m_borderGeometry.isScreenDirty()) {
+ /* Do the border update first */
+ m_polylinenode->update(borderColor(),
+ float(borderWidth()),
+ &m_borderGeometry,
+ combinedMatrix,
+ cameraCenter,
+ Qt::SquareCap,
+ true);
+ m_borderGeometry.setPreserveGeometry(false);
+ m_borderGeometry.markClean();
+ }
+ if (m_geometry.isScreenDirty()) {
+ m_node->update(fillColor(),
+ &m_geometry,
+ combinedMatrix,
+ cameraCenter);
+ m_geometry.setPreserveGeometry(false);
+ m_geometry.markClean();
+ }
- if (clippedPaths.size()) {
- borderLeftBoundWrapped = p.geoToWrappedMapProjection(geometryOrigin);
- m_borderGeometry.pathToScreen(*m_map.data(), clippedPaths, borderLeftBoundWrapped);
- m_borderGeometry.updateScreenPoints(*m_map.data(), borderWidth(), false);
- } else {
- m_borderGeometry.clear();
- }
+ if (!m_polylinenode->isSubtreeBlocked() || !m_node->isSubtreeBlocked()) {
+ m_rootNode->setSubtreeBlocked(false);
+ root->appendChildNode(m_rootNode);
+ return m_rootNode;
+ } else {
+ m_rootNode->setSubtreeBlocked(true);
+ // If the object is currently invisible, but not gone,
+ // it is reasonable to assume it will become visible again.
+ // However, better not to retain unused data.
+ delete m_rootNode;
+ m_rootNode = nullptr;
+ m_node = nullptr;
+ m_polylinenode = nullptr;
+ *visibleNode = nullptr;
+ return nullptr;
}
+}
- QPointF origin = m_map->geoProjection().coordinateToItemPosition(m_geometry.origin(), false).toPointF();
- m_geometry.translate(origin - m_geometry.firstPointOffset());
- m_borderGeometry.translate(origin - m_borderGeometry.firstPointOffset());
+void QMapPolygonObjectPrivateQSG::markSourceDirty()
+{
+ m_geometry.markSourceDirty();
+ m_borderGeometry.markSourceDirty();
}
QT_END_NAMESPACE
diff --git a/src/location/labs/qsg/qmappolygonobjectqsg_p_p.h b/src/location/labs/qsg/qmappolygonobjectqsg_p_p.h
index 8e6ae8a8..9dcece74 100644
--- a/src/location/labs/qsg/qmappolygonobjectqsg_p_p.h
+++ b/src/location/labs/qsg/qmappolygonobjectqsg_p_p.h
@@ -67,6 +67,7 @@ public:
QList<QDoubleVector2D> projectPath();
// QQSGMapObject
+ void markSourceDirty();
void updateGeometry() override;
QSGNode *updateMapObjectNode(QSGNode *oldNode,
VisibleNode **visibleNode,
@@ -84,10 +85,12 @@ public:
virtual void setGeoShape(const QGeoShape &shape) override;
// Data Members
- QGeoMapPolygonGeometry m_geometry;
- QGeoMapPolylineGeometry m_borderGeometry;
-
- bool m_updatingGeometry = false;
+ QDoubleVector2D m_leftBoundMercator;
+ QGeoMapPolygonGeometryOpenGL m_geometry;
+ QGeoMapPolylineGeometryOpenGL m_borderGeometry;
+ QDeclarativePolygonMapItemPrivateOpenGL::RootNode *m_rootNode = nullptr;
+ MapPolygonNodeGL *m_node = nullptr;
+ MapPolylineNodeOpenGLExtruded *m_polylinenode = nullptr;
};
QT_END_NAMESPACE
diff --git a/src/location/labs/qsg/qmappolylineobjectqsg.cpp b/src/location/labs/qsg/qmappolylineobjectqsg.cpp
index 96f66565..817d4df5 100644
--- a/src/location/labs/qsg/qmappolylineobjectqsg.cpp
+++ b/src/location/labs/qsg/qmappolylineobjectqsg.cpp
@@ -53,9 +53,9 @@ QMapPolylineObjectPrivateQSG::QMapPolylineObjectPrivateQSG(QGeoMapObject *q)
QMapPolylineObjectPrivateQSG::QMapPolylineObjectPrivateQSG(const QMapPolylineObjectPrivate &other)
: QMapPolylineObjectPrivateDefault(other)
{
- m_geoPath.setPath(m_path);
// rest of the data already cloned by the *Default copy constructor, but necessary
// update operations triggered only by setters overrides
+ markSourceDirty();
updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
@@ -75,28 +75,31 @@ QList<QDoubleVector2D> QMapPolylineObjectPrivateQSG::projectPath()
const QGeoProjectionWebMercator &p =
static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
- geopathProjected_.reserve(m_geoPath.path().size());
- for (const QGeoCoordinate &c : m_geoPath.path())
+ geopathProjected_.reserve(m_path.path().size());
+ for (const QGeoCoordinate &c : m_path.path())
geopathProjected_ << p.geoToMapProjection(c);
return geopathProjected_;
}
void QMapPolylineObjectPrivateQSG::updateGeometry()
{
- if (!m_map || m_geoPath.path().length() == 0
- || m_map->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
+ if (!m_map || m_map->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
return;
- QScopedValueRollback<bool> rollback(m_updatingGeometry);
- m_updatingGeometry = true;
- m_geometry.markSourceDirty();
- const QList<QDoubleVector2D> &geopathProjected = projectPath();
- m_geometry.setPreserveGeometry(true, m_geoPath.boundingGeoRectangle().topLeft());
- m_geometry.updateSourcePoints(*m_map.data(), geopathProjected, m_geoPath.boundingGeoRectangle().topLeft());
- m_geometry.updateScreenPoints(*m_map.data(), width(), false);
+ if (m_path.path().length() == 0) { // Possibly cleared
+ m_borderGeometry.clear();
+ return;
+ }
- QPointF origin = m_map->geoProjection().coordinateToItemPosition(m_geometry.origin(), false).toPointF();
- m_geometry.translate(origin - m_geometry.firstPointOffset());
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
+ if (m_borderGeometry.isSourceDirty()) {
+ m_borderGeometry.setPreserveGeometry(true, m_path.boundingGeoRectangle().topLeft());
+ m_borderGeometry.m_dataChanged = true;
+ m_borderGeometry.updateSourcePoints(*m_map, m_path);
+ m_leftBoundMercator = p.geoToMapProjection(m_borderGeometry.origin());
+ }
+ m_borderGeometry.markScreenDirty();
+ m_borderGeometry.m_wrapOffset = p.projectionWrapFactor(m_leftBoundMercator) + 1;
}
QSGNode *QMapPolylineObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode,
@@ -104,41 +107,52 @@ QSGNode *QMapPolylineObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode,
QSGNode *root,
QQuickWindow * /*window*/)
{
- Q_UNUSED(visibleNode);
- MapPolylineNode *node = static_cast<MapPolylineNode *>(oldNode);
-
- if (!node) {
- if (!m_geometry.size()) // condition to block the subtree
- return nullptr;
- node = new MapPolylineNode();
- *visibleNode = static_cast<VisibleNode *>(node);
+ if (!m_polylinenode || !oldNode) {
+ m_polylinenode = new MapPolylineNodeOpenGLExtruded();
+ *visibleNode = static_cast<VisibleNode *>(m_polylinenode);
+ if (oldNode)
+ delete oldNode;
+ } else {
+ m_polylinenode = static_cast<MapPolylineNodeOpenGLExtruded *>(oldNode);
}
- //TODO: update only material
- if (m_geometry.isScreenDirty() || !oldNode) {
- node->update(color(), &m_geometry);
- m_geometry.setPreserveGeometry(false);
- m_geometry.markClean();
+ const QMatrix4x4 &combinedMatrix = m_map->geoProjection().qsgTransform();
+ const QDoubleVector3D &cameraCenter = m_map->geoProjection().centerMercator();
+
+ if (m_borderGeometry.isScreenDirty()) {
+ /* Do the border update first */
+ m_polylinenode->update(color(),
+ float(width()),
+ &m_borderGeometry,
+ combinedMatrix,
+ cameraCenter,
+ Qt::SquareCap,
+ true);
+ m_borderGeometry.setPreserveGeometry(false);
+ m_borderGeometry.markClean();
}
- if (m_geometry.size()) {
- root->appendChildNode(node);
+ if (!m_polylinenode->isSubtreeBlocked() ) {
+ m_polylinenode->setSubtreeBlocked(false);
+ root->appendChildNode(m_polylinenode);
+ return m_polylinenode;
} else {
- delete node;
+ delete m_polylinenode;
+ m_polylinenode = nullptr;
+ *visibleNode = nullptr;
return nullptr;
}
- return node;
}
QList<QGeoCoordinate> QMapPolylineObjectPrivateQSG::path() const
{
- return m_geoPath.path();
+ return m_path.path();
}
void QMapPolylineObjectPrivateQSG::setPath(const QList<QGeoCoordinate> &path)
{
- m_path = path;
- m_geoPath.setPath(path);
+ m_path.setPath(path);
+ markSourceDirty();
updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
@@ -147,7 +161,6 @@ void QMapPolylineObjectPrivateQSG::setPath(const QList<QGeoCoordinate> &path)
void QMapPolylineObjectPrivateQSG::setColor(const QColor &color)
{
QMapPolylineObjectPrivateDefault::setColor(color);
- updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
@@ -156,7 +169,6 @@ void QMapPolylineObjectPrivateQSG::setColor(const QColor &color)
void QMapPolylineObjectPrivateQSG::setWidth(qreal width)
{
QMapPolylineObjectPrivateDefault::setWidth(width);
- updateGeometry();
if (m_map)
emit m_map->sgNodeChanged();
@@ -169,7 +181,12 @@ QGeoMapObjectPrivate *QMapPolylineObjectPrivateQSG::clone()
QGeoShape QMapPolylineObjectPrivateQSG::geoShape() const
{
- return m_geoPath;
+ return m_path;
+}
+
+void QMapPolylineObjectPrivateQSG::markSourceDirty()
+{
+ m_borderGeometry.markSourceDirty();
}
QT_END_NAMESPACE
diff --git a/src/location/labs/qsg/qmappolylineobjectqsg_p_p.h b/src/location/labs/qsg/qmappolylineobjectqsg_p_p.h
index e8eb5839..63ebcde9 100644
--- a/src/location/labs/qsg/qmappolylineobjectqsg_p_p.h
+++ b/src/location/labs/qsg/qmappolylineobjectqsg_p_p.h
@@ -68,6 +68,7 @@ public:
QList<QDoubleVector2D> projectPath();
// QQSGMapObject
+ void markSourceDirty();
void updateGeometry() override;
QSGNode *updateMapObjectNode(QSGNode *oldNode,
VisibleNode **visibleNode,
@@ -85,9 +86,9 @@ public:
virtual QGeoShape geoShape() const override;
// Data Members
- QGeoPathEager m_geoPath;
- QGeoMapPolylineGeometry m_geometry;
- bool m_updatingGeometry = false;
+ QDoubleVector2D m_leftBoundMercator;
+ QGeoMapPolylineGeometryOpenGL m_borderGeometry;
+ MapPolylineNodeOpenGLExtruded *m_polylinenode = nullptr;
};
QT_END_NAMESPACE