diff --git a/docs/assets/viewer_3d/open_3d_viewer.jpg b/docs/assets/viewer_3d/open_3d_viewer.jpg
new file mode 100644
index 00000000000..16569ab636a
Binary files /dev/null and b/docs/assets/viewer_3d/open_3d_viewer.jpg differ
diff --git a/docs/en/qgc-dev-guide/getting_started/index.md b/docs/en/qgc-dev-guide/getting_started/index.md
index e92ffde4ad6..db0241d6711 100644
--- a/docs/en/qgc-dev-guide/getting_started/index.md
+++ b/docs/en/qgc-dev-guide/getting_started/index.md
@@ -78,6 +78,10 @@ To install Qt:
Then install the following components:
+::: info
+To see a complete list of all available components in the installer _Select Components_ dialog, you might need to check the **"Archive"** box in the right column under the **"Categories"** tab, then click on **"Filter"**.
+:::
+
- Under _Qt _{{ $frontmatter.qt_version }}_ select:
- Depending on the OS you want to build for:
- **Windows**: _MSVC 2019 64 bit_
diff --git a/docs/en/qgc-user-guide/viewer_3d/viewer_3d.md b/docs/en/qgc-user-guide/viewer_3d/viewer_3d.md
index 8aba720ce4e..58b333f315b 100644
--- a/docs/en/qgc-user-guide/viewer_3d/viewer_3d.md
+++ b/docs/en/qgc-user-guide/viewer_3d/viewer_3d.md
@@ -16,11 +16,24 @@ You can use it to:
![3D View](../../../assets/viewer_3d/viewer_3d_overview.jpg)
# UI Overview
-The screenshot above shows the main elements of the 3D View. You can navigate through the 3D View by using the mouse as follows:
-- **To move horizontally and vertically**: Press and hold mouse left click, then move the cursor.
-- **To rotate**: Press and hold mouse right click, then move the cursor.
-- **To zoom**: Use the mouse wheel\middle button.
+The screenshot above shows the main elements of the 3D View.
+To open the 3D View, when you are in the [Fly View](../fly_view/fly_view.md), from the toolbar on the left, select the 3D View icon as shown below:
+
+![3D View](../../../assets/viewer_3d/open_3d_viewer.jpg)
+
+Once the 3D View is opened, you can navigate through the 3D environment by using either a mouse or a touchscreen as follows:
+- **Mouse:**
+ - **To move horizontally and vertically**: Press and hold the mouse left-click, then move the cursor.
+ - **To rotate**: Press and hold the mouse right-click, then move the cursor.
+ - **To zoom**: Use the mouse wheel\middle button.
+
+- **Touchscreen:**
+ - **To move horizontally and vertically**: Use a single finger, then tap and move your finger.
+ - **To rotate**: Use two fingers, then tap and move your fingers while keeping them together.
+ - **To zoom**: Use a pinch with two fingers and move them together or apart to zoom in or out.
+
+To visualize the 3D map of a particular area in the 3D viewer, you have to download the .osm file of that area from the [OpenStreetMap](https://www.openstreetmap.org/#map=16/47.3964/8.5498) website and then import it through the Setting menu. More details on the Setting menu can be found in the next section.
# Setting icon ![Setting icons](../../../assets/viewer_3d/icon_3d_view.jpg)
This icon will open a pop-up window for setting up the 3D View as shown below:
diff --git a/qgcimages.qrc b/qgcimages.qrc
index 5a1d3340472..8c071fe5526 100644
--- a/qgcimages.qrc
+++ b/qgcimages.qrc
@@ -207,7 +207,6 @@
src/ui/toolbar/Images/Yield.svg
src/FlightMap/Images/ZoomMinus.svg
src/FlightMap/Images/ZoomPlus.svg
- src/Viewer3D/Images/gear_icon.png
src/Viewer3D/Images/city_3d_map_icon.svg
diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc
index de1435f8505..daa1cc8275e 100644
--- a/qgroundcontrol.qrc
+++ b/qgroundcontrol.qrc
@@ -315,7 +315,6 @@
src/PlanView/VTOLLandingPatternEditor.qml
src/comm/MockLinkOptionsDlg.qml
src/FlightDisplay/FlyViewInsetViewer.qml
- src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml
src/Viewer3D/Viewer3D/Viewer3D.qml
src/Viewer3D/Viewer3D/qmldir
src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml
diff --git a/src/FlightDisplay/FlyView.qml b/src/FlightDisplay/FlyView.qml
index 9092014341b..a956f605206 100644
--- a/src/FlightDisplay/FlyView.qml
+++ b/src/FlightDisplay/FlyView.qml
@@ -165,6 +165,7 @@ Item {
pipMode: !_mainWindowIsMap
toolInsets: customOverlay.totalToolInsets
mapName: "FlightDisplayView"
+ enabled: !viewer3DWindow.isOpen
}
FlyViewVideo {
diff --git a/src/FlightDisplay/FlyViewToolStripActionList.qml b/src/FlightDisplay/FlyViewToolStripActionList.qml
index 367d0700544..25fec526325 100644
--- a/src/FlightDisplay/FlyViewToolStripActionList.qml
+++ b/src/FlightDisplay/FlyViewToolStripActionList.qml
@@ -16,6 +16,7 @@ ToolStripActionList {
id: _root
signal displayPreFlightChecklist
+ property bool _viewer3DEnabled: QGroundControl.settingsManager.viewer3DSettings.enabled.rawValue
model: [
ToolStripAction {
@@ -23,50 +24,33 @@ ToolStripActionList {
iconSource: "/qmlimages/Plan.svg"
onTriggered:{
mainWindow.showPlanView()
- map_icon.showFlyMap()
+ mapIcon.showFlyMap()
}
},
ToolStripAction {
- id: map_icon
+ property bool _is3DViewOpen: viewer3DWindow.isOpen
+
+ id: mapIcon
+ visible: _viewer3DEnabled
text: qsTr("3D View")
iconSource: "/qmlimages/Viewer3D/City3DMapIcon.svg"
onTriggered:{
- if(viewer3DWindow.viewer3DOpen === false)
- {
- show3dMap();
- }
- else
- {
- showFlyMap();
+ if(_is3DViewOpen === false){
+ viewer3DWindow.open()
+ }else{
+ viewer3DWindow.close()
}
}
- function show3dMap()
- {
- viewer3DWindow.viewer3DOpen = true
- map_icon.iconSource = "/qmlimages/PaperPlane.svg"
- text= qsTr("Fly")
- city_map_setting_icon.enabled = true
- }
-
- function showFlyMap()
- {
- viewer3DWindow.viewer3DOpen = false
- iconSource = "/qmlimages/Viewer3D/City3DMapIcon.svg"
- text = qsTr("3D View")
- city_map_setting_icon.enabled = false
- viewer3DWindow.settingMenuOpen = false
- city_map_setting_icon.checked = false
- }
- },
- ToolStripAction {
- id: city_map_setting_icon
- text: qsTr("Setting")
- iconSource: "/qmlimages/Viewer3D/GearIcon.png"
- enabled: false
- visible: enabled
- onTriggered:{
- viewer3DWindow.settingMenuOpen = !viewer3DWindow.settingMenuOpen
+ on_Is3DViewOpenChanged: {
+ if(_is3DViewOpen === true){
+ mapIcon.iconSource = "/qmlimages/PaperPlane.svg"
+ text= qsTr("Fly")
+ }else{
+ viewer3DWindow.close()
+ iconSource = "/qmlimages/Viewer3D/City3DMapIcon.svg"
+ text = qsTr("3D View")
+ }
}
},
PreFlightCheckListShowAction { onTriggered: displayPreFlightChecklist() },
diff --git a/src/Settings/SettingsManager.cc b/src/Settings/SettingsManager.cc
index 1f4366d814c..488913e832d 100644
--- a/src/Settings/SettingsManager.cc
+++ b/src/Settings/SettingsManager.cc
@@ -29,6 +29,7 @@ SettingsManager::SettingsManager(QGCApplication* app, QGCToolbox* toolbox)
, _adsbVehicleManagerSettings (nullptr)
, _batteryIndicatorSettings (nullptr)
, _mapsSettings (nullptr)
+ , _viewer3DSettings (nullptr)
#if !defined(NO_ARDUPILOT_DIALECT)
, _apmMavlinkStreamRateSettings (nullptr)
#endif
@@ -58,6 +59,7 @@ void SettingsManager::setToolbox(QGCToolbox *toolbox)
_adsbVehicleManagerSettings = new ADSBVehicleManagerSettings (this);
_batteryIndicatorSettings = new BatteryIndicatorSettings (this);
_mapsSettings = new MapsSettings (this);
+ _viewer3DSettings = new Viewer3DSettings (this);
#if !defined(NO_ARDUPILOT_DIALECT)
_apmMavlinkStreamRateSettings = new APMMavlinkStreamRateSettings(this);
#endif
diff --git a/src/Settings/SettingsManager.h b/src/Settings/SettingsManager.h
index b44f93217da..fc089213452 100644
--- a/src/Settings/SettingsManager.h
+++ b/src/Settings/SettingsManager.h
@@ -32,6 +32,7 @@
#include "BatteryIndicatorSettings.h"
#include
#include "RemoteIDSettings.h"
+#include "Viewer3DSettings.h"
/// Provides access to all app settings
class SettingsManager : public QGCTool
@@ -56,6 +57,7 @@ class SettingsManager : public QGCTool
Q_PROPERTY(QObject* adsbVehicleManagerSettings READ adsbVehicleManagerSettings CONSTANT)
Q_PROPERTY(QObject* batteryIndicatorSettings READ batteryIndicatorSettings CONSTANT)
Q_PROPERTY(QObject* mapsSettings READ mapsSettings CONSTANT)
+ Q_PROPERTY(QObject* viewer3DSettings READ viewer3DSettings CONSTANT)
#if !defined(NO_ARDUPILOT_DIALECT)
Q_PROPERTY(QObject* apmMavlinkStreamRateSettings READ apmMavlinkStreamRateSettings CONSTANT)
#endif
@@ -78,6 +80,7 @@ class SettingsManager : public QGCTool
ADSBVehicleManagerSettings* adsbVehicleManagerSettings (void) { return _adsbVehicleManagerSettings; }
BatteryIndicatorSettings* batteryIndicatorSettings (void) { return _batteryIndicatorSettings; }
MapsSettings* mapsSettings (void) { return _mapsSettings; }
+ Viewer3DSettings* viewer3DSettings (void) { return _viewer3DSettings; }
#if !defined(NO_ARDUPILOT_DIALECT)
APMMavlinkStreamRateSettings* apmMavlinkStreamRateSettings(void) { return _apmMavlinkStreamRateSettings; }
#endif
@@ -98,6 +101,7 @@ class SettingsManager : public QGCTool
ADSBVehicleManagerSettings* _adsbVehicleManagerSettings;
BatteryIndicatorSettings* _batteryIndicatorSettings;
MapsSettings* _mapsSettings;
+ Viewer3DSettings* _viewer3DSettings;
#if !defined(NO_ARDUPILOT_DIALECT)
APMMavlinkStreamRateSettings* _apmMavlinkStreamRateSettings;
#endif
diff --git a/src/Settings/Viewer3D.SettingsGroup.json b/src/Settings/Viewer3D.SettingsGroup.json
index e9523742a9c..6aa548f5c71 100644
--- a/src/Settings/Viewer3D.SettingsGroup.json
+++ b/src/Settings/Viewer3D.SettingsGroup.json
@@ -3,6 +3,12 @@
"fileType": "FactMetaData",
"QGC.MetaData.Facts":
[
+{
+ "name": "enabled",
+ "shortDesc": "Enable the 3D viewer",
+ "type": "bool",
+ "default": false
+},
{
"name": "osmFilePath",
"shortDesc": "Path to the OSM file for the 3D viewer.",
diff --git a/src/Settings/Viewer3DSettings.cc b/src/Settings/Viewer3DSettings.cc
index 86d2eda5f2d..1583f973ae1 100644
--- a/src/Settings/Viewer3DSettings.cc
+++ b/src/Settings/Viewer3DSettings.cc
@@ -17,6 +17,7 @@ DECLARE_SETTINGGROUP(Viewer3D, "Viewer3D")
qmlRegisterUncreatableType("QGroundControl.SettingsManager", 1, 0, "Viewer3DSettings", "Reference only");
}
+DECLARE_SETTINGSFACT(Viewer3DSettings, enabled)
DECLARE_SETTINGSFACT(Viewer3DSettings, osmFilePath)
DECLARE_SETTINGSFACT(Viewer3DSettings, buildingLevelHeight)
DECLARE_SETTINGSFACT(Viewer3DSettings, altitudeBias)
diff --git a/src/Settings/Viewer3DSettings.h b/src/Settings/Viewer3DSettings.h
index 8a202ffd984..c112d5d8174 100644
--- a/src/Settings/Viewer3DSettings.h
+++ b/src/Settings/Viewer3DSettings.h
@@ -21,6 +21,7 @@ class Viewer3DSettings : public SettingsGroup
DEFINE_SETTING_NAME_GROUP()
+ DEFINE_SETTINGFACT(enabled)
DEFINE_SETTINGFACT(osmFilePath)
DEFINE_SETTINGFACT(buildingLevelHeight)
DEFINE_SETTINGFACT(altitudeBias)
diff --git a/src/Viewer3D/CityMapGeometry.cc b/src/Viewer3D/CityMapGeometry.cc
index 235846459ee..d31b04ee227 100644
--- a/src/Viewer3D/CityMapGeometry.cc
+++ b/src/Viewer3D/CityMapGeometry.cc
@@ -2,6 +2,9 @@
#include
+#include "QGCApplication.h"
+#include "SettingsManager.h"
+
CityMapGeometry::CityMapGeometry()
{
@@ -10,8 +13,10 @@ CityMapGeometry::CityMapGeometry()
_vertexData.clear();
_mapLoadedFlag = 0;
- connect(this, &CityMapGeometry::osmFilePathChanged, this, &CityMapGeometry::updateData);
- connect(this, &CityMapGeometry::osmParserChanged, this, &CityMapGeometry::updateData);
+ _viewer3DSettings = qgcApp()->toolbox()->settingsManager()->viewer3DSettings();
+
+ setOsmFilePath(_viewer3DSettings->osmFilePath()->rawValue());
+ connect(_viewer3DSettings->osmFilePath(), &Fact::rawValueChanged, this, &CityMapGeometry::setOsmFilePath);
}
void CityMapGeometry::setModelName(QString modelName)
@@ -22,17 +27,17 @@ void CityMapGeometry::setModelName(QString modelName)
emit modelNameChanged();
}
-void CityMapGeometry::setOsmFilePath(QString filePath)
+void CityMapGeometry::setOsmFilePath(QVariant value)
{
- if(_osmFilePath.compare(filePath) == 0){
+ if(_osmFilePath.compare(value.toString()) == 0){
return;
}
+ clearViewer();
_mapLoadedFlag = 0;
- _osmFilePath = filePath;
+ _osmFilePath = value.toString();
emit osmFilePathChanged();
-
- updateData();
+ loadOsmMap();
}
void CityMapGeometry::setOsmParser(OsmParser *newOsmParser)
@@ -40,26 +45,36 @@ void CityMapGeometry::setOsmParser(OsmParser *newOsmParser)
_osmParser = newOsmParser;
if(_osmParser){
- connect(_osmParser, &OsmParser::buildingLevelHeightChanged, this, &CityMapGeometry::updateData);
+ connect(_osmParser, &OsmParser::buildingLevelHeightChanged, this, &CityMapGeometry::updateViewer);
+ connect(_osmParser, &OsmParser::mapChanged, this, &CityMapGeometry::updateViewer);
}
emit osmParserChanged();
+ loadOsmMap();
}
-//! [update data]
-void CityMapGeometry::updateData()
+bool CityMapGeometry::loadOsmMap()
{
- clear();
+ if(_mapLoadedFlag){
+ return true;
+ }
if(!_osmParser){
- return;
+ return false;
}
+ _mapLoadedFlag = 1;
+ _osmParser->parseOsmFile(_osmFilePath);
+ return true;
+}
+
+void CityMapGeometry::updateViewer()
+{
+ clear();
- if(_mapLoadedFlag == 0){
- _osmParser->parseOsmFile(_osmFilePath);
- _mapLoadedFlag = 1;
+ if(!_osmParser){
+ return;
}
- if(_mapLoadedFlag){
+ if(loadOsmMap()){
_vertexData = _osmParser->buildingToMesh();
int stride = 3 * sizeof(float);
@@ -72,8 +87,14 @@ void CityMapGeometry::updateData()
addAttribute(QQuick3DGeometry::Attribute::PositionSemantic,
0,
QQuick3DGeometry::Attribute::F32Type);
-
}
update();
}
}
+
+void CityMapGeometry::clearViewer()
+{
+ clear();
+ _vertexData.clear();
+ update();
+}
diff --git a/src/Viewer3D/CityMapGeometry.h b/src/Viewer3D/CityMapGeometry.h
index b549c94eff2..558a82bfb50 100644
--- a/src/Viewer3D/CityMapGeometry.h
+++ b/src/Viewer3D/CityMapGeometry.h
@@ -9,11 +9,12 @@
/// @author Omid Esrafilian
+class Viewer3DSettings;
+
class CityMapGeometry : public QQuick3DGeometry
{
Q_OBJECT
Q_PROPERTY(QString modelName READ modelName WRITE setModelName NOTIFY modelNameChanged)
- Q_PROPERTY(QString osmFilePath READ osmFilePath WRITE setOsmFilePath NOTIFY osmFilePathChanged)
Q_PROPERTY(OsmParser* osmParser READ osmParser WRITE setOsmParser NOTIFY osmParserChanged)
public:
@@ -24,25 +25,32 @@ class CityMapGeometry : public QQuick3DGeometry
void setModelName(QString modelName);
QString osmFilePath() const {return _osmFilePath;}
- void setOsmFilePath(QString filePath);
OsmParser* osmParser(){ return _osmParser;}
void setOsmParser(OsmParser* newOsmParser);
+ bool loadOsmMap();
+
signals:
void modelNameChanged();
void osmFilePathChanged();
- void gpsRefChanged();
void osmParserChanged();
private:
- void updateData();
+ void updateViewer();
+ void clearViewer();
QString _modelName;
QString _osmFilePath;
QByteArray _vertexData;
OsmParser *_osmParser;
bool _mapLoadedFlag;
+ Viewer3DSettings* _viewer3DSettings = nullptr;
+
+private slots:
+ void setOsmFilePath(QVariant value);
+
+
};
#endif // CITYMAPGEOMETRY_H
diff --git a/src/Viewer3D/Images/gear_icon.png b/src/Viewer3D/Images/gear_icon.png
deleted file mode 100644
index 5ba6043e904..00000000000
Binary files a/src/Viewer3D/Images/gear_icon.png and /dev/null differ
diff --git a/src/Viewer3D/OsmParser.cc b/src/Viewer3D/OsmParser.cc
index 46fbcd0f771..46f7048b6d5 100644
--- a/src/Viewer3D/OsmParser.cc
+++ b/src/Viewer3D/OsmParser.cc
@@ -4,7 +4,8 @@
#include "earcut.hpp"
#include "Viewer3DUtils.h"
-
+#include "QGCApplication.h"
+#include "SettingsManager.h"
typedef union {
uint array[3];
@@ -19,22 +20,51 @@ typedef union {
OsmParser::OsmParser(QObject *parent)
: QObject{parent}
{
- _mainThread = new QThread(this);
+ _viewer3DSettings = qgcApp()->toolbox()->settingsManager()->viewer3DSettings();
- this->moveToThread(_mainThread);
_gpsRefSet = false;
- _buildingLevelHeight = 0; // meters
+ _mapLoadedFlag = false;
+
+ setBuildingLevelHeight(_viewer3DSettings->buildingLevelHeight()->rawValue()); // meters
+ connect(_viewer3DSettings->buildingLevelHeight(), &Fact::rawValueChanged, this, &OsmParser::setBuildingLevelHeight);
}
void OsmParser::setGpsRef(QGeoCoordinate gpsRef)
{
_gpsRefPoint = gpsRef;
_gpsRefSet = true;
- emit gpsRefChanged(_gpsRefPoint);
+ emit gpsRefChanged(_gpsRefPoint, _gpsRefSet);
+}
+
+void OsmParser::resetGpsRef()
+{
+ _gpsRefPoint = QGeoCoordinate(0, 0, 0);
+ _gpsRefSet = false;
+ emit gpsRefChanged(_gpsRefPoint, _gpsRefSet);
+}
+
+void OsmParser::setBuildingLevelHeight(QVariant value)
+{
+ _buildingLevelHeight = value.toFloat();
+ emit buildingLevelHeightChanged();
}
void OsmParser::parseOsmFile(QString filePath)
{
+ if(filePath == "Please select an OSM file"){
+ if(_mapLoadedFlag){
+ qDebug("The 3D View has been cleared!");
+ _mapNodes.clear();
+ _mapBuildings.clear();
+ _gpsRefSet = false;
+ _mapLoadedFlag = false;
+ resetGpsRef();
+ }else{
+ qDebug("No OSM File is selected!");
+ }
+ return;
+ }
+
//The QDomDocument class represents an XML document.
QDomDocument xml_content;
// Load xml file as raw data
@@ -57,11 +87,6 @@ void OsmParser::parseOsmFile(QString filePath)
QDomElement component = root.firstChild().toElement();
- _mapNodes.clear();
- _mapBuildings.clear();
- _gpsRefSet = false;
- _mapLoadedFlag = false;
-
while(!component.isNull()) {
decodeNodeTags(component, _mapNodes);
decodeBuildings(component, _mapBuildings, _mapNodes, _gpsRefPoint);
@@ -69,8 +94,8 @@ void OsmParser::parseOsmFile(QString filePath)
component = component.nextSibling().toElement();
}
_mapLoadedFlag = true;
- emit newMapLoaded();
- qDebug() << _mapBuildings.size() << " Buildings added to the 3D viewer!!!";
+ emit mapChanged();
+ qDebug() << _mapBuildings.size() << " Buildings loaded!!!";
}
void OsmParser::decodeNodeTags(QDomElement &xmlComponent, QMap &nodeMap)
@@ -151,8 +176,8 @@ void OsmParser::decodeBuildings(QDomElement &xmlComponent, QMap 2 && (bld_tmp.height > 0 || bld_tmp.levels > 0)) {
-// float bld_height = (bld_tmp.height >= bld_tmp.levels * _buildingLevelHeight)?(bld_tmp.height):(bld_tmp.levels * _buildingLevelHeight);
-// bld_tmp.height = bld_height;
+ // float bld_height = (bld_tmp.height >= bld_tmp.levels * _buildingLevelHeight)?(bld_tmp.height):(bld_tmp.levels * _buildingLevelHeight);
+ // bld_tmp.height = bld_height;
bld_tmp.points_gps = bld_points;
bld_tmp.points_local = bld_points_local;
bld_tmp.bb_max = QVector2D(bld_x_max, bld_y_max);
@@ -172,7 +197,7 @@ QByteArray OsmParser::buildingToMesh()
std::vector > > polygon;
std::vector triangulated_mesh;
-// bld_height = (ii.value().height >= ii.value().levels * _buildingLevelHeight)?(ii.value().height):(ii.value().levels * _buildingLevelHeight);
+ // bld_height = (ii.value().height >= ii.value().levels * _buildingLevelHeight)?(ii.value().height):(ii.value().levels * _buildingLevelHeight);
if(ii.value().height > 0){
bld_height = ii.value().height;
diff --git a/src/Viewer3D/OsmParser.h b/src/Viewer3D/OsmParser.h
index 77ee0eba26d..07f847c091e 100644
--- a/src/Viewer3D/OsmParser.h
+++ b/src/Viewer3D/OsmParser.h
@@ -9,9 +9,12 @@
#include
#include
#include "qgeocoordinate.h"
+#include
/// @author Omid Esrafilian
+class Viewer3DSettings;
+
class OsmParser : public QObject
{
struct BuildingType
@@ -26,14 +29,15 @@ class OsmParser : public QObject
Q_OBJECT
- Q_PROPERTY(float buildingLevelHeight READ buildingLevelHeight WRITE setBuildingLevelHeight NOTIFY buildingLevelHeightChanged)
+ // Q_PROPERTY(float buildingLevelHeight READ buildingLevelHeight WRITE setBuildingLevelHeight NOTIFY buildingLevelHeightChanged)
public:
explicit OsmParser(QObject *parent = nullptr);
void setGpsRef(QGeoCoordinate gpsRef);
+ void resetGpsRef();
QGeoCoordinate getGpsRef(){ return _gpsRefPoint;}
- void setBuildingLevelHeight(float levelHeight){_buildingLevelHeight = levelHeight; emit buildingLevelHeightChanged();}
+
float buildingLevelHeight(void){return _buildingLevelHeight;}
void parseOsmFile(QString filePath);
void decodeNodeTags(QDomElement& xmlComponent, QMap &nodeMap);
@@ -45,7 +49,6 @@ class OsmParser : public QObject
void trianglateRectangle(std::vector& triangulatedMesh, std::vector verticesCcw, bool invertNormal);
private:
- QThread* _mainThread;
QGeoCoordinate _gpsRefPoint;
QMap _mapNodes;
QMap _mapBuildings;
@@ -53,13 +56,17 @@ class OsmParser : public QObject
bool _gpsRefSet;
float _buildingLevelHeight;
bool _mapLoadedFlag;
+ Viewer3DSettings* _viewer3DSettings = nullptr;
signals:
- void gpsRefChanged(QGeoCoordinate newGpsRef);
- void newMapLoaded();
+ void gpsRefChanged(QGeoCoordinate newGpsRef, bool isRefSet);
+ void mapChanged();
void buildingLevelHeightChanged(void);
+private slots:
+ void setBuildingLevelHeight(QVariant value);
+
};
#endif // OSMPARSER_H
diff --git a/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml b/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml
index e0cc6b8bd65..2bd1f64bbf4 100644
--- a/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml
+++ b/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml
@@ -11,7 +11,23 @@ Node {
property real _tilt: 0.001
property real _pan: 0.001
- property real _zoom: 1000
+ property real _zoom: 1500
+
+ function resetCamera(){
+ camNode.position = Qt.vector3d(0, 0, 0);
+ camNode.eulerRotation = Qt.vector3d(90, 0, 0);
+
+ cameraPerspectiveThree.position = Qt.vector3d(0, 0, 0);
+ cameraPerspectiveThree.eulerRotation = Qt.vector3d(0, 0, 0);
+
+ cameraPerspectiveTwo.position = Qt.vector3d(_zoom * Math.sin(_tilt) * Math.cos(_pan),
+ _zoom * Math.cos(_tilt),
+ _zoom * Math.sin(_tilt) * Math.sin(_pan));
+ cameraPerspectiveTwo.eulerRotation = Qt.vector3d(0, 0, 0);
+
+ cameraPerspectiveOne.position = Qt.vector3d(0, 0, 0);
+ cameraPerspectiveOne.eulerRotation = Qt.vector3d(-90, 0, 0);
+ }
DirectionalLight {
@@ -57,6 +73,11 @@ Node {
PerspectiveCamera {
id: cameraPerspectiveOne
+ clipFar: 100000
+
+ eulerRotation{
+ x: -90
+ }
}
}
diff --git a/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml b/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml
index a989329d325..b0b02f37327 100644
--- a/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml
+++ b/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml
@@ -21,7 +21,59 @@ import QGroundControl.Vehicle
View3D {
id: topView
property var viewer3DManager: null
+ readonly property var _gpsRef: viewer3DManager.qmlBackend.gpsRef
+ property bool isViewer3DOpen: false
+ property real rotationSpeed: 0.1
+ property real movementSpeed: 1
+ property real zoomSpeed: 0.3
+ function rotateCamera(newPose: vector2d, lastPose: vector2d) {
+ let rotation_vec = Qt.vector2d(newPose.y - lastPose.y, newPose.x - lastPose.x);
+
+ let dx_l = rotation_vec.x * rotationSpeed
+ let dy_l = rotation_vec.y * rotationSpeed
+
+ standAloneScene.cameraOneRotation.x += dx_l
+ standAloneScene.cameraOneRotation.y += dy_l
+ }
+
+ function moveCamera(newPose: vector2d, lastPose: vector2d) {
+ let _roll = standAloneScene.cameraOneRotation.x * (3.1415/180)
+ let _pitch = standAloneScene.cameraOneRotation.y * (3.1415/180)
+
+ let dx_l = (newPose.x - lastPose.x) * movementSpeed
+ let dy_l = (newPose.y - lastPose.y) * movementSpeed
+
+ //Note: Rotation Matrix is computed as: R = R(-_pitch) * R(_roll)
+ // Then the corerxt tramslation is: d = R * [dx_l; dy_l; dz_l]
+
+ let dx = dx_l * Math.cos(_pitch) - dy_l * Math.sin(_pitch) * Math.sin(_roll)
+ let dy = dy_l * Math.cos(_roll)
+ let dz = dx_l * Math.sin(_pitch) + dy_l * Math.cos(_pitch) * Math.sin(_roll)
+
+ standAloneScene.cameraTwoPosition.x -= dx
+ standAloneScene.cameraTwoPosition.y += dy
+ standAloneScene.cameraTwoPosition.z += dz
+ }
+
+ function zoomCamera(zoomValue){
+ let dz_l = zoomValue * zoomSpeed;
+
+ let _roll = standAloneScene.cameraOneRotation.x * (3.1415/180)
+ let _pitch = standAloneScene.cameraOneRotation.y * (3.1415/180)
+
+ let dx = -dz_l * Math.cos(_roll) * Math.sin(_pitch)
+ let dy = -dz_l * Math.sin(_roll)
+ let dz = dz_l * Math.cos(_pitch) * Math.cos(_roll)
+
+ standAloneScene.cameraTwoPosition.x -= dx
+ standAloneScene.cameraTwoPosition.y += dy
+ standAloneScene.cameraTwoPosition.z += dz
+ }
+
+ on_GpsRefChanged:{
+ standAloneScene.resetCamera();
+ }
camera: standAloneScene.cameraOne
importScene: CameraLightModel{
@@ -31,7 +83,7 @@ View3D {
// renderMode: View3D.Inline
environment: SceneEnvironment {
- clearColor: "white"
+ clearColor: "#F9F9F9"
backgroundMode: SceneEnvironment.Color
}
@@ -42,7 +94,6 @@ View3D {
geometry: CityMapGeometry {
id: cityMapGeometry
modelName: "city_map"
- osmFilePath: (viewer3DManager)?(viewer3DManager.qmlBackend.osmFilePath):("nan")
osmParser: (viewer3DManager)?(viewer3DManager.osmParser):(null)
}
@@ -78,66 +129,102 @@ View3D {
vehicle3DLoader.sourceComponent = vehicle3DComponent
}
- MouseArea{
- property real _transferSpeed: 1
- property real _rotationSpeed: 0.1
- property real _zoomSpeed: 0.3
+ DragHandler {
+ property bool _isMoving: false
property point _lastPose;
- anchors.fill: parent
- acceptedButtons: Qt.AllButtons;
-
-
- onPressed: (mouse)=> {
- _lastPose = Qt.point(mouse.x, mouse.y);
- }
-
- onPositionChanged: (mouse)=> {
- let _roll = standAloneScene.cameraOneRotation.x * (3.1415/180)
- let _pitch = standAloneScene.cameraOneRotation.y * (3.1415/180)
- // let yaw = standAloneScene.cameraOneRotation.z * (3.1415/180)
+ id: cameraMovementDragHandler
+ target: null
+ acceptedModifiers: Qt.NoModifier
+ acceptedButtons: Qt.LeftButton
+ enabled: isViewer3DOpen
- if (mouse.buttons === Qt.LeftButton) { // Left button for translate
- let dx_l = (mouse.x - _lastPose.x) * _transferSpeed
- let dy_l = (mouse.y - _lastPose.y) * _transferSpeed
-
- //Note: Rotation Matrix is computed as: R = R(-_pitch) * R(_roll)
- // Then the corerxt tramslation is: d = R * [dx_l; dy_l; dz_l]
+ onCentroidChanged: {
+ if(_isMoving){
+ moveCamera(centroid.position, _lastPose);
+ _lastPose = Qt.point(centroid.position.x, centroid.position.y);
+ }
+ }
- let dx = dx_l * Math.cos(_pitch) - dy_l * Math.sin(_pitch) * Math.sin(_roll)
- let dy = dy_l * Math.cos(_roll)
- let dz = dx_l * Math.sin(_pitch) + dy_l * Math.cos(_pitch) * Math.sin(_roll)
+ onActiveChanged: {
+ if(active){ // When mouse is pressed
+ _lastPose = Qt.point(centroid.position.x, centroid.position.y);
+ _isMoving = true
+ }else{ // When mouse is released
+ _isMoving = false
+ }
+ }
+ }
- standAloneScene.cameraTwoPosition.x -= dx
- standAloneScene.cameraTwoPosition.y += dy
- standAloneScene.cameraTwoPosition.z += dz
- }else if (mouse.buttons === Qt.RightButton){ // Right button for rotation
+ DragHandler {
+ property bool _isRotating: false
+ property point _lastPose;
- let rotation_vec = Qt.vector2d(mouse.y - _lastPose.y, mouse.x - _lastPose.x);
+ id: cameraRotationDragHandler
+ target: null
+ acceptedModifiers: Qt.NoModifier
+ acceptedButtons: Qt.RightButton
+ acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
+ enabled: isViewer3DOpen
+
+ onCentroidChanged: {
+ if(_isRotating){
+ rotateCamera(centroid.position, _lastPose);
+ _lastPose = Qt.point(centroid.position.x, centroid.position.y);
+ }
+ }
- let dx_l = rotation_vec.x * _rotationSpeed
- let dy_l = rotation_vec.y * _rotationSpeed
+ onActiveChanged: {
+ if(active){ // When mouse is pressed
+ _lastPose = Qt.point(centroid.position.x, centroid.position.y);
+ _isRotating = true
+ }else{// When mouse is released
+ _isRotating = false
+ }
+ }
+ }
- standAloneScene.cameraOneRotation.x += dx_l
- standAloneScene.cameraOneRotation.y += dy_l
+ PinchHandler {
+ id: zoomRotationPinchHandler
+ target: null
- }
- _lastPose = Qt.point(mouse.x, mouse.y)
- }
+ property bool _isRotating: false
+ property point _lastPose;
+ property real _lastZoomValue;
+ enabled: isViewer3DOpen
- onWheel: (wheel)=> {
- let dz_l = -wheel.angleDelta.y * _zoomSpeed
+ onCentroidChanged: {
+ if(_isRotating){
+ rotateCamera(centroid.position, _lastPose);
+ _lastPose = Qt.point(centroid.position.x, centroid.position.y);
+ }
+ }
- let _roll = standAloneScene.cameraOneRotation.x * (3.1415/180)
- let _pitch = standAloneScene.cameraOneRotation.y * (3.1415/180)
+ onActiveChanged: {
+ if (active) {
+ _lastPose = Qt.point(centroid.position.x, centroid.position.y);
+ _lastZoomValue = 0
+ _isRotating = true;
+ } else {
+ _isRotating = false;
+ }
+ }
+ onActiveScaleChanged: {
+ let zoomValue = (activeScale > 1)?(activeScale - 1):(-((1/activeScale) - 1))
+ zoomCamera(- 1000 * (zoomValue - _lastZoomValue))
+ _lastZoomValue = zoomValue
+ }
+ }
- let dx = -dz_l * Math.cos(_roll) * Math.sin(_pitch)
- let dy = -dz_l * Math.sin(_roll)
- let dz = dz_l * Math.cos(_pitch) * Math.cos(_roll)
+ WheelHandler {
+ id: wheelHandler
+ orientation: Qt.Vertical
+ target: null
+ acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
+ enabled: isViewer3DOpen
- standAloneScene.cameraTwoPosition.x -= dx
- standAloneScene.cameraTwoPosition.y += dy
- standAloneScene.cameraTwoPosition.z += dz
+ onWheel: event => {
+ zoomCamera(-event.angleDelta.y)
}
}
}
diff --git a/src/Viewer3D/Viewer3D/Models3D/Viewer3DVehicleItems.qml b/src/Viewer3D/Viewer3D/Models3D/Viewer3DVehicleItems.qml
index 59f74758ad3..ca586e5115f 100644
--- a/src/Viewer3D/Viewer3D/Models3D/Viewer3DVehicleItems.qml
+++ b/src/Viewer3D/Viewer3D/Models3D/Viewer3DVehicleItems.qml
@@ -23,6 +23,9 @@ Node {
property var _vehicle: null
property var _planMasterController: null
property var _missionController: (_planMasterController)?(_planMasterController.missionController):(null)
+ property var _viewer3DSetting: QGroundControl.settingsManager.viewer3DSettings
+ property var _altitudeBias: _viewer3DSetting.altitudeBias.rawValue
+
function addMissionItemsToListModel() {
missionWaypointListModel.clear()
@@ -85,7 +88,7 @@ Node {
id: droneDji3DModel
vehicle: _vehicle
modelScale: Qt.vector3d(0.05, 0.05, 0.05)
- altitudeBias: _backendQml.altitudeBias
+ altitudeBias: _altitudeBias
gpsRef: _backendQml.gpsRef
}
@@ -96,7 +99,7 @@ Node {
delegate: Waypoint3DModel{
opacity: 0.8
missionItem: model
- altitudeBias: _backendQml.altitudeBias
+ altitudeBias: _altitudeBias
}
}
@@ -105,8 +108,8 @@ Node {
model: missionPathModel
delegate: Line3D{
- p_1: Qt.vector3d(model.x_1 * 10, model.y_1 * 10, (model.z_1 + _backendQml.altitudeBias) * 10)
- p_2: Qt.vector3d(model.x_2 * 10, model.y_2 * 10, (model.z_2 + _backendQml.altitudeBias) * 10)
+ p_1: Qt.vector3d(model.x_1 * 10, model.y_1 * 10, (model.z_1 + _altitudeBias) * 10)
+ p_2: Qt.vector3d(model.x_2 * 10, model.y_2 * 10, (model.z_2 + _altitudeBias) * 10)
lineWidth:8
color: "orange"
}
diff --git a/src/Viewer3D/Viewer3D/Viewer3D.qml b/src/Viewer3D/Viewer3D/Viewer3D.qml
index 309742dcb84..926b7795100 100644
--- a/src/Viewer3D/Viewer3D/Viewer3D.qml
+++ b/src/Viewer3D/Viewer3D/Viewer3D.qml
@@ -3,73 +3,75 @@ import QtQuick.Controls
import QtQuick.Dialogs
import QtQuick.Layouts
+import QGroundControl
import QGroundControl.Palette
import QGroundControl.ScreenTools
import QGroundControl.Controls
-// 3D Viewer modules
import QGroundControl.Viewer3D
import Viewer3D.Models3D
+/// @author Omid Esrafilian
+
Item{
id: viewer3DBody
- property bool viewer3DOpen: false
- property bool settingMenuOpen: false
+ property bool isOpen: false
+ property bool _viewer3DEnabled: QGroundControl.settingsManager.viewer3DSettings.enabled.rawValue
+
- Viewer3DManager{
- id: _viewer3DManager
+ function open(){
+ if(_viewer3DEnabled === true){
+ view3DManagerLoader.sourceComponent = viewer3DManagerComponent
+ view3DManagerLoader.active = true;
+ viewer3DBody.z = 1
+ isOpen = true;
+ }
}
- Loader{
- id: view3DLoader
- anchors.fill: parent
+ function close(){
+ viewer3DBody.z = 0
+ isOpen = false;
+ }
- onLoaded: {
- item.viewer3DManager = _viewer3DManager
+ on_Viewer3DEnabledChanged: {
+ if(_viewer3DEnabled === false){
+ viewer3DBody.close();
+ view3DLoader.active = false;
+ view3DManagerLoader.active = false;
}
}
- onViewer3DOpenChanged: {
- view3DLoader.source = "Models3D/Viewer3DModel.qml"
- if(viewer3DOpen){
- viewer3DBody.z = 1
- }else{
- viewer3DBody.z = 0
+ Component{
+ id: viewer3DManagerComponent
+
+ Viewer3DManager{
+ id: _viewer3DManager
}
}
- onSettingMenuOpenChanged:{
- if(settingMenuOpen === true){
- settingMenuComponent.createObject(mainWindow).open()
+ Loader{
+ id: view3DManagerLoader
+
+ onLoaded: {
+ view3DLoader.source = "Models3D/Viewer3DModel.qml"
+ view3DLoader.active = true;
}
}
- Component {
- id: settingMenuComponent
-
- QGCPopupDialog{
- id: settingMenuDialog
- title: qsTr("3D view setting")
- buttons: Dialog.Ok | Dialog.Cancel
-
- Viewer3DSettingMenu{
- id: viewer3DSettingMenu
- viewer3DManager: _viewer3DManager
- visible: true
- }
-
- onRejected: {
- settingMenuOpen = false
- viewer3DSettingMenu.menuClosed(false)
- settingMenuDialog.close()
- }
-
- onAccepted: {
- settingMenuOpen = false
- viewer3DSettingMenu.menuClosed(true)
- settingMenuDialog.close()
- }
+ Loader{
+ id: view3DLoader
+ anchors.fill: parent
+
+ onLoaded: {
+ item.viewer3DManager = view3DManagerLoader.item
}
}
+
+ Binding{
+ target: view3DLoader.item
+ property: "isViewer3DOpen"
+ value: isOpen
+ when: view3DLoader.status == Loader.Ready
+ }
}
diff --git a/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml b/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml
deleted file mode 100644
index dac15666fd8..00000000000
--- a/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml
+++ /dev/null
@@ -1,171 +0,0 @@
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Dialogs
-import QtQuick.Layouts
-
-import QGroundControl.Palette
-import QGroundControl.ScreenTools
-import QGroundControl.Controls
-
-import QGroundControl.Viewer3D
-
-/// @author Omid Esrafilian
-
-Rectangle {
-
- signal menuClosed(bool accept)
-
- property var viewer3DManager: null
- property int leftMarginSpace: ScreenTools.defaultFontPixelWidth
-
- id: window_body
- clip: true
- color: qgcPal.window
- visible: true
- width: Screen.width * 0.25
- height: Screen.width * 0.15
-
- QGCPalette {
- id: qgcPal
- colorGroupEnabled: enabled
- }
-
- QGCLabel {
- id: map_file_label
- Layout.fillWidth: true
- wrapMode: Text.WordWrap
- visible: true
- text: qsTr("3D Map File:")
- anchors.left: parent.left
- anchors.top: parent.top
- anchors.leftMargin: leftMarginSpace
- anchors.topMargin: ScreenTools.defaultFontPixelWidth * 3
- }
-
- QGCButton {
- id: map_file_btn
- anchors.right: map_file_text_feild.right
- anchors.top: map_file_text_feild.bottom
- anchors.topMargin: ScreenTools.defaultFontPixelWidth * 2
- anchors.rightMargin: ScreenTools.defaultFontPixelWidth
-
- visible: true
- text: qsTr("Select File")
-
- onClicked: {
- fileDialog.openForLoad()
- }
-
- QGCFileDialog {
- id: fileDialog
-
- nameFilters: [qsTr("OpenStreetMap files (*.osm)")]
- title: qsTr("Select map file")
- onAcceptedForLoad: (file) => {
- map_file_text_feild.text = file
- }
- }
- }
-
- QGCTextField {
- id: map_file_text_feild
- height: ScreenTools.defaultFontPixelWidth * 4.5
- unitsLabel: ""
- showUnits: false
- visible: true
-
- anchors.verticalCenter: map_file_label.verticalCenter
- anchors.right: parent.right
- anchors.left: map_file_label.right
- anchors.rightMargin: 20
- anchors.leftMargin: 20
- readOnly: true
-
- text: (viewer3DManager)?(viewer3DManager.viewer3DSetting.osmFilePath.rawValue):("nan")
- }
-
- QGCLabel {
- id: bld_level_height
- Layout.fillWidth: true
- wrapMode: Text.WordWrap
- visible: true
- text: qsTr("Average Building Level Height:")
- anchors.left: parent.left
- anchors.top: map_file_btn.bottom
- anchors.leftMargin: leftMarginSpace
- anchors.topMargin: ScreenTools.defaultFontPixelWidth * 2
- }
-
- QGCTextField {
- id: bld_level_height_textfeild
- width: ScreenTools.defaultFontPixelWidth * 15
- unitsLabel: "m"
- showUnits: true
- numericValuesOnly: true
- visible: true
-
- anchors.verticalCenter: bld_level_height.verticalCenter
- anchors.left: bld_level_height.right
- anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
-
- text: (viewer3DManager)?(Number(viewer3DManager.viewer3DSetting.buildingLevelHeight.rawValue)):("nan")
-
- validator: RegularExpressionValidator{
- regularExpression: /(-?\d{1,10})([.]\d{1,6})?$/
- }
-
- onAccepted:
- {
- focus = false
- }
- }
-
- QGCLabel {
- id: height_bias_label
- Layout.fillWidth: true
- wrapMode: Text.WordWrap
- visible: true
- text: qsTr("Vehicles Altitude Bias:")
- anchors.left: parent.left
- anchors.top: bld_level_height.bottom
- anchors.leftMargin: leftMarginSpace
- anchors.topMargin: ScreenTools.defaultFontPixelWidth * 4
- }
-
- QGCTextField {
- id: height_bias_textfeild
- width: ScreenTools.defaultFontPixelWidth * 15
- unitsLabel: "m"
- showUnits: true
- numericValuesOnly: true
- visible: true
-
- anchors.verticalCenter: height_bias_label.verticalCenter
- anchors.left: height_bias_label.right
- anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2
-
- text: (viewer3DManager)?(Number(viewer3DManager.viewer3DSetting.altitudeBias.rawValue)):("nan")
-
- validator: RegularExpressionValidator{
- regularExpression: /(-?\d{1,10})([.]\d{1,6})?$/
- }
-
- onAccepted:
- {
- focus = false
- }
- }
-
- onMenuClosed: function (accept){
- if(accept === true){
- viewer3DManager.qmlBackend.osmFilePath = map_file_text_feild.text
- viewer3DManager.qmlBackend.altitudeBias = parseFloat(height_bias_textfeild.text)
-
- viewer3DManager.viewer3DSetting.osmFilePath.rawValue = map_file_text_feild.text
- viewer3DManager.viewer3DSetting.buildingLevelHeight.rawValue = parseFloat(bld_level_height_textfeild.text)
- viewer3DManager.viewer3DSetting.altitudeBias.rawValue = parseFloat(height_bias_textfeild.text)
-
- viewer3DManager.osmParser.buildingLevelHeight = parseFloat(bld_level_height_textfeild.text)
- }
- }
-}
diff --git a/src/Viewer3D/Viewer3D/qmldir b/src/Viewer3D/Viewer3D/qmldir
index 8c326b1c8ba..15a9da02437 100644
--- a/src/Viewer3D/Viewer3D/qmldir
+++ b/src/Viewer3D/Viewer3D/qmldir
@@ -1,4 +1,3 @@
Module Viewer3D
Viewer3D 1.0 Viewer3D.qml
-Viewer3DSettingMenu 1.0 Viewer3DSettingMenu.qml
diff --git a/src/Viewer3D/Viewer3DManager.cc b/src/Viewer3D/Viewer3DManager.cc
index 6fc52ca6cc8..9358a3558ed 100644
--- a/src/Viewer3D/Viewer3DManager.cc
+++ b/src/Viewer3D/Viewer3DManager.cc
@@ -5,8 +5,12 @@ Viewer3DManager::Viewer3DManager()
{
_qmlBackend = new Viewer3DQmlBackend(this);
_osmParser = new OsmParser();
- _viewer3DSetting = new Viewer3DSettings();
- _osmParser->setBuildingLevelHeight(_viewer3DSetting->buildingLevelHeight()->rawValue().toFloat()); // meters
- _qmlBackend->init(_viewer3DSetting, _osmParser);
+ _qmlBackend->init(_osmParser);
+}
+
+Viewer3DManager::~Viewer3DManager()
+{
+ delete _osmParser;
+ delete _qmlBackend;
}
diff --git a/src/Viewer3D/Viewer3DManager.h b/src/Viewer3D/Viewer3DManager.h
index ab87f0c1a12..e212c4f88ff 100644
--- a/src/Viewer3D/Viewer3DManager.h
+++ b/src/Viewer3D/Viewer3DManager.h
@@ -5,10 +5,11 @@
#include "Viewer3DQmlBackend.h"
#include "OsmParser.h"
-#include "Viewer3DSettings.h"
/// @author Omid Esrafilian
+class SettingsManager;
+
// This class contains all the variables shared between the C++ and QML sides for 3D viewer.
class Viewer3DManager : public QObject
{
@@ -16,15 +17,15 @@ class Viewer3DManager : public QObject
Q_PROPERTY(OsmParser* osmParser MEMBER _osmParser CONSTANT)
Q_PROPERTY(Viewer3DQmlBackend* qmlBackend MEMBER _qmlBackend CONSTANT)
- Q_PROPERTY(Viewer3DSettings* viewer3DSetting MEMBER _viewer3DSetting CONSTANT)
public:
explicit Viewer3DManager();
+ ~Viewer3DManager();
+
protected:
OsmParser *_osmParser = nullptr;
Viewer3DQmlBackend *_qmlBackend = nullptr;
- Viewer3DSettings* _viewer3DSetting = nullptr;
};
diff --git a/src/Viewer3D/Viewer3DQmlBackend.cc b/src/Viewer3D/Viewer3DQmlBackend.cc
index b3186cf0404..947262f0ae2 100644
--- a/src/Viewer3D/Viewer3DQmlBackend.cc
+++ b/src/Viewer3D/Viewer3DQmlBackend.cc
@@ -3,35 +3,69 @@
#include
#include
+#include "QGCApplication.h"
+#include "SettingsManager.h"
+
+#define GPS_REF_NOT_SET 0
+#define GPS_REF_SET_BY_MAP 1
+#define GPS_REF_SET_BY_VEHICLE 2
+
Viewer3DQmlBackend::Viewer3DQmlBackend(QObject *parent)
: QObject{parent}
{
+ _gpsRefSet = GPS_REF_NOT_SET;
+ _activeVehicle = nullptr;
+ _viewer3DSettings = qgcApp()->toolbox()->settingsManager()->viewer3DSettings();
}
-void Viewer3DQmlBackend::init(Viewer3DSettings *viewerSettingThr, OsmParser* osmThr)
+void Viewer3DQmlBackend::init(OsmParser* osmThr)
{
- _altitudeBias = viewerSettingThr->altitudeBias()->rawValue().toFloat();
- _osmFilePath = viewerSettingThr->osmFilePath()->rawValue().toString();
-
_osmParserThread = osmThr;
+ _activeVehicleChangedEvent(qgcApp()->toolbox()->multiVehicleManager()->activeVehicle());
+
connect(_osmParserThread, &OsmParser::gpsRefChanged, this, &Viewer3DQmlBackend::_gpsRefChangedEvent);
+ connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::activeVehicleChanged, this, &Viewer3DQmlBackend::_activeVehicleChangedEvent);
}
-void Viewer3DQmlBackend::setGpsRef(const QGeoCoordinate &gpsRef)
+void Viewer3DQmlBackend::_activeVehicleChangedEvent(Vehicle *vehicle)
{
- if(_gpsRef == gpsRef){
- return;
+ if(_activeVehicle){
+ disconnect(_activeVehicle, &Vehicle::coordinateChanged, this, &Viewer3DQmlBackend::_activeVehicleCoordinateChanged);
}
- _gpsRef = gpsRef;
- emit gpsRefChanged();
+ _activeVehicle = vehicle;
+ if(!_activeVehicle){ // means that all the vehicle have been disconnected
+ if(_gpsRefSet == GPS_REF_SET_BY_VEHICLE){
+ _gpsRefSet = GPS_REF_NOT_SET;
+ }
+ }else{
+ connect(_activeVehicle, &Vehicle::coordinateChanged, this, &Viewer3DQmlBackend::_activeVehicleCoordinateChanged);
+ }
}
-void Viewer3DQmlBackend::_gpsRefChangedEvent(QGeoCoordinate newGpsRef)
-{
- _gpsRef = newGpsRef;
+void Viewer3DQmlBackend::_activeVehicleCoordinateChanged(QGeoCoordinate newCoordinate)
+{
+ if(_gpsRefSet == GPS_REF_NOT_SET){
+ if(newCoordinate.latitude() && newCoordinate.longitude()){
+ _gpsRef = newCoordinate;
+ _gpsRef.setAltitude(0);
+ _gpsRefSet = GPS_REF_SET_BY_VEHICLE;
+ emit gpsRefChanged();
- emit gpsRefChanged();
+ qDebug() << "3D viewer gps reference set by vehicles:" << _gpsRef.latitude() << _gpsRef.longitude() << _gpsRef.altitude();
+ }
+ }
+}
+
+void Viewer3DQmlBackend::_gpsRefChangedEvent(QGeoCoordinate newGpsRef, bool isRefSet)
+{
+ if(isRefSet){
+ _gpsRef = newGpsRef;
+ _gpsRefSet = GPS_REF_SET_BY_MAP;
+ emit gpsRefChanged();
+ }else{
+ _gpsRefSet = GPS_REF_NOT_SET;
+ }
- qDebug() << "3D map gps reference:" << _gpsRef.latitude() << _gpsRef.longitude() << _gpsRef.altitude();
+ qDebug() << "3D viewer gps reference set by osm map:" << _gpsRef.latitude() << _gpsRef.longitude() << _gpsRef.altitude();
}
diff --git a/src/Viewer3D/Viewer3DQmlBackend.h b/src/Viewer3D/Viewer3DQmlBackend.h
index b248ad83dae..f79fbe8226b 100644
--- a/src/Viewer3D/Viewer3DQmlBackend.h
+++ b/src/Viewer3D/Viewer3DQmlBackend.h
@@ -10,36 +10,38 @@
/// @author Omid Esrafilian
+class Viewer3DSettings;
+
class Viewer3DQmlBackend : public QObject
{
Q_OBJECT
- Q_PROPERTY(QString osmFilePath MEMBER _osmFilePath NOTIFY cityMapPathChanged)
Q_PROPERTY(QGeoCoordinate gpsRef READ gpsRef NOTIFY gpsRefChanged)
- Q_PROPERTY(float altitudeBias MEMBER _altitudeBias NOTIFY altitudeBiasChanged)
public:
explicit Viewer3DQmlBackend(QObject *parent = nullptr);
- void init(Viewer3DSettings* viewerSettingThr, OsmParser* osmThr=nullptr);
+ void init(OsmParser* osmThr=nullptr);
QGeoCoordinate gpsRef(){return _gpsRef;}
- void setGpsRef(const QGeoCoordinate& gpsRef);
signals:
void gpsRefChanged();
- void altitudeBiasChanged();
- void cityMapPathChanged();
private:
OsmParser *_osmParserThread;
- QString _osmFilePath;
QGeoCoordinate _gpsRef;
- float _altitudeBias;
+ uint8_t _gpsRefSet;
+
+ Vehicle *_activeVehicle;
+ Viewer3DSettings* _viewer3DSettings = nullptr;
+
protected slots:
- void _gpsRefChangedEvent(QGeoCoordinate newGpsRef);
+ void _gpsRefChangedEvent(QGeoCoordinate newGpsRef, bool isRefSet);
+ void _activeVehicleChangedEvent(Vehicle* vehicle);
+ void _activeVehicleCoordinateChanged(QGeoCoordinate newCoordinate);
};
#endif // Viewer3DQmlBackend_H
diff --git a/src/ui/preferences/FlyViewSettings.qml b/src/ui/preferences/FlyViewSettings.qml
index b9fddbb1f90..29515b31a6e 100644
--- a/src/ui/preferences/FlyViewSettings.qml
+++ b/src/ui/preferences/FlyViewSettings.qml
@@ -30,6 +30,11 @@ SettingsPage {
property Fact _guidedMinimumAltitude: _settingsManager.flyViewSettings.guidedMinimumAltitude
property Fact _guidedMaximumAltitude: _settingsManager.flyViewSettings.guidedMaximumAltitude
property Fact _maxGoToLocationDistance: _settingsManager.flyViewSettings.maxGoToLocationDistance
+ property Fact _viewer3DEnabled: _settingsManager.viewer3DSettings.enabled
+ property Fact _viewer3DOsmFilePath: _settingsManager.viewer3DSettings.osmFilePath
+ property Fact _viewer3DBuildingLevelHeight: _settingsManager.viewer3DSettings.buildingLevelHeight
+ property Fact _viewer3DAltitudeBias: _settingsManager.viewer3DSettings.altitudeBias
+
SettingsGroupLayout {
Layout.fillWidth: true
@@ -116,7 +121,7 @@ SettingsPage {
SettingsGroupLayout {
Layout.fillWidth: true
- heading: qsTr("Virtual Joystick")
+ heading: qsTr("Virtual Joystick")
visible: _virtualJoystick.visible || _virtualJoystickAutoCenterThrottle.visible
FactCheckBoxSlider {
@@ -154,4 +159,87 @@ SettingsPage {
fact: _lockNoseUpCompass
}
}
+
+ SettingsGroupLayout {
+ Layout.fillWidth: true
+ heading: qsTr("3D View")
+
+ FactCheckBoxSlider {
+ Layout.fillWidth: true
+ text: qsTr("Enabled")
+ fact: _viewer3DEnabled
+ }
+ ColumnLayout{
+ Layout.fillWidth: true
+ spacing: ScreenTools.defaultFontPixelWidth
+ enabled: _viewer3DEnabled.rawValue
+
+ RowLayout{
+ Layout.fillWidth: true
+ spacing: ScreenTools.defaultFontPixelWidth
+
+ QGCLabel {
+ wrapMode: Text.WordWrap
+ visible: true
+ text: qsTr("3D Map File:")
+ }
+
+ QGCTextField {
+ id: osmFileTextField
+ height: ScreenTools.defaultFontPixelWidth * 4.5
+ unitsLabel: ""
+ showUnits: false
+ visible: true
+ Layout.fillWidth: true
+ readOnly: true
+ text: _viewer3DOsmFilePath.rawValue
+ }
+ }
+ RowLayout{
+ Layout.alignment: Qt.AlignRight
+ spacing: ScreenTools.defaultFontPixelWidth
+
+ QGCButton {
+ text: qsTr("Clear")
+
+ onClicked: {
+ osmFileTextField.text = "Please select an OSM file"
+ _viewer3DOsmFilePath.value = osmFileTextField.text
+ }
+ }
+
+ QGCButton {
+ text: qsTr("Select File")
+
+ onClicked: {
+ fileDialog.openForLoad()
+ }
+
+ QGCFileDialog {
+ id: fileDialog
+ nameFilters: [qsTr("OpenStreetMap files (*.osm)")]
+ title: qsTr("Select map file")
+ onAcceptedForLoad: (file) => {
+ osmFileTextField.text = file
+ _viewer3DOsmFilePath.value = osmFileTextField.text
+ }
+ }
+ }
+ }
+ }
+
+ LabelledFactTextField {
+ Layout.fillWidth: true
+ label: qsTr("Average Building Level Height")
+ fact: _viewer3DBuildingLevelHeight
+ enabled: _viewer3DEnabled.rawValue
+ }
+
+ LabelledFactTextField {
+ Layout.fillWidth: true
+ label: qsTr("Vehicles Altitude Bias")
+ fact: _viewer3DAltitudeBias
+ enabled: _viewer3DEnabled.rawValue
+ }
+ }
}