bool
EarthManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
bool handled = false; // first order of business: make sure the CSN is established.
if ( !established() )
return false; // make sure the camera projection is up to date:
osg::View* view = aa.asView();
updateProjection( view->getCamera() ); double time_s_now = osg::Timer::instance()->time_s(); if ( ea.getEventType() == osgGA::GUIEventAdapter::FRAME )
{
_time_s_last_frame = _time_s_now;
_time_s_now = time_s_now;
_delta_t = _time_s_now - _time_s_last_frame; if ( _node.valid() )
{
if ( _pendingViewpoint.isSet() )
{
setViewpoint( _pendingViewpoint.get(), _pendingViewpointDuration.as(Units::SECONDS) );
_pendingViewpoint.unset();
aa.requestRedraw();
} else if ( isSettingViewpoint() && !isTethering() )
{
if ( _frameCount < )
_setVPStartTime->set(_time_s_now, Units::SECONDS); setViewpointFrame( time_s_now );
} if (_thrown)
{
double decayFactor = 1.0 - _settings->getThrowDecayRate(); _throw_dx = osg::absolute(_throw_dx) > osg::absolute(_dx * 0.01) ? _throw_dx * decayFactor : 0.0;
_throw_dy = osg::absolute(_throw_dy) > osg::absolute(_dy * 0.01) ? _throw_dy * decayFactor : 0.0; if (_throw_dx == 0.0 && _throw_dy == 0.0)
_thrown = false;
else
handleMovementAction(_last_action._type, _throw_dx, _throw_dy, aa.asView());
} aa.requestContinuousUpdate( isSettingViewpoint() || _thrown ); if ( _continuous )
{
handleContinuousAction( _last_action, aa.asView() );
aa.requestRedraw();
}
else
{
_continuous_dx = 0.0;
_continuous_dy = 0.0;
} if ( _task.valid() && _task->_type != TASK_NONE )
{
bool stillRunning = serviceTask();
if ( stillRunning )
{
aa.requestContinuousUpdate( true );
}
else
{
// turn off the continuous, but we still need one last redraw
// to process the final state.
aa.requestContinuousUpdate( false );
aa.requestRedraw();
}
}
} _frameCount++; return false;
} // the camera manipulator runs last after any other event handlers. So bail out
// if the incoming event has already been handled by another handler.
if ( ea.getHandled() )
{
return false;
} // form the current Action based on the event type:
Action action = ACTION_NULL; // if tethering is active, check to see whether the incoming event
// will break the tether.
if ( isTethering() )
{
const ActionTypeVector& atv = _settings->getBreakTetherActions();
if ( atv.size() > )
{
const Action& action = _settings->getAction( ea.getEventType(), ea.getButtonMask(), ea.getModKeyMask() );
if ( std::find(atv.begin(), atv.end(), action._type) != atv.end() )
{
clearViewpoint();
}
}
} if ( ea.isMultiTouchEvent() )
{
// not a mouse event; clear the mouse queue.
resetMouse( aa, false ); // queue up a touch event set and figure out the current state:
addTouchEvents(ea);
TouchEvents te;
if ( parseTouchEvents(te) )
{
for( TouchEvents::iterator i = te.begin(); i != te.end(); ++i )
{
action = _settings->getAction(i->_eventType, i->_mbmask, ); if (action._type != ACTION_NULL)
{
_last_event = i->_eventType; // here we adjust for action scale, global sensitivy
double dx = i->_dx, dy = i->_dy;
dx *= _settings->getMouseSensitivity();
dy *= _settings->getMouseSensitivity();
applyOptionsToDeltas( action, dx, dy ); _dx = dx;
_dy = dy; if (action._type == ACTION_GOTO)
handlePointAction(action, ea.getX(), ea.getY(), view);
else
handleMovementAction(action._type, dx, dy, view); aa.requestRedraw();
}
} handled = true;
}
else
{
// The only multitouch event we want passed on if not handled is a release
handled = ea.getEventType() != osgGA::GUIEventAdapter::RELEASE; // if a new push occurs we want to reset the dx/dy values to stop/prevent throwing
if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH)
_dx = _dy = 0.0;
}
} if ( !handled )
{
// not a touch event; clear the touch queue.
//_touchPointQueue.clear(); switch( ea.getEventType() )
{
case osgGA::GUIEventAdapter::PUSH:
resetMouse( aa );
addMouseEvent( ea );
_mouse_down_event = &ea;
aa.requestRedraw();
handled = true;
break; case osgGA::GUIEventAdapter::RELEASE:
if ( _continuous )
{
// bail out of continuous mode if necessary:
_continuous = false;
aa.requestContinuousUpdate( false );
}
else
{
action = _last_action; _throw_dx = fabs(_dx) > 0.01 ? _dx : 0.0;
_throw_dy = fabs(_dy) > 0.01 ? _dy : 0.0; if (_settings->getThrowingEnabled() && ( time_s_now - _time_s_last_event < 0.05 ) && (_throw_dx != 0.0 || _throw_dy != 0.0))
{
_thrown = true;
aa.requestRedraw();
aa.requestContinuousUpdate( true );
}
else if ( isMouseClick( &ea ) )
{
addMouseEvent( ea );
if ( _mouse_down_event )
{
action = _settings->getAction( EVENT_MOUSE_CLICK, _mouse_down_event->getButtonMask(), _mouse_down_event->getModKeyMask() );
if ( handlePointAction( action, ea.getX(), ea.getY(), aa.asView() ))
aa.requestRedraw();
}
resetMouse( aa );
}
else
{
resetMouse( aa );
addMouseEvent( ea );
}
}
handled = true;
break; case osgGA::GUIEventAdapter::DOUBLECLICK:
// bail out of continuous mode if necessary:
_continuous = false;
addMouseEvent( ea );
if (_mouse_down_event)
{
action = _settings->getAction( ea.getEventType(), _mouse_down_event->getButtonMask(), _mouse_down_event->getModKeyMask() );
if ( handlePointAction( action, ea.getX(), ea.getY(), aa.asView() ) )
aa.requestRedraw();
resetMouse( aa );
handled = true;
}
break; case osgGA::GUIEventAdapter::MOVE: // MOVE not currently bindable
//NOP
break; case osgGA::GUIEventAdapter::DRAG:
{
action = _settings->getAction( ea.getEventType(), ea.getButtonMask(), ea.getModKeyMask() );
addMouseEvent( ea );
bool wasContinuous = _continuous;
_continuous = action.getBoolOption(OPTION_CONTINUOUS, false);
if ( handleMouseAction( action, aa.asView() ) )
aa.requestRedraw(); if ( _continuous && !wasContinuous )
_last_continuous_action_time = time_s_now; //_time_s_now; aa.requestContinuousUpdate(_continuous);
_thrown = false;
handled = true;
}
break; case osgGA::GUIEventAdapter::KEYDOWN:
if ( ea.getKey() < osgGA::GUIEventAdapter::KEY_Shift_L )
{
resetMouse( aa );
action = _settings->getAction( ea.getEventType(), ea.getKey(), ea.getModKeyMask() );
if ( handleKeyboardAction( action ) )
aa.requestRedraw();
handled = true;
}
break; case osgGA::GUIEventAdapter::KEYUP:
resetMouse( aa );
_task->_type = TASK_NONE;
handled = true;
break; case osgGA::GUIEventAdapter::SCROLL:
resetMouse( aa );
addMouseEvent( ea );
action = _settings->getAction( ea.getEventType(), ea.getScrollingMotion(), ea.getModKeyMask() );
if ( handleScrollAction( action, action.getDoubleOption(OPTION_DURATION, 0.2) ) )
aa.requestRedraw();
handled = true;
break;
default: break;
}
} // if a new task was started, request continuous updates.
if ( _task.valid() && _task->_type != TASK_NONE )
{
aa.requestContinuousUpdate( true );
} if ( handled && action._type != ACTION_NULL )
{
_last_action = action;
_time_s_last_event = time_s_now;
} return handled;
}

