From Nico Kruithof, "Attached is a patch that makes the spherical manipulator frame rate independent. This is similar to what Lee did for the trackball manipulator a couple of months ago."

This commit is contained in:
Robert Osfield
2009-12-02 14:21:13 +00:00
parent 3c8fe13194
commit b278660799
2 changed files with 29 additions and 8 deletions

View File

@@ -143,6 +143,17 @@ class OSGGA_EXPORT SphericalManipulator : public MatrixManipulator
bool _thrown;
bool _allowThrow;
/** The approximate amount of time it is currently taking to draw a frame.
* This is used to compute the delta in translation/rotation during a thrown display update.
* It allows us to match an delta in position/rotation independent of the rendering frame rate.
*/
double _delta_frame_time;
/** The time the last frame started.
* Used when _rate_sensitive is true so that we can match display update rate to rotation/translation rate.
*/
double _last_frame_time;
RotationMode _rotationMode;
osg::Vec3d _center;
double _distance;

View File

@@ -115,11 +115,18 @@ bool SphericalManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us
switch(ea.getEventType())
{
case(GUIEventAdapter::FRAME):
if (_thrown)
{
if (calcMovement()) us.requestRedraw();
double current_frame_time = ea.getTime();
_delta_frame_time = current_frame_time - _last_frame_time;
_last_frame_time = current_frame_time;
if (_thrown)
{
if (calcMovement()) us.requestRedraw();
}
return false;
}
return false;
default:
break;
}
@@ -304,6 +311,9 @@ bool SphericalManipulator::calcMovement()
buttonMask = _ga_t1->getButtonMask();
}
double throwScale = (_thrown && _ga_t0.valid() && _ga_t1.valid()) ?
_delta_frame_time / (_ga_t0->getTime() - _ga_t1->getTime()) : 1.0;
if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON)
{
// rotate camera.
@@ -321,7 +331,7 @@ bool SphericalManipulator::calcMovement()
float angle=atan2(py1-pyc,px1-pxc)-atan2(py0-pyc,px0-pxc);
_heading+=angle;
_heading+=throwScale*angle;
if(_heading < -PI)
_heading+=2*PI;
else if(_heading > PI)
@@ -331,7 +341,7 @@ bool SphericalManipulator::calcMovement()
{
if((_rotationMode != ELEVATION) && ((_ga_t1->getModKeyMask() & GUIEventAdapter::MODKEY_SHIFT) == 0))
{
_heading-=dx*PI_2;
_heading-=throwScale*dx*PI_2;
if(_heading < 0)
_heading+=2*PI;
@@ -341,7 +351,7 @@ bool SphericalManipulator::calcMovement()
if((_rotationMode != HEADING) && ((_ga_t1->getModKeyMask() & GUIEventAdapter::MODKEY_ALT) == 0))
{
_elevation-=dy*osg::PI_4;
_elevation-=throwScale*dy*osg::PI_4;
// Only allows vertical rotation of 180deg
if(_elevation < -osg::PI_2)
@@ -363,7 +373,7 @@ bool SphericalManipulator::calcMovement()
osg::Matrix rotation_matrix;
rotation_matrix=osg::Matrixd::rotate(_elevation,-1,0,0)*osg::Matrixd::rotate(PI_2+_heading,0,0,1);
osg::Vec3 dv(dx*scale,0,dy*scale);
osg::Vec3 dv(throwScale*dx*scale,0,throwScale*dy*scale);
_center += dv*rotation_matrix;
return true;
@@ -375,7 +385,7 @@ bool SphericalManipulator::calcMovement()
// zoom model.
double fd = _distance;
double scale = 1.0+dy;
double scale = 1.0+throwScale*dy;
if(fd*scale > _modelScale*_minimumZoomScale)
{
_distance *= scale;