Eclipse SUMO - Simulation of Urban MObility
GUIOSGManipulator.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-2024 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 /****************************************************************************/
18 // A custom camera manipulator to interact with the OSG view directly
19 /****************************************************************************/
20 #include <config.h>
21 
22 #include <utils/geom/GeomHelper.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;
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
@ KEY_F
Definition: GUIShortcuts.h:75
#define TLF(string,...)
Definition: MsgHandler.h:317