仔细分析:

            else if ( isSettingViewpoint() && !isTethering() )
{
if ( _frameCount < )
_setVPStartTime->set(_time_s_now, Units::SECONDS); setViewpointFrame( time_s_now );
}

这是需要调整相机漫游器位置了

isSettingViewpoint

这个函数主要是判断当前_setVP0和_setVP1是否有值

有值就从当前_setVP0视点经过一条弧线飞到_setVP1视点下

飞行过程调用的函数就是setViewpointFrame()

// returns "t" [0..1], the interpolation coefficient.
double
CVRECameraManipulator::setViewpointFrame(double time_s)
{
if ( !_setVPStartTime.isSet() )
{
_setVPStartTime->set( time_s, Units::SECONDS );
return 0.0;
}
else
{
// Start point is the current manipulator center:
osg::Vec3d startWorld;
osg::ref_ptr<osg::Node> startNode;
if ( _setVP0->getNode(startNode) )
startWorld = computeWorld(startNode);
else
_setVP0->focalPoint()->transform( _srs.get() ).toWorld(startWorld); // End point is the world coordinates of the target viewpoint:
osg::Vec3d endWorld;
osg::ref_ptr<osg::Node> endNode;
if ( _setVP1->getNode(endNode) )
endWorld = computeWorld(endNode);
else
_setVP1->focalPoint()->transform( _srs.get() ).toWorld(endWorld); // Remaining time is the full duration minus the time since initiation:
double elapsed = time_s - _setVPStartTime->as(Units::SECONDS);
double t = std::min(1.0, elapsed / _setVPDuration.as(Units::SECONDS)); double tp = t; if ( _setVPArcHeight > 0.0 )
{
if ( tp <= 0.5 )
{
double t2 = 2.0*tp;
tp = 0.5*t2;
}
else
{
double t2 = 2.0*(tp-0.5);
tp = 0.5+(0.5*t2);
} // the more smoothsteps you do, the more pronounced the fade-in/out effect
tp = smoothStepInterp( tp );
}
else if ( t > 0.0 )
{
tp = smoothStepInterp( tp );
} osg::Vec3d newCenter =
_srs->isGeographic() ? nlerp(startWorld, endWorld, tp) : lerp(startWorld, endWorld, tp); // Calculate the delta-heading, and make sure we are going in the shortest direction:
Angle d_azim = _setVP1->heading().get() - _setVP0->heading().get();
if ( d_azim.as(Units::RADIANS) > osg::PI )
d_azim = d_azim - Angle(2.0*osg::PI, Units::RADIANS);
else if ( d_azim.as(Units::RADIANS) < -osg::PI )
d_azim = d_azim + Angle(2.0*osg::PI, Units::RADIANS);
double newAzim = _setVP0->heading()->as(Units::RADIANS) + tp*d_azim.as(Units::RADIANS); // Calculate the new pitch:
Angle d_pitch = _setVP1->pitch().get() - _setVP0->pitch().get();
double newPitch = _setVP0->pitch()->as(Units::RADIANS) + tp*d_pitch.as(Units::RADIANS); // Calculate the new range:
Distance d_range = _setVP1->range().get() - _setVP0->range().get();
double newRange =
_setVP0->range()->as(Units::METERS) +
d_range.as(Units::METERS)*tp + sin(osg::PI*tp)*_setVPArcHeight; // Calculate the offsets
osg::Vec3d offset0 = _setVP0->positionOffset().getOrUse(osg::Vec3d(,,));
osg::Vec3d offset1 = _setVP1->positionOffset().getOrUse(osg::Vec3d(,,));
osg::Vec3d newOffset = offset0 + (offset1-offset0)*tp; // Activate.
setLookAt( newCenter, newAzim, newPitch, newRange, newOffset ); // interpolate tether rotation:
_tetherRotation.slerp(tp, _tetherRotationVP0, _tetherRotationVP1); // At t=1 the transition is complete.
if ( t >= 1.0 )
{
_setVP0.unset(); // If this was a transition into a tether, keep the endpoint around so we can
// continue tracking it.
if ( !isTethering() )
{
_setVP1.unset();
}
} return tp;
}
}

