26 TGLVector3 gLowNormalDefault(0., 0., -1.);
 
   27 TGLVector3 gHighNormalDefault(0., 0., 1.);
 
   35    Double_t fRmin1, fRmax1, fRmin2, fRmax2;
 
   42    void GetNormal(
const TGLVertex3 &vertex, TGLVector3 &normal)
const;
 
   43    Double_t GetZcoord(Double_t x, Double_t y, Double_t z)
const;
 
   44    const TGLVertex3 &MakeVertex(Double_t x, Double_t y, Double_t z)
const;
 
   47    TGLMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t r3, Double_t r4, Double_t dz,
 
   48            const TGLVector3 &l = gLowNormalDefault, 
const TGLVector3 &h = gHighNormalDefault);
 
   49    virtual ~TGLMesh() { }
 
   50    virtual void Draw() 
const = 0;
 
   55 class TubeSegMesh : 
public TGLMesh {
 
   58    TGLVertex3 fMesh[(TGLRnrCtx::kLODHigh + 1) * 8 + 8];
 
   59    TGLVector3 fNorm[(TGLRnrCtx::kLODHigh + 1) * 8 + 8];
 
   62    TubeSegMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t r3, Double_t r4, Double_t dz,
 
   63                Double_t phi1, Double_t phi2, 
const TGLVector3 &l = gLowNormalDefault,
 
   64                const TGLVector3 &h = gHighNormalDefault);
 
   71 class TubeMesh : 
public TGLMesh
 
   75    TGLVertex3 fMesh[(TGLRnrCtx::kLODHigh + 1) * 8];
 
   76    TGLVector3 fNorm[(TGLRnrCtx::kLODHigh + 1) * 8];
 
   79    TubeMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t r3, Double_t r4, Double_t dz,
 
   80             const TGLVector3 &l = gLowNormalDefault, 
const TGLVector3 &h = gHighNormalDefault);
 
   86 class TCylinderMesh : 
public TGLMesh {
 
   89    TGLVertex3 fMesh[(TGLRnrCtx::kLODHigh + 1) * 4 + 2];
 
   90    TGLVector3 fNorm[(TGLRnrCtx::kLODHigh + 1) * 4 + 2];
 
   93    TCylinderMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t dz,
 
   94                  const TGLVector3 &l = gLowNormalDefault, 
const TGLVector3 &h = gHighNormalDefault);
 
  100 class TCylinderSegMesh : 
public TGLMesh
 
  104    TGLVertex3 fMesh[(TGLRnrCtx::kLODHigh + 1) * 4 + 10];
 
  105    TGLVector3 fNorm[(TGLRnrCtx::kLODHigh + 1) * 4 + 10];
 
  108    TCylinderSegMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t dz, Double_t phi1, Double_t phi2,
 
  109                     const TGLVector3 &l = gLowNormalDefault, 
const TGLVector3 &h = gHighNormalDefault);
 
  113 TGLMesh::TGLMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t r3, Double_t r4, Double_t dz,
 
  114                  const TGLVector3 &l, 
const TGLVector3 &h) :
 
  116    fRmin1(r1), fRmax1(r2), fRmin2(r3), fRmax2(r4),
 
  117    fDz(dz), fNlow(l), fNhigh(h)
 
  125 void TGLMesh::GetNormal(
const TGLVertex3 &v, TGLVector3 &n)
const 
  132    Double_t z = (fRmax1 - fRmax2) / (2 * fDz);
 
  133    Double_t mag = TMath::Sqrt(v[0] * v[0] + v[1] * v[1] + z * z);
 
  148 Double_t TGLMesh::GetZcoord(Double_t x, Double_t y, Double_t z)
const 
  151    if (z < 0) newz = -fDz - (x * fNlow[0] + y * fNlow[1]) / fNlow[2];
 
  152    else newz = fDz - (x * fNhigh[0] + y * fNhigh[1]) / fNhigh[2];
 
  160 const TGLVertex3 &TGLMesh::MakeVertex(Double_t x, Double_t y, Double_t z)
const 
  162    static TGLVertex3 vert(0., 0., 0.);
 
  165    vert[2] = GetZcoord(x, y, z);
 
  172 TubeSegMesh::TubeSegMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t r3, Double_t r4, Double_t dz,
 
  173                          Double_t phi1, Double_t phi2,
 
  174                          const TGLVector3 &l, 
