LCOV - code coverage report
Current view: top level - src/osgview - GUIOSGView.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 70.5 % 44 31
Test Date: 2025-12-06 15:35:27 Functions: 64.7 % 17 11

            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
        

Generated by: LCOV version 2.0-1