setViewpointFrame函数返回的就是0到1之间的插值系数。

注意:_setVPArcHeight   是弧顶高(初始和结束两点之间如果,有一个是最高点则,弧顶高为0)

setViewpointFrame函数里做了:
1.计算当前间隔系数(使其趋近于cos)
2.计算旋转角度、偏航、范围、偏移
3.移动相机setLookAt
4.收尾 ===============================================================================================================
好下面开始动刀:
我要改变OE镜头跳转的速度变化,OE默认速度变化方式是按照cos的方式。就是加速,再减速
我不喜欢,因为最后会出现镜头跳变,我要将cos的方式改成抛物线的方式。(*^__^*) 嘻嘻……

从之前的分析看出,我要修改的就是tp(间隔系数)与传入的时间的关系。

传入时间经过以下转换:

        double elapsed = time_s - _setVPStartTime->as(Units::SECONDS);
double t = std::min(1.0, elapsed / _setVPDuration.as(Units::SECONDS));

  elapsed      是间隔时间

  t = tp      是间隔系数

tp本来是线性[0~1]的,

经过tp = smoothStepInterp( tp );变成了cos的

先把它变回线性的试试。就是去掉

第一次尝试:

tp = tp;直接赋值

得到结果:漫游器以某固定速度飞到另一个点

第二次尝试:(非常失败,但是我还是要记录一下)

