zoukankan      html  css  js  c++  java
  • [osgearth][原]仿照谷歌,修改oe漫游器中focal(视角切换)功能

    oe中的视角加速感觉好奇怪,就仿照谷歌方式去改了。

    先看看oe原来的漫游器改变视角的接口:

    void
    CameraManipulator::setViewpoint(const Viewpoint& vp, double duration_seconds)
    {
        // If the manip is not set up, save the viewpoint for later.
        if ( !established() )
        {
            _pendingViewpoint = vp;
            _pendingViewpointDuration.set(duration_seconds, Units::SECONDS);
        }
    
        else
        {
            // Save any existing tether node so we can properly invoke the callback.
            osg::ref_ptr<osg::Node> oldEndNode;
            if ( isTethering() && _tetherCallback.valid() )
                _setVP1->getNode(oldEndNode);
    
            // starting viewpoint; all fields will be set:
            _setVP0 = getViewpoint();
    
            // ending viewpoint
            _setVP1 = vp;
    
            // Reset the tethering offset quat.
            _tetherRotationVP0 = _tetherRotation;
            _tetherRotationVP1 = osg::Quat();
    
            // Fill in any missing end-point data with defaults matching the current camera setup.
            // Then all fields are guaranteed to contain usable data during transition.
            double defPitch, defAzim;
            getEulerAngles( _rotation, &defAzim, &defPitch );
    
            if ( !_setVP1->heading().isSet() )
                _setVP1->heading() = Angle(defAzim, Units::RADIANS);
    
            if ( !_setVP1->pitch().isSet() )
                _setVP1->pitch() = Angle(defPitch, Units::RADIANS);
    
            if ( !_setVP1->range().isSet() )
                _setVP1->range() = Distance(_distance, Units::METERS);
    
            if ( !_setVP1->nodeIsSet() && !_setVP1->focalPoint().isSet() )
            {
                osg::ref_ptr<osg::Node> safeNode;
                if ( _setVP0->getNode( safeNode ) )
                    _setVP1->setNode( safeNode.get() );
                else
                    _setVP1->focalPoint() = _setVP0->focalPoint().get();
            }
    
            _setVPDuration.set( std::max(duration_seconds, 0.0), Units::SECONDS );
    
            OE_DEBUG << LC << "setViewpoint:
    "
                << "    from " << _setVP0->toString() << "
    "
                << "    to   " << _setVP1->toString() << "
    ";
    
            // access the new tether node if it exists:
            osg::ref_ptr<osg::Node> endNode;
            _setVP1->getNode(endNode);
    
            // Timed transition, we need to calculate some things:
            if ( duration_seconds > 0.0 )
            {
                // Start point is the current manipulator center:
                osg::Vec3d startWorld;
                osg::ref_ptr<osg::Node> startNode;
                startWorld = _setVP0->getNode(startNode) ? computeWorld(startNode.get()) : _center;
    
                _setVPStartTime.unset();
    
                // End point is the world coordinates of the target viewpoint:
                osg::Vec3d endWorld;
                if ( endNode.valid() )
                    endWorld = computeWorld(endNode.get());
                else
                    _setVP1->focalPoint()->transform( _srs.get() ).toWorld(endWorld);
    
                // calculate an acceleration factor based on the Z differential.
                _setVPArcHeight = 0.0;
                double range0 = _setVP0->range()->as(Units::METERS);
                double range1 = _setVP1->range()->as(Units::METERS);
    
                double pitch0 = _setVP0->pitch()->as(Units::RADIANS);
                double pitch1 = _setVP1->pitch()->as(Units::RADIANS);
    
                double h0 = range0 * sin( -pitch0 );
                double h1 = range1 * sin( -pitch1 );
                double dh = (h1 - h0);
    
                // calculate the total distance the focal point will travel and derive an arc height:
                double de = (endWorld - startWorld).length();
    
                // maximum height during viewpoint transition
                if ( _settings->getArcViewpointTransitions() )
                {
                    _setVPArcHeight = osg::maximum( de - fabs(dh), 0.0 );
                }
    
                // calculate acceleration coefficients
                if ( _setVPArcHeight > 0.0 )
                {
                    // if we're arcing, we need seperate coefficients for the up and down stages
                    double h_apex = 2.0*(h0+h1) + _setVPArcHeight;
                    double dh2_up = fabs(h_apex - h0)/100000.0;
                    _setVPAccel = log10( dh2_up );
                    double dh2_down = fabs(h_apex - h1)/100000.0;
                    _setVPAccel2 = -log10( dh2_down );
                }
                else
                {
                    // on arc => simple unidirectional acceleration:
                    double dh2 = (h1 - h0)/100000.0;
                    _setVPAccel = fabs(dh2) <= 1.0? 0.0 : dh2 > 0.0? log10( dh2 ) : -log10( -dh2 );
                    if ( fabs( _setVPAccel ) < 1.0 ) _setVPAccel = 0.0;
                }
    
                // Adjust the duration if necessary.
                if ( _settings->getAutoViewpointDurationEnabled() )
                {
                    double maxDistance = _srs->getEllipsoid()->getRadiusEquator();
                    double ratio = osg::clampBetween( de/maxDistance, 0.0, 1.0 );
                    ratio = accelerationInterp( ratio, -4.5 );
                    double minDur, maxDur;
                    _settings->getAutoViewpointDurationLimits( minDur, maxDur );
                    _setVPDuration.set( minDur + ratio*(maxDur-minDur), Units::SECONDS );
                }
            }
    
            else
            {
                // Immediate transition? Just do it now.
                _setVPStartTime->set( _time_s_now, Units::SECONDS );
                setViewpointFrame( _time_s_now );
            }
    
            // Fire a tether callback if required.
            if ( _tetherCallback.valid() )
            {
                // starting a tether to a NEW node:
                if ( isTethering() && oldEndNode.get() != endNode.get() )
                    (*_tetherCallback)( endNode.get() );
    
                // breaking a tether:
                else if ( !isTethering() && oldEndNode.valid() )
                    (*_tetherCallback)( 0L );
            }
        }
    
        // reset other global state flags.
        _thrown      = false;
        _task->_type = TASK_NONE;
    }

     这里有几个重点参数:

    osgEarth::optional<osgEarth::Viewpoint>  _setVP0和_setVP1 :开始视点,结束视点

    double                  _setVPAccel, _setVPAccel2; 开始点去最高点加速度,最高点去结束点加速度

    修改方案:https://www.cnblogs.com/lyggqm/p/8534619.html

  • 相关阅读:
    Window 服务安装
    SQL
    vb To c# or c# To vb
    CacheHelper-缓存
    让Linq的OrderBy支持动态字段
    哪些列上适合建立索引???
    如何查看Oracle数据库中无效的对象,约束,触发器和索引
    如何查看Oracle中被锁定的表
    ORACLE ASM
    WebLogic Server
  • 原文地址:https://www.cnblogs.com/lyggqm/p/8404230.html
Copyright © 2011-2022 走看看