From b1a99ba25fe741d7ae8e9d95cdf4e01e3d82da11 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 25 Jun 2009 18:11:29 +0000 Subject: [PATCH] From Lee Bulter, "I noticed that when "throwing" things the rate of motion once thrown was dependent on the complexity of the geometry. For complex scenes this meant that it looked like you were "throwing" the display into molasses. For simple geometry things get over-excited once thrown. The fix is to factor in the frame rendering time to the caluclated motion. I've implemented this for rotation and panning. Now when things are thrown they maintain a rate very close to what was happening when the mouse button was released." --- include/osgGA/TrackballManipulator | 18 ++++++++++++++++++ src/osgGA/TrackballManipulator.cpp | 25 ++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) 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;