Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "MultiTouchOrbit3DManipulator.h"
- #include <osg/io_utils>
- #include <vector>
- MultiTouchOrbit3DManipulator::MultiTouchOrbit3DManipulator(IfcPlusPlusSystem * sys, int flags) : Orbit3DManipulator (sys , flags)
- {
- setVerticalAxisFixed(false) ;
- }
- /// Handles the multi - touch camera pan and zoom
- void MultiTouchOrbit3DManipulator::handleMultiTouchGesture (
- osgGA::GUIEventAdapter::TouchData * now,
- osgGA::GUIEventAdapter::TouchData * last,
- const osgGA :: GUIEventAdapter & ea,
- osgGA :: GUIActionAdapter & aa,
- const double eventTimeDelta)
- {
- /// Multipliers for screen size independent manipulations
- osg::Vec2 screenCompensationMultipliers(ea.getXmax() - ea.getXmin(),
- ea.getYmax() - ea.getYmin());
- // Computations were done relative to iPhone screen
- screenCompensationMultipliers /= 640;
- // Touch points normalized to [-1 , 1]
- osg::Vec2 pt1Now (now->get(0).x, now->get(0).y);
- osg::Vec2 pt2Now (now->get(1).x, now->get(1).y);
- osg::Vec2 pt1Last (last->get(0).x, last->get(0).y);
- osg::Vec2 pt2Last (last->get(1).x, last->get(1).y);
- // Centers of the touch points for determining the ray intersection
- osg::Vec2 pxCenterPointLast = (pt1Last + pt2Last) / 2.;
- osg::Vec2 pxCenterPointNow = (pt1Now + pt2Now) / 2.;
- osg::Vec2 centerPointLast = normalizedScreenPoint (pxCenterPointLast, ea);
- osg::Vec2 centerPointNow = normalizedScreenPoint (pxCenterPointNow , ea);
- // if any of the two fingers just begun , compute the ray
- // pointer intersection
- if (last->get(0).phase == osgGA::GUIEventAdapter::TOUCH_BEGAN
- || last->get(1).phase == osgGA::GUIEventAdapter::TOUCH_BEGAN) {
- // The y axis is flipped in the device screen
- // coordinates
- computeRayPointer (ea , aa, osg::Vec2 (centerPointLast.x(), - centerPointLast.y()));
- }
- // compensate the vectors for different screen
- // dimensions than the tested device
- std::vector <osg::Vec2 *> compensationVectors =
- {& pt1Now, &pt2Now , &pt1Last, &pt2Last, ¢erPointLast, ¢erPointNow};
- for (auto vec : compensationVectors) {
- vec->x() *= screenCompensationMultipliers.x();
- vec->y() *= screenCompensationMultipliers.y();
- }
- // compute sizes of gaps between fingers
- float gapNow ((pt1Now - pt2Now).length());
- float gapLast ((pt1Last - pt2Last).length());
- osg::Vec3 intersectionCameraVector = m_eye - m_rotate_center;
- float gapDifference = gapNow - gapLast;
- // empirically reached factor constant
- float scrollDistanceFactor = intersectionCameraVector.length() * 0.1;
- // zoom camera more the further it is from the ray
- // intersection point
- zoomCamera (gapDifference * eventTimeDelta * scrollDistanceFactor);
- // drag gesture
- osgViewer::View * view = dynamic_cast<osgViewer::View *>(&aa);
- if (!view) {
- return ;
- }
- // move camera more the further it is from the ray intersection point
- osg :: Vec2 distanceRatioPanFactors =
- screenCompensationMultipliers * fmax(0.8, intersectionCameraVector.length() * 0.2);
- osg::Vec2 dCenter = centerPointLast - centerPointNow;
- // left camera vector is perpendicular to the camera up
- // vector and the direction of camera
- osg::Vec3 left = m_up ^ (m_lookat - m_eye);
- // the m_up vector only defines camera 's roll but not its pitch
- // get the camera 's up direction vector
- osg::Vec3 camUp = left ^ (m_lookat - m_eye);
- camUp.normalize();
- left.normalize();
- osg::Vec3 leftShift = left * dCenter.x();
- osg::Vec3 upShift = camUp * dCenter.y();
- leftShift *= distanceRatioPanFactors.x();
- upShift *= distanceRatioPanFactors.y();
- // translate the camera eye and lookat
- m_eye.set(m_eye - leftShift + upShift) ;
- m_lookat.set(m_lookat - leftShift + upShift);
- }
- /// returns screen point normalized into interval [ -1 , 1]
- osg::Vec2 MultiTouchOrbit3DManipulator::normalizedScreenPoint (osg::Vec2 point,
- const osgGA::GUIEventAdapter & ea)
- {
- return ((osg::Vec2(point.x() / (ea.getXmax() - ea.getXmin()),
- point.y() / (ea.getYmax() - ea.getYmin()))) * 2.) - osg::Vec2(1., 1);
- }
- bool MultiTouchOrbit3DManipulator::handle (const osgGA::GUIEventAdapter& ea ,
- osgGA::GUIActionAdapter& aa)
- {
- bool handled (false);
- switch (ea.getEventType()) {
- case osgGA::GUIEventAdapter::PUSH:
- case osgGA::GUIEventAdapter::DRAG:
- case osgGA::GUIEventAdapter::RELEASE:
- // Deselect the selected object and dismiss the menu
- if (this->selectionWasDismissedHandler) {
- this->selectionWasDismissedHandler (ea.getXnormalized(),
- ea.getYnormalized());
- }
- if (ea.isMultiTouchEvent()) {
- float eventTimeDelta = 1./60.;
- osgGA::GUIEventAdapter::TouchData * touchData = ea.getTouchData();
- // Ensure the number of touches is at least 2,
- // the others will be ignored
- if (touchData->getNumTouchPoints() >= 2) {
- if (( _lastTouchData . valid () ) &&
- ( _lastTouchData- > getNumTouchPoints () >= 2)) {
- handleMultiTouchGesture (touchData, _lastTouchData.get(), ea, aa, eventTimeDelta);
- }
- handled = true;
- }
- _lastTouchData = touchData;
- // check if all touches ended
- unsigned int num_touches_ended(0);
- for (osgGA::GUIEventAdapter::TouchData::iterator i = touchData->begin(); i != touchData-> end(); ++i) {
- if ((*i).phase == osgGA::GUIEventAdapter::TOUCH_ENDED) {
- num_touches_ended ++;
- }
- }
- }
- break;
- default:
- break;
- }
- // if the touches were not handled , call the superclass's implementation
- return handled ? handled : Orbit3DManipulator::handle (ea, aa);
- }
- void Orbit3DManipulator::zoomCamera (const float dy)
- {
- // push camera forward along mouse ray
- osg::Vec3d zoom_direction = m_ray_pointer_direction;
- zoom_direction.normalize();
- zoom_direction *= dy;
- m_eye += zoom_direction;
- m_lookat += zoom_direction;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement