GteTrackball.cpp
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #include <GTEnginePCH.h>
10 #include <LowLevel/GteLogger.h>
11 using namespace gte;
12 
13 
15  :
16  mXSize(0),
17  mYSize(0),
18  mMultiplier(0.0f),
19  mX0(0.0f),
20  mY0(0.0f),
21  mX1(0.0f),
22  mY1(0.0f),
23  mActive(false),
24  mValidTrackball(false)
25 {
26  mRoot = std::make_shared<Node>();
27  mInitialOrientation.MakeIdentity();
28 }
29 
30 Trackball::Trackball(int xSize, int ySize,
31  std::shared_ptr<Camera> const& camera)
32  :
33  mXSize(0),
34  mYSize(0),
35  mMultiplier(0.0f),
36  mX0(0.0f),
37  mY0(0.0f),
38  mX1(0.0f),
39  mY1(0.0f),
40  mActive(false),
41  mValidTrackball(false)
42 {
43  Set(xSize, ySize, camera);
44  mRoot = std::make_shared<Node>();
45  mInitialOrientation.MakeIdentity();
46 }
47 
48 void Trackball::Set(int xSize, int ySize,
49  std::shared_ptr<Camera> const& camera)
50 {
51  if (xSize > 0 && ySize > 0 && camera)
52  {
53  mXSize = xSize;
54  mYSize = ySize;
55  mCamera = camera;
56  mMultiplier = 1.0f / (mXSize >= mYSize ? mYSize : mXSize);
57  mX0 = 0.5f * mXSize;
58  mY0 = 0.5f * mYSize;
59  mX1 = mX0;
60  mY1 = mY0;
61  mValidTrackball = true;
62  }
63  else
64  {
65  LogError("Invalid Trackball parameters.");
66  mValidTrackball = false;
67  }
68 }
69 
70 void Trackball::Attach(std::shared_ptr<Spatial> const& object)
71 {
72  if (mValidTrackball && object)
73  {
74  mRoot->AttachChild(object);
75  }
76 }
77 
78 void Trackball::Detach(std::shared_ptr<Spatial> const& object)
79 {
80  if (mValidTrackball && object)
81  {
82  mRoot->DetachChild(object);
83  }
84 }
85 
87 {
88  mRoot->DetachAllChildren();
89 }
90 
92 {
93  if (mValidTrackball)
94  {
95  mX0 = (2.0f * x - mXSize) * mMultiplier;
96  mY0 = (2.0f * y - mYSize) * mMultiplier;
97  mInitialOrientation = mRoot->worldTransform.GetRotation();
98  }
99 }
100 
102 {
103  if (mValidTrackball)
104  {
105  mX1 = (2.0f * x - mXSize) * mMultiplier;
106  mY1 = (2.0f * y - mYSize) * mMultiplier;
107  if (mX1 != mX0 || mY1 != mY0)
108  {
110  }
111  }
112 }
113 
115 {
116  // Get the first vector on the sphere.
117  float sqrLength0 = mX0 * mX0 + mY0 * mY0;
118  float length0 = sqrt(sqrLength0), invLength0 = 0.0f, z0, z1;
119  if (length0 > 1.0f)
120  {
121  // Outside the unit disk, project onto it.
122  invLength0 = 1.0f / length0;
123  mX0 *= invLength0;
124  mY0 *= invLength0;
125  z0 = 0.0f;
126  }
127  else
128  {
129  // Compute point (mX0,mY0,z0) on negative unit hemisphere.
130  z0 = 1.0f - sqrLength0;
131  z0 = (z0 <= 0.0f ? 0.0f : sqrt(z0));
132  }
133  z0 *= -1.0f;
134 
135  // Use camera world coordinates, order is (D,U,R), so point is (z,y,x).
136  Vector4<float> vec0{ z0, mY0, mX0, 0.0f };
137 
138  // Get the second vector on the sphere.
139  float sqrLength1 = mX1 * mX1 + mY1 * mY1;
140  float length1 = sqrt(sqrLength1), invLength1 = 0.0f;
141  if (length1 > 1.0f)
142  {
143  // Outside unit disk, project onto it.
144  invLength1 = 1.0f / length1;
145  mX1 *= invLength1;
146  mY1 *= invLength1;
147  z1 = 0.0f;
148  }
149  else
150  {
151  // Compute point (mX1,mY1,z1) on negative unit hemisphere.
152  z1 = 1.0f - sqrLength1;
153  z1 = (z1 <= 0.0f ? 0.0f : sqrt(z1));
154  }
155  z1 *= -1.0f;
156 
157  // Use camera world coordinates whose order is (D,U,R), so the
158  // point is (z,y,x).
159  Vector4<float> vec1{ z1, mY1, mX1, 0.0f };
160 
161  // Create axis and angle for the rotation.
162  Vector4<float> axis = Cross(vec0, vec1);
163  float dot = Dot(vec0, vec1);
164  float angle;
165  if (Normalize(axis) > 0.0f)
166  {
167  angle = acos(std::min(std::max(dot, -1.0f), 1.0f));
168  }
169  else // Vectors are parallel.
170  {
171  if (dot < 0.0f)
172  {
173  // Rotated pi radians.
174  axis[0] = mY0 * invLength0;
175  axis[1] = -mX0 * invLength0;
176  axis[2] = 0.0f;
177  angle = (float)GTE_C_PI;
178  }
179  else
180  {
181  // Rotation by zero radians.
182  axis.MakeUnit(0);
183  angle = 0.0f;
184  }
185  }
186 
187  // Compute the rotation matrix implied by trackball motion. The axis
188  // vector was computed in camera coordinates. It must be converted
189  // to world coordinates. Once again, I use the camera ordering (D,U,R).
190  Vector4<float> worldAxis =
191  axis[0] * mCamera->GetDVector() +
192  axis[1] * mCamera->GetUVector() +
193  axis[2] * mCamera->GetRVector();
194 
195  Matrix4x4<float> trackRotate = Rotation<4, float>(
196  AxisAngle<4, float>(worldAxis, angle));
197 
198  // Compute the new rotation, which is the incremental rotation of
199  // the trackball appiled after the object has been rotated by its old
200  // rotation.
201 #if defined(GTE_USE_MAT_VEC)
202  Matrix4x4<float> rotate = trackRotate * mInitialOrientation;
203 #else
204  Matrix4x4<float> rotate = mInitialOrientation * trackRotate;
205 #endif
206 
207  // Renormalize to avoid accumulated rounding errors that can cause the
208  // rotation matrix to degenerate.
209  Vector4<float> v[3] =
210  {
211  rotate.GetCol(0),
212  rotate.GetCol(1),
213  rotate.GetCol(2)
214  };
215  Orthonormalize<4, float>(3, v);
216  rotate.SetCol(0, v[0]);
217  rotate.SetCol(1, v[1]);
218  rotate.SetCol(2, v[2]);
219 
220  mRoot->localTransform.SetRotation(rotate);
221  mRoot->Update();
222 }
223 
void SetFinalPoint(int x, int y)
Vector< NumRows, Real > GetCol(int c) const
Definition: GteMatrix.h:383
void UpdateOrientation()
GLfloat angle
Definition: glext.h:6466
Matrix4x4< float > mInitialOrientation
Definition: GteTrackball.h:71
GLint GLenum GLint x
Definition: glcorearb.h:404
std::shared_ptr< Node > mRoot
Definition: GteTrackball.h:70
#define GTE_C_PI
Definition: GteConstants.h:17
#define LogError(message)
Definition: GteLogger.h:92
void SetInitialPoint(int x, int y)
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
void SetCol(int c, Vector< NumRows, Real > const &vec)
Definition: GteMatrix.h:362
Real Normalize(GVector< Real > &v, bool robust=false)
Definition: GteGVector.h:454
DualQuaternion< Real > Cross(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
const GLdouble * v
Definition: glcorearb.h:832
GLfloat f
Definition: glcorearb.h:1921
void Attach(std::shared_ptr< Spatial > const &object)
bool mValidTrackball
Definition: GteTrackball.h:73
void Detach(std::shared_ptr< Spatial > const &object)
std::shared_ptr< Camera > mCamera
Definition: GteTrackball.h:69
void Set(int xSize, int ySize, std::shared_ptr< Camera > const &camera)
void MakeUnit(int d)
Definition: GteVector.h:285
GLint y
Definition: glcorearb.h:98


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:01