double GY_CameraFocal_Time_RatioTurningpoint = 0.2;        //[0.0,  1.0]
double GY_CameraFocal_Distance_RatioTurningpoint = 0.8; //[0.0, 1.0] double GY_SpeedUp_SpeedDown(double timeRatio) {
//输入的是时间比例系数,返回的是距离比例系数;将整个过程分为两个阶段:1.加速阶段,2.减速阶段
/*
//设计整条路径条件是:
一个飞机以初速度speed1向前飞行,并以acceleration1加速度加速飞行,飞行了time1秒;共飞行了distance1米;
然后飞机开始降落,以acceleration2减速度,减速滑行,滑行了time2秒,滑行了distance2米并停下。
已知:time1,time2,distance1,distance2
求:1.初始速度speed1 2.第一段加速度acceleration1 3.第二段加速度acceleration2
最终求:在经过x时间后,当前位置position? 已知公式分析:
1. speed1 * time1 + acceleration1 * time1 * time1 / 2.0 = distance1 //第一段飞行过程
2. speed1 + acceleration1 * time1 + acceleration2 * time2 = 0 //整个过程最后速度为0
3. (speed1 + acceleration1 * time1)* time2 + acceleration2 * time2 * time2 / 2.0 = distance2 //第二段飞行过程 化简公式:
1.sp1*t1 + t1*t1*a1/2 = d1
2.t2*sp1/2.0 + t1*t2*a1/2.0 = d2 解:
sp1 = (d1 - d2)/(t1 - t2/2.0)
a1 = (d2*t1 - d1*t2/2.0)/(t1 - t2/2.0)
a2 = (d1 - d2 + d2*t1*t1 - d1*t1*t2)/(t2*t2/2.0 - t1*t2) 第一段加速导致计算过于复杂,导致,有可能出现初始速度为负数的情况;
直接第一段使用匀速运动,第二段减速
则出现公式:
1.sp1 = d1/time1
2.d2 = sp1 *time2 + a2*time2*time2/2
到处
a2 = 2*(d2 - sp1*t2)/(t2*t2)
但是条件末速度为0,则不会被满足 */
double distanceRatio = timeRatio;
double time1 = osg::clampBetween(GY_CameraFocal_Time_RatioTurningpoint, 0.0, 1.0);
double time2 = 1.0 - time1;
double distance1 = osg::clampBetween(GY_CameraFocal_Distance_RatioTurningpoint, 0.0, 1.0);
double distance2 = 1.0 - distance1;
double speedAtBegin = ;
//double acceleration1 = 0;
double acceleration2 = ;
if (time1 != )
{
speedAtBegin = distance1 / time1;
}
if (time2 != )
{
//a2 = 2*(d2 - sp1*t2)/(t2*t2)
acceleration2 = * (distance2 - speedAtBegin*time2) / (time2*time2);
} if (timeRatio < time1)//加速阶段从0加速到(规定时间1内到达距离1)
{
distanceRatio = timeRatio * speedAtBegin;
}
else//减速阶段从某速度(前一阶段的最后速度)
{
double usetime = timeRatio - time1;
//d2 = sp1 *time2 + a2*time2*time2/2
distanceRatio = distance1 + speedAtBegin*usetime + acceleration2*usetime*usetime /2.0;
} return distanceRatio;//距离系数【0到1】
}

可以看出,我第二次失败是因为考虑了两段不同的加速导致的:最后减速使得,我过了终点后又回倒到终点。。。

高中物理可不管你是否有回倒的过程。。。可耻的应试教育

第三次尝试:

我使用了高等数学的:正态分布算法。

对此,我发现我的数学基础不支持我继续做下去,虽然这应该是最正确的算法。。。我只能找替代

第四次尝试

正态分布的构图让我觉得,我第二次尝试的思路出现了偏颇:

我不应该分两段不同的加速,分两段不同的路径考虑。于是有了下面的代码

double GY_testGaosi(double timeRatio)
{
double distanceRatio = timeRatio;
//s/2 = a*t*t*t/4 前一半 s
// s = a*t*t/2; a = 2*s/t*t
double ac = / 0.25;
//
if (timeRatio < 0.5)
{
distanceRatio = ac*timeRatio*timeRatio / 2.0;
}
else
{
double ftp = 1.0 - timeRatio;
distanceRatio = ac*ftp*ftp / 2.0;
distanceRatio = 1.0 - distanceRatio;
}
return distanceRatio;
}

得出的结果确实比模拟的cos更符合我喜欢的漫游方式,或者说更接近GoogleEarth的漫游方式;

下面给出数据对比

第一组,原来的算法

