Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/osgview/GUIOSGManipulator.cpp
169665 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file GUIOSGManipulator.cpp
15
/// @author Mirko Barthauer
16
/// @date 27.11.2022
17
///
18
// A custom camera manipulator to interact with the OSG view directly
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <utils/geom/GeomHelper.h>
23
#include <utils/common/MsgHandler.h>
24
#include <utils/common/StringBijection.h>
25
26
#include "GUIOSGManipulator.h"
27
#include "GUIOSGView.h"
28
29
#ifdef HAVE_OSG
30
31
#define DEFAULT_MOVESPEED_MIN 1.0
32
//#define DEFAULT_MOVESPEED_MAX 30.0
33
//#define DEFAULT_MOVEACCEL 2.0
34
35
static StringBijection<ManipulatorMode>::Entry ModeTextInitializer[] = {
36
{"Ego", MODE_EGO},
37
{"Walk", MODE_WALK},
38
{"Terrain", MODE_TERRAIN}
39
};
40
41
StringBijection<ManipulatorMode> ModeText(ModeTextInitializer, MODE_TERRAIN, false);
42
43
44
// ===========================================================================
45
// method definitions
46
// ===========================================================================
47
GUIOSGManipulator::GUIOSGManipulator(GUIOSGView* parent, ManipulatorMode initMode, bool verticalFixed, double /* eyeHeight */) :
48
myParent(parent), myCurrentMode(initMode), /*myWalkEyeHeight(eyeHeight),*/ myMoveSpeed(DEFAULT_MOVESPEED_MIN) {
49
setAllowThrow(false);
50
setVerticalAxisFixed(verticalFixed);
51
}
52
53
54
GUIOSGManipulator::~GUIOSGManipulator() {
55
}
56
57
58
bool
59
GUIOSGManipulator::performMovementLeftMouseButton(const double eventTimeDelta, const double dx, const double dy) {
60
if (myCurrentMode == MODE_TERRAIN) {
61
return osgGA::TerrainManipulator::performMovementMiddleMouseButton(eventTimeDelta, dx, dy);
62
}
63
return false;
64
}
65
66
67
bool
68
GUIOSGManipulator::performMovementMiddleMouseButton(const double eventTimeDelta, const double dx, const double dy) {
69
if (myCurrentMode == MODE_TERRAIN) {
70
return osgGA::TerrainManipulator::performMovementLeftMouseButton(eventTimeDelta, dx, dy);
71
}
72
return false;
73
}
74
75
76
bool
77
GUIOSGManipulator::performMovementRightMouseButton(const double eventTimeDelta, const double dx, const double dy) {
78
if (myCurrentMode == MODE_TERRAIN) {
79
return osgGA::TerrainManipulator::performMovementRightMouseButton(eventTimeDelta, dx, -dy);
80
}
81
return false;
82
}
83
84
85
bool
86
GUIOSGManipulator::handleMouseMove(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
87
if (myCurrentMode == MODE_EGO || myCurrentMode == MODE_WALK) {
88
return handleMouseDeltaMovement(ea, aa);
89
}
90
return false;
91
}
92
93
94
bool
95
GUIOSGManipulator::handleMouseDrag(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
96
if (myCurrentMode == MODE_TERRAIN) {
97
return osgGA::TerrainManipulator::handleMouseDrag(ea, aa);
98
}
99
return handleMouseDeltaMovement(ea, aa);
100
}
101
102
103
bool
104
GUIOSGManipulator::handleMousePush(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
105
if (myCurrentMode == MODE_TERRAIN) {
106
return osgGA::TerrainManipulator::handleMousePush(ea, aa);
107
}
108
return handleMouseDeltaMovement(ea, aa);
109
}
110
111
112
bool
113
GUIOSGManipulator::handleMouseRelease(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
114
if (myCurrentMode == MODE_TERRAIN) {
115
return osgGA::TerrainManipulator::handleMouseRelease(ea, aa);
116
}
117
return false;
118
}
119
120
121
bool
122
GUIOSGManipulator::handleMouseDeltaMovement(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
123
addMouseEvent(ea);
124
if (_ga_t0.get() == NULL || _ga_t1.get() == NULL) {
125
return false;
126
}
127
float dt = static_cast<float>(_ga_t0->getTime() - _ga_t1->getTime());
128
if (dt > 0.1) { // wait until the mouse movement is sufficiently smooth
129
return false;
130
}
131
float intensity = 50.;
132
float dx = _ga_t0->getXnormalized() * intensity * dt;
133
float dy = _ga_t0->getYnormalized() * intensity * dt;
134
if (dx == 0. && dy == 0.) {
135
return false;
136
}
137
centerMousePointer(ea, aa);
138
// calculate delta angles from dx and dy movements
139
if (performMouseDeltaMovement(dx, dy)) {
140
aa.requestRedraw();
141
}
142
return true;
143
}
144
145
146
bool
147
GUIOSGManipulator::performMouseDeltaMovement(const float dx, const float dy) {
148
rotateYawPitch(_rotation, dx, dy, osg::Z_AXIS);
149
return true;
150
}
151
152
153
void GUIOSGManipulator::centerMousePointer(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
154
_mouseCenterX = (ea.getXmin() + ea.getXmax()) / 2.0f;
155
_mouseCenterY = (ea.getYmin() + ea.getYmax()) / 2.0f;
156
aa.requestWarpPointer(_mouseCenterX, _mouseCenterY);
157
}
158
159
160
void
161
GUIOSGManipulator::rotateYawPitch(osg::Quat& rotation, const double yaw, const double pitch, const osg::Vec3d& localUp) {
162
bool verticalAxisFixed = (localUp != osg::Vec3d(0., 0., 0.));
163
164
// fix current rotation
165
if (verticalAxisFixed) {
166
fixVerticalAxis(rotation, localUp, true);
167
}
168
169
// rotations
170
osg::Quat rotateYaw(-yaw, verticalAxisFixed ? localUp : rotation * osg::Vec3d(0., 1., 0.));
171
osg::Quat rotatePitch;
172
osg::Quat newRotation;
173
osg::Vec3d cameraRight(rotation * osg::Vec3d(1., 0., 0.));
174
175
double my_dy = pitch;
176
int i = 0;
177
osg::Vec3f eye = _center - _rotation * osg::Vec3d(0., 0., -_distance);
178
do {
179
// rotations
180
rotatePitch.makeRotate(my_dy, cameraRight);
181
newRotation = rotation * rotateYaw * rotatePitch;
182
183
// update vertical axis
184
if (verticalAxisFixed) {
185
fixVerticalAxis(newRotation, localUp, false);
186
}
187
188
// check for viewer's up vector to be more than 90 degrees from "up" axis
189
osg::Vec3d newCameraUp = newRotation * osg::Vec3d(0., 1., 0.);
190
if (newCameraUp * localUp > 0.) {
191
// apply new rotation
192
setByMatrix(osg::Matrixd::rotate(newRotation) * osg::Matrixd::translate(eye));
193
return;
194
}
195
my_dy /= 2.;
196
if (++i == 20) {
197
setByMatrix(osg::Matrixd::rotate(rotation) * osg::Matrixd::rotate(rotateYaw) * osg::Matrixd::translate(eye));
198
return;
199
}
200
} while (true);
201
}
202
203
204
bool
205
GUIOSGManipulator::handleKeyDown(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& /* aa */) {
206
bool result = false;
207
switch (ea.getKey()) {
208
case osgGA::GUIEventAdapter::KEY_Up:
209
myMove.z() -= myMoveSpeed;
210
result = true;
211
break;
212
case osgGA::GUIEventAdapter::KEY_Down:
213
myMove.z() += myMoveSpeed;
214
result = true;
215
break;
216
case osgGA::GUIEventAdapter::KEY_Right:
217
myMove.x() += myMoveSpeed;
218
result = true;
219
break;
220
case osgGA::GUIEventAdapter::KEY_Left:
221
myMove.x() -= myMoveSpeed;
222
result = true;
223
break;
224
}
225
_center += getMatrix().getRotate() * myMove;
226
return result;
227
}
228
229
230
bool
231
GUIOSGManipulator::handleKeyUp(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& /* aa */) {
232
bool result = false;
233
switch (ea.getKey()) {
234
case osgGA::GUIEventAdapter::KEY_Up:
235
case osgGA::GUIEventAdapter::KEY_Down:
236
case osgGA::GUIEventAdapter::KEY_Right:
237
case osgGA::GUIEventAdapter::KEY_Left:
238
myMove.set(0, 0, 0);
239
return true;
240
case osgGA::GUIEventAdapter::KEY_F:
241
if (myCurrentMode == MODE_EGO) {
242
myCurrentMode = MODE_TERRAIN; // MODE_WALK disabled until it's fully implemented
243
} else if (myCurrentMode == MODE_WALK) {
244
myCurrentMode = MODE_TERRAIN;
245
} else {
246
myCurrentMode = MODE_EGO;
247
}
248
updateHUDText();
249
return true;
250
}
251
return result;
252
}
253
254
255
void
256
GUIOSGManipulator::updateHUDText() {
257
myParent->updateHUDText(TLF("Currently in % camera mode. Press [F] to switch.", ModeText.getString(myCurrentMode)));
258
}
259
260
261
void
262
GUIOSGManipulator::setByMatrix(const osg::Matrixd& matrix) {
263
_center = osg::Vec3d(0., 0., -_distance) * matrix;
264
_rotation = matrix.getRotate();
265
266
// fix current rotation
267
if (getVerticalAxisFixed()) {
268
fixVerticalAxis(_center, _rotation, true);
269
}
270
}
271
272
273
osg::Matrixd GUIOSGManipulator::getMatrix() const {
274
if (myCurrentMode == MODE_TERRAIN) {
275
return osg::Matrixd::translate(0., 0., _distance) *
276
osg::Matrixd::rotate(_rotation) *
277
osg::Matrixd::translate(_center);
278
} else {
279
osg::Vec3f eye = _center - _rotation * osg::Vec3d(0., 0., -_distance);
280
return osg::Matrixd::rotate(_rotation) * osg::Matrixd::translate(eye);
281
}
282
}
283
284
285
osg::Matrixd GUIOSGManipulator::getInverseMatrix() const {
286
if (myCurrentMode == MODE_TERRAIN) {
287
return osg::Matrixd::translate(-_center) *
288
osg::Matrixd::rotate(_rotation.inverse()) *
289
osg::Matrixd::translate(0.0, 0.0, -_distance);
290
} else {
291
osg::Vec3f eye = _center - _rotation * osg::Vec3d(0., 0., -_distance);
292
return osg::Matrixd::translate(-eye) * osg::Matrixd::rotate(_rotation.inverse());
293
}
294
}
295
296
#endif
297
298