diff --git a/include/osgGA/TrackballManipulator b/include/osgGA/TrackballManipulator index 32202e273..1cae1676a 100644 --- a/include/osgGA/TrackballManipulator +++ b/include/osgGA/TrackballManipulator @@ -149,6 +149,24 @@ class OSGGA_EXPORT TrackballManipulator : public MatrixManipulator bool _allowThrow; bool _thrown; + + /** Indicates whether "thrown" display should match rate of motion at time of throw. + * This is significant on systems where the delta between mouse events can be radically different + * from the delta in display update events. + */ + bool _rate_sensitive; + + /** 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; + osg::Vec3d _center; osg::Quat _rotation; double _distance; diff --git a/src/osgGA/TrackballManipulator.cpp b/src/osgGA/TrackballManipulator.cpp index 566481bc6..d01da3bef 100644 --- a/src/osgGA/TrackballManipulator.cpp +++ b/src/osgGA/TrackballManipulator.cpp @@ -12,6 +12,7 @@ TrackballManipulator::TrackballManipulator() _minimumZoomScale = 0.05f; _allowThrow = true; _thrown = false; + _rate_sensitive = true; _distance = 1.0f; _trackballSize = 0.8f; @@ -81,11 +82,18 @@ bool TrackballManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us switch(ea.getEventType()) { case(GUIEventAdapter::FRAME): + { + double current_frame_time = ea.getTime(); + + _delta_frame_time = current_frame_time - _last_frame_time; + _last_frame_time = current_frame_time; + if (_thrown && _allowThrow) { if (calcMovement()) us.requestRedraw(); } return false; + } default: break; } @@ -321,7 +329,15 @@ bool TrackballManipulator::calcMovement() trackball(axis,angle,px1,py1,px0,py0); osg::Quat new_rotate; - new_rotate.makeRotate(angle,axis); + + if (_thrown && _rate_sensitive && _ga_t0.valid() && _ga_t1.valid()) + { + // frame_time / delta_event_time + double rate = _delta_frame_time / (_ga_t0->getTime() - _ga_t1->getTime()); + new_rotate.makeRotate(angle * rate,axis); + } else { + new_rotate.makeRotate(angle,axis); + } _rotation = _rotation*new_rotate; @@ -339,6 +355,13 @@ bool TrackballManipulator::calcMovement() osg::Matrix rotation_matrix; rotation_matrix.makeRotate(_rotation); + if (_thrown && _rate_sensitive && _ga_t0.valid() && _ga_t1.valid()) + { + // frame_time / delta_event_time + double rate = _delta_frame_time / (_ga_t0->getTime() - _ga_t1->getTime()); + scale *= rate; + } + osg::Vec3 dv(dx*scale,dy*scale,0.0f); _center += dv*rotation_matrix;