16 const Double_t Epsilon = 1.0e-5;
 
   33 inline void Vector3dCross(Double_t *NewObj, 
const Double_t * v1, 
const Double_t *v2)
 
   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];
 
   42 inline Double_t Vector3dDot(
const Double_t *NewObj, 
const Double_t *v1)
 
   44    return  NewObj[0] * v1[0] + NewObj[1] * v1[1] + NewObj[2] * v1[2];
 
   49 inline Double_t Vector3dLengthSquared(
const Double_t *NewObj)
 
   51    return  NewObj[0] * NewObj[0] + NewObj[1] * NewObj[1] + NewObj[2] * NewObj[2];
 
   56 inline Double_t Vector3dLength(
const Double_t *NewObj)
 
   58    return TMath::Sqrt(Vector3dLengthSquared(NewObj));
 
   63 inline void Matrix3dSetZero(Double_t * NewObj)
 
   65    for (Int_t i = 0; i < 9; ++i)
 
   71 inline void Matrix3dSetIdentity(Double_t *NewObj)
 
   73    Matrix3dSetZero(NewObj);
 
   75    NewObj[0] = NewObj[4] = NewObj[8] = 1.;
 
   80 void Matrix3dSetRotationFromQuat4d(Double_t *NewObj, 
const Double_t *q1)
 
   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;
 
   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);
 
   96 void Matrix3dMulMatrix3d(Double_t *NewObj, 
const Double_t *m1)
 
  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]);
 
  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]);
 
  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]);
 
  112    for (Int_t i = 0; i < 9; ++i)
 
  113       NewObj[i] = result[i];
 
  118 inline void Matrix4dSetRotationScaleFromMatrix4d(Double_t *NewObj, 
const Double_t *m1)
 
  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];
 
  127 inline Double_t Matrix4fSVD(
const Double_t *NewObj, Double_t *rot3, Double_t *rot4)
 
  129    Double_t s = TMath::Sqrt(
 
  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 );
 
  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];
 
  139       Double_t n = 1. / TMath::Sqrt(NewObj[0] * NewObj[0] + NewObj[1] * NewObj[1] + NewObj[2] * NewObj[2] + 0.0001);
 
  145       n = 1. / TMath::Sqrt(NewObj[4] * NewObj[4] + NewObj[5] * NewObj[5] + NewObj[6] * NewObj[6] + 0.0001);
 
  150       n = 1.0f / TMath::Sqrt(NewObj[8] * NewObj[8] + NewObj[9] * NewObj[9] + NewObj[10] * NewObj[10] + 0.0001);
 
  158          Matrix4dSetRotationScaleFromMatrix4d(rot4, NewObj);
 
  160       Double_t n = 1. / TMath::Sqrt(NewObj[0] * NewObj[0] + NewObj[1] * NewObj[1] + NewObj[2] * NewObj[2] + 0.0001);
 
  166       n = 1. / TMath::Sqrt(NewObj[4] * NewObj[4] + NewObj[5] * NewObj[5] + NewObj[6] * NewObj[6] + 0.0001);
 
  171       n = 1. / TMath::Sqrt(NewObj[8] * NewObj[8] + NewObj[9] * NewObj[9] + NewObj[10] * NewObj[10] + 0.0001);
 
  182 inline void Matrix4dSetRotationScaleFromMatrix3d(Double_t *NewObj, 
const Double_t *m1)
 
  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];
 
  191 inline void Matrix4dMulRotationScale(Double_t *NewObj, Double_t scale)
 
  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;
 
  200 void Matrix4dSetRotationFromMatrix3d(Double_t *NewObj, 
const Double_t *m1)
 
  202    Double_t scale = Matrix4fSVD(NewObj, 0, 0);
 
  203    Matrix4dSetRotationScaleFromMatrix3d(NewObj, m1);
 
  204    Matrix4dMulRotationScale(NewObj, scale);
 
  210 inline void TArcBall::MapToSphere(
const TPoint &NewPt, Double_t *NewVec)
 const 
  212    Double_t tempPt[] = { 
static_cast<Double_t
>(NewPt.fX), static_cast<Double_t>(NewPt.fY)};
 
  214    tempPt[0]  = tempPt[0] * fAdjustWidth  - 1.;
 
  215    tempPt[1]  = 1. - tempPt[1] * fAdjustHeight;
 
  217    Double_t length = tempPt[0] * tempPt[0] + tempPt[1] * tempPt[1];
 
  220       Double_t norm = 1.0f / TMath::Sqrt(length);
 
  222       NewVec[0] = tempPt[0] * norm;
 
  223       NewVec[1] = tempPt[1] * norm;
 
  227       NewVec[0] = tempPt[0];
 
  228       NewVec[1] = tempPt[1];
 
  229       NewVec[2] = TMath::Sqrt(1. - length);
 
  236 TArcBall::TArcBall(UInt_t Width, UInt_t Height)
 
  237          :fThisRot(), fLastRot(),
 
  238          fTransform(), fStVec(),
 
  239          fEnVec(), fAdjustWidth(0.),
 
  242    SetBounds(Width, Height);
 
  249 void TArcBall::Click(
const TPoint &NewPt)
 
  251    MapToSphere(NewPt, fStVec);
 
  253    for (Int_t i = 0; i < 9; ++i)
 
  254       fLastRot[i] = fThisRot[i];
 
  260 void TArcBall::Drag(
const TPoint &NewPt)
 
  262    MapToSphere(NewPt, fEnVec);
 
  264    Double_t newRot[4] = {0.};
 
  265    Double_t perp[3] = {0.};
 
  267    Vector3dCross(perp, fStVec, fEnVec);
 
  269    if (Vector3dLength(perp) > Epsilon) {
 
  275       newRot[3]= Vector3dDot(fStVec, fEnVec);
 
  277       newRot[0] = newRot[1] = newRot[2] = newRot[3] = 0.;
 
  279    Matrix3dSetRotationFromQuat4d(fThisRot, newRot);
 
  280    Matrix3dMulMatrix3d(fThisRot, fLastRot);
 
  281    Matrix4dSetRotationFromMatrix3d(fTransform, fThisRot);
 
  287 void TArcBall::ResetMatrices()
 
  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;
 
  293    Matrix3dSetIdentity(fLastRot);
 
  294    Matrix3dSetIdentity(fThisRot);