QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
Viewer3DModel.qml
Go to the documentation of this file.
1import QtQuick3D
2
3import QGroundControl
4import QGroundControl.Controls
5
6View3D {
7 id: topView
8
9 readonly property real _viewDistance: 50000
10 readonly property var _gpsRef: QGCViewer3DManager.gpsRef
11
12 property real movementSpeed: 1
13 property real rotationSpeed: 0.1
14 property real zoomSpeed: 0.3
15
16 function moveCamera(newPose: vector2d, lastPose: vector2d) {
17 let _roll = standAloneScene.cameraOneRotation.x * (Math.PI / 180);
18 let _pitch = standAloneScene.cameraOneRotation.y * (Math.PI / 180);
19
20 let dx_l = (newPose.x - lastPose.x) * movementSpeed * movementSpeedAdjustment(2000.0, 4);
21 let dy_l = (newPose.y - lastPose.y) * movementSpeed * movementSpeedAdjustment(2000.0, 4);
22
23 //Note: Rotation Matrix is computed as: R = R(-_pitch) * R(_roll)
24 // Then the corerxt tramslation is: d = R * [dx_l; dy_l; dz_l]
25
26 let dx = dx_l * Math.cos(_pitch) - dy_l * Math.sin(_pitch) * Math.sin(_roll);
27 let dy = dy_l * Math.cos(_roll);
28 let dz = dx_l * Math.sin(_pitch) + dy_l * Math.cos(_pitch) * Math.sin(_roll);
29
30 standAloneScene.cameraTwoPosition.x -= dx;
31 standAloneScene.cameraTwoPosition.y += dy;
32 standAloneScene.cameraTwoPosition.z += dz;
33 }
34
35 function movementSpeedAdjustment(adjustmentScale, maxValue) {
36 let _adjustmentValue = standAloneScene.cameraTwoPosition.length() / adjustmentScale;
37 return Math.min(Math.max(1, _adjustmentValue), maxValue);
38 }
39
40 function rotateCamera(newPose: vector2d, lastPose: vector2d) {
41 let rotation_vec = Qt.vector2d(newPose.y - lastPose.y, newPose.x - lastPose.x);
42
43 let dx_l = rotation_vec.x * rotationSpeed;
44 let dy_l = rotation_vec.y * rotationSpeed;
45
46 standAloneScene.cameraOneRotation.x += dx_l;
47 standAloneScene.cameraOneRotation.y += dy_l;
48 }
49
50 function zoomCamera(zoomValue) {
51 let dz_l = zoomValue * zoomSpeed * movementSpeedAdjustment(2000.0, 4);
52
53 let _roll = standAloneScene.cameraOneRotation.x * (Math.PI / 180);
54 let _pitch = standAloneScene.cameraOneRotation.y * (Math.PI / 180);
55
56 let dx = -dz_l * Math.cos(_roll) * Math.sin(_pitch);
57 let dy = -dz_l * Math.sin(_roll);
58 let dz = dz_l * Math.cos(_pitch) * Math.cos(_roll);
59
60 standAloneScene.cameraTwoPosition.x -= dx;
61 standAloneScene.cameraTwoPosition.y += dy;
62 standAloneScene.cameraTwoPosition.z += dz;
63 }
64
65 camera: standAloneScene.cameraOne
66
67 environment: SceneEnvironment {
68 antialiasingMode: SceneEnvironment.MSAA
69 antialiasingQuality: SceneEnvironment.High
70 backgroundMode: SceneEnvironment.Color
71 clearColor: _skyColor
72
73 fog: Fog {
74 color: _skyColor
75 depthCurve: 1.0
76 depthEnabled: true
77 depthFar: _viewDistance
78 depthNear: 1000
79 enabled: true
80 }
81 }
82
83 QGCPalette { id: qgcPal }
84
85 readonly property color _skyColor: qgcPal.window
86 importScene: CameraLightModel {
87 id: standAloneScene
88
89 viewDistance: _viewDistance
90 }
91
92 Component.onCompleted: {
93 vehicle3DLoader.active = true;
94 mapGeometryLoader.active = true;
95 }
96 on_GpsRefChanged: {
97 standAloneScene.resetCamera();
98 }
99
100 Viewer3DProgressBar {
101 id: _terrainProgressBar
102
103 progressText: qsTr("Downloading Imageries: ")
104 width: ScreenTools.screenWidth * 0.2
105
106 anchors {
107 bottom: parent.bottom
108 horizontalCenter: parent.horizontalCenter
109 margins: ScreenTools.defaultFontPixelWidth
110 }
111 }
112
113 Binding {
114 property: "progressValue"
115 target: _terrainProgressBar
116 value: (mapGeometryLoader.active) ? (mapGeometryLoader.item.textureDownloadProgress) : (100)
117 when: mapGeometryLoader.status == Loader.Ready
118 }
119
120 Component {
121 id: buildingsGeometryComponent
122
123 Node {
124 property real textureDownloadProgress: _terrainTextureManager.textureDownloadProgress
125
126 Model {
127 id: cityMapModel
128
129 scale: Qt.vector3d(10, 10, 10)
130 visible: true
131
132 geometry: CityMapGeometry {
133 id: cityMapGeometry
134
135 mapProvider: QGCViewer3DManager.mapProvider
136 modelName: "city_map"
137 }
138 materials: [
139 PrincipledMaterial {
140 baseColor: "gray"
141 indexOfRefraction: 4.0
142 metalness: 0.1
143 opacity: 1.0
144 roughness: 0.5
145 specularAmount: 1.0
146 }
147 ]
148 }
149
150 Model {
151 id: pointModel
152
153 scale: Qt.vector3d(10, 10, 10)
154 visible: true
155
156 geometry: Viewer3DTerrainGeometry {
157 id: terrainGeometryManager
158
159 refCoordinate: _gpsRef
160 }
161 materials: CustomMaterial {
162 property TextureInput someTextureMap: TextureInput {
163 texture: Texture {
164 textureData: _terrainTextureManager
165 }
166 }
167
168 fragmentShader: "/qml/QGroundControl/Viewer3D/ShaderFragment/earthMaterial.frag"
169 vertexShader: "/qml/QGroundControl/Viewer3D/ShaderVertex/earthMaterial.vert"
170 }
171 }
172
173 Viewer3DTerrainTexture {
174 id: _terrainTextureManager
175
176 mapProvider: QGCViewer3DManager.mapProvider
177
178 onTextureGeometryDoneChanged: {
179 if (textureGeometryDone === true) {
180 terrainGeometryManager.sectorCount = tileCount.width;
181 terrainGeometryManager.stackCount = tileCount.height;
182 terrainGeometryManager.roiMin = roiMinCoordinate;
183 terrainGeometryManager.roiMax = roiMaxCoordinate;
184 terrainGeometryManager.updateEarthData();
185 }
186 }
187 }
188 }
189 }
190
191 Loader3D {
192 id: mapGeometryLoader
193
194 active: false
195 sourceComponent: buildingsGeometryComponent
196 }
197
198 Component {
199 id: vehicle3DComponent
200
201 Repeater3D {
202 model: QGroundControl.multiVehicleManager.vehicles
203
204 delegate: Viewer3DVehicleItems {
205 _backendQml: QGCViewer3DManager
206 _camera: standAloneScene.cameraOne
207 _planMasterController: masterController
208 _vehicle: object
209
210 PlanMasterController {
211 id: masterController
212
213 Component.onCompleted: startStaticActiveVehicle(object)
214 }
215 }
216 }
217 }
218
219 Loader3D {
220 id: vehicle3DLoader
221
222 active: false
223 sourceComponent: vehicle3DComponent
224 }
225
226 DragHandler {
227 id: cameraMovementDragHandler
228
229 property bool _isMoving: false
230 property point _lastPose
231
232 acceptedButtons: Qt.LeftButton
233 acceptedModifiers: Qt.NoModifier
234 target: null
235
236 onActiveChanged: {
237 if (active) { // When mouse is pressed
238 _lastPose = Qt.point(centroid.position.x, centroid.position.y);
239 _isMoving = true;
240 } else { // When mouse is released
241 _isMoving = false;
242 }
243 }
244 onCentroidChanged: {
245 if (_isMoving) {
246 moveCamera(centroid.position, _lastPose);
247 _lastPose = Qt.point(centroid.position.x, centroid.position.y);
248 }
249 }
250 }
251
252 DragHandler {
253 id: cameraRotationDragHandler
254
255 property bool _isRotating: false
256 property point _lastPose
257
258 acceptedButtons: Qt.RightButton
259 acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
260 acceptedModifiers: Qt.NoModifier
261 target: null
262
263 onActiveChanged: {
264 if (active) { // When mouse is pressed
265 _lastPose = Qt.point(centroid.position.x, centroid.position.y);
266 _isRotating = true;
267 } else {// When mouse is released
268 _isRotating = false;
269 }
270 }
271 onCentroidChanged: {
272 if (_isRotating) {
273 rotateCamera(centroid.position, _lastPose);
274 _lastPose = Qt.point(centroid.position.x, centroid.position.y);
275 }
276 }
277 }
278
279 PinchHandler {
280 id: zoomRotationPinchHandler
281
282 property bool _isRotating: false
283 property point _lastPose
284 property real _lastZoomValue
285
286 target: null
287
288 onActiveChanged: {
289 if (active) {
290 _lastPose = Qt.point(centroid.position.x, centroid.position.y);
291 _lastZoomValue = 0;
292 _isRotating = true;
293 } else {
294 _isRotating = false;
295 }
296 }
297 onActiveScaleChanged: {
298 let zoomValue = (activeScale > 1) ? (activeScale - 1) : (-((1 / activeScale) - 1));
299 zoomCamera(-1000 * (zoomValue - _lastZoomValue));
300 _lastZoomValue = zoomValue;
301 }
302 onCentroidChanged: {
303 if (_isRotating) {
304 rotateCamera(centroid.position, _lastPose);
305 _lastPose = Qt.point(centroid.position.x, centroid.position.y);
306 }
307 }
308 }
309
310 WheelHandler {
311 id: wheelHandler
312
313 acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
314 orientation: Qt.Vertical
315 target: null
316
317 onWheel: event => {
318 zoomCamera(-event.angleDelta.y);
319 }
320 }
321
322 TapHandler {
323 function deselectAllWaypoints() {
324 if (!vehicle3DLoader.item)
325 return;
326 for (var i = 0; i < vehicle3DLoader.item.count; i++) {
327 vehicle3DLoader.item.objectAt(i).waypointInstancing.selectedIndex = -1;
328 }
329 }
330
331 onTapped: function (eventPoint) {
332 if (!vehicle3DLoader.item)
333 return;
334
335 var models = [];
336 for (var i = 0; i < vehicle3DLoader.item.count; i++) {
337 models.push(vehicle3DLoader.item.objectAt(i).waypointConeModel);
338 }
339
340 var results = topView.pickSubset(eventPoint.position.x, eventPoint.position.y, models);
341 if (results.length === 0) {
342 deselectAllWaypoints();
343 return;
344 }
345
346 var result = results[0];
347 for (var i = 0; i < vehicle3DLoader.item.count; i++) {
348 var vehicleItem = vehicle3DLoader.item.objectAt(i);
349 if (result.objectHit === vehicleItem.waypointConeModel) {
350 vehicleItem.waypointInstancing.selectedIndex = result.instanceIndex;
351 return;
352 }
353 }
354
355 deselectAllWaypoints();
356 }
357 }
358}