Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/osgview/GUIOSGPerspectiveChanger.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 GUIOSGPerspectiveChanger.cpp
15
/// @author Mirko Barthauer
16
/// @date August 2022
17
///
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>
26
#include <utils/gui/settings/GUICompleteSchemeStorage.h>
27
#include "GUIOSGPerspectiveChanger.h"
28
29
30
// ===========================================================================
31
// method definitions
32
// ===========================================================================
33
GUIOSGPerspectiveChanger::GUIOSGPerspectiveChanger(
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
43
GUIOSGPerspectiveChanger::~GUIOSGPerspectiveChanger() {}
44
45
46
bool
47
GUIOSGPerspectiveChanger::onLeftBtnRelease(void* /* data */) {
48
updateViewport();
49
return false;
50
}
51
52
53
bool
54
GUIOSGPerspectiveChanger::onRightBtnRelease(void* /* data */) {
55
updateViewport();
56
return false;
57
}
58
59
60
bool
61
GUIOSGPerspectiveChanger::onMiddleBtnRelease(void* /* data */) {
62
updateViewport();
63
return false;
64
}
65
66
67
void GUIOSGPerspectiveChanger::onMouseMove(void* /* data */) {
68
//updateViewport();
69
}
70
71
72
double
73
GUIOSGPerspectiveChanger::getRotation() const {
74
return myRotation;
75
}
76
77
78
double
79
GUIOSGPerspectiveChanger::getXPos() const {
80
osg::Vec3d lookFrom, lookAt, up;
81
myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
82
return lookFrom.x();
83
}
84
85
86
double
87
GUIOSGPerspectiveChanger::getYPos() const {
88
osg::Vec3d lookFrom, lookAt, up;
89
myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
90
return lookFrom.y();
91
}
92
93
94
double
95
GUIOSGPerspectiveChanger::getZPos() const {
96
osg::Vec3d lookFrom, lookAt, up;
97
myCameraManipulator->getInverseMatrix().getLookAt(lookFrom, lookAt, up);
98
return lookFrom.z();
99
}
100
101
102
double
103
GUIOSGPerspectiveChanger::getZoom() const {
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
121
GUIOSGPerspectiveChanger::setRotation(double rotation) {
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
195
GUIOSGPerspectiveChanger::updateViewport() {
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
218
GUIOSGPerspectiveChanger::getPositionOnGround(double x, double y) {
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
239
GUIOSGPerspectiveChanger::changeCanvasSizeLeft(int /* change */) {
240
}
241
242
243
void
244
GUIOSGPerspectiveChanger::setViewport(const Boundary& viewPort) {
245
setViewport(100., viewPort.getCenter().x(), viewPort.getCenter().y());
246
}
247
248