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. Kattis之旅——Eight Queens

    In the game of chess, the queen is a powerful piece. It can attack by moving any number of spaces in ...

  2. Vue中的事件与常见的问题处理

    Vue的事件:获取事件对象$event: 事件冒泡:事件会向上传播 原生js阻止事件冒泡,需要先获取事件对象,再调用stopPropagation()方法: vue事件修饰符stop,例@clik.s ...

  3. mongodb安装、远程访问设置、基本常用操作和命令以及GUI

    https://www.mongodb.com/download-center?jmp=nav下载对应OS的版本,tar -xzvf解压 对于最新版本比如3.4,windows 7下可能回报api-m ...

  4. mysql Out of range value adjusted for column导致Warning(1265)Data truncated for column 'column_name' at row 1

    今天下午,我们的一个开发来找我,说线上有个环境报了"Warning(1265)Data truncated for column 'column_name' at row 1",定 ...

  5. 【题解】Luogu P2522 [HAOI2011]Problem b

    原题传送门 这题需要运用莫比乌斯反演(懵逼钨丝繁衍) 我们看题面,让求对于区间\([a,b]\)内的整数x和\([c,d]\)内的y,满足$ gcd(x,y)=k$的数对的个数 我们珂以跟容斥原理(二 ...

  6. Linux系统更改默认Python版本

    Linux 默认的Python版本为Python2.X,但是在很多时候我们需要使用Python3.X,那么我们需要更改Linux的默认Python版本,更改很简单,只需要两句话. sudo updat ...

  7. 数据结构(C语言)—排序

    数据结构(C语言)—排序 排序 排序是按关键字的非递增或递减顺序对一组记录中心进行排序的操作.(将一组杂乱无章的数据按一定规律顺次排列起来.) 未定列表与不稳定列表 假设 Ki = Kj ( 1 ≤ ...

  8. (3网络化部署)自己动手,编写神经网络程序,解决Mnist问题,并网络化部署

    我们使用google提供的colab,对我们现有的GoNetwork进行适当修改,利用网络资源进行运算. 一.什么是 Colaboratory? Colaboratory 是一款研究工具,用于进行机器 ...

  9. 20145320《网络对抗》逆向及Bof基础实践

    1 逆向及Bof基础实践说明 1.1 实践目标 本次实践的对象是一个名为pwn20145320的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的 ...

  10. tf.argmax()以及axis解析

    首先,明确一点,tf.argmax可以认为就是np.argmax.tensorflow使用numpy实现的这个API.    简单的说,tf.argmax就是返回最大的那个数值所在的下标.    这个 ...