Logo ROOT   6.12/07
Reference Guide
TArcBall.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Timur Pocheptsov 03/08/2004
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TArcBall.h"
13 #include "TPoint.h"
14 #include "TMath.h"
15 
16 const Double_t Epsilon = 1.0e-5;
17 
18 /** \class TArcBall
19 \ingroup opengl
20 Implements the arc-ball rotation manipulator. Used by plot-painters.
21 
22 Arcball sphere constants:
23  - Diameter is 2.0f
24  - Radius is 1.0f
25 */
26 
28 
29 
30 
31 ////////////////////////////////////////////////////////////////////////////////
32 
33 inline void Vector3dCross(Double_t *NewObj, const Double_t * v1, const Double_t *v2)
34 {
35  NewObj[0] = v1[1] * v2[2] - v1[2] * v2[1];
36  NewObj[1] = v1[2] * v2[0] - v1[0] * v2[2];
37  NewObj[2] = v1[0] * v2[1] - v1[1] * v2[0];
38 }
39 
40 ////////////////////////////////////////////////////////////////////////////////
41 
42 inline Double_t Vector3dDot(const Double_t *NewObj, const Double_t *v1)
43 {
44  return NewObj[0] * v1[0] + NewObj[1] * v1[1] + NewObj[2] * v1[2];
45 }
46 
47 ////////////////////////////////////////////////////////////////////////////////
48 
50 {
51  return NewObj[0] * NewObj[0] + NewObj[1] * NewObj[1] + NewObj[2] * NewObj[2];
52 }
53 
54 ////////////////////////////////////////////////////////////////////////////////
55 
56 inline Double_t Vector3dLength(const Double_t *NewObj)
57 {
58  return TMath::Sqrt(Vector3dLengthSquared(NewObj));
59 }
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 
63 inline void Matrix3dSetZero(Double_t * NewObj)
64 {
65  for (Int_t i = 0; i < 9; ++i)
66  NewObj[i] = 0.;
67 }
68 
69 ////////////////////////////////////////////////////////////////////////////////
70 
71 inline void Matrix3dSetIdentity(Double_t *NewObj)
72 {
73  Matrix3dSetZero(NewObj);
74  //then set diagonal as 1
75  NewObj[0] = NewObj[4] = NewObj[8] = 1.;
76 }
77 
78 ////////////////////////////////////////////////////////////////////////////////
79 
81 {
82  Double_t n = (q1[0] * q1[0]) + (q1[1] * q1[1]) + (q1[2] * q1[2]) + (q1[3] * q1[3]);
83  Double_t s = (n > 0.0f) ? (2.0f / n) : 0.0f;
84  Double_t xs = q1[0] * s, ys = q1[1] * s, zs = q1[2] * s;
85  Double_t wx = q1[3] * xs, wy = q1[3] * ys, wz = q1[3] * zs;
86  Double_t xx = q1[0] * xs, xy = q1[0] * ys, xz = q1[0] * zs;
87  Double_t yy = q1[1] * ys, yz = q1[1] * zs, zz = q1[2] * zs;
88 
89  NewObj[0] = 1.0f - (yy + zz); NewObj[3] = xy - wz; NewObj[6] = xz + wy;
90  NewObj[1] = xy + wz; NewObj[4] = 1.0f - (xx + zz); NewObj[7] = yz - wx;
91  NewObj[2] = xz - wy; NewObj[5] = yz + wx; NewObj[8] = 1.0f - (xx + yy);
92 }
93 
94 ////////////////////////////////////////////////////////////////////////////////
95 
96 void Matrix3dMulMatrix3d(Double_t *NewObj, const Double_t *m1)
97 {
98  Double_t result[9];
99 
100  result[0] = (NewObj[0] * m1[0]) + (NewObj[3] * m1[1]) + (NewObj[6] * m1[2]);
101  result[3] = (NewObj[0] * m1[3]) + (NewObj[3] * m1[4]) + (NewObj[6] * m1[5]);
102  result[6] = (NewObj[0] * m1[6]) + (NewObj[3] * m1[7]) + (NewObj[6] * m1[8]);
103 
104  result[1] = (NewObj[1] * m1[0]) + (NewObj[4] * m1[1]) + (NewObj[7] * m1[2]);
105  result[4] = (NewObj[1] * m1[3]) + (NewObj[4] * m1[4]) + (NewObj[7] * m1[5]);
106  result[7] = (NewObj[1] * m1[6]) + (NewObj[4] * m1[7]) + (NewObj[7] * m1[8]);
107 
108  result[2] = (NewObj[2] * m1[0]) + (NewObj[5] * m1[1]) + (NewObj[8] * m1[2]);
109  result[5] = (NewObj[2] * m1[3]) + (NewObj[5] * m1[4]) + (NewObj[8] * m1[5]);
110  result[8] = (NewObj[2] * m1[6]) + (NewObj[5] * m1[7]) + (NewObj[8] * m1[8]);
111 
112  for (Int_t i = 0; i < 9; ++i)
113  NewObj[i] = result[i];
114 }
115 
116 ////////////////////////////////////////////////////////////////////////////////
117 
119 {
120  NewObj[0] = m1[0]; NewObj[4] = m1[4]; NewObj[8] = m1[8];
121  NewObj[1] = m1[1]; NewObj[5] = m1[5]; NewObj[9] = m1[9];
122  NewObj[2] = m1[2]; NewObj[6] = m1[6]; NewObj[10] = m1[10];
123 }
124 
125 ////////////////////////////////////////////////////////////////////////////////
126 
127 inline Double_t Matrix4fSVD(const Double_t *NewObj, Double_t *rot3, Double_t *rot4)
128 {
130  ( (NewObj[0] * NewObj[0]) + (NewObj[1] * NewObj[1]) + (NewObj[2] * NewObj[2]) +
131  (NewObj[4] * NewObj[4]) + (NewObj[5] * NewObj[5]) + (NewObj[6] * NewObj[6]) +
132  (NewObj[8] * NewObj[8]) + (NewObj[9] * NewObj[9]) + (NewObj[10] * NewObj[10]) ) / 3.0f );
133 
134  if (rot3) {
135  rot3[0] = NewObj[0]; rot3[1] = NewObj[1]; rot3[2] = NewObj[2];
136  rot3[3] = NewObj[4]; rot3[4] = NewObj[5]; rot3[5] = NewObj[6];
137  rot3[6] = NewObj[8]; rot3[7] = NewObj[9]; rot3[8] = NewObj[10];
138 
139  Double_t n = 1. / TMath::Sqrt(NewObj[0] * NewObj[0] + NewObj[1] * NewObj[1] + NewObj[2] * NewObj[2] + 0.0001);
140 
141  rot3[0] *= n;
142  rot3[1] *= n;
143  rot3[2] *= n;
144 
145  n = 1. / TMath::Sqrt(NewObj[4] * NewObj[4] + NewObj[5] * NewObj[5] + NewObj[6] * NewObj[6] + 0.0001);
146  rot3[3] *= n;
147  rot3[4] *= n;
148  rot3[5] *= n;
149 
150  n = 1.0f / TMath::Sqrt(NewObj[8] * NewObj[8] + NewObj[9] * NewObj[9] + NewObj[10] * NewObj[10] + 0.0001);
151  rot3[6] *= n;
152  rot3[7] *= n;
153  rot3[8] *= n;
154  }
155 
156  if (rot4) {
157  if (rot4 != NewObj)
159 
160  Double_t n = 1. / TMath::Sqrt(NewObj[0] * NewObj[0] + NewObj[1] * NewObj[1] + NewObj[2] * NewObj[2] + 0.0001);
161 
162  rot4[0] *= n;
163  rot4[1] *= n;
164  rot4[2] *= n;
165 
166  n = 1. / TMath::Sqrt(NewObj[4] * NewObj[4] + NewObj[5] * NewObj[5] + NewObj[6] * NewObj[6] + 0.0001);
167  rot4[4] *= n;
168  rot4[5] *= n;
169  rot4[6] *= n;
170 
171  n = 1. / TMath::Sqrt(NewObj[8] * NewObj[8] + NewObj[9] * NewObj[9] + NewObj[10] * NewObj[10] + 0.0001);
172  rot4[8] *= n;
173  rot4[9] *= n;
174  rot4[10] *= n;
175  }
176 
177  return s;
178 }
179 
180 ////////////////////////////////////////////////////////////////////////////////
181 
183 {
184  NewObj[0] = m1[0]; NewObj[4] = m1[3]; NewObj[8] = m1[6];
185  NewObj[1] = m1[1]; NewObj[5] = m1[4]; NewObj[9] = m1[7];
186  NewObj[2] = m1[2]; NewObj[6] = m1[5]; NewObj[10] = m1[8];
187 }
188 
189 ////////////////////////////////////////////////////////////////////////////////
190 
191 inline void Matrix4dMulRotationScale(Double_t *NewObj, Double_t scale)
192 {
193  NewObj[0] *= scale; NewObj[4] *= scale; NewObj[8] *= scale;
194  NewObj[1] *= scale; NewObj[5] *= scale; NewObj[9] *= scale;
195  NewObj[2] *= scale; NewObj[6] *= scale; NewObj[10] *= scale;
196 }
197 
198 ////////////////////////////////////////////////////////////////////////////////
199 
201 {
202  Double_t scale = Matrix4fSVD(NewObj, 0, 0);
204  Matrix4dMulRotationScale(NewObj, scale);
205 }
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 ///map to sphere
209 
210 inline void TArcBall::MapToSphere(const TPoint &NewPt, Double_t *NewVec) const
211 {
212  Double_t tempPt[] = { static_cast<Double_t>(NewPt.fX), static_cast<Double_t>(NewPt.fY)};
213  //Adjust point coords and scale down to range of [-1 ... 1]
214  tempPt[0] = tempPt[0] * fAdjustWidth - 1.;
215  tempPt[1] = 1. - tempPt[1] * fAdjustHeight;
216  //Compute the square of the length of the vector to the point from the center
217  Double_t length = tempPt[0] * tempPt[0] + tempPt[1] * tempPt[1];
218  //If the point is mapped outside of the sphere... (length > radius squared)
219  if (length > 1.) {
220  Double_t norm = 1.0f / TMath::Sqrt(length);
221  //Return the "normalized" vector, a point on the sphere
222  NewVec[0] = tempPt[0] * norm;
223  NewVec[1] = tempPt[1] * norm;
224  NewVec[2] = 0.;
225  } else { //Else it's on the inside
226  //Return a vector to a point mapped inside the sphere sqrt(radius squared - length)
227  NewVec[0] = tempPt[0];
228  NewVec[1] = tempPt[1];
229  NewVec[2] = TMath::Sqrt(1. - length);
230  }
231 }
232 
233 ////////////////////////////////////////////////////////////////////////////////
234 /// constructor
235 
237  :fThisRot(), fLastRot(),
238  fTransform(), fStVec(),
239  fEnVec(), fAdjustWidth(0.),
240  fAdjustHeight(0.)
241 {
242  SetBounds(Width, Height);
243  ResetMatrices();
244 }
245 
246 ////////////////////////////////////////////////////////////////////////////////
247 ///Mouse down
248 
249 void TArcBall::Click(const TPoint &NewPt)
250 {
251  MapToSphere(NewPt, fStVec);
252 
253  for (Int_t i = 0; i < 9; ++i)
254  fLastRot[i] = fThisRot[i];
255 }
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 ///Mouse drag, calculate rotation
259 
260 void TArcBall::Drag(const TPoint &NewPt)
261 {
262  MapToSphere(NewPt, fEnVec);
263  //Return the quaternion equivalent to the rotation
264  Double_t newRot[4] = {0.};
265  Double_t perp[3] = {0.};
266 
267  Vector3dCross(perp, fStVec, fEnVec);
268  //Compute the length of the perpendicular vector
269  if (Vector3dLength(perp) > Epsilon) {
270  //We're ok, so return the perpendicular vector as the transform after all
271  newRot[0] = perp[0];
272  newRot[1] = perp[1];
273  newRot[2] = perp[2];
274  //In the quaternion values, w is cosine (theta / 2), where theta is rotation angle
275  newRot[3]= Vector3dDot(fStVec, fEnVec);
276  } else //if it's zero
277  newRot[0] = newRot[1] = newRot[2] = newRot[3] = 0.;
278 
282 }
283 
284 ////////////////////////////////////////////////////////////////////////////////
285 ///Set rotation matrix as union
286 
288 {
289  fTransform[0] = 1.f, fTransform[1] = fTransform[2] = fTransform[3] =
290  fTransform[4] = 0.f, fTransform[5] = 1.f, fTransform[6] = fTransform[7] =
291  fTransform[8] = fTransform[9] = 0.f, fTransform[10] = 1.f, fTransform[11] =
292  fTransform[12] = fTransform[13] = fTransform[14] = 0.f, fTransform[15] = 1.f;
295 }
296 
void Matrix4dSetRotationFromMatrix3d(Double_t *NewObj, const Double_t *m1)
Definition: TArcBall.cxx:200
Double_t fTransform[16]
Definition: TArcBall.h:23
void Click(const TPoint &NewPt)
Mouse down.
Definition: TArcBall.cxx:249
Double_t fEnVec[3]
Definition: TArcBall.h:25
SCoord_t fX
Definition: TPoint.h:35
SCoord_t fY
Definition: TPoint.h:36
int Int_t
Definition: RtypesCore.h:41
void Matrix4dSetRotationScaleFromMatrix3d(Double_t *NewObj, const Double_t *m1)
Definition: TArcBall.cxx:182
Double_t fLastRot[9]
Definition: TArcBall.h:22
Double_t fStVec[3]
Definition: TArcBall.h:24
Double_t fThisRot[9]
Definition: TArcBall.h:21
void Drag(const TPoint &NewPt)
Mouse drag, calculate rotation.
Definition: TArcBall.cxx:260
void Matrix4dSetRotationScaleFromMatrix4d(Double_t *NewObj, const Double_t *m1)
Definition: TArcBall.cxx:118
Definition: TPoint.h:31
void Matrix4dMulRotationScale(Double_t *NewObj, Double_t scale)
Definition: TArcBall.cxx:191
XPoint xy[kMAXMK]
Definition: TGX11.cxx:122
unsigned int UInt_t
Definition: RtypesCore.h:42
void Vector3dCross(Double_t *NewObj, const Double_t *v1, const Double_t *v2)
Definition: TArcBall.cxx:33
Double_t Matrix4fSVD(const Double_t *NewObj, Double_t *rot3, Double_t *rot4)
Definition: TArcBall.cxx:127
#define ClassImp(name)
Definition: Rtypes.h:359
double Double_t
Definition: RtypesCore.h:55
TArcBall(const TArcBall &)
void ResetMatrices()
Set rotation matrix as union.
Definition: TArcBall.cxx:287
static constexpr double s
Double_t fAdjustWidth
Definition: TArcBall.h:26
Double_t Vector3dDot(const Double_t *NewObj, const Double_t *v1)
Definition: TArcBall.cxx:42
Implements the arc-ball rotation manipulator.
Definition: TArcBall.h:19
Double_t Vector3dLength(const Double_t *NewObj)
Definition: TArcBall.cxx:56
void Matrix3dSetZero(Double_t *NewObj)
Definition: TArcBall.cxx:63
const Double_t Epsilon
Definition: TArcBall.cxx:16
void Matrix3dSetIdentity(Double_t *NewObj)
Definition: TArcBall.cxx:71
Double_t fAdjustHeight
Definition: TArcBall.h:27
void SetBounds(UInt_t NewWidth, UInt_t NewHeight)
Definition: TArcBall.h:38
void Matrix3dMulMatrix3d(Double_t *NewObj, const Double_t *m1)
Definition: TArcBall.cxx:96
Double_t Vector3dLengthSquared(const Double_t *NewObj)
Definition: TArcBall.cxx:49
Double_t Sqrt(Double_t x)
Definition: TMath.h:590
const Int_t n
Definition: legend1.C:16
void Matrix3dSetRotationFromQuat4d(Double_t *NewObj, const Double_t *q1)
Definition: TArcBall.cxx:80
void MapToSphere(const TPoint &NewPt, Double_t *NewVec) const
map to sphere
Definition: TArcBall.cxx:210