LCOV - code coverage report
Current view: top level - src/osgview - GUIOSGManipulator.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 12.7 % 118 15
Test Date: 2024-11-21 15:56:26 Functions: 22.7 % 22 5

            Line data    Source code
       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              : /****************************************************************************/
      14              : /// @file    GUIOSGManipulator.cpp
      15              : /// @author  Mirko Barthauer
      16              : /// @date    27.11.2022
      17              : ///
      18              : // A custom camera manipulator to interact with the OSG view directly
      19              : /****************************************************************************/
      20              : #include <config.h>
      21              : 
      22              : #include <utils/geom/GeomHelper.h>
      23              : #include <utils/common/MsgHandler.h>
      24              : #include <utils/common/StringBijection.h>
      25              : 
      26              : #include "GUIOSGManipulator.h"
      27              : #include "GUIOSGView.h"
      28              : 
      29              : #ifdef HAVE_OSG
      30              : 
      31              : #define DEFAULT_MOVESPEED_MIN 1.0
      32              : //#define DEFAULT_MOVESPEED_MAX 30.0
      33              : //#define DEFAULT_MOVEACCEL 2.0
      34              : 
      35              : static StringBijection<ManipulatorMode>::Entry ModeTextInitializer[] = {
      36              :     {"Ego",        MODE_EGO},
      37              :     {"Walk",       MODE_WALK},
      38              :     {"Terrain",    MODE_TERRAIN}
      39              : };
      40              : 
      41              : StringBijection<ManipulatorMode> ModeText(ModeTextInitializer, MODE_TERRAIN, false);
      42              : 
      43              : 
      44              : // ===========================================================================
      45              : // method definitions
      46              : // ===========================================================================
      47          411 : GUIOSGManipulator::GUIOSGManipulator(GUIOSGView* parent, ManipulatorMode initMode, bool verticalFixed, double /* eyeHeight */) :
      48          411 :     myParent(parent), myCurrentMode(initMode), /*myWalkEyeHeight(eyeHeight),*/ myMoveSpeed(DEFAULT_MOVESPEED_MIN) {
      49          411 :     setAllowThrow(false);
      50          411 :     setVerticalAxisFixed(verticalFixed);
      51          411 : }
      52              : 
      53              : 
      54          822 : GUIOSGManipulator::~GUIOSGManipulator() {
      55          822 : }
      56              : 
      57              : 
      58              : bool
      59            0 : GUIOSGManipulator::performMovementLeftMouseButton(const double eventTimeDelta, const double dx, const double dy) {
      60            0 :     if (myCurrentMode == MODE_TERRAIN) {
      61            0 :         return osgGA::TerrainManipulator::performMovementMiddleMouseButton(eventTimeDelta, dx, dy);
      62              :     }
      63              :     return false;
      64              : }
      65              : 
      66              : 
      67              : bool
      68            0 : GUIOSGManipulator::performMovementMiddleMouseButton(const double eventTimeDelta, const double dx, const double dy) {
      69            0 :     if (myCurrentMode == MODE_TERRAIN) {
      70            0 :         return osgGA::TerrainManipulator::performMovementLeftMouseButton(eventTimeDelta, dx, dy);
      71              :     }
      72              :     return false;
      73              : }
      74              : 
      75              : 
      76              : bool
      77            0 : GUIOSGManipulator::performMovementRightMouseButton(const double eventTimeDelta, const double dx, const double dy) {
      78            0 :     if (myCurrentMode == MODE_TERRAIN) {
      79            0 :         return osgGA::TerrainManipulator::performMovementRightMouseButton(eventTimeDelta, dx, -dy);
      80              :     }
      81              :     return false;
      82              : }
      83              : 
      84              : 
      85              : bool
      86            0 : GUIOSGManipulator::handleMouseMove(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
      87            0 :     if (myCurrentMode == MODE_EGO || myCurrentMode == MODE_WALK) {
      88            0 :         return handleMouseDeltaMovement(ea, aa);
      89              :     }
      90              :     return false;
      91              : }
      92              : 
      93              : 
      94              : bool
      95            0 : GUIOSGManipulator::handleMouseDrag(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
      96            0 :     if (myCurrentMode == MODE_TERRAIN) {
      97            0 :         return osgGA::TerrainManipulator::handleMouseDrag(ea, aa);
      98              :     }
      99            0 :     return handleMouseDeltaMovement(ea, aa);
     100              : }
     101              : 
     102              : 
     103              : bool
     104            0 : GUIOSGManipulator::handleMousePush(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
     105            0 :     if (myCurrentMode == MODE_TERRAIN) {
     106            0 :         return osgGA::TerrainManipulator::handleMousePush(ea, aa);
     107              :     }
     108            0 :     return handleMouseDeltaMovement(ea, aa);
     109              : }
     110              : 
     111              : 
     112              : bool
     113            0 : GUIOSGManipulator::handleMouseRelease(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
     114            0 :     if (myCurrentMode == MODE_TERRAIN) {
     115            0 :         return osgGA::TerrainManipulator::handleMouseRelease(ea, aa);
     116              :     }
     117              :     return false;
     118              : }
     119              : 
     120              : 
     121              : bool
     122            0 : GUIOSGManipulator::handleMouseDeltaMovement(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
     123            0 :     addMouseEvent(ea);
     124            0 :     if (_ga_t0.get() == NULL || _ga_t1.get() == NULL) {
     125              :         return false;
     126              :     }
     127            0 :     float dt = static_cast<float>(_ga_t0->getTime() - _ga_t1->getTime());
     128            0 :     if (dt > 0.1) { // wait until the mouse movement is sufficiently smooth
     129              :         return false;
     130              :     }
     131              :     float intensity = 50.;
     132            0 :     float dx = _ga_t0->getXnormalized() * intensity * dt;
     133            0 :     float dy = _ga_t0->getYnormalized() * intensity * dt;
     134            0 :     if (dx == 0. && dy == 0.) {
     135              :         return false;
     136              :     }
     137            0 :     centerMousePointer(ea, aa);
     138              :     // calculate delta angles from dx and dy movements
     139            0 :     if (performMouseDeltaMovement(dx, dy)) {
     140            0 :         aa.requestRedraw();
     141              :     }
     142              :     return true;
     143              : }
     144              : 
     145              : 
     146              : bool
     147            0 : GUIOSGManipulator::performMouseDeltaMovement(const float dx, const float dy) {
     148            0 :     rotateYawPitch(_rotation, dx, dy, osg::Z_AXIS);
     149            0 :     return true;
     150              : }
     151              : 
     152              : 
     153            0 : void GUIOSGManipulator::centerMousePointer(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
     154            0 :     _mouseCenterX = (ea.getXmin() + ea.getXmax()) / 2.0f;
     155            0 :     _mouseCenterY = (ea.getYmin() + ea.getYmax()) / 2.0f;
     156            0 :     aa.requestWarpPointer(_mouseCenterX, _mouseCenterY);
     157            0 : }
     158              : 
     159              : 
     160              : void
     161            0 : GUIOSGManipulator::rotateYawPitch(osg::Quat& rotation, const double yaw, const double pitch, const osg::Vec3d& localUp) {
     162              :     bool verticalAxisFixed = (localUp != osg::Vec3d(0., 0., 0.));
     163              : 
     164              :     // fix current rotation
     165              :     if (verticalAxisFixed) {
     166            0 :         fixVerticalAxis(rotation, localUp, true);
     167              :     }
     168              : 
     169              :     // rotations
     170            0 :     osg::Quat rotateYaw(-yaw, verticalAxisFixed ? localUp : rotation * osg::Vec3d(0., 1., 0.));
     171              :     osg::Quat rotatePitch;
     172              :     osg::Quat newRotation;
     173            0 :     osg::Vec3d cameraRight(rotation * osg::Vec3d(1., 0., 0.));
     174              : 
     175              :     double my_dy = pitch;
     176              :     int i = 0;
     177            0 :     osg::Vec3f eye = _center - _rotation * osg::Vec3d(0., 0., -_distance);
     178              :     do {
     179              :         // rotations
     180            0 :         rotatePitch.makeRotate(my_dy, cameraRight);
     181            0 :         newRotation = rotation * rotateYaw * rotatePitch;
     182              : 
     183              :         // update vertical axis
     184            0 :         if (verticalAxisFixed) {
     185            0 :             fixVerticalAxis(newRotation, localUp, false);
     186              :         }
     187              : 
     188              :         // check for viewer's up vector to be more than 90 degrees from "up" axis
     189            0 :         osg::Vec3d newCameraUp = newRotation * osg::Vec3d(0., 1., 0.);
     190            0 :         if (newCameraUp * localUp > 0.) {
     191              :             // apply new rotation
     192            0 :             setByMatrix(osg::Matrixd::rotate(newRotation) * osg::Matrixd::translate(eye));
     193            0 :             return;
     194              :         }
     195            0 :         my_dy /= 2.;
     196            0 :         if (++i == 20) {
     197            0 :             setByMatrix(osg::Matrixd::rotate(rotation) * osg::Matrixd::rotate(rotateYaw) * osg::Matrixd::translate(eye));
     198            0 :             return;
     199              :         }
     200            0 :     } while (true);
     201              : }
     202              : 
     203              : 
     204              : bool
     205            0 : GUIOSGManipulator::handleKeyDown(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& /* aa */) {
     206              :     bool result = false;
     207            0 :     switch (ea.getKey()) {
     208            0 :         case osgGA::GUIEventAdapter::KEY_Up:
     209            0 :             myMove.z() -= myMoveSpeed;
     210              :             result = true;
     211            0 :             break;
     212            0 :         case osgGA::GUIEventAdapter::KEY_Down:
     213            0 :             myMove.z() += myMoveSpeed;
     214              :             result = true;
     215            0 :             break;
     216            0 :         case osgGA::GUIEventAdapter::KEY_Right:
     217            0 :             myMove.x() += myMoveSpeed;
     218              :             result = true;
     219            0 :             break;
     220            0 :         case osgGA::GUIEventAdapter::KEY_Left:
     221            0 :             myMove.x() -= myMoveSpeed;
     222              :             result = true;
     223            0 :             break;
     224              :     }
     225            0 :     _center += getMatrix().getRotate() * myMove;
     226            0 :     return result;
     227              : }
     228              : 
     229              : 
     230              : bool
     231            0 : GUIOSGManipulator::handleKeyUp(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& /* aa */) {
     232              :     bool result = false;
     233            0 :     switch (ea.getKey()) {
     234            0 :         case osgGA::GUIEventAdapter::KEY_Up:
     235              :         case osgGA::GUIEventAdapter::KEY_Down:
     236              :         case osgGA::GUIEventAdapter::KEY_Right:
     237              :         case osgGA::GUIEventAdapter::KEY_Left:
     238              :             myMove.set(0, 0, 0);
     239            0 :             return true;
     240            0 :         case osgGA::GUIEventAdapter::KEY_F:
     241            0 :             if (myCurrentMode == MODE_EGO) {
     242            0 :                 myCurrentMode = MODE_TERRAIN; // MODE_WALK disabled until it's fully implemented
     243            0 :             } else if (myCurrentMode == MODE_WALK) {
     244            0 :                 myCurrentMode = MODE_TERRAIN;
     245              :             } else {
     246            0 :                 myCurrentMode = MODE_EGO;
     247              :             }
     248            0 :             updateHUDText();
     249            0 :             return true;
     250              :     }
     251              :     return result;
     252              : }
     253              : 
     254              : 
     255              : void
     256          411 : GUIOSGManipulator::updateHUDText() {
     257         1233 :     myParent->updateHUDText(TLF("Currently in % camera mode. Press [F] to switch.", ModeText.getString(myCurrentMode)));
     258          411 : }
     259              : 
     260              : 
     261              : void
     262            0 : GUIOSGManipulator::setByMatrix(const osg::Matrixd& matrix) {
     263            0 :     _center = osg::Vec3d(0., 0., -_distance) * matrix;
     264            0 :     _rotation = matrix.getRotate();
     265              : 
     266              :     // fix current rotation
     267            0 :     if (getVerticalAxisFixed()) {
     268            0 :         fixVerticalAxis(_center, _rotation, true);
     269              :     }
     270            0 : }
     271              : 
     272              : 
     273            0 : osg::Matrixd GUIOSGManipulator::getMatrix() const {
     274            0 :     if (myCurrentMode == MODE_TERRAIN) {
     275            0 :         return osg::Matrixd::translate(0., 0., _distance) *
     276            0 :                osg::Matrixd::rotate(_rotation) *
     277            0 :                osg::Matrixd::translate(_center);
     278              :     } else {
     279            0 :         osg::Vec3f eye = _center - _rotation * osg::Vec3d(0., 0., -_distance);
     280            0 :         return osg::Matrixd::rotate(_rotation) * osg::Matrixd::translate(eye);
     281              :     }
     282              : }
     283              : 
     284              : 
     285        21662 : osg::Matrixd GUIOSGManipulator::getInverseMatrix() const {
     286        21662 :     if (myCurrentMode == MODE_TERRAIN) {
     287        21662 :         return osg::Matrixd::translate(-_center) *
     288        21662 :                osg::Matrixd::rotate(_rotation.inverse()) *
     289        43324 :                osg::Matrixd::translate(0.0, 0.0, -_distance);
     290              :     } else {
     291            0 :         osg::Vec3f eye = _center - _rotation * osg::Vec3d(0., 0., -_distance);
     292            0 :         return osg::Matrixd::translate(-eye) * osg::Matrixd::rotate(_rotation.inverse());
     293              :     }
     294              : }
     295              : 
     296              : #endif
        

Generated by: LCOV version 2.0-1