OpenWalnut  1.5.0dev
WGEZoomTrackballManipulator.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include "WGEZoomTrackballManipulator.h"
26 #include "WGraphicsEngine.h"
27 
29  TrackballManipulator( 0x02 ),
30  m_zoom( 1.0 ),
31  m_allowThrow( false ),
32  m_paintMode( 0 )
33 {
34  setTrackballSize( .3 ); // changes the effect of a mouse move for rotation
35 }
36 
37 void WGEZoomTrackballManipulator::setByMatrix( const osg::Matrixd& matrix )
38 {
39  m_zoom = 1.0 / matrix.getScale()[0];
40 
41  // The zoom needs to be undone before forwarding the matrix.
42  TrackballManipulator::setByMatrix( osg::Matrixd::inverse( osg::Matrixd::scale( 1.0 / m_zoom, 1.0 / m_zoom, 1.0 / m_zoom ) ) * matrix );
43 }
44 
46 {
47  return osg::Matrixd::scale( 1.0 / m_zoom, 1.0 / m_zoom, 1.0 / m_zoom ) * TrackballManipulator::getMatrix();
48 }
49 
51 {
52  return TrackballManipulator::getMatrix();
53 }
54 
56 {
57  return TrackballManipulator::getInverseMatrix() * osg::Matrixd::scale( m_zoom, m_zoom, m_zoom );
58 }
59 
60 void WGEZoomTrackballManipulator::home( double /* currentTime */ )
61 {
62  m_zoom = 1.0;
63  TrackballManipulator::home( 0 /* currentTime */ );
64 }
65 
66 bool WGEZoomTrackballManipulator::zoom( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us )
67 {
68  double zoomDelta = 0.0;
69 
70  if( ea.getKey() && ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN )
71  {
72  if( ea.getKey() == osgGA::GUIEventAdapter::KEY_Minus )
73  {
74  zoomDelta = -0.05;
75  }
76  if( ea.getKey() == osgGA::GUIEventAdapter::KEY_Plus )
77  {
78  zoomDelta = 0.05;
79  }
80  if( zoomDelta != 0.0 )
81  {
82  m_zoom *= 1.0 + zoomDelta;
83  us.requestRedraw();
84  }
85  }
86  else
87  {
88  if( ea.getHandled() )
89  {
90  return true;
91  }
92 
93  switch( ea.getScrollingMotion() )
94  {
95  case osgGA::GUIEventAdapter::SCROLL_UP:
96  zoomDelta = 0.05;
97  break;
98  case osgGA::GUIEventAdapter::SCROLL_DOWN:
99  zoomDelta = -0.05;
100  break;
101  case osgGA::GUIEventAdapter::SCROLL_2D:
102  zoomDelta = 0.05 / 120.0 * ea.getScrollingDeltaY();
103  break;
104  // case osgGA::GUIEventAdapter::SCROLL_LEFT:
105  // case osgGA::GUIEventAdapter::SCROLL_RIGHT:
106  // case osgGA::GUIEventAdapter::SCROLL_NONE:
107  default:
108  // do nothing
109  zoomDelta = 0.0;
110  break;
111  }
112  }
113 
114  if( zoomDelta != 0.0 )
115  {
116  m_zoom *= 1.0 + zoomDelta;
117  us.requestRedraw();
118  }
119 
120  us.requestContinuousUpdate( false );
121  return true;
122 }
123 
124 bool WGEZoomTrackballManipulator::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us )
125 {
126  _thrown &= m_allowThrow; // By default we do not want the auto-rotation thingy.
127 
128  if( WGraphicsEngine::getGraphicsEngine()->getScene()->isHomePositionRequested() )
129  {
130  // We set the scene to the manipulator home position if the scene
131  // requests to do so. See WGEScene for more details.
132  home( 0 );
133  return true;
134  }
135  else if( ea.getEventType() == osgGA::GUIEventAdapter::SCROLL
136  || ea.getKey() == osgGA::GUIEventAdapter::KEY_Minus
137  || ea.getKey() == osgGA::GUIEventAdapter::KEY_Plus )
138  {
139  return zoom( ea, us );
140  }
141  // NOTE: we need to ignore the right mouse-button drag! This manipulates the underlying Trackball Manipulator while, at the same time, is
142  // used for moving ROIS! Zooming is done using Scroll Wheel or +/- keys.
143  else if( ( ea.getEventType() == osgGA::GUIEventAdapter::DRAG ) || ( ea.getEventType() == osgGA::GUIEventAdapter::PUSH ) )
144  {
145  if( ea.getButtonMask() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON )
146  {
147  return true;
148  }
149  else if( ( ea.getButtonMask() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON ) && ( m_paintMode == 1 ) )
150  {
151  return true;
152  }
153  else
154  {
155  return TrackballManipulator::handle( ea, us );
156  }
157  }
158  else
159  {
160  return TrackballManipulator::handle( ea, us );
161  }
162 }
163 
165 {
166  m_paintMode = mode;
167 }
168 
170 {
171  m_allowThrow = allowThrow;
172 }
173 
175 {
176  return m_allowThrow;
177 }
178 
179 void WGEZoomTrackballManipulator::computeHomePosition( const osg::Camera*, bool useBoundingBox )
180 {
181  if( getNode() )
182  {
183  osg::BoundingSphere boundingSphere;
184 
185  if( useBoundingBox )
186  {
187  WGEZoomTrackballNodeVisitor cbVisitor;
188  getNode()->accept( cbVisitor );
189  osg::BoundingBox& bb = cbVisitor.getBoundingBox();
190 
191  if( bb.valid() )
192  {
193  boundingSphere.expandBy( bb );
194  }
195  else
196  {
197  boundingSphere = getNode()->getBound();
198  }
199  }
200  else
201  {
202  boundingSphere = getNode()->getBound();
203  }
204 
205  m_radius = osg::maximum( ( double ) boundingSphere.radius(), 1e-6 );
206 
207  // The more far away the number from 0 is, the stronger is the pan
208  setHomePosition( boundingSphere.center() + osg::Vec3d( 0.0, -m_radius, 0.0 ),
209  boundingSphere.center(),
210  osg::Vec3d( 0.0, 0.0, 1.0 ),
211  _autoComputeHomePosition );
212  }
213 }
214 
215 void WGEZoomTrackballManipulator::fitToScreen( const osg::Camera* camera )
216 {
217  if( !camera )
218  {
219  return;
220  }
221 
222  computeHomePosition( camera, true );
223 
224  double radiusFac[] = {
225  1, 1, 1,
226  -1, 1, 1,
227  1, -1, 1,
228  -1, -1, 1,
229  1, 1, -1,
230  -1, 1, -1,
231  1, -1, -1,
232  -1, -1, -1
233  };
234  osg::Vec3 center = _homeCenter;
235  osg::Matrix transf = camera->getProjectionMatrix() * camera->getViewport()->computeWindowMatrix();
236  double fac = INFINITY;
237  for( int i = 0; i < 8; i++ )
238  {
239  osg::Vec3d vec = osg::Vec3( center.x() + m_radius * radiusFac[ i * 3 ],
240  center.y() + m_radius * radiusFac[ i * 3 + 1 ],
241  center.z() + m_radius * radiusFac[ i * 3 + 2 ] );
242  osg::Vec3d screenCoords = vec * transf;
243 
244  double facX = abs( camera->getViewport()->width() / screenCoords.x() );
245  double facY = abs( camera->getViewport()->height() / screenCoords.y() );
246 
247  fac = fmin( fac, facX );
248  fac = fmin( fac, facY );
249  }
250 
251  m_zoom = fac;
252  setCenter( center );
253 }
254 
255 bool WGEZoomTrackballManipulator::performMovementMiddleMouseButton( const double eventTimeDelta, const double dx, const double dy )
256 {
257  // scale panning based on zoom
258  float scale = -0.5 * ( _distance / m_zoom ) * getThrowScale( eventTimeDelta );
259  panModel( dx * scale, dy * scale );
260  return true;
261 }
262 
bool getThrow() const
Checks whether throwing is active.
void setThrow(bool allowThrow=true)
En-/Disables throwing.
virtual bool performMovementMiddleMouseButton(const double eventTimeDelta, const double dx, const double dy)
Performs the middle mouse button click.
virtual void computeHomePosition(const osg::Camera *camera, bool useBoundingBox)
Computes the home position.
void fitToScreen(const osg::Camera *camera)
Zooms and centers to fit screen.
bool zoom(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us)
Handles events related to zooming.
bool m_allowThrow
Do we want the auto-rotation thingy?
virtual osg::Matrixd getInverseMatrix() const
Get the position of the manipulator as a inverse matrix of the manipulator, typically used as a model...
WGEZoomTrackballManipulator()
Default constructor.
double m_radius
The radius of the bounding sphere.
virtual void setByMatrix(const osg::Matrixd &matrix)
Set the position of the manipulator using a 4x4 matrix.
virtual osg::Matrixd getMatrix() const
Get the position of the manipulator as 4x4 matrix.
virtual void home(double currentTime)
Move the camera to the default position.
virtual osg::Matrixd getMatrixWithoutZoom() const
Get the manipulator only containing rotation and translation.
virtual bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us)
Handle events, return true if handled, false otherwise.
void setPaintMode(int mode)
setter for paint mode when set to something different from 0, a left drag should move the scene
A visitor that ignores specific nodes that are irrelevant for the trackball.
osg::BoundingBox & getBoundingBox()
Gets the bounding box.
static std::shared_ptr< WGraphicsEngine > getGraphicsEngine()
Returns instance of the graphics engine.