const TGLVector3 &h)
 
  175                  :TGLMesh(LOD, r1, r2, r3, r4, dz, l, h), fMesh(), fNorm()
 
  179    const Double_t delta = (phi2 - phi1) / LOD;
 
  180    Double_t currAngle = phi1;
 
  183    Double_t c = TMath::Cos(currAngle);
 
  184    Double_t s = TMath::Sin(currAngle);
 
  185    const Int_t topShift = (fLOD + 1) * 4 + 8;
 
  186    const Int_t botShift = (fLOD + 1) * 6 + 8;
 
  187    Int_t j = 4 * (fLOD + 1) + 2;
 
  190    for (Int_t i = 0, e = (fLOD + 1) * 2; i < e; ++i) {
 
  192          fMesh[i] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
 
  193          fMesh[j] = MakeVertex(fRmin2 * c, fRmin2 * s, fDz);
 
  194          fMesh[i + topShift] = MakeVertex(fRmin2 * c, fRmin2 * s, fDz);
 
  195          fMesh[i + botShift] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
 
  196          GetNormal(fMesh[j], fNorm[j]);
 
  200          fMesh[i] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
 
  201          fMesh[j + 1] = MakeVertex(fRmin1 * c, fRmin1 * s, -fDz);
 
  202          fMesh[i + topShift] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
 
  203          fMesh[i + botShift] = MakeVertex(fRmin1 * c, fRmin1 * s, - fDz);
 
  204          GetNormal(fMesh[j + 1], fNorm[j + 1]);
 
  205          fNorm[j + 1].Negate();
 
  208          c = TMath::Cos(currAngle);
 
  209          s = TMath::Sin(currAngle);
 
  213       GetNormal(fMesh[i], fNorm[i]);
 
  214       fNorm[i + topShift] = fNhigh;
 
  215       fNorm[i + botShift] = fNlow;
 
  219    Int_t ind = 2 * (fLOD + 1);
 
  220    TGLVector3 norm(0., 0., 0.);
 
  222    fMesh[ind] = fMesh[ind - 2];
 
  223    fMesh[ind + 1] = fMesh[ind - 1];
 
  224    fMesh[ind + 2] = fMesh[ind + 4];
 
  225    fMesh[ind + 3] = fMesh[ind + 5];
 
  226    TMath::Normal2Plane(fMesh[ind].CArr(), fMesh[ind + 1].CArr(), fMesh[ind + 2].CArr(),
 
  229    fNorm[ind + 1] = norm;
 
  230    fNorm[ind + 2] = norm;
 
  231    fNorm[ind + 3] = norm;
 
  234    fMesh[ind] = fMesh[ind - 2];
 
  235    fMesh[ind + 1] = fMesh[ind - 1];
 
  236    fMesh[ind + 2] = fMesh[0];
 
  237    fMesh[ind + 3] = fMesh[1];
 
  238    TMath::Normal2Plane(fMesh[ind].CArr(), fMesh[ind + 1].CArr(), fMesh[ind + 2].CArr(),
 
  241    fNorm[ind + 1] = norm;
 
  242    fNorm[ind + 2] = norm;
 
  243    fNorm[ind + 3] = norm;
 
  250 void TubeSegMesh::Draw()
 const 
  252    glEnableClientState(GL_VERTEX_ARRAY);
 
  253    glEnableClientState(GL_NORMAL_ARRAY);
 
  255    glVertexPointer(3, GL_DOUBLE, 
sizeof(TGLVertex3), fMesh[0].CArr());
 
  256    glNormalPointer(GL_DOUBLE, 
sizeof(TGLVector3), fNorm[0].CArr());
 
  258    glDrawArrays(GL_QUAD_STRIP, 0, 4 * (fLOD + 1) + 8);
 
  260    glDrawArrays(GL_QUAD_STRIP, 4 * (fLOD + 1) + 8, 2 * (fLOD + 1));
 
  261    glDrawArrays(GL_QUAD_STRIP, 6 * (fLOD + 1) + 8, 2 * (fLOD + 1));
 
  263    glDisableClientState(GL_VERTEX_ARRAY);
 
  264    glDisableClientState(GL_NORMAL_ARRAY);
 
  270 TubeMesh::TubeMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t r3, Double_t r4, Double_t z,
 
  271                    const TGLVector3 &l, 
const TGLVector3 &h)
 
  272              :TGLMesh(LOD, r1, r2, r3, r4, z, l, h), fMesh(), fNorm()
 
  274    const Double_t delta = TMath::TwoPi() / fLOD;
 
  275    Double_t currAngle = 0.;
 
  278    Double_t c = TMath::Cos(currAngle);
 
  279    Double_t s = TMath::Sin(currAngle);
 
  281    const Int_t topShift = (fLOD + 1) * 4;
 
  282    const Int_t botShift = (fLOD + 1) * 6;
 
  283    Int_t j = 4 * (fLOD + 1) - 2;
 
  286    for (Int_t i = 0, e = (fLOD + 1) * 2; i < e; ++i) {
 
  288          fMesh[i] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
 
  289          fMesh[j] = MakeVertex(fRmin2 * c, fRmin2 * s, fDz);
 
  290          fMesh[i + topShift] = MakeVertex(fRmin2 * c, fRmin2 * s, fDz);
 
  291          fMesh[i + botShift] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
 
  292          GetNormal(fMesh[j], fNorm[j]);
 
  296          fMesh[i] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
 
  297          fMesh[j + 1] = MakeVertex(fRmin1 * c, fRmin1 * s, -fDz);
 
  298          fMesh[i + topShift] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
 
  299          fMesh[i + botShift] = MakeVertex(fRmin1 * c, fRmin1 * s, - fDz);
 
  300          GetNormal(fMesh[j + 1], fNorm[j + 1]);
 
  301          fNorm[j + 1].Negate();
 
  304          c = TMath::Cos(currAngle);
 
  305          s = TMath::Sin(currAngle);
 
  309       GetNormal(fMesh[i], fNorm[i]);
 
  310       fNorm[i + topShift] = fNhigh;
 
  311       fNorm[i + botShift] = fNlow;
 
  318 void TubeMesh::Draw()
 const 
  320    glEnableClientState(GL_VERTEX_ARRAY);
 
  321    glEnableClientState(GL_NORMAL_ARRAY);
 
  323    glVertexPointer(3, GL_DOUBLE, 
sizeof(TGLVertex3), fMesh[0].CArr());
 
  324    glNormalPointer(GL_DOUBLE, 
sizeof(TGLVector3), fNorm[0].CArr());
 
  326    glDrawArrays(GL_QUAD_STRIP, 0, 2 * (fLOD + 1));
 
  327    glDrawArrays(GL_QUAD_STRIP, 2 * (fLOD + 1), 2 * (fLOD + 1));
 
  329    glDrawArrays(GL_QUAD_STRIP, 4 * (fLOD + 1), 2 * (fLOD + 1));
 
  330    glDrawArrays(GL_QUAD_STRIP, 6 * (fLOD + 1), 2 * (fLOD + 1));
 
  332    glDisableClientState(GL_VERTEX_ARRAY);
 
  333    glDisableClientState(GL_NORMAL_ARRAY);
 
  339 TCylinderMesh::TCylinderMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t dz,
 
  340                              const TGLVector3 &l, 
const TGLVector3 &h)
 
  341                  :TGLMesh(LOD, 0., r1, 0., r2, dz, l, h), fMesh(), fNorm()
 
  343    const Double_t delta = TMath::TwoPi() / fLOD;
 
  344    Double_t currAngle = 0.;
 
  347    Double_t c = TMath::Cos(currAngle);
 
  348    Double_t s = TMath::Sin(currAngle);
 
  351    Int_t topShift = (fLOD + 1) * 2;
 
  352    fMesh[topShift][0] = fMesh[topShift][1] = 0., fMesh[topShift][2] = fDz;
 
  353    fNorm[topShift] = fNhigh;
 
  357    Int_t botShift = topShift + 2 * (fLOD + 1);
 
  358    fMesh[botShift][0] = fMesh[botShift][1] = 0., fMesh[botShift][2] = -fDz;
 
  359    fNorm[botShift] = fNlow;
 
  363    for (Int_t i = 0, e = (fLOD + 1) * 2, j = 0; i < e; ++i) {
 
  365          fMesh[i] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
 
  366          fMesh[j + topShift] = MakeVertex(fRmin2 * c, fRmin2 * s, fDz);
 
  367          fMesh[j + botShift] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
 
  370          fMesh[i] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
 
  373          c = TMath::Cos(currAngle);
 
  374          s = TMath::Sin(currAngle);
 
  378       GetNormal(fMesh[i], fNorm[i]);
 
  379       fNorm[i + topShift] = fNhigh;
 
  380       fNorm[i + botShift] = fNlow;
 
  387 void TCylinderMesh::Draw()
 const 
  389    glEnableClientState(GL_VERTEX_ARRAY);
 
  390    glEnableClientState(GL_NORMAL_ARRAY);
 
  392    glVertexPointer(3, GL_DOUBLE, 
sizeof(TGLVertex3), fMesh[0].CArr());
 
  393    glNormalPointer(GL_DOUBLE, 
sizeof(TGLVector3), fNorm[0].CArr());
 
  396    glDrawArrays(GL_QUAD_STRIP, 0, 2 * (fLOD + 1));
 
  398    glDrawArrays(GL_TRIANGLE_FAN, 2 * (fLOD + 1), fLOD + 2);
 
  399    glDrawArrays(GL_TRIANGLE_FAN, 3 * (fLOD + 1) + 1, fLOD + 2);
 
  401    glDisableClientState(GL_VERTEX_ARRAY);
 
  402    glDisableClientState(GL_NORMAL_ARRAY);
 
  408 TCylinderSegMesh::TCylinderSegMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t dz, Double_t phi1,
 
  409                                     Double_t phi2, 
const TGLVector3 &l,
 
  411                      :TGLMesh(LOD, 0., r1, 0., r2, dz, l, h), fMesh(), fNorm()
 
  413    Double_t delta = (phi2 - phi1) / fLOD;
 
  414    Double_t currAngle = phi1;
 
  417    Double_t c = TMath::Cos(currAngle);
 
  418    Double_t s = TMath::Sin(currAngle);
 
  420    const TGLVertex3 vTop(0., 0., fDz);
 
  421    const TGLVertex3 vBot(0., 0., - fDz);
 
  424    Int_t topShift = (fLOD + 1) * 2 + 8;
 
  425    fMesh[topShift] = vTop;
 
  426    fNorm[topShift] = fNhigh;
 
  430    Int_t botShift = topShift + fLOD + 1;
 
  431    fMesh[botShift] = vBot;
 
  432    fNorm[botShift] = fNlow;
 
  438    for (Int_t e = (fLOD + 1) * 2, j = 0; i < e; ++i) {
 
  440          fMesh[i] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
 
  441          fMesh[j + topShift] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
 
  442          fMesh[j + botShift] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
 
  444          fNorm[j + topShift] = fNhigh;
 
  445          fNorm[j + botShift] = fNlow;
 
  447          fMesh[i] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
 
  450          c = TMath::Cos(currAngle);
 
  451          s = TMath::Sin(currAngle);
 
  455       GetNormal(fMesh[i], fNorm[i]);
 
  459    Int_t ind = 2 * (fLOD + 1);
 
  460    TGLVector3 norm(0., 0., 0.);
 
  462    fMesh[ind] = fMesh[ind - 2];
 
  463    fMesh[ind + 1] = fMesh[ind - 1];
 
  464    fMesh[ind + 2] = vTop;
 
  465    fMesh[ind + 3] = vBot;
 
  466    TMath::Normal2Plane(fMesh[ind].CArr(), fMesh[ind + 1].CArr(), fMesh[ind + 2].CArr(),
 
  469    fNorm[ind + 1] = norm;
 
  470    fNorm[ind + 2] = norm;
 
  471    fNorm[ind + 3] = norm;
 
  475    fMesh[ind + 1] = vBot;
 
  476    fMesh[ind + 2] = fMesh[0];
 
  477    fMesh[ind + 3] = fMesh[1];
 
  478    TMath::Normal2Plane(fMesh[ind].CArr(), fMesh[ind + 1].CArr(), fMesh[ind + 2].CArr(),
 
  481    fNorm[ind + 1] = norm;
 
  482    fNorm[ind + 2] = norm;
 
  483    fNorm[ind + 3] = norm;
 
  491 void TCylinderSegMesh::Draw()
 const 
  493    glEnableClientState(GL_VERTEX_ARRAY);
 
  494    glEnableClientState(GL_NORMAL_ARRAY);
 
  496    glVertexPointer(3, GL_DOUBLE, 
sizeof(TGLVertex3), fMesh[0].CArr());
 
  497    glNormalPointer(GL_DOUBLE, 
sizeof(TGLVector3), fNorm[0].CArr());
 
  499    glDrawArrays(GL_QUAD_STRIP, 0, 2 * (fLOD + 1) + 8);
 
  501    glDrawArrays(GL_TRIANGLE_FAN, 2 * (fLOD + 1) + 8, fLOD + 2);
 
  504    glDisableClientState(GL_VERTEX_ARRAY);
 
  505    glDisableClientState(GL_NORMAL_ARRAY);
 
  515 ClassImp(TGLCylinder);
 
  521 TGLCylinder::TGLCylinder(
const TBuffer3DTube &buffer) :
 
  522    TGLLogicalShape(buffer)
 
  526    fR1 = buffer.fRadiusInner;
 
  527    fR2 = buffer.fRadiusOuter;
 
  528    fR3 = buffer.fRadiusInner;
 
  529    fR4 = buffer.fRadiusOuter;
 
  530    fDz = buffer.fHalfLength;
 
  532    fLowPlaneNorm = gLowNormalDefault;
 
  533    fHighPlaneNorm = gHighNormalDefault;
 
  535    switch (buffer.Type())
 
  538       case TBuffer3DTypes::kTube:
 
  546       case TBuffer3DTypes::kTubeSeg:
 
  547       case TBuffer3DTypes::kCutTube:
 
  551          const TBuffer3DTubeSeg * segBuffer = 
dynamic_cast<const TBuffer3DTubeSeg *
>(&buffer);
 
  553             Error(
"TGLCylinder::TGLCylinder", 
"cannot cast TBuffer3D");
 
  557          fPhi1 = segBuffer->fPhiMin;
 
  558          fPhi2 = segBuffer->fPhiMax;
 
  559          if (fPhi2 < fPhi1) fPhi2 += 360.;
 
  560          fPhi1 *= TMath::DegToRad();
 
  561          fPhi2 *= TMath::DegToRad();
 
  563          if (buffer.Type() == TBuffer3DTypes::kCutTube) {
 
  564             const TBuffer3DCutTube * cutBuffer = 
dynamic_cast<const TBuffer3DCutTube *
>(&buffer);
 
  566                Error(
"TGLCylinder::TGLCylinder", 
"cannot cast TBuffer3D");
 
  570             for (UInt_t i =0; i < 3; i++) {
 
  571                fLowPlaneNorm[i] = cutBuffer->fLowPlaneNorm[i];
 
  572                fHighPlaneNorm[i] = cutBuffer->fHighPlaneNorm[i];
 
  583 TGLCylinder::~TGLCylinder()
 
  591 UInt_t TGLCylinder::DLOffset(Short_t lod)
 const 
  594    if      (lod >= 100) off = 0;
 
  595    else if (lod <  10)  off = lod / 2;
 
  596    else                 off = lod / 10 + 4;
 
  603 Short_t TGLCylinder::QuantizeShapeLOD(Short_t shapeLOD, Short_t combiLOD)
 const 
  605    Int_t lod = ((Int_t)shapeLOD * (Int_t)combiLOD) / 100;
 
  613       Double_t quant = 0.1 * ((
static_cast<Double_t
>(lod)) + 0.5);
 
  614       lod            = 10  *   
static_cast<Int_t
>(quant);
 
  618       Double_t quant = 0.5 * ((
static_cast<Double_t
>(lod)) + 0.5);
 
  619       lod            = 2   *   
static_cast<Int_t
>(quant);
 
  621    return static_cast<Short_t
>(lod);
 
  627 void TGLCylinder::DirectDraw(TGLRnrCtx & rnrCtx)
 const 
  630       Info(
"TGLCylinder::DirectDraw", 
"this %ld (class %s) LOD %d",
 
  631            (Long_t)
this, IsA()->GetName(), rnrCtx.ShapeLOD());
 
  639    std::vector<TGLMesh *> meshParts;
 
  643       meshParts.push_back(
new TubeMesh   (rnrCtx.ShapeLOD(), fR1, fR2, fR3, fR4,
 
  644                                           fDz, fLowPlaneNorm, fHighPlaneNorm));
 
  646       meshParts.push_back(
new TubeSegMesh(rnrCtx.ShapeLOD(), fR1, fR2, fR3, fR4,
 
  648                                           fLowPlaneNorm, fHighPlaneNorm));
 
  652    for (UInt_t i = 0; i < meshParts.size(); ++i) meshParts[i]->Draw();
 
  655    for (UInt_t i = 0; i < meshParts.size(); ++i) {