double
smoothStepInterp( double t ) {
return (t*t)*(3.0-2.0*t);
} 0.000000:::0.000000
0.010000:::0.000298
0.020000:::0.001184
0.030000:::0.002646
0.040000:::0.004672
0.050000:::0.007250
0.060000:::0.010368
0.070000:::0.014014
0.080000:::0.018176
0.090000:::0.022842
0.100000:::0.028000
0.110000:::0.033638
0.120000:::0.039744
0.130000:::0.046306
0.140000:::0.053312
0.150000:::0.060750
0.160000:::0.068608
0.170000:::0.076874
0.180000:::0.085536
0.190000:::0.094582
0.200000:::0.104000
0.210000:::0.113778
0.220000:::0.123904
0.230000:::0.134366
0.240000:::0.145152
0.250000:::0.156250
0.260000:::0.167648
0.270000:::0.179334
0.280000:::0.191296
0.290000:::0.203522
0.300000:::0.216000
0.310000:::0.228718
0.320000:::0.241664
0.330000:::0.254826
0.340000:::0.268192
0.350000:::0.281750
0.360000:::0.295488
0.370000:::0.309394
0.380000:::0.323456
0.390000:::0.337662
0.400000:::0.352000
0.410000:::0.366458
0.420000:::0.381024
0.430000:::0.395686
0.440000:::0.410432
0.450000:::0.425250
0.460000:::0.440128
0.470000:::0.455054
0.480000:::0.470016
0.490000:::0.485002
0.500000:::0.500000
0.510000:::0.514998
0.520000:::0.529984
0.530000:::0.544946
0.540000:::0.559872
0.550000:::0.574750
0.560000:::0.589568
0.570000:::0.604314
0.580000:::0.618976
0.590000:::0.633542
0.600000:::0.648000
0.610000:::0.662338
0.620000:::0.676544
0.630000:::0.690606
0.640000:::0.704512
0.650000:::0.718250
0.660000:::0.731808
0.670000:::0.745174
0.680000:::0.758336
0.690000:::0.771282
0.700000:::0.784000
0.710000:::0.796478
0.720000:::0.808704
0.730000:::0.820666
0.740000:::0.832352
0.750000:::0.843750
0.760000:::0.854848
0.770000:::0.865634
0.780000:::0.876096
0.790000:::0.886222
0.800000:::0.896000
0.810000:::0.905418
0.820000:::0.914464
0.830000:::0.923126
0.840000:::0.931392
0.850000:::0.939250
0.860000:::0.946688
0.870000:::0.953694
0.880000:::0.960256
0.890000:::0.966362
0.900000:::0.972000
0.910000:::0.977158
0.920000:::0.981824
0.930000:::0.985986
0.940000:::0.989632
0.950000:::0.992750
0.960000:::0.995328
0.970000:::0.997354
0.980000:::0.998816
0.990000:::0.999702

第二组,使用了自己的GY_testGaos算法

GY_testGaos
0.000000:::0.000000
0.010000:::0.000200
0.020000:::0.000800
0.030000:::0.001800
0.040000:::0.003200
0.050000:::0.005000
0.060000:::0.007200
0.070000:::0.009800
0.080000:::0.012800
0.090000:::0.016200
0.100000:::0.020000
0.110000:::0.024200
0.120000:::0.028800
0.130000:::0.033800
0.140000:::0.039200
0.150000:::0.045000
0.160000:::0.051200
0.170000:::0.057800
0.180000:::0.064800
0.190000:::0.072200
0.200000:::0.080000
0.210000:::0.088200
0.220000:::0.096800
0.230000:::0.105800
0.240000:::0.115200
0.250000:::0.125000
0.260000:::0.135200
0.270000:::0.145800
0.280000:::0.156800
0.290000:::0.168200
0.300000:::0.180000
0.310000:::0.192200
0.320000:::0.204800
0.330000:::0.217800
0.340000:::0.231200
0.350000:::0.245000
0.360000:::0.259200
0.370000:::0.273800
0.380000:::0.288800
0.390000:::0.304200
0.400000:::0.320000
0.410000:::0.336200
0.420000:::0.352800
0.430000:::0.369800
0.440000:::0.387200
0.450000:::0.405000
0.460000:::0.423200
0.470000:::0.441800
0.480000:::0.460800
0.490000:::0.480200
0.500000:::0.500000
0.510000:::0.519800
0.520000:::0.539200
0.530000:::0.558200
0.540000:::0.576800
0.550000:::0.595000
0.560000:::0.612800
0.570000:::0.630200
0.580000:::0.647200
0.590000:::0.663800
0.600000:::0.680000
0.610000:::0.695800
0.620000:::0.711200
0.630000:::0.726200
0.640000:::0.740800
0.650000:::0.755000
0.660000:::0.768800
0.670000:::0.782200
0.680000:::0.795200
0.690000:::0.807800
0.700000:::0.820000
0.710000:::0.831800
0.720000:::0.843200
0.730000:::0.854200
0.740000:::0.864800
0.750000:::0.875000
0.760000:::0.884800
0.770000:::0.894200
0.780000:::0.903200
0.790000:::0.911800
0.800000:::0.920000
0.810000:::0.927800
0.820000:::0.935200
0.830000:::0.942200
0.840000:::0.948800
0.850000:::0.955000
0.860000:::0.960800
0.870000:::0.966200
0.880000:::0.971200
0.890000:::0.975800
0.900000:::0.980000
0.910000:::0.983800
0.920000:::0.987200
0.930000:::0.990200
0.940000:::0.992800
0.950000:::0.995000
0.960000:::0.996800
0.970000:::0.998200
0.980000:::0.999200
0.990000:::0.999800

