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:\n"
<< " from " << _setVP0->toString() << "\n"
<< " to " << _setVP1->toString() << "\n"; // 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

[osgearth][原]仿照谷歌,修改oe漫游器中focal(视角切换)功能的更多相关文章

  1. [原][osg][osgEarth]EarthManipulator关于oe漫游器的handle部分解读以及修改(仿照谷歌,修改oe漫游器中focal(视角切换)功能 续 二)

    bool EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) ...

  2. 【原】thinkphp修改Redis操作类,支持选择数据库功能及添加其他方法

    版本3.2.2(ThinkPHP\Library\Think\Cache\Driver\Redis.class.php), 一:官方默认不支持选择数据库功能及,现就可选择数据库功能进行说明. 1 co ...

  3. [osg][osgEarth][原]基于OE自定义自由飞行漫游器(初级版)

    由于受够了OE的漫游器,想搞个可以在全球飞行的漫游器,所以就做了一个: 请无视我的起名规则······ 类头文件:EarthWalkManipulator.h #pragma once //南水之源 ...

  4. [osg][osgEarth][原]基于OE自定义自由飞行漫游器(第二版)

    在初级版上,进行新的漫游方式调整 头文件: #pragma once //南水之源 20180101 #include <osgGA/CameraManipulator> #include ...

  5. [osg][osgEarth][osgGA][原] EarthManipulator------基于oe的相机漫游器(浅析)

    知识基础:osg漫游器基础 class OSGEARTHUTIL_EXPORT EarthManipulator : public osgGA::CameraManipulator EarthMani ...

  6. [原][osgEarth]添加自由飞行漫游器

    //头文件里 #define MANIPULATOR_W 0x01#define MANIPULATOR_A 0x02#define MANIPULATOR_S 0x04#define MANIPUL ...

  7. [osg][原]自定义osgGA漫游器

    相机矩阵变化基础:http://blog.csdn.net/popy007/article/details/5120158 osg漫游器原理:http://blog.csdn.net/csxiaosh ...

  8. 《Python cookbook》 “定义一个属性可由用户修改的装饰器” 笔记

    看<Python cookbook>的时候,第9.5部分,"定义一个属性可由用户修改的装饰器",有个装饰器理解起来花了一些时间,做个笔记免得二刷这本书的时候忘了 完整代 ...

  9. python_如何修改装饰器中参数?

    案例: 为分析程序内哪些函数执行时间开销较大,我们需定义一个带timeout参数的装饰器 需求: 统计被装饰函数的运行时间 时间大于timeout时,将此次函数调用记录到log日志中 运行时可以修改t ...

随机推荐

  1. jQuery获取子元素个数的方法

    //获取id=div1下的子元素的个数 $('#id').children().length; //获取id=div1下的p元素个数 $('#id').children('p').length;

  2. #mxnet# 权值共享

    https://www.cnblogs.com/chenyliang/p/6847744.html Note:后记此权值共享非彼卷积共享.说的是layer实体间的参数共享. Introduction ...

  3. PHP多进程非阻塞模式下结合原生Mysql与单进程效率测试对比

    公司在做游戏服务器合并的时候,对大批量数据表做了合并操作,难免会出现数据格式不一致问题.根据玩家反映BUG排查,是因为某个模块下日志表出现了数据格式问题导致. 目前想到的是有两种方案解决,第一种就是把 ...

  4. Mac配置java运行环境的步骤

    官网下载地址:jdk1.8版本的  http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.htm ...

  5. eclipse maven Errors while generating javadoc on java8

    With JDK 8, we are unable to get Javadoc unless your tool meets the standards of doclint. Some of it ...

  6. mongodb三种引擎测试(转)

    文章http://diyitui.com/content-1459560904.39084552.html亲测了根据证券行情存储的性能情况,我们目前使用load local infile,平均每秒更新 ...

  7. nginx负载均衡fair方式分发

    fair采用的不是内建负载均衡使用的轮换的均衡算法,而是可以根据页面大小.加载时间长短智能的进行负载均衡. 这算是没有安装fair的情况 [root@localhost sbin]# ./nginx ...

  8. 1.面向过程编程 2.面向对象编程 3.类和对象 4.python 创建类和对象 如何使用对象 5.属性的查找顺序 6.初始化函数 7.绑定方法 与非绑定方法

    1.面向过程编程 面向过程:一种编程思想在编写代码时 要时刻想着过程这个两个字过程指的是什么? 解决问题的步骤 流程,即第一步干什么 第二步干什么,其目的是将一个复杂的问题,拆分为若干的小的问题,按照 ...

  9. ScheduledTheadPool线程池的使用

    ScheduledTheadPool线程池的特点在于可以延迟执行任务,也可以周期性执行任务. 创建线程池 ScheduledExecutorService scheduled = Executors. ...

  10. topcoder srm 540 div1

    problem1 link 设第一个数字为$x$,那么第2到第$n$个数字都可以表示成$a+bx$的形式,其中$b=1$或者$b=-1$.然后可以求出关于$x$的一些范围,求交集即可. problem ...