Eclipse SUMO - Simulation of Urban MObility
GUIOSGPerspectiveChanger.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 // Implementation of GUIPerspectiveChanger for OSG 3D views
19 /****************************************************************************/
20 #include <config.h>
21 
22 #include <fxkeys.h>
23 #include <utils/geom/Boundary.h>
24 #include <utils/geom/Position.h>
25 #include <utils/geom/GeomHelper.h>
28 
29 
30 // ===========================================================================
31 // method definitions
32 // ===========================================================================
34  GUIOSGView& callBack, const Boundary& viewPort) :
35  GUIPerspectiveChanger(callBack, viewPort),
36  myOrigWidth(viewPort.getWidth()),
37  myOrigHeight(viewPort.getHeight()),
38  myRotation(0) {
39  myCameraManipulator = callBack.myCameraManipulator;
40 }
41 
42 
44 
45 
46 bool
49  return false;
50 }
51 
52 
53 bool
56  return false;
57 }
58 
59 
60 bool
63  return false;
64 }
65 
66 
67 void GUIOSGPerspectiveChanger::onMouseMove(void* /* data */) {
68  //updateViewport();
69 }
70 
71 
72 double
74  return myRotation;
75 }
76 
77 
78 double
80  osg::Vec3d lookFrom, lookAt, up;
81  myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
82  return lookFrom.x();
83 }
84 
85 
86 double
88  osg::Vec3d lookFrom, lookAt, up;
89  myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
90  return lookFrom.y();
91 }
92 
93 
94 double
96  osg::Vec3d lookFrom, lookAt, up;
97  myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
98  return lookFrom.z();
99 }
100 
101 
102 double
104  return 100.;
105 }
106 
107 
108 double
109 GUIOSGPerspectiveChanger::zPos2Zoom(double /* zPos */) const {
110  return 100.;
111 }
112 
113 
114 double
115 GUIOSGPerspectiveChanger::zoom2ZPos(double /* zoom */) const {
116  return getZPos();
117 }
118 
119 
120 void
122  myRotation = rotation;
123 }
124 
125 
126 void
127 GUIOSGPerspectiveChanger::centerTo(const Position& pos, double radius, bool /* applyZoom */) {
128  // maintain view direction if possible and scale so that the position and the
129  // radius region around it are visible
130  osg::Vec3d lookFrom, lookAt, up, dir, orthoDir;
131  myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
132  dir = lookAt - lookFrom;
133  // create helper vectors // check if parallel to z
134  if ((dir ^ osg::Z_AXIS).length() > 0) {
135  orthoDir[0] = -dir[1];
136  orthoDir[1] = dir[0];
137  up = osg::Z_AXIS;
138  } else {
139  orthoDir = -osg::X_AXIS;
140  up = osg::Y_AXIS;
141  }
142  orthoDir.normalize();
143  osg::Vec3d center(pos.x(), pos.y(), pos.z());
144  osg::Vec3d leftBorder = center + orthoDir * radius;
145  // construct new camera location which respects the fovy, resets the up vector
146  double fovy, aspectRatio, zNear, zFar;
147  dynamic_cast<GUIOSGView&>(myCallback).myViewer->getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
148  double halfFovy = DEG2RAD(.5 * fovy);
149  osg::Vec3d outerFov = dir * cos(halfFovy) + orthoDir * sin(halfFovy);
150  osg::Vec3d radiusVec = leftBorder - center;
151  int sign = ((outerFov ^ radiusVec) * (outerFov ^ dir) > 0) ? 1 : -1;
152  osg::Vec3d camUpdate = center + dir * sign * (outerFov ^ radiusVec).length() / (outerFov ^ dir).length();
153  myCameraManipulator->setHomePosition(camUpdate, center, up);
154  myRotation = 0.;
155  dynamic_cast<GUIOSGView&>(myCallback).myViewer->home();
156  updateViewport(camUpdate);
157 }
158 
159 
160 void
161 GUIOSGPerspectiveChanger::setViewport(double /* zoom */, double xPos, double yPos) {
162  setViewportFrom(xPos, yPos, 0.);
163 }
164 
165 
166 void
167 GUIOSGPerspectiveChanger::setViewportFrom(double xPos, double yPos, double /* zPos */) {
168  // Keep camera orientation if possible and point it to point to (x,y,0) if possible.
169  // get current camera orientation
170  osg::Vec3d lookFrom, lookAt, up, dir;
171  myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
172  dir = lookAt - lookFrom;
173  if ((dir.z() > 0. && lookFrom.z() >= 0.) || dir.z() == 0.) { // create bird view
174  lookFrom[0] = xPos;
175  lookFrom[1] = yPos;
176  lookAt = lookFrom - osg::Vec3d(0., 0., 1.);
177  } else { // shift current view to reach (x,y,0)
178  osg::Vec3d shift;
179  // compute the point on the ground which is in line with the camera direction (solve for z=0)
180  double factor = -lookFrom.z() / dir.z();
181  osg::Vec3d groundTarget = lookFrom + dir * factor;
182  shift[0] = xPos - groundTarget.x();
183  shift[1] = yPos - groundTarget.y();
184  lookFrom += shift;
185  lookAt += shift;
186  }
187  osg::Matrix m;
188  m.makeLookAt(lookFrom, lookAt, up);
189  myCameraManipulator->setByInverseMatrix(m);
190  updateViewport(lookFrom);
191 }
192 
193 
194 void
196  osg::Vec3d lookFrom, lookAt, up, dir;
197  myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
198  updateViewport(lookFrom);
199 }
200 
201 
202 void
203 GUIOSGPerspectiveChanger::updateViewport(osg::Vec3d& /* lookFrom */) {
204  osg::Vec3d bottomLeft = getPositionOnGround(-1., -1.);
205  osg::Vec3d bottomRight = getPositionOnGround(1., -1.);
206  osg::Vec3d topLeft = getPositionOnGround(1., -1.);
207  osg::Vec3d topRight = getPositionOnGround(1., 1.);
208  double xMin, xMax, yMin, yMax;
209  xMin = MIN4(bottomLeft.x(), bottomRight.x(), topLeft.x(), topRight.x());
210  xMax = MAX4(bottomLeft.x(), bottomRight.x(), topLeft.x(), topRight.x());
211  yMin = MIN4(bottomLeft.y(), bottomRight.y(), topLeft.y(), topRight.y());
212  yMax = MAX4(bottomLeft.y(), bottomRight.y(), topLeft.y(), topRight.y());
213  myViewPort.set(xMin, yMin, xMax, yMax);
214 }
215 
216 
217 osg::Vec3d
219  osg::Matrix VP = dynamic_cast<GUIOSGView&>(myCallback).myViewer->getCamera()->getViewMatrix() * dynamic_cast<GUIOSGView&>(myCallback).myViewer->getCamera()->getProjectionMatrix();
220  osg::Matrix inverseVP;
221  inverseVP.invert(VP);
222 
223  // compute world near far
224  osg::Vec3d nearPoint(x, y, -1.);
225  osg::Vec3d farPoint(x, y, 1.);
226  osg::Vec3d nearPointWorld = nearPoint * inverseVP;
227  osg::Vec3d farPointWorld = farPoint * inverseVP;
228 
229  // compute crossing with ground plane
230  osg::Vec3d ray = farPointWorld - nearPointWorld;
231  if (abs(ray.z()) > 0) {
232  return nearPointWorld + ray * (-nearPointWorld.z() / ray.z());
233  }
234  return osg::Vec3d(0., 0., 0.);
235 }
236 
237 
238 void
240 }
241 
242 
243 void
245  setViewport(100., viewPort.getCenter().x(), viewPort.getCenter().y());
246 }
#define DEG2RAD(x)
Definition: GeomHelper.h:35
T MIN4(T a, T b, T c, T d)
Definition: StdDefs.h:103
T MAX4(T a, T b, T c, T d)
Definition: StdDefs.h:110
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:39
Position getCenter() const
Returns the center of the boundary.
Definition: Boundary.cpp:112
void set(double xmin, double ymin, double xmax, double ymax)
Sets the boundary to the given values.
Definition: Boundary.cpp:388
void setRotation(double rotation)
Sets the rotation.
double getYPos() const
Returns the y-offset of the field to show stored in this changer.
void updateViewport()
update the min/max coordinates of the view on the ground plane after changing the camera pos / direct...
GUIOSGPerspectiveChanger(GUIOSGView &callBack, const Boundary &viewPort)
void setViewportFrom(double xPos, double yPos, double zPos)
Alternative method for setting the viewport.
double getRotation() const
Returns the rotation of the canvas stored in this changer.
osg::Vec3d getPositionOnGround(double x, double y)
calculate the position on the ground (in world coordinates) given a normalised view coordinate (x,...
double getZPos() const
Returns the camera height corresponding to the current zoom factor.
double getXPos() const
Returns the x-offset of the field to show stored in this changer.
bool onMiddleBtnRelease(void *data)
called when user releases middle button
double zPos2Zoom(double zPos) const
Returns the zoom level that is achieved at a given camera height.
bool onRightBtnRelease(void *data)
called when user releases right button
double zoom2ZPos(double zoom) const
Returns the camera height at which the given zoom level is reached.
osg::ref_ptr< osgGA::TerrainManipulator > myCameraManipulator
the OSG camera structure to gather the view coordinates
double myRotation
the current rotation
void centerTo(const Position &pos, double radius, bool applyZoom=true)
Centers the view to the given position, setting it to a size that covers the radius....
bool onLeftBtnRelease(void *data)
mouse functions
void setViewport(double zoom, double xPos, double yPos)
Sets the viewport Used for: Adapting a new viewport.
double getZoom() const
Returns the zoom factor computed stored in this changer.
void onMouseMove(void *data)
called when user moves mouse
GUISUMOAbstractView & myCallback
The parent window (canvas to scale)
Boundary myViewPort
the intended viewport
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
double x() const
Returns the x-position.
Definition: Position.h:55
double z() const
Returns the z-position.
Definition: Position.h:65
double y() const
Returns the y-position.
Definition: Position.h:60