第五次尝试:邪恶的尝试

因为对匀加速结果的不太满意,我又尝试了匀加加速度(急动度)

网上TM的连基本的算法都没有···

我只想要一个匀急动度与距离的时间公式而已啊~~汗

没办法,只能近似了,自己编了一个急动度与距离的表达式:s = a*t*t*t/8

//blind add by gaoyuan  -_-!!
double GY_testdong(double timeRatio)
{
double distanceRatio = timeRatio;
//s = a*t*t*t/8 前一半 a = 8*s/t*t*t
double ac = * 0.5 / (0.5*0.5*0.5);
//
if (timeRatio < 0.5)
{
distanceRatio = ac*timeRatio*timeRatio*timeRatio / 8.0;
}
else
{
double ftp = 1.0 - timeRatio;
distanceRatio = ac*ftp*ftp*ftp / 8.0;
distanceRatio = 1.0 - distanceRatio;
}
return distanceRatio;
}

结果,给大家展示一下,不一定能用啊,但是绝对刺激!

0.000000:::0.000000
0.010000:::0.000004
0.020000:::0.000032
0.030000:::0.000108
0.040000:::0.000256
0.050000:::0.000500
0.060000:::0.000864
0.070000:::0.001372
0.080000:::0.002048
0.090000:::0.002916
0.100000:::0.004000
0.110000:::0.005324
0.120000:::0.006912
0.130000:::0.008788
0.140000:::0.010976
0.150000:::0.013500
0.160000:::0.016384
0.170000:::0.019652
0.180000:::0.023328
0.190000:::0.027436
0.200000:::0.032000
0.210000:::0.037044
0.220000:::0.042592
0.230000:::0.048668
0.240000:::0.055296
0.250000:::0.062500
0.260000:::0.070304
0.270000:::0.078732
0.280000:::0.087808
0.290000:::0.097556
0.300000:::0.108000
0.310000:::0.119164
0.320000:::0.131072
0.330000:::0.143748
0.340000:::0.157216
0.350000:::0.171500
0.360000:::0.186624
0.370000:::0.202612
0.380000:::0.219488
0.390000:::0.237276
0.400000:::0.256000
0.410000:::0.275684
0.420000:::0.296352
0.430000:::0.318028
0.440000:::0.340736
0.450000:::0.364500
0.460000:::0.389344
0.470000:::0.415292
0.480000:::0.442368
0.490000:::0.470596
0.500000:::0.500000
0.510000:::0.529404
0.520000:::0.557632
0.530000:::0.584708
0.540000:::0.610656
0.550000:::0.635500
0.560000:::0.659264
0.570000:::0.681972
0.580000:::0.703648
0.590000:::0.724316
0.600000:::0.744000
0.610000:::0.762724
0.620000:::0.780512
0.630000:::0.797388
0.640000:::0.813376
0.650000:::0.828500
0.660000:::0.842784
0.670000:::0.856252
0.680000:::0.868928
0.690000:::0.880836
0.700000:::0.892000
0.710000:::0.902444
0.720000:::0.912192
0.730000:::0.921268
0.740000:::0.929696
0.750000:::0.937500
0.760000:::0.944704
0.770000:::0.951332
0.780000:::0.957408
0.790000:::0.962956
0.800000:::0.968000
0.810000:::0.972564
0.820000:::0.976672
0.830000:::0.980348
0.840000:::0.983616
0.850000:::0.986500
0.860000:::0.989024
0.870000:::0.991212
0.880000:::0.993088
0.890000:::0.994676
0.900000:::0.996000
0.910000:::0.997084
0.920000:::0.997952
0.930000:::0.998628
0.940000:::0.999136
0.950000:::0.999500
0.960000:::0.999744
0.970000:::0.999892
0.980000:::0.999968
0.990000:::0.999996

