diff options
author | Fabian Bumberger <fbumberger@rim.com> | 2013-11-20 19:23:47 +0100 |
---|---|---|
committer | Fabian Bumberger <fbumberger@rim.com> | 2014-01-28 16:57:17 +0100 |
commit | 40523fde410adf74d021bec4869e9bf6a7aef39c (patch) | |
tree | ceba858c1e7795665ec976cb676eafb17f8d4d1f | |
parent | c056043611675eb894a6d4417324438b28fd952c (diff) |
Prepare to get rid of the Qt3D dependency
This patch puts most Qt3D dependencies in ifdefs and thus is the
first step to eliminate the dependency.
Change-Id: Ifa3c3213aacd8dd50aec18fedd4df3d3c34671e8
Reviewed-by: Alex Blasche <alexander.blasche@digia.com>
25 files changed, 882 insertions, 522 deletions
diff --git a/src/imports/location/location.pro b/src/imports/location/location.pro index 8dccfa2d..c437eb77 100644 --- a/src/imports/location/location.pro +++ b/src/imports/location/location.pro @@ -1,4 +1,4 @@ -QT += quick-private network positioning-private location-private qml-private 3d core-private gui-private +QT += quick-private network positioning-private location-private qml-private core-private gui-private INCLUDEPATH += ../../location INCLUDEPATH += ../../location/maps @@ -15,6 +15,21 @@ win32 { } } +qtHaveModule(3d):!no_qt3d { + QT += 3d + + SOURCES += mapnode_qt3d.cpp + + HEADERS += mapnode_qt3d_p.h +} else { + DEFINES += NO_QT3D_RENDERER + SOURCES += mapnode_sg.cpp + + HEADERS += mapnode_sg_p.h +} + + + HEADERS += \ qdeclarativegeomapitemview_p.h \ qdeclarativegeomapmouseevent_p.h \ @@ -29,7 +44,6 @@ HEADERS += \ qdeclarativegeomaptype_p.h \ qdeclarativegeomapitembase_p.h \ qdeclarativegeomapquickitem_p.h \ - mapnode_p.h \ qdeclarativecirclemapitem_p.h \ qdeclarativerectanglemapitem_p.h \ qdeclarativepolygonmapitem_p.h \ @@ -56,7 +70,6 @@ SOURCES += \ qdeclarativegeomaptype.cpp \ qdeclarativegeomapitembase.cpp \ qdeclarativegeomapquickitem.cpp \ - mapnode.cpp \ qdeclarativecirclemapitem.cpp \ qdeclarativerectanglemapitem.cpp \ qdeclarativepolygonmapitem.cpp \ diff --git a/src/imports/location/mapnode.cpp b/src/imports/location/mapnode_qt3d.cpp index 3c557d35..f02b8158 100644 --- a/src/imports/location/mapnode.cpp +++ b/src/imports/location/mapnode_qt3d.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "mapnode_p.h" +#include "mapnode_qt3d_p.h" #include "qgeomap_p.h" #include <Qt3D/qglpainter.h> #include <Qt3D/QGLFramebufferObjectSurface> diff --git a/src/imports/location/mapnode_p.h b/src/imports/location/mapnode_qt3d_p.h index 911b8f77..911b8f77 100644 --- a/src/imports/location/mapnode_p.h +++ b/src/imports/location/mapnode_qt3d_p.h diff --git a/src/imports/location/mapnode_sg.cpp b/src/imports/location/mapnode_sg.cpp new file mode 100644 index 00000000..3a44e0b1 --- /dev/null +++ b/src/imports/location/mapnode_sg.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "mapnode_sg_p.h" + +MapNode::MapNode(QGeoMap *map) : + m_map(map) +{ +} + +MapNode::~MapNode() +{ + +} + +void MapNode::setSize(const QSize &size) +{ + if (size == m_size) + return; + m_size = size; + markDirty(DirtyGeometry); +} + +void MapNode::update() +{ + +} diff --git a/src/imports/location/mapnode_sg_p.h b/src/imports/location/mapnode_sg_p.h new file mode 100644 index 00000000..02c2ddd9 --- /dev/null +++ b/src/imports/location/mapnode_sg_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAPNODE_SG_P_H +#define MAPNODE_SG_P_H + +#include <QSGNode> + +QT_BEGIN_NAMESPACE + +class QGeoMap; + +class MapNode : public QSGNode +{ +public: + explicit MapNode(QGeoMap *m_map); + ~MapNode(); + + void setSize(const QSize &size); + QSize size() const { return m_size; } + void update(); + +private: + QGeoMap *m_map; + QSize m_size; +}; + +QT_END_NAMESPACE + +#endif // MAPNODE_SG_P_H diff --git a/src/imports/location/qdeclarativegeomap.cpp b/src/imports/location/qdeclarativegeomap.cpp index bc97bed1..02f65437 100644 --- a/src/imports/location/qdeclarativegeomap.cpp +++ b/src/imports/location/qdeclarativegeomap.cpp @@ -54,7 +54,13 @@ #include "qgeocameradata_p.h" #include "qgeocameracapabilities_p.h" #include "qgeomapcontroller_p.h" -#include "mapnode_p.h" + +#ifdef NO_QT3D_RENDERER +#include "mapnode_sg_p.h" +#else +#include "mapnode_qt3d_p.h" +#endif + #include <cmath> #include <QtPositioning/QGeoCoordinate> diff --git a/src/imports/location/qdeclarativegeomap_p.h b/src/imports/location/qdeclarativegeomap_p.h index b024d006..b231c76e 100644 --- a/src/imports/location/qdeclarativegeomap_p.h +++ b/src/imports/location/qdeclarativegeomap_p.h @@ -223,10 +223,6 @@ private: QDeclarativeGeoMapGestureArea *gestureArea_; - void paintGL(QGLPainter *painter); - void earlyDraw(QGLPainter *painter); - void restoreDefaults(QGLPainter *painter); - QQuickWindow *window_; int touchTimer_; diff --git a/src/location/maps/maps.pri b/src/location/maps/maps.pri index 3a43c5ea..df0b0f2d 100644 --- a/src/location/maps/maps.pri +++ b/src/location/maps/maps.pri @@ -1,7 +1,16 @@ INCLUDEPATH += maps -QT_PRIVATE += gui 3d +QT_PRIVATE += gui + +qtHaveModule(3d):!no_qt3d { + QT_PRIVATE += 3d + SOURCES += maps/qgeomapsscene_qt3d.cpp +} else { + QT_PRIVATE += quick + DEFINES += NO_QT3D_RENDERER + SOURCES += maps/qgeomapscene_sg.cpp +} PUBLIC_HEADERS += \ maps/qgeocodereply.h \ @@ -55,7 +64,8 @@ PRIVATE_HEADERS += \ maps/qgeotiledmapreply_p_p.h \ maps/qgeotilespec_p.h \ maps/qgeotilespec_p_p.h \ - maps/qcache3q_p.h + maps/qcache3q_p.h \ + maps/qgeomapscene_p_p.h SOURCES += \ maps/qgeocameracapabilities.cpp \ @@ -89,3 +99,4 @@ SOURCES += \ maps/qgeotilespec.cpp + diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp index 1f2b6e9b..c9e79fcb 100644 --- a/src/location/maps/qgeomap.cpp +++ b/src/location/maps/qgeomap.cpp @@ -95,6 +95,7 @@ QGeoMapController *QGeoMap::mapController() return mapData_->mapController(); } +#ifndef NO_QT3D_RENDERER QGLCamera *QGeoMap::glCamera() const { return mapData_->glCamera(); @@ -104,6 +105,7 @@ void QGeoMap::paintGL(QGLPainter *painter) { mapData_->paintGL(painter); } +#endif void QGeoMap::resize(int width, int height) { diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h index e956d886..d27fd178 100644 --- a/src/location/maps/qgeomap_p.h +++ b/src/location/maps/qgeomap_p.h @@ -87,8 +87,10 @@ public: QGeoMapController *mapController(); +#ifndef NO_QT3D_RENDERER QGLCamera *glCamera() const; void paintGL(QGLPainter *painter); +#endif void resize(int width, int height); int width() const; diff --git a/src/location/maps/qgeomapdata.cpp b/src/location/maps/qgeomapdata.cpp index 69e11530..7cb74920 100644 --- a/src/location/maps/qgeomapdata.cpp +++ b/src/location/maps/qgeomapdata.cpp @@ -91,11 +91,13 @@ QGeoMapController *QGeoMapData::mapController() return d->mapController(); } +#ifndef NO_QT3D_RENDERER QGLCamera *QGeoMapData::glCamera() const { Q_D(const QGeoMapData); return d->glCamera(); } +#endif void QGeoMapData::resize(int width, int height) { @@ -178,7 +180,9 @@ QGeoMapDataPrivate::QGeoMapDataPrivate(QGeoMappingManagerEngine *engine, QGeoMap : width_(0), height_(0), aspectRatio_(0.0), +#ifndef NO_QT3D_RENDERER camera_(new QGLCamera()), +#endif map_(parent), engine_(engine), controller_(0), @@ -190,8 +194,9 @@ QGeoMapDataPrivate::QGeoMapDataPrivate(QGeoMappingManagerEngine *engine, QGeoMap QGeoMapDataPrivate::~QGeoMapDataPrivate() { // controller_ is a child of map_, don't need to delete it here - +#ifndef NO_QT3D_RENDERER delete camera_; +#endif // TODO map items are not deallocated! // However: how to ensure this is done in rendering thread? } @@ -213,10 +218,12 @@ QGeoMapController *QGeoMapDataPrivate::mapController() return controller_; } +#ifndef NO_QT3D_RENDERER QGLCamera *QGeoMapDataPrivate::glCamera() const { return camera_; } +#endif void QGeoMapDataPrivate::setCameraData(const QGeoCameraData &cameraData) { diff --git a/src/location/maps/qgeomapdata_p.h b/src/location/maps/qgeomapdata_p.h index 35ed32c2..40a1b0d2 100644 --- a/src/location/maps/qgeomapdata_p.h +++ b/src/location/maps/qgeomapdata_p.h @@ -83,8 +83,10 @@ public: QGeoMapController *mapController(); +#ifndef NO_QT3D_RENDERER QGLCamera *glCamera() const; virtual void paintGL(QGLPainter *painter) = 0; +#endif void resize(int width, int height); int width() const; diff --git a/src/location/maps/qgeomapdata_p_p.h b/src/location/maps/qgeomapdata_p_p.h index 5e81d457..0c1238a9 100644 --- a/src/location/maps/qgeomapdata_p_p.h +++ b/src/location/maps/qgeomapdata_p_p.h @@ -87,8 +87,9 @@ public: QGeoMapController *mapController(); +#ifndef NO_QT3D_RENDERER QGLCamera *glCamera() const; - +#endif void setCameraData(const QGeoCameraData &cameraData); QGeoCameraData cameraData() const; diff --git a/src/location/maps/qgeomapscene.cpp b/src/location/maps/qgeomapscene.cpp index cb24861f..feade05e 100644 --- a/src/location/maps/qgeomapscene.cpp +++ b/src/location/maps/qgeomapscene.cpp @@ -49,100 +49,21 @@ #include <QtPositioning/private/qdoublevector2d_p.h> #include <QtPositioning/private/qdoublevector3d_p.h> -#include <Qt3D/qglscenenode.h> -#include <Qt3D/qglbuilder.h> -#include <Qt3D/qglmaterial.h> -#include <Qt3D/qgltexture2d.h> -#include <Qt3D/qgeometrydata.h> -#include <Qt3D/qglcamera.h> -#include <Qt3D/qglpainter.h> -#include <Qt3D/QGLLightParameters> - - #include <QHash> #include <QPointF> #include <cmath> -QT_BEGIN_NAMESPACE +#include "qgeomapscene_p_p.h" -class QGeoMapScenePrivate -{ -public: - explicit QGeoMapScenePrivate(QGeoMapScene *scene); - ~QGeoMapScenePrivate(); - - QSize screenSize_; // in pixels - int tileSize_; // the pixel resolution for each tile - QGeoCameraData cameraData_; - QSet<QGeoTileSpec> visibleTiles_; - - QGLCamera *camera_; - QGLSceneNode *sceneNode_; - QGLLightParameters* light_; - - // scales up the tile geometry and the camera altitude, resulting in no visible effect - // other than to control the accuracy of the render by keeping the values in a sensible range - double scaleFactor_; - - // rounded down, positive zoom is zooming in, corresponding to reduced altitude - int intZoomLevel_; - - // mercatorToGrid transform - // the number of tiles in each direction for the whole map (earth) at the current zoom level. - // it is 1<<zoomLevel - int sideLength_; - - QHash<QGeoTileSpec, QGLSceneNode *> nodes_; - QHash<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > textures_; - QList<QSharedPointer<QGeoTileTexture> > newUploads_; - - // tilesToGrid transform - int minTileX_; // the minimum tile index, i.e. 0 to sideLength which is 1<< zoomLevel - int minTileY_; - int maxTileX_; - int maxTileY_; - int tileZ_; // caches the zoom level for this tile set - int tileXWrapsBelow_; // the wrap point as a tile index - - // cameraToGrid transform - double mercatorCenterX_; // centre of camera in grid space (0 to sideLength) - double mercatorCenterY_; - double mercatorWidth_; // width of camera in grid space (0 to sideLength) - double mercatorHeight_; - - // screenToWindow transform - double screenOffsetX_; // in pixels - double screenOffsetY_; // in pixels - // cameraToScreen transform - double screenWidth_; // in pixels - double screenHeight_; // in pixels - - bool useVerticalLock_; - bool verticalLock_; - bool linearScaling_; - - void addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture); - - QDoubleVector2D screenPositionToMercator(const QDoubleVector2D &pos) const; - QDoubleVector2D mercatorToScreenPosition(const QDoubleVector2D &mercator) const; - - void setVisibleTiles(const QSet<QGeoTileSpec> &tiles); - void removeTiles(const QSet<QGeoTileSpec> &oldTiles); - void updateTiles(const QSet<QGeoTileSpec> &tiles); - QGeometryData buildGeometry(const QGeoTileSpec &spec); - QGLSceneNode *buildSceneNodeFromGeometry(const QGeometryData &geom); - void setTileBounds(const QSet<QGeoTileSpec> &tiles); - void setupCamera(); - void setScalingOnTextures(); - - void paintGL(QGLPainter *painter); - -private: - QGeoMapScene *q_ptr; - Q_DECLARE_PUBLIC(QGeoMapScene) -}; +#ifndef NO_QT3D_RENDERER +#include <QGLLightParameters> +#include <QGLSceneNode> +#include <QGLCamera> +#endif + +QT_BEGIN_NAMESPACE QGeoMapScene::QGeoMapScene() : QObject(), @@ -211,17 +132,17 @@ QDoubleVector2D QGeoMapScene::mercatorToScreenPosition(const QDoubleVector2D &me return d->mercatorToScreenPosition(mercator); } -QGLCamera *QGeoMapScene::camera() const -{ - Q_D(const QGeoMapScene); - return d->camera_; -} +//QGLCamera *QGeoMapScene::camera() const +//{ +// Q_D(const QGeoMapScene); +// return d->camera_; +//} -QGLSceneNode *QGeoMapScene::sceneNode() const -{ - Q_D(const QGeoMapScene); - return d->sceneNode_; -} +//QGLSceneNode *QGeoMapScene::sceneNode() const +//{ +// Q_D(const QGeoMapScene); +// return d->sceneNode_; +//} bool QGeoMapScene::verticalLock() const { @@ -229,11 +150,13 @@ bool QGeoMapScene::verticalLock() const return d->verticalLock_; } +#ifndef NO_QT3D_RENDERER void QGeoMapScene::paintGL(QGLPainter *painter) { Q_D(QGeoMapScene); d->paintGL(painter); } +#endif QSet<QGeoTileSpec> QGeoMapScene::texturedTiles() { @@ -247,9 +170,11 @@ QSet<QGeoTileSpec> QGeoMapScene::texturedTiles() QGeoMapScenePrivate::QGeoMapScenePrivate(QGeoMapScene *scene) : tileSize_(0), +#ifndef NO_QT3D_RENDERER camera_(new QGLCamera()), sceneNode_(new QGLSceneNode()), light_(new QGLLightParameters()), +#endif scaleFactor_(10.0), intZoomLevel_(0), sideLength_(0), @@ -272,12 +197,6 @@ QGeoMapScenePrivate::QGeoMapScenePrivate(QGeoMapScene *scene) linearScaling_(true), q_ptr(scene) {} -QGeoMapScenePrivate::~QGeoMapScenePrivate() -{ - delete sceneNode_; - delete camera_; - delete light_; -} QDoubleVector2D QGeoMapScenePrivate::screenPositionToMercator(const QDoubleVector2D &pos) const { @@ -340,215 +259,6 @@ QDoubleVector2D QGeoMapScenePrivate::mercatorToScreenPosition(const QDoubleVecto return QDoubleVector2D(x + screenOffsetX_, y + screenOffsetY_); } -QGeometryData QGeoMapScenePrivate::buildGeometry(const QGeoTileSpec &spec) -{ - int x = spec.x(); - - if (x < tileXWrapsBelow_) - x += sideLength_; - - if ((x < minTileX_) - || (maxTileX_ < x) - || (spec.y() < minTileY_) - || (maxTileY_ < spec.y()) - || (spec.zoom() != tileZ_)) { - return 0; - } - - double edge = scaleFactor_ * tileSize_; - - double x1 = (x - minTileX_); - double x2 = x1 + 1.0; - - double y1 = (minTileY_ - spec.y()); - double y2 = y1 - 1.0; - - x1 *= edge; - x2 *= edge; - y1 *= edge; - y2 *= edge; - - QGeometryData g; - - QDoubleVector3D n = QDoubleVector3D(0, 0, 1); - - //Texture coordinate order for veritcal flip of texture - g.appendVertex(QVector3D(x1, y1, 0.0)); - g.appendNormal(n); - g.appendTexCoord(QVector2D(0.0, 0.0)); - - g.appendVertex(QVector3D(x1, y2, 0.0)); - g.appendNormal(n); - g.appendTexCoord(QVector2D(0.0, 1.0)); - - g.appendVertex(QVector3D(x2, y2, 0.0)); - g.appendNormal(n); - g.appendTexCoord(QVector2D(1.0, 1.0)); - - g.appendVertex(QVector3D(x2, y1, 0.0)); - g.appendNormal(n); - g.appendTexCoord(QVector2D(1.0, 0.0)); - - return g; -} - -QGLSceneNode *QGeoMapScenePrivate::buildSceneNodeFromGeometry(const QGeometryData &geom) -{ - QGLBuilder builder; - builder.addQuads(geom); - return builder.finalizedSceneNode(); -} - - -void QGeoMapScenePrivate::setScalingOnTextures() -{ - if (!linearScaling_) { - foreach (const QSharedPointer<QGeoTileTexture> &tex, textures_.values()) { - tex->texture->setBindOptions(tex->texture->bindOptions() & - (~QGLTexture2D::LinearFilteringBindOption)); - } - } else { - foreach (const QSharedPointer<QGeoTileTexture> &tex, textures_.values()) { - tex->texture->setBindOptions(tex->texture->bindOptions() | - (QGLTexture2D::LinearFilteringBindOption)); - } - } -} - -void QGeoMapScenePrivate::addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture) -{ - if (!visibleTiles_.contains(spec)) // Don't add the geometry if it isn't visible - return; - if (linearScaling_) { - texture->texture->setBindOptions(texture->texture->bindOptions() | - (QGLTexture2D::LinearFilteringBindOption)); - } else { - texture->texture->setBindOptions(texture->texture->bindOptions() & - (~QGLTexture2D::LinearFilteringBindOption)); - } - - //Avoid expensive conversion of ARGB32_Premultiplied to ARGB32 - if (texture->texture->image().format() == QImage::Format_ARGB32_Premultiplied) { - texture->texture->setBindOptions(texture->texture->bindOptions() | - (QGLTexture2D::PremultipliedAlphaBindOption)); - } - - //There are tiles for different zoom levels, no need for mipmaps - texture->texture->setBindOptions(texture->texture->bindOptions() & (~QGLTexture2D::MipmapBindOption)); - - //We flip the texture coordinates instead of the texture - texture->texture->setBindOptions(texture->texture->bindOptions() & (~QGLTexture2D::InvertedYBindOption)); - - QGLSceneNode *node = nodes_.value(spec, 0); - if (!node) { - QGeometryData geom = buildGeometry(spec); - node = buildSceneNodeFromGeometry(geom); - if (!node) - return; - - QGLMaterial *mat = new QGLMaterial(node); - mat->setTexture(texture->texture); - node->setEffect(QGL::LitDecalTexture2D); - node->setMaterial(mat); - - sceneNode_->addNode(node); - nodes_.insert(spec, node); - textures_.insert(spec, texture); - newUploads_ << texture; - - } else { - // TODO handle texture updates when we make node removal more efficient - if (textures_[spec].data() != texture.data()) { - textures_.insert(spec, texture); - node->material()->setTexture(texture->texture); - newUploads_ << texture; - } - } -} - -// return true if new tiles introduced in [tiles] -void QGeoMapScenePrivate::setVisibleTiles(const QSet<QGeoTileSpec> &tiles) -{ - Q_Q(QGeoMapScene); - - // detect if new tiles introduced - bool newTilesIntroduced = !visibleTiles_.contains(tiles); - - // work out the tile bounds for the new scene - setTileBounds(tiles); - - // set up the gl camera for the new scene - setupCamera(); - - QSet<QGeoTileSpec> toRemove = visibleTiles_ - tiles; - QSet<QGeoTileSpec> toUpdate = visibleTiles_ - toRemove; - if (!toRemove.isEmpty()) - removeTiles(toRemove); - - // only need to update tiles when the bounds have changed, - if (visibleTiles_ != tiles && !toUpdate.isEmpty()) - updateTiles(toUpdate); - - visibleTiles_ = tiles; - if (newTilesIntroduced) - emit q->newTilesVisible(visibleTiles_); -} - -void QGeoMapScenePrivate::updateTiles(const QSet<QGeoTileSpec> &tiles) -{ - typedef QSet<QGeoTileSpec>::const_iterator iter; - iter i = tiles.constBegin(); - iter end = tiles.constEnd(); - for (; i != end; ++i) { - QGeoTileSpec tile = *i; - QGLSceneNode *node = nodes_.value(tile, 0); - - if (node) { - QGeometryData geom = buildGeometry(tile); - // if the new geometry (after wrapping) is the same as the old one, - // it can be reused - if ( node->children().size() > 0) { - if (node->children().front()->geometry() == geom) - continue; - } - - sceneNode_->removeNode(node); - QGLSceneNode *newNode = buildSceneNodeFromGeometry(geom); - if (newNode) { - QGLMaterial *mat = new QGLMaterial(newNode); - mat->setTexture(textures_[tile]->texture); - newNode->setEffect(QGL::LitDecalTexture2D); - newNode->setMaterial(mat); - sceneNode_->addNode(newNode); - nodes_.insert(tile, newNode); - } else { - nodes_.remove(tile); - textures_.remove(tile); - } - delete node; - } - } -} - -void QGeoMapScenePrivate::removeTiles(const QSet<QGeoTileSpec> &oldTiles) -{ - typedef QSet<QGeoTileSpec>::const_iterator iter; - iter i = oldTiles.constBegin(); - iter end = oldTiles.constEnd(); - - for (; i != end; ++i) { - QGeoTileSpec tile = *i; - QGLSceneNode *node = nodes_.value(tile, 0); - if (node) { - // TODO protect with mutex? - sceneNode_->removeNode(node); - nodes_.remove(tile); - textures_.remove(tile); - delete node; - } - } -} - void QGeoMapScenePrivate::setTileBounds(const QSet<QGeoTileSpec> &tiles) { if (tiles.isEmpty()) { @@ -627,188 +337,5 @@ void QGeoMapScenePrivate::setTileBounds(const QSet<QGeoTileSpec> &tiles) } } -void QGeoMapScenePrivate::setupCamera() -{ - - double f = 1.0 * qMin(screenSize_.width(), screenSize_.height()); - - // fraction of zoom level - double z = std::pow(2.0, cameraData_.zoomLevel() - intZoomLevel_); - - // calculate altitdue that allows the visible map tiles - // to fit in the screen correctly (note that a larger f will cause - // the camera be higher, resulting in gray areas displayed around - // the tiles) - double altitude = scaleFactor_ * f / (2.0 * z); - - double aspectRatio = 1.0 * screenSize_.width() / screenSize_.height(); - - double a = f / (z * tileSize_); - - // mercatorWidth_ and mercatorHeight_ define the ratio for - // mercator and screen coordinate conversion, - // see mercatorToScreenPosition() and screenPositionToMercator() - if (aspectRatio > 1.0) { - mercatorHeight_ = a; - mercatorWidth_ = a * aspectRatio; - } else { - mercatorWidth_ = a; - mercatorHeight_ = a / aspectRatio; - } - - // calculate center - - double edge = scaleFactor_ * tileSize_; - - // first calculate the camera center in map space in the range of 0 <-> sideLength (2^z) - QDoubleVector3D center = (sideLength_ * QGeoProjection::coordToMercator(cameraData_.center())); - - // wrap the center if necessary (due to dateline crossing) - if (center.x() < tileXWrapsBelow_) - center.setX(center.x() + 1.0 * sideLength_); - - mercatorCenterX_ = center.x(); - mercatorCenterY_ = center.y(); - - // work out where the camera center is w.r.t minimum tile bounds - center.setX(center.x() - 1.0 * minTileX_); - center.setY(1.0 * minTileY_ - center.y()); - - // letter box vertically - if (useVerticalLock_ && (mercatorHeight_ > 1.0 * sideLength_)) { - center.setY(-1.0 * sideLength_ / 2.0); - mercatorCenterY_ = sideLength_ / 2.0; - screenOffsetY_ = screenSize_.height() * (0.5 - sideLength_ / (2 * mercatorHeight_)); - screenHeight_ = screenSize_.height() - 2 * screenOffsetY_; - mercatorHeight_ = 1.0 * sideLength_; - verticalLock_ = true; - } else { - screenOffsetY_ = 0.0; - screenHeight_ = screenSize_.height(); - verticalLock_ = false; - } - - if (mercatorWidth_ > 1.0 * sideLength_) { - screenOffsetX_ = screenSize_.width() * (0.5 - (sideLength_ / (2 * mercatorWidth_))); - screenWidth_ = screenSize_.width() - 2 * screenOffsetX_; - mercatorWidth_ = 1.0 * sideLength_; - } else { - screenOffsetX_ = 0.0; - screenWidth_ = screenSize_.width(); - } - - // apply necessary scaling to the camera center - center *= edge; - - // calculate eye - - QDoubleVector3D eye = center; - eye.setZ(altitude); - - // calculate up - - QDoubleVector3D view = eye - center; - QDoubleVector3D side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); - QDoubleVector3D up = QDoubleVector3D::normal(side, view); - - // old bearing, tilt and roll code - // QMatrix4x4 mBearing; - // mBearing.rotate(-1.0 * camera.bearing(), view); - // up = mBearing * up; - - // QDoubleVector3D side2 = QDoubleVector3D::normal(up, view); - // QMatrix4x4 mTilt; - // mTilt.rotate(camera.tilt(), side2); - // eye = (mTilt * view) + center; - - // view = eye - center; - // side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); - // up = QDoubleVector3D::normal(view, side2); - - // QMatrix4x4 mRoll; - // mRoll.rotate(camera.roll(), view); - // up = mRoll * up; - - // near plane and far plane - - double nearPlane = 1.0; - double farPlane = 4.0 * edge; - - // TODO protect with mutex? - // set glcamera parameters - camera_->setCenter(center); - camera_->setEye(eye); - camera_->setUpVector(up); - camera_->setNearPlane(nearPlane); - camera_->setFarPlane(farPlane); -} - -void QGeoMapScenePrivate::paintGL(QGLPainter *painter) -{ - // TODO protect with mutex? - - // TODO add a shortcut here for when we don't need to repeat and clip the map - // NOTE- this is important as the repeat code below removes a lot of accuracy - // by converting to float and adding/removing large numbers when at high zoom - - // do any pending upload/releases - while (!newUploads_.isEmpty()) { - if (!newUploads_.front()->textureBound) { - newUploads_.front()->texture->bind(); - newUploads_.front()->texture->clearImage(); - newUploads_.front()->textureBound = true; - } - newUploads_.pop_front(); - } - - glEnable(GL_SCISSOR_TEST); - - painter->setScissor(QRect(screenOffsetX_, screenOffsetY_, screenWidth_, screenHeight_)); - - painter->setCamera(camera_); - - painter->setMainLight(light_); - - sceneNode_->draw(painter); - - QGLCamera *camera = camera_; - - bool old = camera->blockSignals(true); - - glDisable(GL_DEPTH_TEST); - - double sideLength = scaleFactor_ * tileSize_ * sideLength_; - - QDoubleVector3D c = QDoubleVector3D(camera->center()); - c.setX(c.x() + sideLength); - camera->setCenter(c); - - QDoubleVector3D e = QDoubleVector3D(camera->eye()); - e.setX(e.x() + sideLength); - camera->setEye(e); - - painter->setCamera(camera); - sceneNode_->draw(painter); - - c.setX(c.x() - 2 * sideLength); - camera->setCenter(c); - e.setX(e.x() - 2 * sideLength); - camera->setEye(e); - - painter->setCamera(camera); - sceneNode_->draw(painter); - - c.setX(c.x() + sideLength); - camera->setCenter(c); - e.setX(e.x() + sideLength); - camera->setEye(e); - - painter->setCamera(camera); - sceneNode_->draw(painter); - - glEnable(GL_DEPTH_TEST); - - camera->blockSignals(old); -} QT_END_NAMESPACE diff --git a/src/location/maps/qgeomapscene_p.h b/src/location/maps/qgeomapscene_p.h index 203eeb8a..47c82e2a 100644 --- a/src/location/maps/qgeomapscene_p.h +++ b/src/location/maps/qgeomapscene_p.h @@ -67,10 +67,12 @@ class QGeoTileSpec; class QDoubleVector2D; +#ifndef NO_QT3D_RENDERER class QGLSceneNode; class QGLCamera; class QGLPainter; class QGLTexture2D; +#endif class QGeoTileTexture; class QPointF; @@ -97,10 +99,11 @@ public: QDoubleVector2D screenPositionToMercator(const QDoubleVector2D &pos) const; QDoubleVector2D mercatorToScreenPosition(const QDoubleVector2D &mercator) const; - QGLCamera *camera() const; - QGLSceneNode *sceneNode() const; + //QGLCamera *camera() const; + //QGLSceneNode *sceneNode() const; +#ifndef NO_QT3D_RENDERER void paintGL(QGLPainter *painter); - +#endif bool verticalLock() const; QSet<QGeoTileSpec> texturedTiles(); diff --git a/src/location/maps/qgeomapscene_p_p.h b/src/location/maps/qgeomapscene_p_p.h new file mode 100644 index 00000000..f1fb6c48 --- /dev/null +++ b/src/location/maps/qgeomapscene_p_p.h @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited and/or its subsidiary(-ies). +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPSCENE_P_P_H +#define QGEOMAPSCENE_P_P_H + +#ifndef NO_QT3D_RENDERER +#include <Qt3D/qgeometrydata.h> +#else +#include <QSGNode> +#endif + +#include "qgeocameradata_p.h" +#include "qgeomapscene_p.h" + +#ifndef NO_QT3D_RENDERER +class QGLLightParameters; +#endif + +class QGeoMapScenePrivate +{ +public: + explicit QGeoMapScenePrivate(QGeoMapScene *scene); + ~QGeoMapScenePrivate(); + + QSize screenSize_; // in pixels + int tileSize_; // the pixel resolution for each tile + QGeoCameraData cameraData_; + QSet<QGeoTileSpec> visibleTiles_; + +#ifndef NO_QT3D_RENDERER + QGLCamera *camera_; + QGLSceneNode *sceneNode_; + QGLLightParameters* light_; +#endif + + // scales up the tile geometry and the camera altitude, resulting in no visible effect + // other than to control the accuracy of the render by keeping the values in a sensible range + double scaleFactor_; + + // rounded down, positive zoom is zooming in, corresponding to reduced altitude + int intZoomLevel_; + + // mercatorToGrid transform + // the number of tiles in each direction for the whole map (earth) at the current zoom level. + // it is 1<<zoomLevel + int sideLength_; + +#ifndef NO_QT3D_RENDERER + QHash<QGeoTileSpec, QGLSceneNode *> nodes_; +#else + QHash<QGeoTileSpec, QSGNode *> nodes_; +#endif + QHash<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > textures_; + QList<QSharedPointer<QGeoTileTexture> > newUploads_; + + // tilesToGrid transform + int minTileX_; // the minimum tile index, i.e. 0 to sideLength which is 1<< zoomLevel + int minTileY_; + int maxTileX_; + int maxTileY_; + int tileZ_; // caches the zoom level for this tile set + int tileXWrapsBelow_; // the wrap point as a tile index + + // cameraToGrid transform + double mercatorCenterX_; // center of camera in grid space (0 to sideLength) + double mercatorCenterY_; + double mercatorWidth_; // width of camera in grid space (0 to sideLength) + double mercatorHeight_; + + // screenToWindow transform + double screenOffsetX_; // in pixels + double screenOffsetY_; // in pixels + // cameraToScreen transform + double screenWidth_; // in pixels + double screenHeight_; // in pixels + + bool useVerticalLock_; + bool verticalLock_; + bool linearScaling_; + + void addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture); + + QDoubleVector2D screenPositionToMercator(const QDoubleVector2D &pos) const; + QDoubleVector2D mercatorToScreenPosition(const QDoubleVector2D &mercator) const; + + void setVisibleTiles(const QSet<QGeoTileSpec> &tiles); + void removeTiles(const QSet<QGeoTileSpec> &oldTiles); + void updateTiles(const QSet<QGeoTileSpec> &tiles); +#ifndef NO_QT3D_RENDERER + QGeometryData buildGeometry(const QGeoTileSpec &spec); + QGLSceneNode *buildSceneNodeFromGeometry(const QGeometryData &geom); + void paintGL(QGLPainter *painter); +#endif + void setTileBounds(const QSet<QGeoTileSpec> &tiles); + void setupCamera(); + void setScalingOnTextures(); + +private: + QGeoMapScene *q_ptr; + Q_DECLARE_PUBLIC(QGeoMapScene) +}; + + +#endif // QGEOMAPSCENE_P_P_H diff --git a/src/location/maps/qgeomapscene_sg.cpp b/src/location/maps/qgeomapscene_sg.cpp new file mode 100644 index 00000000..1b0b5a35 --- /dev/null +++ b/src/location/maps/qgeomapscene_sg.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeomapscene_p_p.h" + +QT_BEGIN_NAMESPACE + + +QGeoMapScenePrivate::~QGeoMapScenePrivate() +{ +} + +void QGeoMapScenePrivate::setScalingOnTextures() +{ +} + +void QGeoMapScenePrivate::addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture) +{ +} + +// return true if new tiles introduced in [tiles] +void QGeoMapScenePrivate::setVisibleTiles(const QSet<QGeoTileSpec> &tiles) +{ +} + +QT_END_NAMESPACE + diff --git a/src/location/maps/qgeomapsscene_qt3d.cpp b/src/location/maps/qgeomapsscene_qt3d.cpp new file mode 100644 index 00000000..9ef66398 --- /dev/null +++ b/src/location/maps/qgeomapsscene_qt3d.cpp @@ -0,0 +1,420 @@ +#include <Qt3D/qglscenenode.h> +#include <Qt3D/qglbuilder.h> +#include <Qt3D/qglmaterial.h> +#include <Qt3D/qgltexture2d.h> +#include <Qt3D/qglcamera.h> +#include <Qt3D/qglpainter.h> +#include <Qt3D/QGLLightParameters> + +#include "qgeomapscene_p_p.h" + +#include "qgeotilespec_p.h" +#include "qgeotilecache_p.h" +#include <QtPositioning/private/qgeoprojection_p.h> +#include <QtPositioning/private/qdoublevector2d_p.h> +#include <QtPositioning/private/qdoublevector3d_p.h> + +QT_BEGIN_NAMESPACE + +QGeoMapScenePrivate::~QGeoMapScenePrivate() +{ + delete sceneNode_; + delete camera_; + delete light_; +} + +QGeometryData QGeoMapScenePrivate::buildGeometry(const QGeoTileSpec &spec) +{ + int x = spec.x(); + + if (x < tileXWrapsBelow_) + x += sideLength_; + + if ((x < minTileX_) + || (maxTileX_ < x) + || (spec.y() < minTileY_) + || (maxTileY_ < spec.y()) + || (spec.zoom() != tileZ_)) { + return 0; + } + + double edge = scaleFactor_ * tileSize_; + + double x1 = (x - minTileX_); + double x2 = x1 + 1.0; + + double y1 = (minTileY_ - spec.y()); + double y2 = y1 - 1.0; + + x1 *= edge; + x2 *= edge; + y1 *= edge; + y2 *= edge; + + QGeometryData g; + + QDoubleVector3D n = QDoubleVector3D(0, 0, 1); + + //Texture coordinate order for veritcal flip of texture + g.appendVertex(QVector3D(x1, y1, 0.0)); + g.appendNormal(n); + g.appendTexCoord(QVector2D(0.0, 0.0)); + + g.appendVertex(QVector3D(x1, y2, 0.0)); + g.appendNormal(n); + g.appendTexCoord(QVector2D(0.0, 1.0)); + + g.appendVertex(QVector3D(x2, y2, 0.0)); + g.appendNormal(n); + g.appendTexCoord(QVector2D(1.0, 1.0)); + + g.appendVertex(QVector3D(x2, y1, 0.0)); + g.appendNormal(n); + g.appendTexCoord(QVector2D(1.0, 0.0)); + + return g; +} + +QGLSceneNode *QGeoMapScenePrivate::buildSceneNodeFromGeometry(const QGeometryData &geom) +{ + QGLBuilder builder; + builder.addQuads(geom); + return builder.finalizedSceneNode(); +} + + +void QGeoMapScenePrivate::setScalingOnTextures() +{ + if (!linearScaling_) { + foreach (const QSharedPointer<QGeoTileTexture> &tex, textures_.values()) { + tex->texture->setBindOptions(tex->texture->bindOptions() & + (~QGLTexture2D::LinearFilteringBindOption)); + } + } else { + foreach (const QSharedPointer<QGeoTileTexture> &tex, textures_.values()) { + tex->texture->setBindOptions(tex->texture->bindOptions() | + (QGLTexture2D::LinearFilteringBindOption)); + } + } +} + +void QGeoMapScenePrivate::addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture) +{ + if (!visibleTiles_.contains(spec)) // Don't add the geometry if it isn't visible + return; + if (linearScaling_) { + texture->texture->setBindOptions(texture->texture->bindOptions() | + (QGLTexture2D::LinearFilteringBindOption)); + } else { + texture->texture->setBindOptions(texture->texture->bindOptions() & + (~QGLTexture2D::LinearFilteringBindOption)); + } + + //Avoid expensive conversion of ARGB32_Premultiplied to ARGB32 + if (texture->texture->image().format() == QImage::Format_ARGB32_Premultiplied) { + texture->texture->setBindOptions(texture->texture->bindOptions() | + (QGLTexture2D::PremultipliedAlphaBindOption)); + } + + //There are tiles for different zoom levels, no need for mipmaps + texture->texture->setBindOptions(texture->texture->bindOptions() & (~QGLTexture2D::MipmapBindOption)); + + //We flip the texture coordinates instead of the texture + texture->texture->setBindOptions(texture->texture->bindOptions() & (~QGLTexture2D::InvertedYBindOption)); + + QGLSceneNode *node = nodes_.value(spec, 0); + if (!node) { + QGeometryData geom = buildGeometry(spec); + node = buildSceneNodeFromGeometry(geom); + if (!node) + return; + + QGLMaterial *mat = new QGLMaterial(node); + mat->setTexture(texture->texture); + node->setEffect(QGL::LitDecalTexture2D); + node->setMaterial(mat); + + sceneNode_->addNode(node); + nodes_.insert(spec, node); + textures_.insert(spec, texture); + newUploads_ << texture; + + } else { + // TODO handle texture updates when we make node removal more efficient + if (textures_[spec].data() != texture.data()) { + textures_.insert(spec, texture); + node->material()->setTexture(texture->texture); + newUploads_ << texture; + } + } +} + +// return true if new tiles introduced in [tiles] +void QGeoMapScenePrivate::setVisibleTiles(const QSet<QGeoTileSpec> &tiles) +{ + Q_Q(QGeoMapScene); + + // detect if new tiles introduced + bool newTilesIntroduced = !visibleTiles_.contains(tiles); + + // work out the tile bounds for the new scene + setTileBounds(tiles); + + // set up the gl camera for the new scene + setupCamera(); + + QSet<QGeoTileSpec> toRemove = visibleTiles_ - tiles; + QSet<QGeoTileSpec> toUpdate = visibleTiles_ - toRemove; + if (!toRemove.isEmpty()) + removeTiles(toRemove); + + // only need to update tiles when the bounds have changed, + if (visibleTiles_ != tiles && !toUpdate.isEmpty()) + updateTiles(toUpdate); + + visibleTiles_ = tiles; + if (newTilesIntroduced) + emit q->newTilesVisible(visibleTiles_); +} + +void QGeoMapScenePrivate::updateTiles(const QSet<QGeoTileSpec> &tiles) +{ + typedef QSet<QGeoTileSpec>::const_iterator iter; + iter i = tiles.constBegin(); + iter end = tiles.constEnd(); + for (; i != end; ++i) { + QGeoTileSpec tile = *i; + QGLSceneNode *node = nodes_.value(tile, 0); + + if (node) { + QGeometryData geom = buildGeometry(tile); + // if the new geometry (after wrapping) is the same as the old one, + // it can be reused + if ( node->children().size() > 0) { + if (node->children().front()->geometry() == geom) + continue; + } + + sceneNode_->removeNode(node); + QGLSceneNode *newNode = buildSceneNodeFromGeometry(geom); + if (newNode) { + QGLMaterial *mat = new QGLMaterial(newNode); + mat->setTexture(textures_[tile]->texture); + newNode->setEffect(QGL::LitDecalTexture2D); + newNode->setMaterial(mat); + sceneNode_->addNode(newNode); + nodes_.insert(tile, newNode); + } else { + nodes_.remove(tile); + textures_.remove(tile); + } + delete node; + } + } +} + +void QGeoMapScenePrivate::removeTiles(const QSet<QGeoTileSpec> &oldTiles) +{ + typedef QSet<QGeoTileSpec>::const_iterator iter; + iter i = oldTiles.constBegin(); + iter end = oldTiles.constEnd(); + + for (; i != end; ++i) { + QGeoTileSpec tile = *i; + QGLSceneNode *node = nodes_.value(tile, 0); + if (node) { + // TODO protect with mutex? + sceneNode_->removeNode(node); + nodes_.remove(tile); + textures_.remove(tile); + delete node; + } + } +} + +void QGeoMapScenePrivate::setupCamera() +{ + + double f = 1.0 * qMin(screenSize_.width(), screenSize_.height()); + + // fraction of zoom level + double z = std::pow(2.0, cameraData_.zoomLevel() - intZoomLevel_); + + // calculate altitdue that allows the visible map tiles + // to fit in the screen correctly (note that a larger f will cause + // the camera be higher, resulting in gray areas displayed around + // the tiles) + double altitude = scaleFactor_ * f / (2.0 * z); + + double aspectRatio = 1.0 * screenSize_.width() / screenSize_.height(); + + double a = f / (z * tileSize_); + + // mercatorWidth_ and mercatorHeight_ define the ratio for + // mercator and screen coordinate conversion, + // see mercatorToScreenPosition() and screenPositionToMercator() + if (aspectRatio > 1.0) { + mercatorHeight_ = a; + mercatorWidth_ = a * aspectRatio; + } else { + mercatorWidth_ = a; + mercatorHeight_ = a / aspectRatio; + } + + // calculate center + + double edge = scaleFactor_ * tileSize_; + + // first calculate the camera center in map space in the range of 0 <-> sideLength (2^z) + QDoubleVector3D center = (sideLength_ * QGeoProjection::coordToMercator(cameraData_.center())); + + // wrap the center if necessary (due to dateline crossing) + if (center.x() < tileXWrapsBelow_) + center.setX(center.x() + 1.0 * sideLength_); + + mercatorCenterX_ = center.x(); + mercatorCenterY_ = center.y(); + + // work out where the camera center is w.r.t minimum tile bounds + center.setX(center.x() - 1.0 * minTileX_); + center.setY(1.0 * minTileY_ - center.y()); + + // letter box vertically + if (useVerticalLock_ && (mercatorHeight_ > 1.0 * sideLength_)) { + center.setY(-1.0 * sideLength_ / 2.0); + mercatorCenterY_ = sideLength_ / 2.0; + screenOffsetY_ = screenSize_.height() * (0.5 - sideLength_ / (2 * mercatorHeight_)); + screenHeight_ = screenSize_.height() - 2 * screenOffsetY_; + mercatorHeight_ = 1.0 * sideLength_; + verticalLock_ = true; + } else { + screenOffsetY_ = 0.0; + screenHeight_ = screenSize_.height(); + verticalLock_ = false; + } + + if (mercatorWidth_ > 1.0 * sideLength_) { + screenOffsetX_ = screenSize_.width() * (0.5 - (sideLength_ / (2 * mercatorWidth_))); + screenWidth_ = screenSize_.width() - 2 * screenOffsetX_; + mercatorWidth_ = 1.0 * sideLength_; + } else { + screenOffsetX_ = 0.0; + screenWidth_ = screenSize_.width(); + } + + // apply necessary scaling to the camera center + center *= edge; + + // calculate eye + + QDoubleVector3D eye = center; + eye.setZ(altitude); + + // calculate up + + QDoubleVector3D view = eye - center; + QDoubleVector3D side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); + QDoubleVector3D up = QDoubleVector3D::normal(side, view); + + // old bearing, tilt and roll code + // QMatrix4x4 mBearing; + // mBearing.rotate(-1.0 * camera.bearing(), view); + // up = mBearing * up; + + // QDoubleVector3D side2 = QDoubleVector3D::normal(up, view); + // QMatrix4x4 mTilt; + // mTilt.rotate(camera.tilt(), side2); + // eye = (mTilt * view) + center; + + // view = eye - center; + // side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0)); + // up = QDoubleVector3D::normal(view, side2); + + // QMatrix4x4 mRoll; + // mRoll.rotate(camera.roll(), view); + // up = mRoll * up; + + // near plane and far plane + + double nearPlane = 1.0; + double farPlane = 4.0 * edge; + + // TODO protect with mutex? + // set glcamera parameters + camera_->setCenter(center); + camera_->setEye(eye); + camera_->setUpVector(up); + camera_->setNearPlane(nearPlane); + camera_->setFarPlane(farPlane); +} + +void QGeoMapScenePrivate::paintGL(QGLPainter *painter) +{ + // TODO protect with mutex? + + // TODO add a shortcut here for when we don't need to repeat and clip the map + // NOTE- this is important as the repeat code below removes a lot of accuracy + // by converting to float and adding/removing large numbers when at high zoom + + // do any pending upload/releases + while (!newUploads_.isEmpty()) { + if (!newUploads_.front()->textureBound) { + newUploads_.front()->texture->bind(); + newUploads_.front()->texture->clearImage(); + newUploads_.front()->textureBound = true; + } + newUploads_.pop_front(); + } + + glEnable(GL_SCISSOR_TEST); + + painter->setScissor(QRect(screenOffsetX_, screenOffsetY_, screenWidth_, screenHeight_)); + + painter->setCamera(camera_); + + painter->setMainLight(light_); + + sceneNode_->draw(painter); + + QGLCamera *camera = camera_; + + bool old = camera->blockSignals(true); + + glDisable(GL_DEPTH_TEST); + + double sideLength = scaleFactor_ * tileSize_ * sideLength_; + + QDoubleVector3D c = QDoubleVector3D(camera->center()); + c.setX(c.x() + sideLength); + camera->setCenter(c); + + QDoubleVector3D e = QDoubleVector3D(camera->eye()); + e.setX(e.x() + sideLength); + camera->setEye(e); + + painter->setCamera(camera); + sceneNode_->draw(painter); + + c.setX(c.x() - 2 * sideLength); + camera->setCenter(c); + e.setX(e.x() - 2 * sideLength); + camera->setEye(e); + + painter->setCamera(camera); + sceneNode_->draw(painter); + + c.setX(c.x() + sideLength); + camera->setCenter(c); + e.setX(e.x() + sideLength); + camera->setEye(e); + + painter->setCamera(camera); + sceneNode_->draw(painter); + + glEnable(GL_DEPTH_TEST); + + camera->blockSignals(old); +} + + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeotilecache.cpp b/src/location/maps/qgeotilecache.cpp index 8a86b7c4..a1852490 100644 --- a/src/location/maps/qgeotilecache.cpp +++ b/src/location/maps/qgeotilecache.cpp @@ -57,7 +57,12 @@ Q_DECLARE_METATYPE(QSet<QGeoTileSpec>) QT_BEGIN_NAMESPACE QMutex QGeoTileCache::cleanupMutex_; +#ifndef NO_QT3D_RENDERER QList<QGLTexture2D*> QGeoTileCache::cleanupList_; +#else +QList<void*> QGeoTileCache::cleanupList_; +#endif + class QGeoCachedTileMemory { @@ -272,6 +277,7 @@ int QGeoTileCache::textureUsage() const return textureCache_.totalCost(); } +#ifndef NO_QT3D_RENDERER void QGeoTileCache::GLContextAvailable() { QMutexLocker ml(&cleanupMutex_); @@ -290,6 +296,7 @@ void QGeoTileCache::GLContextAvailable() cleanupList_.pop_front(); } } +#endif QSharedPointer<QGeoTileTexture> QGeoTileCache::get(const QGeoTileSpec &spec) { @@ -402,10 +409,12 @@ QSharedPointer<QGeoTileTexture> QGeoTileCache::addToTextureCache(const QGeoTileS { QSharedPointer<QGeoTileTexture> tt(new QGeoTileTexture); tt->spec = spec; +#ifndef NO_QT3D_RENDERER tt->texture = new QGLTexture2D(); tt->texture->setPixmap(pixmap); tt->texture->setHorizontalWrap(QGL::ClampToEdge); tt->texture->setVerticalWrap(QGL::ClampToEdge); +#endif /* Do not bind/cleanImage on the texture here -- it needs to be done * in the render thread (by qgeomapscene) */ diff --git a/src/location/maps/qgeotilecache_p.h b/src/location/maps/qgeotilecache_p.h index 6fecfa8f..9e51860d 100644 --- a/src/location/maps/qgeotilecache_p.h +++ b/src/location/maps/qgeotilecache_p.h @@ -98,7 +98,11 @@ public: ~QGeoTileTexture(); QGeoTileSpec spec; +#ifndef NO_QT3D_RENDERER QGLTexture2D *texture; +#else + void *texture; //need a custom texture class here +#endif bool textureBound; }; @@ -132,7 +136,9 @@ public: int minTextureUsage() const; int textureUsage() const; +#ifndef NO_QT3D_RENDERER void GLContextAvailable(); +#endif QSharedPointer<QGeoTileTexture> get(const QGeoTileSpec &spec); @@ -169,7 +175,11 @@ private: int extraTextureUsage_; static QMutex cleanupMutex_; +#ifndef NO_QT3D_RENDERER static QList<QGLTexture2D*> cleanupList_; +#else + static QList<void*> cleanupList_; +#endif }; QT_END_NAMESPACE diff --git a/src/location/maps/qgeotiledmapdata.cpp b/src/location/maps/qgeotiledmapdata.cpp index 1655327b..bf45fdd7 100644 --- a/src/location/maps/qgeotiledmapdata.cpp +++ b/src/location/maps/qgeotiledmapdata.cpp @@ -55,14 +55,7 @@ #include <qnumeric.h> -#include <Qt3D/qglscenenode.h> -#include <Qt3D/qgeometrydata.h> -#include <Qt3D/qglbuilder.h> #include <Qt3D/qglpainter.h> -#include <Qt3D/qgeometrydata.h> -#include <Qt3D/qglbuilder.h> -#include <Qt3D/qglcamera.h> -#include <Qt3D/qglsubsurface.h> #include <QtPositioning/private/qgeoprojection_p.h> #include <QtPositioning/private/qdoublevector2d_p.h> @@ -103,11 +96,13 @@ QGeoTileCache *QGeoTiledMapData::tileCache() return d->tileCache(); } +#ifndef NO_QT3D_RENDERER void QGeoTiledMapData::paintGL(QGLPainter *painter) { Q_D(QGeoTiledMapData); d->paintGL(painter); } +#endif void QGeoTiledMapData::mapResized(int width, int height) { @@ -308,11 +303,13 @@ QSet<QGeoTileSpec> QGeoTiledMapDataPrivate::visibleTiles() return cameraTiles_->tiles(); } +#ifndef NO_QT3D_RENDERER void QGeoTiledMapDataPrivate::paintGL(QGLPainter *painter) { mapScene_->paintGL(painter); cache_->GLContextAvailable(); } +#endif QGeoCoordinate QGeoTiledMapDataPrivate::screenPositionToCoordinate(const QDoubleVector2D &pos) const { diff --git a/src/location/maps/qgeotiledmapdata_p.h b/src/location/maps/qgeotiledmapdata_p.h index 126454e4..c760926f 100644 --- a/src/location/maps/qgeotiledmapdata_p.h +++ b/src/location/maps/qgeotiledmapdata_p.h @@ -82,8 +82,9 @@ public: QGeoTileCache *tileCache(); +#ifndef NO_QT3D_RENDERER void paintGL(QGLPainter *painter); - +#endif void newTileFetched(const QGeoTileSpec &spec); QGeoCoordinate screenPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const; diff --git a/src/location/maps/qgeotiledmapdata_p_p.h b/src/location/maps/qgeotiledmapdata_p_p.h index 67ad5cc1..89f34e36 100644 --- a/src/location/maps/qgeotiledmapdata_p_p.h +++ b/src/location/maps/qgeotiledmapdata_p_p.h @@ -93,7 +93,9 @@ public: QGeoTileCache *tileCache(); +#ifndef NO_QT3D_RENDERER void paintGL(QGLPainter *painter); +#endif void changeCameraData(const QGeoCameraData &oldCameraData); void changeActiveMapType(const QGeoMapType mapType); diff --git a/src/plugins/geoservices/nokia/nokia.pro b/src/plugins/geoservices/nokia/nokia.pro index 597f8bae..c093bef8 100644 --- a/src/plugins/geoservices/nokia/nokia.pro +++ b/src/plugins/geoservices/nokia/nokia.pro @@ -49,6 +49,11 @@ SOURCES += \ include(placesv2/placesv2.pri) +qtHaveModule(3d):!no_qt3d { +} else { + DEFINES += NO_QT3D_RENDERER +} + RESOURCES += resource.qrc INCLUDEPATH += $$QT.location.includes diff --git a/src/src.pro b/src/src.pro index 72274cdc..4a42f439 100644 --- a/src/src.pro +++ b/src/src.pro @@ -10,11 +10,16 @@ positioning_doc_snippets.depends = positioning SUBDIRS += positioning_doc_snippets #no point in building QtLocation without Qt3D -qtHaveModule(3d) { - SUBDIRS += 3rdparty +qtHaveModule(3d)|no_qt3d { + qtHaveModule(3d):!no_qt3d { + message(Using Qt3D Renderer) + } else { + DEFINES += NO_QT3D_RENDERER + warning(Not using Qt3D as renderer backend) + } location.depends = positioning 3rdparty - SUBDIRS += location + SUBDIRS += location 3rdparty plugins.depends += location qtHaveModule(quick):imports.depends += location |