[原][osg][osgEarth]EarthManipulator关于oe漫游器的handle部分解读以及修改(仿照谷歌,修改oe漫游器中focal(视角切换)功能 续 二)
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(视角切换)功能 续 二)的更多相关文章
- [原][osg][osgEarth]关于在OE中使用物理引擎的调研
关于物理引擎旋转的一些整理 参考文档 http://blog.wolfire.com/2010/03/Comparing-ODE-and-Bullet 介绍ODE和bullet的利弊 http://s ...
- [原][osg][OSGEARTH]OE的关闭打开自动计算裁剪面被OE的海洋ocean影响
在osgEarthUtil 下 Ocean.cpp 的 traverse函数中: // we don't want the ocean participating in the N/F calcul ...
- [原][osg][osgearth]我眼中的osgearth
看了一下,OE生成的可执行文件 除了osg库和第三方库 OE生产最多的dll就是 osgdb_osgearth_XXXX.dll了 这些都是为了通过osgDB机制加载earth的数据用的. 所以,我觉 ...
- [原][osg][osgEarth][粒子特效]关于粒子特效库在osgEarth中,位置摆放问题,跟踪节点移动问题
首先粒子在地球上位置摆放很简单: //传入的经纬度坐标 osg::Vec3d geoPoint; const SpatialReference* latLong = SpatialReference: ...
- [原][osg][osgEarth]osg::Matrix 父子节点的变化关系
//osg::Matrix offsetmatrix 计算出子节点在父节点下的绝对坐标 //osg::Matrix offposition 用来计算当前节点相对父节点的位置 osg::Matrix o ...
- [原][osg][osgearth]简单的通过osgDB,读取高程tif,修改高程tif
ReadResult result; osg::ref_ptr<osgDB::ReaderWriter> reader = osgDB::Registry::instance()-> ...
- [原][OSG][osgEarth]osgEarth例子程序简介
1.osgearth_graticule:生成经纬线. 2.osgearth_annotation:各类标注(点.线.面.模型.文本等). 3.osgearth_city:加载一个城市三维模型,可以浏 ...
- [原][osg][osgearth]倾斜摄影2.文件格式分析:OSGB
倾斜摄影三维模型格式包含:*.osgb,*.dae等 文件格式包含:*.xml, *.desc, *.lfp等 例如:LocaSpace Viewer软件把osgb分块模型文件建立索引生成一个lfp文 ...
- [原][osg][osgearth]倾斜摄影1.介绍
总体介绍: 倾斜摄影就是将拍好的数据,三角网格化再附上贴图. 目前流行处理软件: Street Factory.PIX4DMapper.smart3D 后期开发平台:超图 Skyline smart3 ...
随机推荐
- javaweb项目中errorPage的问题
我们的请求找不到时,会跳到错误页面,tomcat提供了一个错误页面,但是不太好.分析:tomcat自带错误页面不好的原因:有一下两点: 1.不好看: 2.不能为seo做出贡献.思考:如何解决以上问题? ...
- DBCP数据库连接池的使用
DBCP的简单介绍: DBCP(DataBase Connection Pool)数据库连接池,是java数据库连接池的一种,由apache开发通过数据库连接池可以让程序自动管理数据库连接的释放和断开 ...
- Python3 Pandas的DataFrame数据的增、删、改、查
Python3 Pandas的DataFrame数据的增.删.改.查 一.DataFrame数据准备 增.删.改.查的方法有很多很多种,这里只展示出常用的几种. 参数inplace默认为False,只 ...
- Java利用JNI调用C/C++写成的DLL
前言 由于学期作业的要求,笔者需要开发一个语音识别系统.出于对Java的热爱,笔者非常想用Java来写上层程序(前台+数据库的三层),又要用到Microsoft Speech SDK,所以在这些条件下 ...
- Linux使用退格键时出现^H + Tab键命令补全失效/方向键失效 + ls文件夹和文件没有颜色
删除问题 安装kalilinux使用普通用户的的时候按退格键无法实现删除功能 解决的办法有两个 一改变快捷键: 使用Ctrl+Backspace组合键可以实现删除功能 ctrl + backspace ...
- 在eclipse中, 如何快速输入(快捷键)System.out.println();
1.快速输入(快捷键)System.out.println(); 首先输入sysout或syso,然后ALT+/ System.out.println(); 2.快速输入(快捷键)System.err ...
- topcoder srm 380 div1
problem1 link 分类讨论.高度没有太大关系.主要看长度. problem2 link 二分答案$mid$.计算每种$card$不足的部分,加起来,小于等于$min(jokers,mid)$ ...
- Bootstrap3基础 pagination 分页按钮 简单示例
内容 参数 OS Windows 10 x64 browser Firefox 65.0.2 framework Bootstrap 3.3.7 editor ...
- luogu1110[ZJOI2007]报表统计
思路 这里的初始化就不讲了,看完操作讲解就应该明白了,再不行就去看代码 对于操作1 由于操作2的需要,vector[n]存下数 对于操作2的维护 查询相邻两个元素的之间差值(绝对值)的最小值 先把所有 ...
- 【团队】EasyKing的实现_1
完成部分 三个功能类 英雄. 子弹. 瓦片地图. 一个设置类 地图 实现功能 瓦片地图 英雄移动 攻击 受到攻击 TODO 子弹攻击范围 地图.建筑物和英雄的碰撞箱 音效 英雄技能 建筑 双人联机 物 ...