全部对比:

时间基数 原路程基数  新二阶基数  新三阶基数
0.00 0.000000 0.000000 0.000000
0.02 0.001184 0.000800 0.000032
0.04 0.004672 0.003200 0.000256
0.06 0.010368 0.007200 0.000864
0.08 0.018176 0.012800 0.002048
0.10 0.028000 0.02 0.004000
0.12 0.039744 0.028800 0.006912
0.14 0.053312 0.039200 0.010976
0.16 0.068608 0.051200 0.016384
0.18 0.085536 0.064800 0.023328
0.20 0.104000 0.08 0.032000
0.22 0.123904 0.096800 0.042592
0.24 0.145152 0.115200 0.055296
0.26 0.167648 0.135200 0.070304
0.28 0.191296 0.156800 0.087808
0.30 0.216000 0.18 0.108000
0.32 0.241664 0.204800 0.131072
0.34 0.268192 0.231200 0.157216
0.36 0.295488 0.259200 0.186624
0.38 0.323456 0.288800 0.219488
0.40 0.352000 0.32 0.256000
0.42 0.381024 0.352800 0.296352
0.44 0.410432 0.387200 0.340736
0.46 0.440128 0.423200 0.389344
0.48 0.470016 0.460800 0.442368
0.50 0.50 0.50 0.50
0.52 0.529984 0.539200 0.557632
0.54 0.559872 0.576800 0.610656
0.56 0.589568 0.612800 0.659264
0.58 0.618976 0.647200 0.703648
0.60 0.648000 0.68 0.744000
0.62 0.676544 0.711200 0.780512
0.64 0.704512 0.740800 0.813376
0.66 0.731808 0.768800 0.842784
0.68 0.758336 0.795200 0.868928
0.70 0.784000 0.82 0.892000
0.72 0.808704 0.843200 0.912192
0.74 0.832352 0.864800 0.929696
0.76 0.854848 0.884800 0.944704
0.78 0.876096 0.903200 0.957408
0.80 0.896000 0.92 0.968000
0.82 0.914464 0.935200 0.976672
0.84 0.931392 0.948800 0.983616
0.86 0.946688 0.960800 0.989024
0.88 0.960256 0.971200 0.993088
0.90 0.972000 0.98 0.996000
0.92 0.981824 0.987200 0.997952
0.94 0.989632 0.992800 0.999136
0.96 0.995328 0.996800 0.999744
0.98 0.998816 0.999200 0.999968

第六次尝试,因为老大喜欢最后有一个长长的减速过程,所以,下面的算法,我用了一半时间来实现尾部减速

