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 000000000000..16569ab636a3 Binary files /dev/null and b/docs/assets/viewer_3d/open_3d_viewer.jpg differ 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 8aba720ce4e0..58b333f315bc 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/src/Viewer3D/CityMapGeometry.cc b/src/Viewer3D/CityMapGeometry.cc index 235846459ee9..3d9db62657b0 100644 --- a/src/Viewer3D/CityMapGeometry.cc +++ b/src/Viewer3D/CityMapGeometry.cc @@ -9,9 +9,6 @@ CityMapGeometry::CityMapGeometry() _modelName = "city_map_defualt_name"; _vertexData.clear(); _mapLoadedFlag = 0; - - connect(this, &CityMapGeometry::osmFilePathChanged, this, &CityMapGeometry::updateData); - connect(this, &CityMapGeometry::osmParserChanged, this, &CityMapGeometry::updateData); } void CityMapGeometry::setModelName(QString modelName) @@ -31,8 +28,7 @@ void CityMapGeometry::setOsmFilePath(QString filePath) _mapLoadedFlag = 0; _osmFilePath = filePath; emit osmFilePathChanged(); - - updateData(); + loadOsmMap(); } void CityMapGeometry::setOsmParser(OsmParser *newOsmParser) @@ -40,26 +36,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; +} - if(_mapLoadedFlag == 0){ - _osmParser->parseOsmFile(_osmFilePath); - _mapLoadedFlag = 1; +void CityMapGeometry::updateViewer() +{ + clear(); + + if(!_osmParser){ + return; } - if(_mapLoadedFlag){ + if(loadOsmMap()){ _vertexData = _osmParser->buildingToMesh(); int stride = 3 * sizeof(float); @@ -72,7 +78,6 @@ void CityMapGeometry::updateData() addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0, QQuick3DGeometry::Attribute::F32Type); - } update(); } diff --git a/src/Viewer3D/CityMapGeometry.h b/src/Viewer3D/CityMapGeometry.h index b549c94eff2e..f0c8f3cd81fa 100644 --- a/src/Viewer3D/CityMapGeometry.h +++ b/src/Viewer3D/CityMapGeometry.h @@ -29,14 +29,15 @@ class CityMapGeometry : public QQuick3DGeometry OsmParser* osmParser(){ return _osmParser;} void setOsmParser(OsmParser* newOsmParser); + bool loadOsmMap(); + signals: void modelNameChanged(); void osmFilePathChanged(); - void gpsRefChanged(); void osmParserChanged(); private: - void updateData(); + void updateViewer(); QString _modelName; QString _osmFilePath; diff --git a/src/Viewer3D/OsmParser.cc b/src/Viewer3D/OsmParser.cc index 46fbcd0f7711..014ca5442d80 100644 --- a/src/Viewer3D/OsmParser.cc +++ b/src/Viewer3D/OsmParser.cc @@ -69,8 +69,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) diff --git a/src/Viewer3D/OsmParser.h b/src/Viewer3D/OsmParser.h index 77ee0eba26d5..0c101afeab7d 100644 --- a/src/Viewer3D/OsmParser.h +++ b/src/Viewer3D/OsmParser.h @@ -57,7 +57,7 @@ class OsmParser : public QObject signals: void gpsRefChanged(QGeoCoordinate newGpsRef); - void newMapLoaded(); + void mapChanged(); void buildingLevelHeightChanged(void); }; diff --git a/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml b/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml index e0cc6b8bd658..ef3ba0bb90d9 100644 --- a/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml +++ b/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml @@ -11,7 +11,7 @@ Node { property real _tilt: 0.001 property real _pan: 0.001 - property real _zoom: 1000 + property real _zoom: 1500 DirectionalLight { @@ -58,6 +58,10 @@ Node { id: cameraPerspectiveOne + eulerRotation{ + x: -90 + } + } } } diff --git a/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml b/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml index a989329d3254..597841a09767 100644 --- a/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml +++ b/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml @@ -21,7 +21,54 @@ import QGroundControl.Vehicle View3D { id: topView property var viewer3DManager: null + property bool viewer3DOpen: 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 + } camera: standAloneScene.cameraOne importScene: CameraLightModel{ @@ -31,7 +78,7 @@ View3D { // renderMode: View3D.Inline environment: SceneEnvironment { - clearColor: "white" + clearColor: "#F9F9F9" backgroundMode: SceneEnvironment.Color } @@ -78,66 +125,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) - - 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 + id: cameraMovementDragHandler + target: null + acceptedModifiers: Qt.NoModifier + acceptedButtons: Qt.LeftButton + enabled: viewer3DOpen - //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: viewer3DOpen + + 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: viewer3DOpen - 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: viewer3DOpen - standAloneScene.cameraTwoPosition.x -= dx - standAloneScene.cameraTwoPosition.y += dy - standAloneScene.cameraTwoPosition.z += dz + onWheel: event => { + zoomCamera(-event.angleDelta.y) } } } diff --git a/src/Viewer3D/Viewer3D/Viewer3D.qml b/src/Viewer3D/Viewer3D/Viewer3D.qml index 309742dcb84b..4c5fbe019f9d 100644 --- a/src/Viewer3D/Viewer3D/Viewer3D.qml +++ b/src/Viewer3D/Viewer3D/Viewer3D.qml @@ -17,8 +17,20 @@ Item{ property bool viewer3DOpen: false property bool settingMenuOpen: false - Viewer3DManager{ - id: _viewer3DManager + Component{ + id: viewer3DManagerComponent + + Viewer3DManager{ + id: _viewer3DManager + } + } + + Loader{ + id: view3DManagerLoader + + onLoaded: { + view3DLoader.source = "Models3D/Viewer3DModel.qml" + } } Loader{ @@ -26,12 +38,19 @@ Item{ anchors.fill: parent onLoaded: { - item.viewer3DManager = _viewer3DManager + item.viewer3DManager = view3DManagerLoader.item } } + Binding{ + target: view3DLoader.item + property: "viewer3DOpen" + value: viewer3DOpen + when: view3DLoader.status == Loader.Ready + } + onViewer3DOpenChanged: { - view3DLoader.source = "Models3D/Viewer3DModel.qml" + view3DManagerLoader.sourceComponent = viewer3DManagerComponent if(viewer3DOpen){ viewer3DBody.z = 1 }else{ @@ -50,12 +69,12 @@ Item{ QGCPopupDialog{ id: settingMenuDialog - title: qsTr("3D view setting") + title: qsTr("3D view settings") buttons: Dialog.Ok | Dialog.Cancel Viewer3DSettingMenu{ id: viewer3DSettingMenu - viewer3DManager: _viewer3DManager + viewer3DManager: view3DManagerLoader.item visible: true } diff --git a/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml b/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml index dac15666fd89..24130aebd4c6 100644 --- a/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml +++ b/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml @@ -11,7 +11,7 @@ import QGroundControl.Viewer3D /// @author Omid Esrafilian -Rectangle { +Flickable { signal menuClosed(bool accept) @@ -20,139 +20,132 @@ Rectangle { 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})?$/ + height: Screen.height * 0.2 + contentWidth: width; + contentHeight: main_column.height + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: ScrollBar {} + + Column { + id: main_column + anchors{ + right: parent.right + left: parent.left + margins: ScreenTools.defaultFontPixelWidth } - - onAccepted: - { - focus = false + spacing: ScreenTools.defaultFontPixelHeight * 0.5 + + RowLayout{ + anchors{ + right: parent.right + left: parent.left + } + QGCLabel { + wrapMode: Text.WordWrap + visible: true + text: qsTr("3D Map File:") + } + + QGCTextField { + id: map_file_text_feild + height: ScreenTools.defaultFontPixelWidth * 4.5 + unitsLabel: "" + showUnits: false + visible: true + Layout.fillWidth: true + readOnly: true + + text: (viewer3DManager)?(viewer3DManager.viewer3DSetting.osmFilePath.rawValue):("nan") + } } - } - - 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})?$/ + RowLayout{ + anchors{ + right: parent.right + left: parent.left + } + QGCButton { + id: map_file_btn + Layout.alignment: Qt.AlignRight + + 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 + } + } + } } - onAccepted: - { - focus = false + GridLayout{ + anchors{ + left: parent.left + } + columns: 2 + columnSpacing: ScreenTools.defaultFontPixelHeight + rowSpacing: ScreenTools.defaultFontPixelWidth + + QGCLabel { + wrapMode: Text.WordWrap + text: qsTr("Average Building Level Height:") + } + + QGCTextField{ + id: bld_level_height_textfeild + width: ScreenTools.defaultFontPixelWidth * 15 + unitsLabel: "m" + showUnits: true + numericValuesOnly: true + visible: true + + text: (viewer3DManager)?(Number(viewer3DManager.viewer3DSetting.buildingLevelHeight.rawValue)):("nan") + + validator: RegularExpressionValidator{ + regularExpression: /(-?\d{1,10})([.]\d{1,6})?$/ + } + + onAccepted: + { + focus = false + } + } + + QGCLabel { + wrapMode: Text.WordWrap + visible: true + text: qsTr("Vehicles Altitude Bias:") + } + + QGCTextField { + id: height_bias_textfeild + width: ScreenTools.defaultFontPixelWidth * 15 + unitsLabel: "m" + showUnits: true + numericValuesOnly: true + visible: true + + text: (viewer3DManager)?(Number(viewer3DManager.viewer3DSetting.altitudeBias.rawValue)):("nan") + + validator: RegularExpressionValidator{ + regularExpression: /(-?\d{1,10})([.]\d{1,6})?$/ + } + + onAccepted: + { + focus = false + } + } } } diff --git a/src/Viewer3D/Viewer3DQmlBackend.cc b/src/Viewer3D/Viewer3DQmlBackend.cc index b3186cf04047..1fd7f59ac009 100644 --- a/src/Viewer3D/Viewer3DQmlBackend.cc +++ b/src/Viewer3D/Viewer3DQmlBackend.cc @@ -3,9 +3,17 @@ #include #include +#include "QGCApplication.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; } void Viewer3DQmlBackend::init(Viewer3DSettings *viewerSettingThr, OsmParser* osmThr) @@ -14,24 +22,47 @@ void Viewer3DQmlBackend::init(Viewer3DSettings *viewerSettingThr, OsmParser* osm _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::_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(); + + qDebug() << "3D viewer gps reference set by vehicles:" << _gpsRef.latitude() << _gpsRef.longitude() << _gpsRef.altitude(); + } + } } void Viewer3DQmlBackend::_gpsRefChangedEvent(QGeoCoordinate newGpsRef) { _gpsRef = newGpsRef; - + _gpsRefSet = GPS_REF_SET_BY_MAP; emit gpsRefChanged(); - 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 b248ad83daee..bcbda28d0c70 100644 --- a/src/Viewer3D/Viewer3DQmlBackend.h +++ b/src/Viewer3D/Viewer3DQmlBackend.h @@ -24,7 +24,6 @@ class Viewer3DQmlBackend : public QObject void init(Viewer3DSettings* viewerSettingThr, OsmParser* osmThr=nullptr); QGeoCoordinate gpsRef(){return _gpsRef;} - void setGpsRef(const QGeoCoordinate& gpsRef); signals: void gpsRefChanged(); @@ -36,10 +35,16 @@ class Viewer3DQmlBackend : public QObject QString _osmFilePath; QGeoCoordinate _gpsRef; + uint8_t _gpsRefSet; float _altitudeBias; + Vehicle *_activeVehicle; + + protected slots: void _gpsRefChangedEvent(QGeoCoordinate newGpsRef); + void _activeVehicleChangedEvent(Vehicle* vehicle); + void _activeVehicleCoordinateChanged(QGeoCoordinate newCoordinate); }; #endif // Viewer3DQmlBackend_H