Line data Source code
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 GUIOSGView.h
15 : /// @author Daniel Krajzewicz
16 : /// @author Mirko Barthauer
17 : /// @date 19.01.2012
18 : ///
19 : // An OSG-based 3D view on the simulation
20 : /****************************************************************************/
21 : #pragma once
22 : #include <config.h>
23 :
24 : #ifdef HAVE_OSG
25 :
26 : #include "GUIOSGHeader.h"
27 : #include "GUIOSGManipulator.h"
28 :
29 : #include <string>
30 : #include <microsim/traffic_lights/MSTLLogicControl.h>
31 : #include <utils/geom/Boundary.h>
32 : #include <utils/geom/Position.h>
33 : #include <utils/common/RGBColor.h>
34 : #include <utils/geom/PositionVector.h>
35 : #include <gui/GUISUMOViewParent.h>
36 : #include <utils/gui/windows/GUISUMOAbstractView.h>
37 :
38 :
39 : // ===========================================================================
40 : // class declarations
41 : // ===========================================================================
42 :
43 : class GUINet;
44 : class GUISUMOViewParent;
45 : class GUIVehicle;
46 : class GUILaneWrapper;
47 : class MSRoute;
48 : class MSTransportable;
49 : class MSVehicle;
50 :
51 : namespace osgGA {
52 : class CameraManipulator;
53 : }
54 :
55 : // ===========================================================================
56 : // class definitions
57 : // ===========================================================================
58 : /**
59 : * @class GUIOSGView
60 : * @brief An OSG-based 3D view on the simulation
61 : */
62 : class GUIOSGView : public GUISUMOAbstractView {
63 : #ifdef __clang__
64 : #pragma clang diagnostic push
65 : #pragma clang diagnostic ignored "-Winconsistent-missing-override"
66 : #endif
67 0 : FXDECLARE(GUIOSGView)
68 : #ifdef __clang__
69 : #pragma clang diagnostic pop
70 : #endif
71 :
72 : public:
73 : friend class GUIOSGPerspectiveChanger;
74 :
75 : /// @brief Used osg::NodeSet groups
76 : enum NodeSetGroup {
77 : /// @brief semi-transparent domes around user-placed TLS models
78 : NODESET_TLSDOMES = 1,
79 : /// @brief markers above lanes showing the signal state of the corresponding tlIndex
80 : NODESET_TLSLINKMARKERS = 2,
81 : /// @brief auto-generated TLS models
82 : NODESET_TLSMODELS = 4,
83 : };
84 :
85 : /**
86 : * @class Command_TLSChange
87 : * @brief Updates scene on each tls switch
88 : */
89 : class Command_TLSChange : public MSTLLogicControl::OnSwitchAction {
90 : public:
91 : /** @brief Constructor
92 : *
93 : * @param[in] link The link to observe
94 : * @param[in] root the root of the scene
95 : * @param[in] green the green light
96 : * @param[in] yellow the yellow light
97 : * @param[in] red the red light
98 : */
99 : Command_TLSChange(const MSLink* const link, osg::Switch* switchNode);
100 :
101 : /// @brief Destructor
102 : virtual ~Command_TLSChange();
103 :
104 : /** @brief Executes the command
105 : *
106 : * Called when an active tls program switches.
107 : * If the state of the observed linkchanged, this method removes
108 : * the old traffic light and adds a new one.
109 : */
110 : void execute();
111 :
112 : private:
113 : /// @brief The link to observe
114 : const MSLink* const myLink;
115 :
116 : /// @brief The switch for the traffic light models
117 : osg::ref_ptr<osg::Switch> mySwitch;
118 :
119 : /// @brief The previous link state
120 : LinkState myLastState;
121 :
122 : private:
123 : /// @brief Invalidated copy constructor.
124 : Command_TLSChange(const Command_TLSChange&) = delete;
125 :
126 : /// @brief Invalidated assignment operator.
127 : Command_TLSChange& operator=(const Command_TLSChange&) = delete;
128 : };
129 :
130 : /// @brief struct for OSG movable elements
131 : struct OSGMovable {
132 : osg::ref_ptr<osg::PositionAttitudeTransform> pos;
133 : osg::ref_ptr<osg::PositionAttitudeTransform> body;
134 : osg::ref_ptr<osg::Material> mat;
135 : osg::ref_ptr<osg::Switch> lights;
136 : bool active;
137 :
138 3651869 : void activateMaterial(bool state = true) {
139 3651869 : osg::ref_ptr<osg::StateSet> ss = body->getOrCreateStateSet();
140 3651869 : if (state) {
141 : ss->setAttribute(mat, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED);
142 : } else {
143 : ss->setAttribute(mat, osg::StateAttribute::OFF);
144 : }
145 3651869 : }
146 : };
147 :
148 : /// @brief constructor
149 : GUIOSGView(FXComposite* p, GUIMainWindow& app,
150 : GUISUMOViewParent* parent, GUINet& net, FXGLVisual* glVis,
151 : FXGLCanvas* share);
152 :
153 : /// @brief destructor
154 : virtual ~GUIOSGView();
155 :
156 : /// @brief Returns the cursor's x/y position within the network
157 : Position getPositionInformation() const override;
158 :
159 : /// @brief confirm 3D view to viewport editor
160 : bool is3DView() const override;
161 :
162 : /// @brief builds the view toolbars
163 : virtual void buildViewToolBars(GUIGlChildWindow*) override;
164 :
165 : /// @brief recenters the view
166 : void recenterView() override;
167 :
168 : /** @brief centers to the chosen artifact
169 : * @param[in] id The id of the artifact to center to
170 : * @param[in] applyZoom Whether to zoom in
171 : * @param[in] zoomDist The distance in m to use for the zoom, values < 0 means: use the centeringBoundary
172 : * @note caller is responsible for calling update
173 : */
174 : //void centerTo(GUIGlID id, bool applyZoom, double zoomDist = 20);
175 :
176 : /// @brief update the viewport chooser with the current view values
177 : void updateViewportValues() override;
178 :
179 : /// @brief show viewport editor
180 : void showViewportEditor() override;
181 :
182 : /// @brief applies the given viewport settings
183 : void setViewportFromToRot(const Position& lookFrom, const Position& lookAt, double rotation) override;
184 :
185 : /// @brief copy the viewport to the given view
186 : void copyViewportTo(GUISUMOAbstractView* view) override;
187 :
188 : /** @brief Starts vehicle tracking
189 : * @param[in] id The glID of the vehicle to track
190 : */
191 : void startTrack(int id) override;
192 :
193 : /** @brief Stops vehicle tracking
194 : */
195 : void stopTrack() override;
196 :
197 : /** @brief Returns the id of the tracked vehicle (-1 if none)
198 : * @return The glID of the vehicle to track
199 : */
200 : GUIGlID getTrackedID() const override;
201 :
202 : bool setColorScheme(const std::string& name) override;
203 :
204 : /// @brief handle mouse click in gaming mode
205 : void onGamingClick(Position pos) override;
206 :
207 : /// @brief get the current simulation time
208 : SUMOTime getCurrentTimeStep() const override;
209 :
210 : void removeVeh(MSVehicle* veh);
211 : void removeTransportable(MSTransportable* t);
212 :
213 : /// @brief added some callback to OSG to resize
214 : void position(int x, int y, int w, int h) override;
215 : void resize(int w, int h) override;
216 :
217 : // callback
218 : long onConfigure(FXObject*, FXSelector, void*) override;
219 : long onKeyPress(FXObject*, FXSelector, void*) override;
220 : long onKeyRelease(FXObject*, FXSelector, void*) override;
221 : long onLeftBtnPress(FXObject*, FXSelector, void*) override;
222 : long onLeftBtnRelease(FXObject*, FXSelector, void*) override;
223 : long onMiddleBtnPress(FXObject*, FXSelector, void*) override;
224 : long onMiddleBtnRelease(FXObject*, FXSelector, void*) override;
225 : long onRightBtnPress(FXObject*, FXSelector, void*) override;
226 : long onRightBtnRelease(FXObject*, FXSelector, void*) override;
227 : //long onMotion(FXObject*, FXSelector, void*);
228 : long onMouseMove(FXObject*, FXSelector, void*) override;
229 : long onPaint(FXObject*, FXSelector, void*) override;
230 : long onIdle(FXObject* sender, FXSelector sel, void* ptr);
231 :
232 : /// @brief interaction with the simulation
233 : long onCmdCloseLane(FXObject*, FXSelector, void*) override;
234 : long onCmdCloseEdge(FXObject*, FXSelector, void*) override;
235 : long onCmdAddRerouter(FXObject*, FXSelector, void*) override;
236 :
237 : /// @brief highlight edges according to reachability
238 : long onCmdShowReachability(FXObject*, FXSelector, void*) override;
239 :
240 : /// @brief reset graphical settings when forced to refresh the view (triggered by ViewSettings)
241 : long onVisualizationChange(FXObject*, FXSelector, void*) override;
242 :
243 : // @brief get the new camera position given a zoom value
244 : void zoom2Pos(Position& camera, Position& lookAt, double zoom) override;
245 :
246 : // @brief convert RGBColor 0..255 RGBA values to osg::Vec4 0..1 vector
247 : static osg::Vec4d toOSGColorVector(RGBColor c, bool useAlpha = false);
248 :
249 : // @brief Overwrite the HUD text
250 : void updateHUDText(const std::string text);
251 :
252 : protected:
253 : /// @brief Store the normalized OSG window cursor coordinates
254 : void setWindowCursorPosition(float x, float y);
255 :
256 : void updatePositionInformation() const;
257 :
258 : /// @brief Compute the world coordinate on the ground plane given the normalized cursor position inside the OSG view (range X, Y [-1;1])
259 : bool getPositionAtCursor(float xNorm, float yNorm, Position& pos) const;
260 :
261 : /// @brief returns the GUIGlObject under the cursor using OSG ray intersecting
262 : std::vector<GUIGlObject*> getGUIGlObjectsUnderCursor();
263 :
264 : /* @brief Find GUILane which intersects with a ray from the camera to the stored cursor position
265 : * @return The first found GUILane found or nullptr
266 : */
267 : GUILane* getLaneUnderCursor() override;
268 :
269 : /// @brief implement the current view settings in OSG
270 : void adoptViewSettings();
271 :
272 : private:
273 : double calculateRotation(const osg::Vec3d& lookFrom, const osg::Vec3d& lookAt, const osg::Vec3d& up);
274 :
275 : /// @brief inform HUD about the current window size to let it reposition
276 : void updateHUDPosition(int width, int height);
277 :
278 : class FXOSGAdapter : public osgViewer::GraphicsWindow {
279 : public:
280 : FXOSGAdapter(GUISUMOAbstractView* parent, FXCursor* cursor);
281 : void grabFocus();
282 0 : void grabFocusIfPointerInWindow() {}
283 : void useCursor(bool cursorOn);
284 :
285 : bool makeCurrentImplementation();
286 : bool releaseContext();
287 : void swapBuffersImplementation();
288 :
289 : // not implemented yet...just use dummy implementation to get working.
290 440706 : bool valid() const {
291 440706 : return true;
292 : }
293 0 : bool realizeImplementation() {
294 0 : return true;
295 : }
296 1307 : bool isRealizedImplementation() const {
297 1307 : return true;
298 : }
299 436 : void closeImplementation() {}
300 43940 : bool releaseContextImplementation() {
301 43940 : return true;
302 : }
303 0 : void requestWarpPointer(float x, float y) {
304 0 : int xRound = std::lround(x);
305 0 : int yRound = std::lround(y);
306 : int xPrev, yPrev;
307 : unsigned int buttons;
308 0 : myParent->getCursorPosition(xPrev, yPrev, buttons);
309 0 : if (xRound - xPrev != 0 || yRound - yPrev != 0) {
310 0 : myParent->setCursorPosition(xRound, yRound);
311 0 : getEventQueue()->mouseWarped(x, y);
312 : }
313 0 : }
314 :
315 : protected:
316 : ~FXOSGAdapter();
317 : private:
318 : GUISUMOAbstractView* const myParent;
319 : FXCursor* const myOldCursor;
320 : };
321 :
322 : class PlaneMoverCallback : public osg::Callback {
323 : public:
324 436 : PlaneMoverCallback(osg::Camera* camera) : myCamera(camera) {};
325 43504 : virtual bool run(osg::Object* object, osg::Object* /* data */) override {
326 43504 : osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(object);
327 : osg::Vec3d lookFrom, lookAt, up;
328 43504 : myCamera->getViewMatrixAsLookAt(lookFrom, lookAt, up);
329 : osg::Vec3d direction = lookAt - lookFrom;
330 43504 : direction.normalize();
331 43504 : osg::Vec3d lookAtGround = lookFrom - direction * (lookFrom.z() / direction.z());
332 : osg::Matrixd translateMatrix;
333 43504 : translateMatrix.makeTranslate(lookAtGround.x(), lookAtGround.y(), 0.);
334 43504 : double angle = atan2(direction.y(), direction.x());
335 : osg::Matrixd rotMatrix = osg::Matrixd::rotate(angle, osg::Z_AXIS);
336 43504 : mt->setMatrix(rotMatrix * translateMatrix);
337 43504 : return true;
338 : }
339 : protected:
340 436 : ~PlaneMoverCallback() {};
341 : private:
342 : osg::Camera* myCamera;
343 : };
344 :
345 : class PickHandler : public osgGA::GUIEventHandler {
346 : public:
347 436 : PickHandler(GUIOSGView* parent) : myParent(parent), myDrag(false) {};
348 : bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
349 : using osgGA::GUIEventHandler::handle; // to silence the warning C4266 about a hidden function
350 : protected:
351 872 : ~PickHandler() {};
352 : private:
353 : GUIOSGView* const myParent;
354 : bool myDrag;
355 : };
356 :
357 436 : class ExcludeFromNearFarComputationCallback : public osg::NodeCallback {
358 43386 : virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
359 43386 : osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
360 : // Default value
361 : osg::CullSettings::ComputeNearFarMode oldMode = osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES;
362 43386 : if (cv) {
363 : oldMode = cv->getComputeNearFarMode();
364 : cv->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
365 : }
366 43386 : traverse(node, nv);
367 43386 : if (cv) {
368 : cv->setComputeNearFarMode(oldMode);
369 : }
370 43386 : }
371 : };
372 :
373 :
374 :
375 : protected:
376 0 : GUIOSGView() {}
377 :
378 : osg::ref_ptr<FXOSGAdapter> myAdapter;
379 : osg::ref_ptr<osgViewer::Viewer> myViewer;
380 : osg::ref_ptr<osg::Group> myRoot;
381 : osg::ref_ptr<osg::MatrixTransform> myPlane;
382 : osg::ref_ptr<osg::Camera> myHUD;
383 : osg::ref_ptr<osg::Geode> myTextNode;
384 : osg::ref_ptr<osgText::Text> myText;
385 :
386 : private:
387 : GUIVehicle* myTracked;
388 : osg::ref_ptr<GUIOSGManipulator> myCameraManipulator;
389 : SUMOTime myLastUpdate;
390 :
391 : float myOSGNormalizedCursorX, myOSGNormalizedCursorY;
392 :
393 : std::map<MSVehicle*, OSGMovable > myVehicles;
394 : std::map<MSTransportable*, OSGMovable > myPersons;
395 :
396 : osg::ref_ptr<osg::Node> myGreenLight;
397 : osg::ref_ptr<osg::Node> myYellowLight;
398 : osg::ref_ptr<osg::Node> myRedLight;
399 : osg::ref_ptr<osg::Node> myRedYellowLight;
400 : osg::ref_ptr<osg::Node> myPoleBase;
401 : osg::ref_ptr<osg::Node> myPlaneTransform;
402 : };
403 :
404 : #endif
|