Logo ROOT  
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
16const Double_t Epsilon = 1.0e-5;
17
18/** \class TArcBall
19\ingroup opengl
20Implements the arc-ball rotation manipulator. Used by plot-painters.
21
22Arcball sphere constants:
23 - Diameter is 2.0f
24 - Radius is 1.0f
25*/
26
28
29
30
31////////////////////////////////////////////////////////////////////////////////
32
33inline 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
42inline 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
56inline Double_t Vector3dLength(const Double_t *NewObj)
57{
58 return TMath::Sqrt(Vector3dLengthSquared(NewObj));
59}
60
61////////////////////////////////////////////////////////////////////////////////
62
63inline void Matrix3dSetZero(Double_t * NewObj)
64{
65 for (Int_t i = 0; i < 9; ++i)
66 NewObj[i] = 0.;
67}
68
69////////////////////////////////////////////////////////////////////////////////
70
71inline 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
96void 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
127inline 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
191inline 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
210inline 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);
244}
245
246////////////////////////////////////////////////////////////////////////////////
247///Mouse down
248
249void 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
260void 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
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
int Int_t
Definition: RtypesCore.h:43
double Double_t
Definition: RtypesCore.h:57
#define ClassImp(name)
Definition: Rtypes.h:361
Double_t Matrix4fSVD(const Double_t *NewObj, Double_t *rot3, Double_t *rot4)
Definition: TArcBall.cxx:127
void Matrix3dSetIdentity(Double_t *NewObj)
Definition: TArcBall.cxx:71
void Matrix4dSetRotationScaleFromMatrix4d(Double_t *NewObj, const Double_t *m1)
Definition: TArcBall.cxx:118
void Matrix4dMulRotationScale(Double_t *NewObj, Double_t scale)
Definition: TArcBall.cxx:191
Double_t Vector3dDot(const Double_t *NewObj, const Double_t *v1)
Definition: TArcBall.cxx:42
void Matrix3dSetZero(Double_t *NewObj)
Definition: TArcBall.cxx:63
void Matrix3dMulMatrix3d(Double_t *NewObj, const Double_t *m1)
Definition: TArcBall.cxx:96
void Matrix4dSetRotationFromMatrix3d(Double_t *NewObj, const Double_t *m1)
Definition: TArcBall.cxx:200
void Matrix4dSetRotationScaleFromMatrix3d(Double_t *NewObj, const Double_t *m1)
Definition: TArcBall.cxx:182
void Matrix3dSetRotationFromQuat4d(Double_t *NewObj, const Double_t *q1)
Definition: TArcBall.cxx:80
Double_t Vector3dLengthSquared(const Double_t *NewObj)
Definition: TArcBall.cxx:49
const Double_t Epsilon
Definition: TArcBall.cxx:16
void Vector3dCross(Double_t *NewObj, const Double_t *v1, const Double_t *v2)
Definition: TArcBall.cxx:33
Double_t Vector3dLength(const Double_t *NewObj)
Definition: TArcBall.cxx:56
XPoint xy[kMAXMK]
Definition: TGX11.cxx:122
Implements the arc-ball rotation manipulator.
Definition: TArcBall.h:19
Double_t fStVec[3]
Definition: TArcBall.h:24
Double_t fTransform[16]
Definition: TArcBall.h:23
void ResetMatrices()
Set rotation matrix as union.
Definition: TArcBall.cxx:287
void MapToSphere(const TPoint &NewPt, Double_t *NewVec) const
map to sphere
Definition: TArcBall.cxx:210
void Drag(const TPoint &NewPt)
Mouse drag, calculate rotation.
Definition: TArcBall.cxx:260
Double_t fEnVec[3]
Definition: TArcBall.h:25
Double_t fThisRot[9]
Definition: TArcBall.h:21
Double_t fLastRot[9]
Definition: TArcBall.h:22
Double_t fAdjustWidth
Definition: TArcBall.h:26
void SetBounds(UInt_t NewWidth, UInt_t NewHeight)
Definition: TArcBall.h:38
void Click(const TPoint &NewPt)
Mouse down.
Definition: TArcBall.cxx:249
Double_t fAdjustHeight
Definition: TArcBall.h:27
TArcBall(const TArcBall &)
Definition: TPoint.h:31
SCoord_t fY
Definition: TPoint.h:36
SCoord_t fX
Definition: TPoint.h:35
const Int_t n
Definition: legend1.C:16
static constexpr double s
Double_t Sqrt(Double_t x)
Definition: TMath.h:681