double GY_SharpMotionAddTail(double timeRatio, double pathLength = 100000.0)
{
timeRatio *= 2.0;
double pathRatio = pathLength / 10000.0;
pathRatio = std::max(1.0, pathRatio); double ratio = 0.1 / pathRatio; double distanceRatio = timeRatio;
//s = a*t*t*t/8 前一半 a = 8*s/t*t*t
double ac = 8 * 0.5 / (0.5*0.5*0.5);
//
if (timeRatio < 0.5)
{
distanceRatio = ac*timeRatio*timeRatio*timeRatio / 8.0;
//distanceRatio *= (1.0 - ratio);
}
else if(timeRatio < 1.0)
{
double ftp = 1.0 - timeRatio;
ftp *= 0.8;//0~0.4
ftp += 0.1;//0.1~0.5
distanceRatio = ac*ftp*ftp*ftp / 8.0;//0~x~0.5 x=0.1*0.1*0.1*a/8.0 x=0.004 //0.004~0.5
distanceRatio = 1 - distanceRatio;//0.5~0.996
distanceRatio -= 0.5;//0~0.496
distanceRatio *= (0.5 - ratio) / 0.496;//0~0.5-ratio
distanceRatio = 0.5 + distanceRatio;//0.5~1-ratio }
else if (timeRatio <= 2)
{
timeRatio = 2.0 - timeRatio;
distanceRatio = 1 - ratio*timeRatio*timeRatio;
}
return distanceRatio;
}

  

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

  1. [原][osg][osgEarth]关于在OE中使用物理引擎的调研

    关于物理引擎旋转的一些整理 参考文档 http://blog.wolfire.com/2010/03/Comparing-ODE-and-Bullet 介绍ODE和bullet的利弊 http://s ...

  2. [原][osg][OSGEARTH]OE的关闭打开自动计算裁剪面被OE的海洋ocean影响

    在osgEarthUtil 下 Ocean.cpp 的  traverse函数中: // we don't want the ocean participating in the N/F calcul ...

  3. [原][osg][osgearth]我眼中的osgearth

    看了一下,OE生成的可执行文件 除了osg库和第三方库 OE生产最多的dll就是 osgdb_osgearth_XXXX.dll了 这些都是为了通过osgDB机制加载earth的数据用的. 所以,我觉 ...

  4. [原][osg][osgEarth][粒子特效]关于粒子特效库在osgEarth中,位置摆放问题,跟踪节点移动问题

    首先粒子在地球上位置摆放很简单: //传入的经纬度坐标 osg::Vec3d geoPoint; const SpatialReference* latLong = SpatialReference: ...

  5. [原][osg][osgEarth]osg::Matrix 父子节点的变化关系

    //osg::Matrix offsetmatrix 计算出子节点在父节点下的绝对坐标 //osg::Matrix offposition 用来计算当前节点相对父节点的位置 osg::Matrix o ...

  6. [原][osg][osgearth]简单的通过osgDB,读取高程tif,修改高程tif

    ReadResult result; osg::ref_ptr<osgDB::ReaderWriter> reader = osgDB::Registry::instance()-> ...

  7. [原][OSG][osgEarth]osgEarth例子程序简介

    1.osgearth_graticule:生成经纬线. 2.osgearth_annotation:各类标注(点.线.面.模型.文本等). 3.osgearth_city:加载一个城市三维模型,可以浏 ...

  8. [原][osg][osgearth]倾斜摄影2.文件格式分析:OSGB

    倾斜摄影三维模型格式包含:*.osgb,*.dae等 文件格式包含:*.xml, *.desc, *.lfp等 例如:LocaSpace Viewer软件把osgb分块模型文件建立索引生成一个lfp文 ...

  9. [原][osg][osgearth]倾斜摄影1.介绍

    总体介绍: 倾斜摄影就是将拍好的数据,三角网格化再附上贴图. 目前流行处理软件: Street Factory.PIX4DMapper.smart3D 后期开发平台:超图 Skyline smart3 ...

随机推荐

  1. Android 新老两代 Camera API 大起底

    https://blog.csdn.net/Byeweiyang/article/details/80515192 0.背景简介 最近有一部分相机相关的需求,专注于对拍摄的照片.视频的噪点.色温.明暗 ...

  2. sping的quartz设置定时任务

    除了spring相关的jar包之外,还需要引入quartz-all-1.8.6.jar 下载地址:http://www.quartz-scheduler.org/downloads/ spring配置 ...

  3. SQL语句的优化方法

    减少对数据库的查询次数 尽量使用相同的或非常类似的SQL语句进行查询 避免不带任何条件的SQL语句的执行 sql语句用大写 别名的使用(1.5倍)

  4. 成绩统计程序(Java)

    我的程序: package day20181018;/** * 成绩统计系统 * @author Administrator */import java.util.Scanner;//提供计算机直接扫 ...

  5. Java基础语法(下)

    1.数组动态初始化 //数据类型[] 数组名 = new 数据类型[数组长度]; int[] arr = new int[3]; /* * 左边: * int:说明数组中的元素类型是int类型 * [ ...

  6. Installing Jenkins as a Windows service

    Install Jenkins as a Windows service NOTE: if you installed Jenkins using the windows installer, you ...

  7. Docker 使用Docker-Compose编排容器

    简介: Docker Compose是一个用来定义和运行复杂应用的Docker工具.一个使用Docker容器的应用,通常由多个容器组成.使用Docker Compose不再需要使用shell脚本来启动 ...

  8. SpringBoot 使用okhttp3

    1.添加pom.xml依赖 <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId& ...

  9. 【做题】cf603E——线段树分治

    首先感谢题解小哥,他在标算外又总结了三种做法. 此处仅提及最后一种做法. 首先考虑题目中要求的所有结点度数为奇数的限制. 对于每一个联通块,因为所有结点总度数是偶数,所以总结点数也必须是偶数的.即所有 ...

  10. P3727 曼哈顿计划E

    点分治+SG函数还真是令人意外的组合啊 思路 这道题看到找一条满足条件的链,想到点分治 看到博弈,想到SG函数 然后就变成一道SG函数+点分治的题了 然后1e9的SG函数怎么搞?当然是打表了 然后各种 ...