Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
TrackballManipulator.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
34 #include <vlGraphics/Actor.hpp>
36 #include <vlGraphics/Rendering.hpp>
37 
38 using namespace vl;
39 
40 //-----------------------------------------------------------------------------
42 {
43  if ( camera() == NULL )
44  return;
45 
46  // if already busy ignore the event
47  if (mode() != NoMode)
48  return;
49 
50  // enter new mode
51  if (btn == rotationButton())
53  else
54  if (btn == translationButton())
56  else
57  if (btn == zoomButton())
58  mMode = ZoomMode;
59 
60  VL_CHECK(openglContext()->framebuffer())
61 
62  // set x/y relative to the viewport
63  x -= camera()->viewport()->x();
64  y -= openglContext()->framebuffer()->height() - 1 - (camera()->viewport()->y() + camera()->viewport()->height() -1);
65 
66  // check that the click is in the viewport
67  int w = camera()->viewport()->width();
68  int h = camera()->viewport()->height();
69 
70  if (x<0 || y<0 || x>=w || y>=h)
71  return;
72 
73  mMouseStart.x() = x;
74  mMouseStart.y() = y;
75 
76  if (mTransform)
77  {
78  mStartMatrix = mTransform->localMatrix();
80  }
81  else
83 
86 }
87 //-----------------------------------------------------------------------------
88 void TrackballManipulator::mouseUpEvent(EMouseButton btn, int /*x*/, int /*y*/)
89 {
90  if ( camera() == NULL )
91  return;
92 
93  // if the trackball is not doing anything ignore the event
94  if (mode() == NoMode)
95  return;
96 
97  // leave the mode
98  if (btn == rotationButton() && mMode == RotationMode)
99  mMode = NoMode;
100  else
101  if (btn == translationButton() && mMode == TranslationMode)
102  mMode = NoMode;
103  else
104  if (btn == zoomButton() && mMode == ZoomMode)
105  mMode = NoMode;
106 }
107 //-----------------------------------------------------------------------------
109 {
110  if ( camera() == NULL )
111  return;
112 
113  // ignore the event if the trackball is not in any mode
114  if (mode() == NoMode)
115  return;
116 
117  VL_CHECK(openglContext()->framebuffer())
118  // set x/y relative to the top/left cornder of the viewport
119  x -= camera()->viewport()->x();
120  y -= openglContext()->framebuffer()->height() - 1 - (camera()->viewport()->y() + camera()->viewport()->height() -1);
121 
122  if (mode() == RotationMode)
123  {
124  if (mTransform)
125  {
127  mTransform->computeWorldMatrix();
128  mStartMatrix = mTransform->localMatrix();
129  }
130  else
131  {
133  mStartMatrix = camera()->modelingMatrix();
134  }
135 
136  mMouseStart.x() = x;
137  mMouseStart.y() = y;
138  }
139  else
140  if (mode() == ZoomMode)
141  {
142  float t = (y-mMouseStart.y()) / 200.0f;
143  t *= zoomSpeed();
144  real distance = (mStartCameraPos - mPivot).length();
145  vec3 camera_pos = mStartCameraPos - camera()->modelingMatrix().getZ()*t*distance;
146  mat4 m = camera()->modelingMatrix();
147  m.setT(camera_pos);
149  }
150  else
151  if (mode() == TranslationMode)
152  {
153  float tx = (mMouseStart.x() - x) / 400.0f;
154  float ty = -(mMouseStart.y() - y) / 400.0f;
155  tx *= translationSpeed();
156  ty *= translationSpeed();
157  real distance = (mStartCameraPos - mPivot).length();
158  vec3 up = camera()->modelingMatrix().getY();
159  vec3 right = camera()->modelingMatrix().getX();
160  mat4 m = camera()->modelingMatrix();
161  m.setT(mStartCameraPos + up*distance*ty + right*distance*tx);
163  mPivot = mStartPivot + up*distance*ty + right*distance*tx;
164  }
165 
166  // update the view
167  openglContext()->update();
168 }
169 //-----------------------------------------------------------------------------
171 {
172  if( x==mMouseStart.x() && y==mMouseStart.y() )
173  return mat4();
174 
175  VL_CHECK(camera())
177  vec3 b = computeVector(x, y);
178  vec3 n = cross(a, b);
179  n.normalize();
180  a.normalize();
181  b.normalize();
182  real dot_a_b = dot(a,b);
183  dot_a_b = clamp(dot_a_b,(real)-1.0,(real)+1.0);
184  real alpha = acos(dot_a_b) * (mTransform ? 1 : -1);
185  alpha = alpha * rotationSpeed();
186  vec3 nc = camera()->modelingMatrix().get3x3() * n;
187  if (mTransform && mTransform->parent())
188  nc = mTransform->parent()->getComputedWorldMatrix().getInverse() * nc;
189  nc.normalize();
190  return mat4::getRotation(alpha*(real)dRAD_TO_DEG, nc);
191 }
192 //-----------------------------------------------------------------------------
194 {
195  vec3 c(camera()->viewport()->width() / 2.0f, camera()->viewport()->height() / 2.0f, 0);
196 
197  float sphere_x = camera()->viewport()->width() * 0.5f;
198  float sphere_y = camera()->viewport()->height() * 0.5f;
199 
200  VL_CHECK(camera())
201  vec3 v((real)x,(real)y,0);
202  v -= c;
203  v.x() /= sphere_x;
204  v.y() /= sphere_y;
205  v.y() = -v.y();
206  //if (v.length() > 1.0f)
207  // v.normalize();
208 
209  real z2 = 1.0f - v.x()*v.x() - v.y()*v.y();
210  if (z2 < 0)
211  z2 = 0;
212  v.z() = sqrt( z2 );
213  v.normalize();
214  return v;
215 }
216 //-----------------------------------------------------------------------------
217 void TrackballManipulator::adjustView(const AABB& aabb, const vec3& dir, const vec3& up, real bias)
218 {
219  VL_CHECK(camera())
220  VL_CHECK(!aabb.isNull())
221  /*setTransform(NULL);*/
222  setPivot( aabb.center() );
223  camera()->adjustView(aabb, dir, up, bias);
224 }
225 //-----------------------------------------------------------------------------
226 void TrackballManipulator::adjustView(ActorCollection& actors, const vec3& dir, const vec3& up, real bias)
227 {
228  if ( ! actors.empty() ) {
229  AABB aabb;
230  for(int i=0; i<actors.size(); ++i)
231  {
232  if (actors.at(i)->transform())
233  {
234  actors.at(i)->transform()->computeWorldMatrix();
235  }
236  actors.at(i)->lod(0)->setBoundsDirty(true);
237  actors.at(i)->computeBounds();
238  aabb += actors.at(i)->boundingBox();
239  }
240  adjustView(aabb, dir, up, bias);
241  }
242 }
243 //-----------------------------------------------------------------------------
244 void TrackballManipulator::adjustView(SceneManager* scene, const vec3& dir, const vec3& up, real bias)
245 {
246  ActorCollection actors;
247  scene->extractVisibleActors( actors, NULL );
248  adjustView(actors, dir, up, bias);
249 }
250 //-----------------------------------------------------------------------------
251 void TrackballManipulator::adjustView(Rendering* rendering, const vec3& dir, const vec3& up, real bias)
252 {
253  ActorCollection actors;
254  for(int i = 0; i < rendering->sceneManagers()->size(); ++i ) {
255  rendering->sceneManagers()->at( i )->extractVisibleActors( actors, NULL );
256  }
257  adjustView(actors, dir, up, bias);
258 }
259 //-----------------------------------------------------------------------------
261 {
262  if (enabled)
263  {
264  mMode = NoMode;
265  if ( openglContext() )
266  {
269  }
270  }
271 }
272 //-----------------------------------------------------------------------------
const Renderable * lod(int lod_index) const
Returns the Renderable object representing the LOD level specifed by lod_index.
Definition: Actor.hpp:173
float clamp(float x, float minval, float maxval)
Definition: Vector2.hpp:315
const T * at(int i) const
Definition: Collection.hpp:100
int y() const
Definition: Viewport.hpp:67
int rotationButton() const
Mouse button used to rotate.
const Vector3 & normalize(T_Scalar *len=NULL)
Definition: Vector3.hpp:227
T sqrt(T a)
Definition: glsl_math.hpp:592
Transform * transform()
Returns the Transform bound tho an Actor.
Definition: Actor.hpp:190
mat4 trackballRotation(int x, int y)
Vector3< T_Scalar > getZ() const
Definition: Matrix4.hpp:126
virtual void mouseMoveEvent(int x, int y)
Event generated when the mouse moves.
Matrix4 & setT(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:160
bool isNull() const
Returns true if the AABB is null.
Definition: AABB.hpp:60
Framebuffer * framebuffer()
The default render target (always returns leftFramebuffer()).
ETrackballMode mode() const
Returns the current trackball manipulator state.
const T_Scalar & z() const
Definition: Vector3.hpp:91
int size() const
Definition: Collection.hpp:82
void adjustView(const AABB &aabb, const vec3 &dir, const vec3 &up, real bias=1.0f)
Adjusts the camera position so that the given aabb can be properly viewed.
Definition: Camera.cpp:135
Vector3< T_Scalar > getY() const
Definition: Matrix4.hpp:121
void setBoundsDirty(bool dirty)
Marks the bounding box and bounding sphere as dirty in order to be recomputed at the next rendering...
Definition: Renderable.hpp:123
virtual void extractVisibleActors(ActorCollection &list, const Camera *camera)=0
Extracts all the enabled and visible Actors contained in the ActorTree hierarchy and appends them to ...
vec3 center() const
Returns the center of the AABB.
Definition: AABB.cpp:184
const double dRAD_TO_DEG
Constant to convert radian into degree using double precision.
Definition: std_types.hpp:68
void adjustView(const AABB &aabb, const vec3 &dir, const vec3 &up, real bias=1.0f)
Adjusts the camera position in order to nicely see the scene. It also position the rotation pivot to ...
fvec3 cross(const fvec3 &v1, const fvec3 &v2)
Definition: Vector3.hpp:277
Viewport * viewport()
The viewport bound to a camera.
Definition: Camera.hpp:141
Visualization Library main namespace.
Vector3< T_Scalar > getX() const
Definition: Matrix4.hpp:116
float dot(float a, float b)
Definition: glsl_math.hpp:1111
T distance(T p0, T p1)
Definition: glsl_math.hpp:1098
int translationButton() const
Mouse button used to translate the view.
Matrix3< T_Scalar > get3x3() const
Definition: Matrix4.hpp:323
virtual void mouseDownEvent(EMouseButton, int x, int y)
Event generated when one of the mouse buttons is pressed.
int height() const
Definition: Viewport.hpp:71
int width() const
Definition: Viewport.hpp:69
The AABB class implements an axis-aligned bounding box using vl::real precision.
Definition: AABB.hpp:44
virtual void setContinuousUpdate(bool continuous)
If the OpenGL context is a widget this function sets whether its area is continuously updated at each...
virtual void computeWorldMatrix(Camera *=NULL)
Computes the world matrix by concatenating the parent&#39;s world matrix with its own local matrix...
Definition: Transform.hpp:195
int height() const
The height of a render target.
Definition: Framebuffer.hpp:75
virtual void mouseUpEvent(EMouseButton, int x, int y)
Event generated when one of the mouse buttons is released.
const mat4 & modelingMatrix() const
Returns the Camera&#39;s modelingMatrix() (inverse of the view matrix).
Definition: Camera.hpp:169
const T_Scalar & y() const
Definition: Vector3.hpp:90
The SceneManager class is the base class for all the scene managers.
EMouseButton
int x() const
Definition: Viewport.hpp:65
const AABB & boundingBox() const
Returns the bounding box (not guaranteed to be up to date) that contains this Actor.
Definition: Actor.hpp:205
void setModelingMatrix(const mat4 &mat)
Sets the Camera&#39;s modelingMatrix() (inverse of the view matrix).
Definition: Camera.hpp:165
#define NULL
Definition: OpenGLDefs.hpp:81
The Rendering class collects all the information to perform the rendering of a scene.
Definition: Rendering.hpp:69
float rotationSpeed() const
Rotation speed multiplicative factor (default = 1).
static Matrix4 & getRotation(Matrix4 &out, float degrees, float x, float y, float z)
Definition: Matrix4.hpp:904
Vector3< T_Scalar > getT() const
Definition: Matrix4.hpp:131
Defined as a simple subclass of Collection<Actor>, see Collection for more information.
Definition: Actor.hpp:479
fmat4 mat4
Defined as: &#39;typedef fmat4 mat4&#39;. See also VL_PIPELINE_PRECISION.
Definition: Matrix4.hpp:1240
float translationSpeed() const
Translation speed multiplicative factor (default = 1).
static Matrix4 & getTranslation(Matrix4 &out, const Vector3< float > &v)
Definition: Matrix4.hpp:548
void computeBounds()
Computes the bounding box and bounding sphere of an Actor if boundsDirty().
Definition: Actor.cpp:95
float zoomSpeed() const
Zoom speed multiplicative factor (default = 1).
bool empty() const
Definition: Collection.hpp:84
const T_Scalar & x() const
Definition: Vector3.hpp:89
const T_Scalar & x() const
Definition: Vector2.hpp:132
OpenGLContext * openglContext()
Returns the OpenGLContext to which this UIEventListener is bound or NULL if no context is bound...
T length(T v)
Definition: glsl_math.hpp:1084
T acos(T a)
Definition: glsl_math.hpp:329
virtual void enableEvent(bool enabled)
Event generated whenever setEnabled() is called.
void setPivot(vec3 pivot)
The center point around which the camera will rotate.
virtual void setMouseVisible(bool)
If the OpenGL context is a widget this function sets whether the mouse is visible over it or not...
const T_Scalar & y() const
Definition: Vector2.hpp:133
int zoomButton() const
Mouse button used to zoom.
#define VL_CHECK(expr)
Definition: checks.hpp:73
Collection< SceneManager > * sceneManagers()
Returns the list of SceneManager[s] containing the Actor[s] to be rendered.
Definition: Rendering.hpp:137
virtual void update()=0
If the OpenGLContext is a widget this function requests a redraw and generates an updateEvent()...
Camera * camera()
The camera through which the trackball manipulator is used.