zoukankan      html  css  js  c++  java
  • [原][osgEarth]添加自由飞行漫游器

    //头文件里

    #define MANIPULATOR_W 0x01
    #define MANIPULATOR_A 0x02
    #define MANIPULATOR_S 0x04
    #define MANIPULATOR_D 0x08
    #define MANIPULATOR_R 0x10
    #define MANIPULATOR_F 0x20

    
    

    #define MANIPULATOR_MAX 127

    /*

    osgEarth::Map g_map;//这个用自己定义的

    osgEarth::ElevationQuery sElevationQuery(g_map);//少的定义

    */

    //所有漫游器都必须实现的4个纯虚函数  
            virtual void setByMatrix(const osg::Matrixd& matrix);  //设置相机的位置姿态矩阵  
            virtual void setByInverseMatrix(const osg::Matrixd& matrix) {}  //设置相机的视图矩阵  
            virtual osg::Matrixd getMatrix() const;  //获取相机的姿态矩阵 
            virtual osg::Matrixd getInverseMatrix() const;   //获取相机的视图矩阵 
    
            //所有操作在这里响应
            virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);
    
    
            void reFreshSawEarth();//在当前经纬度,姿态回正:1.视点向地面 2.头部向正北
            void reFreshSawSkyline(osg::Vec3d eye=osg::Vec3d(0,0,0));//在当前经纬度,头部回正:1.视点中心不变 2.头部向天
    
            osg::Vec3d   _eye;               //视点位置  
            osg::Quat    _rotate;            //旋转姿态 
            osg::Quat    _rotateNew;            //旋转姿态 
            osg::ref_ptr<osg::Node>  _root;
    
            osg::observer_ptr<osg::Node> _node;
            osg::observer_ptr<osgEarth::MapNode>   _mapNode;
    
            osg::ref_ptr<const osgEarth::SpatialReference> _srs;
    
            float        _speed;                //速度
            float        _speedBase;
            float       _speedMultiple;        //速度倍数
            float        _timerRoll;
            bool        _updateAltitude;
            bool        _updateRollStart;        //更新滚转
            bool        _updateRoll;        //更新滚转
            bool        _openStree;            
            // Internal event stack comprising last two mouse events.
            osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t1;
            osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t0;
    //cpp文件
    void setByMatrix(const osg::Matrixd& matrix)//设置相机的位置姿态矩阵  
    {
        gMinpulatorContgrol = 0;
        _eye = matrix.getTrans();
        osg::Vec3d  v3Eye, v3Center, v3Up;
        v3Eye = _eye;//使用相机实际位置
        osg::Vec3d v3EyeLonLat;
        _srs->transformFromWorld(v3Eye, v3EyeLonLat);
        //先获取当前位置的经纬度,再获取当前正上,正北
        osg::Matrix mRealAttitude;
    
        if (v3EyeLonLat.z() < 10000)//距离地面1千万米以内需要矫正
            //reFreshSawSkyline();
            _updateRoll = true;
        else
            reFreshSawEarth();
    }  
    
    osg::Matrixd getInverseMatrix() const
    {
        osg::Matrix mat;
        mat.setRotate(-_rotate);
        mat.preMultTranslate(-_eye);
        return mat;
        //return osg::Matrixd::inverse(getMatrix());
    }void setNode(osg::Node* node)
    {
        // you can only set the node if it has not already been set, OR if you are setting
        // it to NULL. (So to change it, you must first set it to NULL.) This is to prevent
        // OSG from overwriting the node after you have already set on manually.
        if (node == 0L || !_node.valid())
        {
            _root = node;
            _node = node;
            _mapNode = 0L;
            _srs = 0L;
    
            established();
    
            osg::Matrix matrixGood1;
            GeoPoint point1(_srs, 0, 0, 10000.0);
            point1.createLocalToWorld(matrixGood1);
    
            _eye = matrixGood1.getTrans();
    
            osg::Vec3d worldup;
            point1.createWorldUpVector(worldup);
    
            osg::Matrix mat;
            matrixGood1.getRotate().get(mat);
            osg::Vec3d eye, center, up;
            mat.getLookAt(eye, center, up);
            mat.makeLookAt(eye, -worldup, up);
    
            _rotate = mat.getRotate();
    
        }
    }
    void reFreshSawSkyline(osg::Vec3d eye)
    {
        osg::Vec3d v3Eye;
        osg::Vec3d v3EyeLonLat;
        v3Eye = _eye;//使用相机实际位置
        
        if (eye != osg::Vec3d(0, 0, 0))
        {
            v3Eye += eye;
        }
    
        _srs->transformFromWorld(v3Eye, v3EyeLonLat);
        //先获取当前位置的经纬度,再获取当前正上,正北
    
        if (v3EyeLonLat.z() < 10000)//距离地面1千万米以内需要矫正
        {
                osg::Matrix mRealAttitude;
                GeoPoint gEyeGeo(_srs, v3EyeLonLat.x(), v3EyeLonLat.y(), v3EyeLonLat.z());
                gEyeGeo.createLocalToWorld(mRealAttitude);
    
                osg::Vec3d v3HorizonUp;//指天向量
                gEyeGeo.createWorldUpVector(v3HorizonUp);
    
                _rotate.get(mRealAttitude);//要使用当前相机的姿态
                osg::Vec3d  theEye,v3Center, v3Up;
                mRealAttitude.getLookAt(theEye, v3Center, v3Up);//获取新的位置和姿态
                osg::Vec3d v3Direction = v3Center - theEye;
                mRealAttitude.makeLookAt(osg::Vec3d(0, 0, 0), v3Direction, v3HorizonUp);
                _rotate = mRealAttitude.getRotate();
        
        }
        
        //_eye = v3Eye;
    }
    
    void  reFreshSawEarth()
    {
        osg::Vec3d  v3Eye, v3Center, v3Up;
        v3Eye = _eye;//使用相机实际位置
        osg::Vec3d v3EyeLonLat;
        _srs->transformFromWorld(v3Eye, v3EyeLonLat);
            //先获取当前位置的经纬度,再获取当前正上,正北
            osg::Matrix mRealAttitude;
    
        if (v3EyeLonLat.z() < 0)//v3EyeLonLat.z()是眼点实际海拔
            v3EyeLonLat.z() = 100;//将海拔0以下的物体拉到海拔100米
    
        GeoPoint gEyeGeo(_srs, v3EyeLonLat.x(), v3EyeLonLat.y(), v3EyeLonLat.z());
        gEyeGeo.createLocalToWorld(mRealAttitude);
    
        osg::Vec3d v3HorizonUp;//指天向量
        gEyeGeo.createWorldUpVector(v3HorizonUp);
    
        _eye = mRealAttitude.getTrans();
    
        mRealAttitude.getLookAt(v3Eye, v3Center, v3Up);//获取新的位置和姿态
    
        osg::Matrix mDeviationAttitude;//向北位置偏移0.00001纬度,为了计算正北方向
        GeoPoint gDeviationEyeGeo(_srs, v3EyeLonLat.x(), v3EyeLonLat.y() + 0.00001, v3EyeLonLat.z());
        gDeviationEyeGeo.createLocalToWorld(mDeviationAttitude);
        osg::Vec3d v3DeviationNorthPoint = mDeviationAttitude.getTrans();
        osg::Vec3d v3NorthHeadUp = v3DeviationNorthPoint - v3Eye;
        v3NorthHeadUp.normalize();//指北向量
    
        if (v3EyeLonLat.y() < 89.99999  && v3EyeLonLat.y() > -90.0)
        {
            mRealAttitude.makeLookAt(osg::Vec3d(0, 0, 0), -v3HorizonUp, v3NorthHeadUp);
        }
        _rotate = mRealAttitude.getRotate();
    }
    
    bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
    {
        bool handled = false;
    
        switch (ea.getEventType())
        {
        case(osgGA::GUIEventAdapter::FRAME):
        {
            if (gMinpulatorContgrol & MANIPULATOR_MAX)
            {
                osg::Vec3d   v3Direction;         //视点方向  
                osg::Matrix mCameraQuat;
                osg::Vec3d  v3Eye, v3Center, v3Up;
                _rotate.get(mCameraQuat);
                mCameraQuat.getLookAt(v3Eye, v3Center, v3Up);//这里的v3Eye不是实际相机的位置,而是0,0,0
                v3Direction = v3Center - v3Eye;
                v3Direction.normalize();
                /*********************************************************/
                osg::Vec3d RealEye = _eye;
                osg::Vec3d testHight = v3Direction*100;
                double _DvalueHight = 0.0;
                {
                    osg::Vec3d testLonLat1, testLonLat2;
                    _srs->transformFromWorld(RealEye, testLonLat1);
                    RealEye = _eye;
                    osg::Vec3d testEye = RealEye + testHight;
                    _srs->transformFromWorld(testEye, testLonLat2);
                    _DvalueHight = abs(testLonLat2.z() - testLonLat1.z());
    
                    if (_DvalueHight < 10)//趋近水平使用水平方向
                    {
                        testLonLat2.z() = testLonLat1.z();
                        _srs->transformToWorld(testLonLat2, testEye);
                        v3Direction = testEye - RealEye;
                        v3Direction.normalize();
                    }
                }
    
                osg::Vec3d v3CrossVector = v3Up^v3Direction;
                v3CrossVector.normalize();
    
                /*********************************************************/
                //计算地面高度
                osg::Vec3d v3EyeLonLat;
                v3Eye = _eye;
                _srs->transformFromWorld(v3Eye, v3EyeLonLat);
                double mAltitude = float height = osg::clampBetween(v3EyeLonLat.z() - mAltitude, 100.0, 1000000.0);
                _speed = height / 200.0;//根据离地面高度计算当前速度值
                RealEye = _eye;
                if (gMinpulatorContgrol & MANIPULATOR_W)
                {
                    RealEye += v3Direction * _speed *_speedMultiple * _speedBase;
                    _updateAltitude = false;
                }if (gMinpulatorContgrol & MANIPULATOR_A)
                {
                    RealEye += v3CrossVector * _speed *_speedMultiple * _speedBase;
                    _updateAltitude = false;
                }if (gMinpulatorContgrol & MANIPULATOR_S)
                {
                    RealEye -= v3Direction * _speed *_speedMultiple * _speedBase;
                    _updateAltitude = false;
                }if (gMinpulatorContgrol & MANIPULATOR_D)
                {
                    RealEye -= v3CrossVector * _speed *_speedMultiple * _speedBase;
                    _updateAltitude = false;
                }if (gMinpulatorContgrol & MANIPULATOR_R)
                {
                    //_eye += v3Up * _speed *_speedMultiple * _speedBase;
                    v3EyeLonLat.z() += _speed *_speedMultiple * _speedBase;
                    osg::Vec3d newv3Eye;
                    _srs->transformToWorld(v3EyeLonLat, newv3Eye);
                    RealEye = newv3Eye;
                    _updateAltitude = false;
                }if (gMinpulatorContgrol & MANIPULATOR_F)
                {
                    //_eye -= v3Up * _speed *_speedMultiple * _speedBase;
                    v3EyeLonLat.z() -= _speed *_speedMultiple * _speedBase;
                    osg::Vec3d newv3Eye;
                    _srs->transformToWorld(v3EyeLonLat, newv3Eye);
                    RealEye = newv3Eye;
                    _updateAltitude = false;
                }
    
                _eye = RealEye;
                //reFreshSawSkyline(RealEye);
            }
        
            if (_updateRoll)
            {
                osg::Vec3d v3Eye;
                osg::Vec3d v3EyeLonLat;
                v3Eye = _eye;//使用相机实际位置
                _srs->transformFromWorld(v3Eye, v3EyeLonLat);
                //先获取当前位置的经纬度,再获取当前正上,正北
    
                if (v3EyeLonLat.z() < 10000)//距离地面1千万米以内需要矫正
                {
                    osg::Matrix mRealAttitude;
                    GeoPoint gEyeGeo(_srs, v3EyeLonLat.x(), v3EyeLonLat.y(), v3EyeLonLat.z());
                    gEyeGeo.createLocalToWorld(mRealAttitude);
    
                    osg::Vec3d v3HorizonUp;//指天向量
                    gEyeGeo.createWorldUpVector(v3HorizonUp);
    
                    _rotate.get(mRealAttitude);//要使用当前相机的姿态
                    osg::Vec3d  theEye, v3Center, v3Up;
                    mRealAttitude.getLookAt(theEye, v3Center, v3Up);//获取新的位置和姿态
                    osg::Vec3d v3Direction = v3Center - theEye;
                    mRealAttitude.makeLookAt(osg::Vec3d(0, 0, 0), v3Direction, v3HorizonUp);
                    _rotateNew = mRealAttitude.getRotate();
                    _updateRoll = false;
                    _updateRollStart = true;
                    _timerRoll = 0.0;
                }
                else
                {
                    _updateRoll = false;
                }
            }
    
            if (_updateRollStart)
            {
                _timerRoll += 0.01;
                if (_timerRoll > 1.0)
                {
                    _timerRoll = 1.0;
                    _updateRollStart = false;
                }
                _rotate.slerp(_timerRoll, _rotate, _rotateNew);
            }
    
            if (_updateAltitude)
            {
                //每帧调节高度
                osg::Vec3d newEye = _eye;
                osg::Vec3d v3EyeLonLat;
                _srs->transformFromWorld(newEye, v3EyeLonLat);
                double _mAltitude = v3EyeLonLat.z();

             double mAltitude = sElevationQuery.getElevation(GeoPoint(g_map.getSRS(), fLon, fLat, 0, ALTMODE_ABSOLUTE));

          double interprolationAltitude = mAltitude - _mAltitude;
                if (interprolationAltitude > 1)
                {
                    interprolationAltitude /= 10.0;
                    v3EyeLonLat.z() += interprolationAltitude;
                }
                else if (interprolationAltitude > 0.1)
                {
                    v3EyeLonLat.z() += 0.1;
                }
                else
                {
                    _updateAltitude = false;
                }
                osg::Vec3d FinalEye;
                _srs->transformToWorld(v3EyeLonLat, FinalEye);
                _eye = FinalEye;
            }
        }break;
        case(osgGA::GUIEventAdapter::PUSH):
        {
        }break;
        case(osgGA::GUIEventAdapter::RELEASE):
        {
            flushMouseEventStack();
        }break;
        case(osgGA::GUIEventAdapter::DRAG):
        {
            if (calcMovement(ea))//根据鼠标在屏幕中的位置调整相机转向
            {
                //reFreshSawSkyline();
                _updateRoll = true;
                us.requestRedraw();
                return true;
            }
        };
        case(osgGA::GUIEventAdapter::SCROLL)://由于已经每帧都调整姿态,所以手动滚动不需要了
        {
            osg::Vec3d   v3Direction;         //视点方向  
            osg::Matrix mCameraQuat;
            osg::Vec3d  v3Eye, v3Center, v3Up;
            _rotate.get(mCameraQuat);
            mCameraQuat.getLookAt(v3Eye, v3Center, v3Up);//这里的v3Eye不是实际相机的位置,而是0,0,0
            v3Direction = v3Center - v3Eye;
            v3Direction.normalize();
            osg::Vec3d v3CrossVector = v3Up^v3Direction;
            v3CrossVector.normalize();
            switch (ea.getScrollingMotion())
            {
            case osgGA::GUIEventAdapter::ScrollingMotion::SCROLL_UP:
            {
                _eye += v3Direction * _speed *_speedMultiple;
                //reFreshSawSkyline();
                _updateRoll = true;
            }break;
            case osgGA::GUIEventAdapter::ScrollingMotion::SCROLL_DOWN:
            {
                _eye -= v3Direction * _speed *_speedMultiple;
                //reFreshSawSkyline();
                _updateRoll = true;
            }break;
            }
            //reFreshSawSkyline();
    
            return true;
        }break;
        case (osgGA::GUIEventAdapter::KEYDOWN):
        {
            if (ea.getKey() == 'r' || ea.getKey() == 'R')//往头部前进
            {
                gMinpulatorContgrol |= MANIPULATOR_R;
            }
            if (ea.getKey() == 'f' || ea.getKey() == 'F')//往尾部后退
            {
                gMinpulatorContgrol |= MANIPULATOR_F;
            }
            if (ea.getKey() == 'w' || ea.getKey() == 'W' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)//前进
            {
                gMinpulatorContgrol |= MANIPULATOR_W;
            }
            if (ea.getKey() == 's' || ea.getKey() == 'S' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Down)//后退
            {
                gMinpulatorContgrol |= MANIPULATOR_S;
            }
            if (ea.getKey() == 'a' || ea.getKey() == 'A' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)//左移
            {
                gMinpulatorContgrol |= MANIPULATOR_A;
            }
            if (ea.getKey() == 'd' || ea.getKey() == 'D' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)//右移
            {
                gMinpulatorContgrol |= MANIPULATOR_D;
            }
            if (ea.getKey() == '-' || ea.getKey() == '_' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Down)//减10倍移动速度
            {
                _speedBase /= 10.0;
                if (_speedBase < 0.1)
                {
                    _speedBase = 0.1;
                }
            }
            if (ea.getKey() == '=' || ea.getKey() == '+' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Up)//加10倍移动速度
            {
                _speedBase *= 10.0;
                if (_speedBase > 1000.0)
                {
                    _speedBase = 1000.0;
                }
            }
    
            if (ea.getKey() == 'h' || ea.getKey() == 'H')//在当前经纬度,姿态回正:1.视点向地面 2.头部向正北
            {
                reFreshSawEarth();
            }
            if (ea.getKey() == 'g' || ea.getKey() == 'G')//在当前经纬度,头部回正:1.视点中心不变 2.头部向天
            {
                reFreshSawSkyline();
            }
            if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_L || ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_R)
            {
                _speedMultiple = 10.0;
            }
        }break;
        case (osgGA::GUIEventAdapter::KEYUP):
        {
            if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_L || ea.getKey() == osgGA::GUIEventAdapter::KEY_Shift_R)
            {
                _speedMultiple = 1.0;
            }
            if (ea.getKey() == 'a' || ea.getKey() == 'A' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)//左移
            {
                gMinpulatorContgrol &= ~MANIPULATOR_A;
                _updateAltitude = true;
            }
            if (ea.getKey() == 'd' || ea.getKey() == 'D' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)//右移
            {
                gMinpulatorContgrol &= ~MANIPULATOR_D;
                _updateAltitude = true;
            }
            if (ea.getKey() == 'w' || ea.getKey() == 'W' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)//前进
            {
                gMinpulatorContgrol &= ~MANIPULATOR_W;
                _updateAltitude = true;
            }
            if (ea.getKey() == 'q' || ea.getKey() == 'Q' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Up)//往头部前进
            {
                gMinpulatorContgrol &= ~MANIPULATOR_R;
                _updateAltitude = true;
            }
            if (ea.getKey() == 'e' || ea.getKey() == 'E' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Page_Down)//往尾部后退
            {
                gMinpulatorContgrol &= ~MANIPULATOR_F;
                _updateAltitude = true;
            }
            if (ea.getKey() == 's' || ea.getKey() == 'S' || ea.getKey() == osgGA::GUIEventAdapter::KEY_Down)//后退
            {
                gMinpulatorContgrol &= ~MANIPULATOR_S;
                _updateAltitude = true;
            }
        }break;
        default:
            break;
        }
    
        return handled;
    }
  • 相关阅读:
    java-String类
    多线程的细节
    java-多线程的练习----妖,等待唤醒,代码重构,lock到condition
    javascript函数的声明和调用
    表单
    java-多线程的入门_进阶总结
    uboot命令
    u-boot移植 III
    u-boot移植 II
    汇编词典
  • 原文地址:https://www.cnblogs.com/lyggqm/p/8745971.html
Copyright © 2011-2022 走看看