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."
This commit is contained in:
Robert Osfield 2009-06-25 18:11:29 +00:00
parent 44a8e850f4
commit b1a99ba25f
2 changed files with 42 additions and 1 deletions

View File

@ -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;

View File

@ -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;