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.org/sumo
3// Copyright (C) 2001-2022 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>
28
29// ===========================================================================
30// method definitions
31// ===========================================================================
33 GUIOSGView& callBack, const Boundary& viewPort) :
34 GUIPerspectiveChanger(callBack, viewPort),
35 myOrigWidth(viewPort.getWidth()),
36 myOrigHeight(viewPort.getHeight()),
37 myRotation(0) {
38 myCameraManipulator = callBack.myCameraManipulator;
39}
40
41
43
44
47 return false;
48}
49
50
53 return false;
54}
55
56
58 //updateViewport();
59}
60
61double
63 return myRotation;
64}
65
66
67double
69 osg::Vec3d lookFrom, lookAt, up;
70 myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
71 return lookFrom.x();
72}
73
74
75double
77 osg::Vec3d lookFrom, lookAt, up;
78 myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
79 return lookFrom.y();
80}
81
82
83double
85 osg::Vec3d lookFrom, lookAt, up;
86 myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
87 return lookFrom.z();
88}
89
90
91double
93 return 100.;
94}
95
96
97double
98GUIOSGPerspectiveChanger::zPos2Zoom(double /* zPos */) const {
99 return 100.;
100}
101
102
103double
104GUIOSGPerspectiveChanger::zoom2ZPos(double /* zoom */) const {
105 return getZPos();
106}
107
108
109void
111 myRotation = rotation;
112}
113
114
115void
116GUIOSGPerspectiveChanger::centerTo(const Position& pos, double radius, bool /* applyZoom */) {
117 // maintain view direction if possible and scale so that the position and the
118 // radius region around it are visible
119 osg::Vec3d lookFrom, lookAt, up, dir, orthoDir;
120 myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
121 dir = lookAt - lookFrom;
122 // create helper vectors // check if parallel to z
123 if (dir * osg::Z_AXIS != 0) {
124 orthoDir = -osg::X_AXIS;
125 up = osg::Y_AXIS;
126 } else {
127 orthoDir[0] = -dir[1];
128 orthoDir[1] = dir[0];
129 up = osg::Z_AXIS;
130 }
131 orthoDir.normalize();
132 osg::Vec3d center(pos.x(), pos.y(), pos.z());
133 osg::Vec3d leftBorder = center + orthoDir * radius;
134 // construct new camera location which respects the fovy, resets the up vector
135 double fovy, aspectRatio, zNear, zFar;
136 dynamic_cast<GUIOSGView&>(myCallback).myViewer->getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
137 double halfFovy = DEG2RAD(.5 * fovy);
138 osg::Vec3d outerFov = dir * cos(halfFovy) + orthoDir * sin(halfFovy);
139 osg::Vec3d radiusVec = leftBorder - center;
140 int sign = ((outerFov ^ radiusVec) * (outerFov ^ dir) > 0) ? 1 : -1;
141 osg::Vec3d camUpdate = center + dir * sign * (outerFov ^ radiusVec).length() / (outerFov ^ dir).length();
142 myCameraManipulator->setHomePosition(camUpdate, center, up);
143 myRotation = 0.;
144 dynamic_cast<GUIOSGView&>(myCallback).myViewer->home();
145 updateViewport(lookFrom);
146}
147
148
149void
150GUIOSGPerspectiveChanger::setViewport(double /* zoom */, double xPos, double yPos) {
151 setViewportFrom(xPos, yPos, 0.);
152}
153
154
155void
156GUIOSGPerspectiveChanger::setViewportFrom(double xPos, double yPos, double /* zPos */) {
157 // Keep camera orientation if possible and point it to point to (x,y,0) if possible.
158 // get current camera orientation
159 osg::Vec3d lookFrom, lookAt, up, dir;
160 myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
161 dir = lookAt - lookFrom;
162 if ((dir.z() > 0. && lookFrom.z() >= 0.) || dir.z() == 0.) { // create bird view
163 lookFrom[0] = xPos;
164 lookFrom[1] = yPos;
165 lookAt = lookFrom - osg::Vec3d(0., 0., 1.);
166 } else { // shift current view to reach (x,y,0)
167 osg::Vec3d shift;
168 // compute the point on the ground which is in line with the camera direction (solve for z=0)
169 double factor = -lookFrom.z() / dir.z();
170 osg::Vec3d groundTarget = lookFrom + dir * factor;
171 shift[0] = xPos - groundTarget.x();
172 shift[1] = yPos - groundTarget.y();
173 lookFrom += shift;
174 lookAt += shift;
175 }
176 osg::Matrix m;
177 m.makeLookAt(lookFrom, lookAt, up);
178 myCameraManipulator->setByInverseMatrix(m);
179 updateViewport(lookFrom);
180}
181
182
183void
185 osg::Vec3d lookFrom, lookAt, up, dir;
186 myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
187 updateViewport(lookFrom);
188}
189
190
191void
192GUIOSGPerspectiveChanger::updateViewport(osg::Vec3d& /* lookFrom */) {
193 osg::Vec3d bottomLeft = getPositionOnGround(-1., -1.);
194 osg::Vec3d topRight = getPositionOnGround(1., 1.);
195 myViewPort.set(bottomLeft.x(), bottomLeft.y(), topRight.x(), topRight.y());
196}
197
198
199osg::Vec3d
201 osg::Matrix VP = dynamic_cast<GUIOSGView&>(myCallback).myViewer->getCamera()->getViewMatrix() * dynamic_cast<GUIOSGView&>(myCallback).myViewer->getCamera()->getProjectionMatrix();
202 osg::Matrix inverseVP;
203 inverseVP.invert(VP);
204
205 // compute world near far
206 osg::Vec3d nearPoint(x, y, -1.);
207 osg::Vec3d farPoint(x, y, 1.);
208 osg::Vec3d nearPointWorld = nearPoint * inverseVP;
209 osg::Vec3d farPointWorld = farPoint * inverseVP;
210
211 // compute crossing with ground plane
212 osg::Vec3d ray = farPointWorld - nearPointWorld;
213 if (abs(ray.z()) > 0) {
214 return nearPointWorld + ray * (-nearPointWorld.z() / ray.z());
215 }
216 return osg::Vec3d(0., 0., 0.);
217}
218
219
220void
222}
223
224
225void
227 setViewport(100., viewPort.getCenter().x(), viewPort.getCenter().y());
228}
#define DEG2RAD(x)
Definition: GeomHelper.h:35
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:369
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.
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