3 #include <osgGA/TrackballManipulator>
6 #include <osg/BoundsChecking>
8 #include "OsgTrackballManipulator.h"
11 using namespace osgGA;
15 namespace Visualization
18 OsgTrackballManipulator::OsgTrackballManipulator()
21 _minimumZoomScale = 0.05f;
25 _trackballSize = 0.8f;
29 OsgTrackballManipulator::~OsgTrackballManipulator()
34 void OsgTrackballManipulator::setNode(osg::Node* node)
39 const osg::BoundingSphere& boundingSphere=_node->getBound();
40 _modelScale = boundingSphere._radius;
42 if (getAutoComputeHomePosition()) computeHomePosition();
46 const osg::Node* OsgTrackballManipulator::getNode()
const
52 osg::Node* OsgTrackballManipulator::getNode()
58 void OsgTrackballManipulator::home(
double )
64 if (getAutoComputeHomePosition()) computeHomePosition();
65 computePosition(_homeEye, _homeCenter, _homeEye);
69 void OsgTrackballManipulator::home(
const GUIEventAdapter& ea ,GUIActionAdapter& us)
73 us.requestContinuousUpdate(
false);
77 void OsgTrackballManipulator::init(
const GUIEventAdapter& ,GUIActionAdapter& )
79 flushMouseEventStack();
83 void OsgTrackballManipulator::getUsage(osg::ApplicationUsage& usage)
const
85 usage.addKeyboardMouseBinding(
"Trackball: Space",
"Reset the viewing position to home");
86 usage.addKeyboardMouseBinding(
"Trackball: +",
"When in stereo, increase the fusion distance");
87 usage.addKeyboardMouseBinding(
"Trackball: -",
"When in stereo, reduce the fusion distance");
90 bool OsgTrackballManipulator::handle(
const GUIEventAdapter& ea,GUIActionAdapter& us)
92 switch(ea.getEventType())
94 case(GUIEventAdapter::FRAME):
97 if (calcMovement()) us.requestRedraw();
104 if (ea.getHandled())
return false;
106 switch(ea.getEventType())
108 case(GUIEventAdapter::PUSH):
110 flushMouseEventStack();
112 if (calcMovement()) us.requestRedraw();
113 us.requestContinuousUpdate(
false);
118 case(GUIEventAdapter::RELEASE):
120 if (ea.getButtonMask()==0)
123 double timeSinceLastRecordEvent = _ga_t0.valid() ? (ea.getTime() - _ga_t0->getTime()) : DBL_MAX;
124 if (timeSinceLastRecordEvent>0.02) flushMouseEventStack();
131 us.requestContinuousUpdate(
true);
137 flushMouseEventStack();
139 if (calcMovement()) us.requestRedraw();
140 us.requestContinuousUpdate(
false);
147 flushMouseEventStack();
149 if (calcMovement()) us.requestRedraw();
150 us.requestContinuousUpdate(
false);
156 case(GUIEventAdapter::DRAG):
159 if (calcMovement()) us.requestRedraw();
160 us.requestContinuousUpdate(
false);
165 case(GUIEventAdapter::MOVE):
170 case(GUIEventAdapter::KEYDOWN):
171 if (ea.getKey()== GUIEventAdapter::KEY_Space)
173 flushMouseEventStack();
179 case(GUIEventAdapter::FRAME):
182 if (calcMovement()) us.requestRedraw();
191 bool OsgTrackballManipulator::isMouseMoving()
193 if (_ga_t0.get()==NULL || _ga_t1.get()==NULL)
return false;
195 static const float velocity = 0.1f;
197 float dx = _ga_t0->getXnormalized()-_ga_t1->getXnormalized();
198 float dy = _ga_t0->getYnormalized()-_ga_t1->getYnormalized();
199 float len = sqrtf(dx*dx+dy*dy);
200 float dt = _ga_t0->getTime()-_ga_t1->getTime();
202 return (len>dt*velocity);
206 void OsgTrackballManipulator::flushMouseEventStack()
213 void OsgTrackballManipulator::addMouseEvent(
const GUIEventAdapter& ea)
219 void OsgTrackballManipulator::setByMatrix(
const osg::Matrixd& matrix)
221 _center = osg::Vec3(0.0f,0.0f,-_distance)*matrix;
222 _rotation = matrix.getRotate();
225 osg::Matrixd OsgTrackballManipulator::getMatrix()
const
227 return osg::Matrixd::translate(0.0,0.0,_distance)*osg::Matrixd::rotate(_rotation)*osg::Matrixd::translate(_center);
230 osg::Matrixd OsgTrackballManipulator::getInverseMatrix()
const
232 return osg::Matrixd::translate(-_center)*osg::Matrixd::rotate(_rotation.inverse())*osg::Matrixd::translate(0.0,0.0,-_distance);
235 void OsgTrackballManipulator::computePosition(
const osg::Vec3& eye,
const osg::Vec3& center,
const osg::Vec3& up)
238 osg::Vec3 lv(center-eye);
247 osg::Matrix rotation_matrix(s[0], u[0], -f[0], 0.0f,
248 s[1], u[1], -f[1], 0.0f,
249 s[2], u[2], -f[2], 0.0f,
250 0.0f, 0.0f, 0.0f, 1.0f);
253 _distance = lv.length();
254 _rotation = rotation_matrix.getRotate().inverse();
258 bool OsgTrackballManipulator::calcMovement()
261 if (_ga_t0.get()==NULL || _ga_t1.get()==NULL)
return false;
263 float dx = _ga_t0->getXnormalized()-_ga_t1->getXnormalized();
264 float dy = _ga_t0->getYnormalized()-_ga_t1->getYnormalized();
266 float distance = sqrtf(dx*dx + dy*dy);
279 unsigned int buttonMask = _ga_t1->getButtonMask();
280 if (buttonMask==GUIEventAdapter::LEFT_MOUSE_BUTTON)
288 float px0 = _ga_t0->getXnormalized();
289 float py0 = _ga_t0->getYnormalized();
291 float px1 = _ga_t1->getXnormalized();
292 float py1 = _ga_t1->getYnormalized();
295 trackball(axis,angle,px1,py1,px0,py0);
297 osg::Quat new_rotate;
298 new_rotate.makeRotate(angle,axis);
300 _rotation = _rotation*new_rotate;
305 else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON ||
306 buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON))
311 float scale = -0.3f*_distance;
313 osg::Matrix rotation_matrix;
314 rotation_matrix.makeRotate(_rotation);
316 osg::Vec3 dv(dx*scale,dy*scale,0.0f);
318 _center += dv*rotation_matrix;
323 else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON)
328 float fd = _distance;
329 float scale = 1.0f+dy;
330 if (fd*scale>_modelScale*_minimumZoomScale)
343 osg::Matrix rotation_matrix(_rotation);
345 osg::Vec3 dv = (osg::Vec3(0.0f,0.0f,-1.0f)*rotation_matrix)*(dy*scale);
370 void OsgTrackballManipulator::setTrackballSize(
float size)
372 _trackballSize = size;
373 osg::clampBetweenRange(_trackballSize,0.1f,1.0f,
"OsgTrackballManipulator::setTrackballSize(float)");
388 void OsgTrackballManipulator::trackball(osg::Vec3& axis,
float& angle,
float p1x,
float p1y,
float p2x,
float p2y)
395 osg::Matrix rotation_matrix(_rotation);
398 osg::Vec3 uv = osg::Vec3(0.0f,1.0f,0.0f)*rotation_matrix;
399 osg::Vec3 sv = osg::Vec3(1.0f,0.0f,0.0f)*rotation_matrix;
400 osg::Vec3 lv = osg::Vec3(0.0f,0.0f,-1.0f)*rotation_matrix;
402 osg::Vec3 p1 = sv * p1x + uv * p1y - lv * tb_project_to_sphere(_trackballSize, p1x, p1y);
403 osg::Vec3 p2 = sv * p2x + uv * p2y - lv * tb_project_to_sphere(_trackballSize, p2x, p2y);
421 float t = (p2 - p1).length() / (2.0 * _trackballSize);
426 if (t > 1.0) t = 1.0;
427 if (t < -1.0) t = -1.0;
428 angle = inRadians(asin(t));
437 float OsgTrackballManipulator::tb_project_to_sphere(
float r,
float x,
float y)
443 if (d < r * 0.70710678118654752440)
449 t = r / 1.41421356237309504880;
Classes for implementing the cm-labs vortex physics engine for AnimatLab.