TGLCylinder.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLCylinder.cxx 34245 2010-06-30 13:36:29Z brun $
00002 // Author:  Timur Pocheptsov  03/08/2004
00003 // NOTE: This code moved from obsoleted TGLSceneObject.h / .cxx - see these
00004 // attic files for previous CVS history
00005 
00006 /*************************************************************************
00007  * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
00008  * All rights reserved.                                                  *
00009  *                                                                       *
00010  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00011  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00012  *************************************************************************/
00013 
00014 #include "TGLCylinder.h"
00015 #include "TGLRnrCtx.h"
00016 #include "TGLIncludes.h"
00017 
00018 #include "TBuffer3D.h"
00019 #include "TBuffer3DTypes.h"
00020 #include "TMath.h"
00021 
00022 // For debug tracing
00023 #include "TClass.h"
00024 #include "TError.h"
00025 
00026 TGLVector3 gLowNormalDefault(0., 0., -1.);
00027 TGLVector3 gHighNormalDefault(0., 0., 1.);
00028 
00029 class TGLMesh
00030 {
00031 protected:
00032    // active LOD (level of detail) - quality
00033    UInt_t     fLOD;
00034 
00035    Double_t fRmin1, fRmax1, fRmin2, fRmax2;
00036    Double_t fDz;
00037 
00038    //normals for top and bottom (for cuts)
00039    TGLVector3 fNlow;
00040    TGLVector3 fNhigh;
00041 
00042    void GetNormal(const TGLVertex3 &vertex, TGLVector3 &normal)const;
00043    Double_t GetZcoord(Double_t x, Double_t y, Double_t z)const;
00044    const TGLVertex3 &MakeVertex(Double_t x, Double_t y, Double_t z)const;
00045 
00046 public:
00047    TGLMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t r3, Double_t r4, Double_t dz,
00048            const TGLVector3 &l = gLowNormalDefault, const TGLVector3 &h = gHighNormalDefault);
00049    virtual ~TGLMesh() { }
00050    virtual void Draw() const = 0;
00051 };
00052 
00053 //segment contains 3 quad strips:
00054 //one for inner and outer sides, two for top and bottom
00055 class TubeSegMesh : public TGLMesh {
00056 private:
00057    // Allocate space for highest quality (LOD) meshes
00058    TGLVertex3 fMesh[(TGLRnrCtx::kLODHigh + 1) * 8 + 8];
00059    TGLVector3 fNorm[(TGLRnrCtx::kLODHigh + 1) * 8 + 8];
00060 
00061 public:
00062    TubeSegMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t r3, Double_t r4, Double_t dz,
00063                Double_t phi1, Double_t phi2, const TGLVector3 &l = gLowNormalDefault,
00064                const TGLVector3 &h = gHighNormalDefault);
00065 
00066    void Draw() const;
00067 };
00068 
00069 //four quad strips:
00070 //outer, inner, top, bottom
00071 class TubeMesh : public TGLMesh
00072 {
00073 private:
00074    // Allocate space for highest quality (LOD) meshes
00075    TGLVertex3 fMesh[(TGLRnrCtx::kLODHigh + 1) * 8];
00076    TGLVector3 fNorm[(TGLRnrCtx::kLODHigh + 1) * 8];
00077 
00078 public:
00079    TubeMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t r3, Double_t r4, Double_t dz,
00080             const TGLVector3 &l = gLowNormalDefault, const TGLVector3 &h = gHighNormalDefault);
00081 
00082    void Draw() const;
00083 };
00084 
00085 //One quad mesh and 2 triangle funs
00086 class TCylinderMesh : public TGLMesh {
00087 private:
00088    // Allocate space for highest quality (LOD) meshes
00089    TGLVertex3 fMesh[(TGLRnrCtx::kLODHigh + 1) * 4 + 2];
00090    TGLVector3 fNorm[(TGLRnrCtx::kLODHigh + 1) * 4 + 2];
00091 
00092 public:
00093    TCylinderMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t dz,
00094                  const TGLVector3 &l = gLowNormalDefault, const TGLVector3 &h = gHighNormalDefault);
00095 
00096    void Draw() const;
00097 };
00098 
00099 //One quad mesh and 2 triangle fans
00100 class TCylinderSegMesh : public TGLMesh
00101 {
00102 private:
00103    // Allocate space for highest quality (LOD) meshes
00104    TGLVertex3 fMesh[(TGLRnrCtx::kLODHigh + 1) * 4 + 10];
00105    TGLVector3 fNorm[(TGLRnrCtx::kLODHigh + 1) * 4 + 10];
00106 
00107 public:
00108    TCylinderSegMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t dz, Double_t phi1, Double_t phi2,
00109                     const TGLVector3 &l = gLowNormalDefault, const TGLVector3 &h = gHighNormalDefault);
00110    void Draw() const;
00111 };
00112 
00113 TGLMesh::TGLMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t r3, Double_t r4, Double_t dz,
00114                  const TGLVector3 &l, const TGLVector3 &h) :
00115    fLOD(LOD),
00116    fRmin1(r1), fRmax1(r2), fRmin2(r3), fRmax2(r4),
00117    fDz(dz), fNlow(l), fNhigh(h)
00118 {
00119    // constructor
00120 }
00121 
00122 //______________________________________________________________________________
00123 void TGLMesh::GetNormal(const TGLVertex3 &v, TGLVector3 &n)const
00124 {
00125    // get normal
00126 
00127    if( fDz < 1.e-10 ) {
00128       n[0] = 0.;
00129       n[1] = 0.;
00130       n[2] = 1.;
00131    }
00132    Double_t z = (fRmax1 - fRmax2) / (2 * fDz);
00133    Double_t mag = TMath::Sqrt(v[0] * v[0] + v[1] * v[1] + z * z);
00134    if( mag > 1.e-10 ) {
00135       n[0] = v[0] / mag;
00136       n[1] = v[1] / mag;
00137       n[2] = z / mag;
00138    } else {
00139       n[0] = v[0];
00140       n[1] = v[1];
00141       n[2] = z;
00142    }
00143 }
00144 
00145 //______________________________________________________________________________
00146 Double_t TGLMesh::GetZcoord(Double_t x, Double_t y, Double_t z)const
00147 {
00148    // get Z coordinate
00149    Double_t newz = 0;
00150    if (z < 0) newz = -fDz - (x * fNlow[0] + y * fNlow[1]) / fNlow[2];
00151    else newz = fDz - (x * fNhigh[0] + y * fNhigh[1]) / fNhigh[2];
00152 
00153    return newz;
00154 }
00155 
00156 //______________________________________________________________________________
00157 const TGLVertex3 &TGLMesh::MakeVertex(Double_t x, Double_t y, Double_t z)const
00158 {
00159    // make vertex
00160    static TGLVertex3 vert(0., 0., 0.);
00161    vert[0] = x;
00162    vert[1] = y;
00163    vert[2] = GetZcoord(x, y, z);
00164 
00165    return vert;
00166 }
00167 
00168 //______________________________________________________________________________
00169 TubeSegMesh::TubeSegMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t r3, Double_t r4, Double_t dz,
00170                          Double_t phi1, Double_t phi2,
00171                          const TGLVector3 &l, const TGLVector3 &h)
00172                  :TGLMesh(LOD, r1, r2, r3, r4, dz, l, h), fMesh(), fNorm()
00173 
00174 {
00175    // constructor
00176    const Double_t delta = (phi2 - phi1) / LOD;
00177    Double_t currAngle = phi1;
00178 
00179    Bool_t even = kTRUE;
00180    Double_t c = TMath::Cos(currAngle);
00181    Double_t s = TMath::Sin(currAngle);
00182    const Int_t topShift = (fLOD + 1) * 4 + 8;
00183    const Int_t botShift = (fLOD + 1) * 6 + 8;
00184    Int_t j = 4 * (fLOD + 1) + 2;
00185 
00186    //defining all three strips here, first strip is non-closed here
00187    for (Int_t i = 0, e = (fLOD + 1) * 2; i < e; ++i) {
00188       if (even) {
00189          fMesh[i] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
00190          fMesh[j] = MakeVertex(fRmin2 * c, fRmin2 * s, fDz);
00191          fMesh[i + topShift] = MakeVertex(fRmin2 * c, fRmin2 * s, fDz);
00192          fMesh[i + botShift] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
00193          GetNormal(fMesh[j], fNorm[j]);
00194          fNorm[j].Negate();
00195          even = kFALSE;
00196       } else {
00197          fMesh[i] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
00198          fMesh[j + 1] = MakeVertex(fRmin1 * c, fRmin1 * s, -fDz);
00199          fMesh[i + topShift] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
00200          fMesh[i + botShift] = MakeVertex(fRmin1 * c, fRmin1 * s, - fDz);
00201          GetNormal(fMesh[j + 1], fNorm[j + 1]);
00202          fNorm[j + 1].Negate();
00203          even = kTRUE;
00204          currAngle += delta;
00205          c = TMath::Cos(currAngle);
00206          s = TMath::Sin(currAngle);
00207          j -= 2;
00208       }
00209 
00210       GetNormal(fMesh[i], fNorm[i]);
00211       fNorm[i + topShift] = fNhigh;
00212       fNorm[i + botShift] = fNlow;
00213    }
00214 
00215    //closing first strip
00216    Int_t ind = 2 * (fLOD + 1);
00217    TGLVector3 norm(0., 0., 0.);
00218 
00219    fMesh[ind] = fMesh[ind - 2];
00220    fMesh[ind + 1] = fMesh[ind - 1];
00221    fMesh[ind + 2] = fMesh[ind + 4];
00222    fMesh[ind + 3] = fMesh[ind + 5];
00223    TMath::Normal2Plane(fMesh[ind].CArr(), fMesh[ind + 1].CArr(), fMesh[ind + 2].CArr(),
00224                        norm.Arr());
00225    fNorm[ind] = norm;
00226    fNorm[ind + 1] = norm;
00227    fNorm[ind + 2] = norm;
00228    fNorm[ind + 3] = norm;
00229 
00230    ind = topShift - 4;
00231    fMesh[ind] = fMesh[ind - 2];
00232    fMesh[ind + 1] = fMesh[ind - 1];
00233    fMesh[ind + 2] = fMesh[0];
00234    fMesh[ind + 3] = fMesh[1];
00235    TMath::Normal2Plane(fMesh[ind].CArr(), fMesh[ind + 1].CArr(), fMesh[ind + 2].CArr(),
00236                        norm.Arr());
00237    fNorm[ind] = norm;
00238    fNorm[ind + 1] = norm;
00239    fNorm[ind + 2] = norm;
00240    fNorm[ind + 3] = norm;
00241 }
00242 
00243 //______________________________________________________________________________
00244 void TubeSegMesh::Draw() const
00245 {
00246    //Tube segment is drawn as three quad strips
00247    //1. enabling vertex arrays
00248    glEnableClientState(GL_VERTEX_ARRAY);
00249    glEnableClientState(GL_NORMAL_ARRAY);
00250    //2. setting arrays
00251    glVertexPointer(3, GL_DOUBLE, sizeof(TGLVertex3), fMesh[0].CArr());
00252    glNormalPointer(GL_DOUBLE, sizeof(TGLVector3), fNorm[0].CArr());
00253    //3. draw first strip
00254    glDrawArrays(GL_QUAD_STRIP, 0, 4 * (fLOD + 1) + 8);
00255    //4. draw top and bottom strips
00256    glDrawArrays(GL_QUAD_STRIP, 4 * (fLOD + 1) + 8, 2 * (fLOD + 1));
00257    glDrawArrays(GL_QUAD_STRIP, 6 * (fLOD + 1) + 8, 2 * (fLOD + 1));
00258 
00259    glDisableClientState(GL_VERTEX_ARRAY);
00260    glDisableClientState(GL_NORMAL_ARRAY);
00261 }
00262 
00263 //______________________________________________________________________________
00264 TubeMesh::TubeMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t r3, Double_t r4, Double_t z,
00265                    const TGLVector3 &l, const TGLVector3 &h)
00266              :TGLMesh(LOD, r1, r2, r3, r4, z, l, h), fMesh(), fNorm()
00267 {
00268    // constructor
00269    const Double_t delta = TMath::TwoPi() / fLOD;
00270    Double_t currAngle = 0.;
00271 
00272    Bool_t even = kTRUE;
00273    Double_t c = TMath::Cos(currAngle);
00274    Double_t s = TMath::Sin(currAngle);
00275 
00276    const Int_t topShift = (fLOD + 1) * 4;
00277    const Int_t botShift = (fLOD + 1) * 6;
00278    Int_t j = 4 * (fLOD + 1) - 2;
00279 
00280    //defining all four strips here
00281    for (Int_t i = 0, e = (fLOD + 1) * 2; i < e; ++i) {
00282       if (even) {
00283          fMesh[i] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
00284          fMesh[j] = MakeVertex(fRmin2 * c, fRmin2 * s, fDz);
00285          fMesh[i + topShift] = MakeVertex(fRmin2 * c, fRmin2 * s, fDz);
00286          fMesh[i + botShift] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
00287          GetNormal(fMesh[j], fNorm[j]);
00288          fNorm[j].Negate();
00289          even = kFALSE;
00290       } else {
00291          fMesh[i] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
00292          fMesh[j + 1] = MakeVertex(fRmin1 * c, fRmin1 * s, -fDz);
00293          fMesh[i + topShift] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
00294          fMesh[i + botShift] = MakeVertex(fRmin1 * c, fRmin1 * s, - fDz);
00295          GetNormal(fMesh[j + 1], fNorm[j + 1]);
00296          fNorm[j + 1].Negate();
00297          even = kTRUE;
00298          currAngle += delta;
00299          c = TMath::Cos(currAngle);
00300          s = TMath::Sin(currAngle);
00301          j -= 2;
00302       }
00303 
00304       GetNormal(fMesh[i], fNorm[i]);
00305       fNorm[i + topShift] = fNhigh;
00306       fNorm[i + botShift] = fNlow;
00307    }
00308 }
00309 
00310 //______________________________________________________________________________
00311 void TubeMesh::Draw() const
00312 {
00313    //Tube is drawn as four quad strips
00314    glEnableClientState(GL_VERTEX_ARRAY);
00315    glEnableClientState(GL_NORMAL_ARRAY);
00316 
00317    glVertexPointer(3, GL_DOUBLE, sizeof(TGLVertex3), fMesh[0].CArr());
00318    glNormalPointer(GL_DOUBLE, sizeof(TGLVector3), fNorm[0].CArr());
00319    //draw outer and inner strips
00320    glDrawArrays(GL_QUAD_STRIP, 0, 2 * (fLOD + 1));
00321    glDrawArrays(GL_QUAD_STRIP, 2 * (fLOD + 1), 2 * (fLOD + 1));
00322    //draw top and bottom strips
00323    glDrawArrays(GL_QUAD_STRIP, 4 * (fLOD + 1), 2 * (fLOD + 1));
00324    glDrawArrays(GL_QUAD_STRIP, 6 * (fLOD + 1), 2 * (fLOD + 1));
00325    //5. disabling vertex arrays
00326    glDisableClientState(GL_VERTEX_ARRAY);
00327    glDisableClientState(GL_NORMAL_ARRAY);
00328 }
00329 
00330 //______________________________________________________________________________
00331 TCylinderMesh::TCylinderMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t dz,
00332                              const TGLVector3 &l, const TGLVector3 &h)
00333                  :TGLMesh(LOD, 0., r1, 0., r2, dz, l, h), fMesh(), fNorm()
00334 {
00335    // constructor
00336    const Double_t delta = TMath::TwoPi() / fLOD;
00337    Double_t currAngle = 0.;
00338 
00339    Bool_t even = kTRUE;
00340    Double_t c = TMath::Cos(currAngle);
00341    Double_t s = TMath::Sin(currAngle);
00342 
00343    //central point of top fan
00344    Int_t topShift = (fLOD + 1) * 2;
00345    fMesh[topShift][0] = fMesh[topShift][1] = 0., fMesh[topShift][2] = fDz;
00346    fNorm[topShift] = fNhigh;
00347    ++topShift;
00348 
00349    //central point of bottom fun
00350    Int_t botShift = topShift + 2 * (fLOD + 1);
00351    fMesh[botShift][0] = fMesh[botShift][1] = 0., fMesh[botShift][2] = -fDz;
00352    fNorm[botShift] = fNlow;
00353    ++botShift;
00354 
00355    //defining 1 strip and 2 fans
00356    for (Int_t i = 0, e = (fLOD + 1) * 2, j = 0; i < e; ++i) {
00357       if (even) {
00358          fMesh[i] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
00359          fMesh[j + topShift] = MakeVertex(fRmin2 * c, fRmin2 * s, fDz);
00360          fMesh[j + botShift] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
00361          even = kFALSE;
00362       } else {
00363          fMesh[i] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
00364          even = kTRUE;
00365          currAngle += delta;
00366          c = TMath::Cos(currAngle);
00367          s = TMath::Sin(currAngle);
00368          ++j;
00369       }
00370 
00371       GetNormal(fMesh[i], fNorm[i]);
00372       fNorm[i + topShift] = fNhigh;
00373       fNorm[i + botShift] = fNlow;
00374    }
00375 }
00376 
00377 //______________________________________________________________________________
00378 void TCylinderMesh::Draw() const
00379 {
00380    // draw cylinder mesh
00381    glEnableClientState(GL_VERTEX_ARRAY);
00382    glEnableClientState(GL_NORMAL_ARRAY);
00383 
00384    glVertexPointer(3, GL_DOUBLE, sizeof(TGLVertex3), fMesh[0].CArr());
00385    glNormalPointer(GL_DOUBLE, sizeof(TGLVector3), fNorm[0].CArr());
00386 
00387    //draw quad strip
00388    glDrawArrays(GL_QUAD_STRIP, 0, 2 * (fLOD + 1));
00389    //draw top and bottom funs
00390    glDrawArrays(GL_TRIANGLE_FAN, 2 * (fLOD + 1), fLOD + 2);
00391    glDrawArrays(GL_TRIANGLE_FAN, 3 * (fLOD + 1) + 1, fLOD + 2);
00392 
00393    glDisableClientState(GL_VERTEX_ARRAY);
00394    glDisableClientState(GL_NORMAL_ARRAY);
00395 }
00396 
00397 //______________________________________________________________________________
00398 TCylinderSegMesh::TCylinderSegMesh(UInt_t LOD, Double_t r1, Double_t r2, Double_t dz, Double_t phi1,
00399                                     Double_t phi2, const TGLVector3 &l,
00400                                     const TGLVector3 &h)
00401                      :TGLMesh(LOD, 0., r1, 0., r2, dz, l, h), fMesh(), fNorm()
00402 {
00403    //One quad mesh and two fans
00404    Double_t delta = (phi2 - phi1) / fLOD;
00405    Double_t currAngle = phi1;
00406 
00407    Bool_t even = kTRUE;
00408    Double_t c = TMath::Cos(currAngle);
00409    Double_t s = TMath::Sin(currAngle);
00410 
00411    const TGLVertex3 vTop(0., 0., fDz);
00412    const TGLVertex3 vBot(0., 0., - fDz);
00413 
00414    //center of top fan
00415    Int_t topShift = (fLOD + 1) * 2 + 8;
00416    fMesh[topShift] = vTop;
00417    fNorm[topShift] = fNhigh;
00418    ++topShift;
00419 
00420    //center of bottom fan
00421    Int_t botShift = topShift + fLOD + 1;
00422    fMesh[botShift] = vBot;
00423    fNorm[botShift] = fNlow;
00424    ++botShift;
00425 
00426    //defining strip and two fans
00427    //strip is not closed here
00428    Int_t i = 0;
00429    for (Int_t e = (fLOD + 1) * 2, j = 0; i < e; ++i) {
00430       if (even) {
00431          fMesh[i] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
00432          fMesh[j + topShift] = MakeVertex(fRmax2 * c, fRmax2 * s, fDz);
00433          fMesh[j + botShift] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
00434          even = kFALSE;
00435          fNorm[j + topShift] = fNhigh;
00436          fNorm[j + botShift] = fNlow;
00437       } else {
00438          fMesh[i] = MakeVertex(fRmax1 * c, fRmax1 * s, - fDz);
00439          even = kTRUE;
00440          currAngle += delta;
00441          c = TMath::Cos(currAngle);
00442          s = TMath::Sin(currAngle);
00443          ++j;
00444       }
00445 
00446       GetNormal(fMesh[i], fNorm[i]);
00447    }
00448 
00449    //closing first strip
00450    Int_t ind = 2 * (fLOD + 1);
00451    TGLVector3 norm(0., 0., 0.);
00452 
00453    fMesh[ind] = fMesh[ind - 2];
00454    fMesh[ind + 1] = fMesh[ind - 1];
00455    fMesh[ind + 2] = vTop;
00456    fMesh[ind + 3] = vBot;
00457    TMath::Normal2Plane(fMesh[ind].CArr(), fMesh[ind + 1].CArr(), fMesh[ind + 2].CArr(),
00458                           norm.Arr());
00459    fNorm[ind] = norm;
00460    fNorm[ind + 1] = norm;
00461    fNorm[ind + 2] = norm;
00462    fNorm[ind + 3] = norm;
00463 
00464    ind += 4;
00465    fMesh[ind] = vTop;
00466    fMesh[ind + 1] = vBot;
00467    fMesh[ind + 2] = fMesh[0];
00468    fMesh[ind + 3] = fMesh[1];
00469    TMath::Normal2Plane(fMesh[ind].CArr(), fMesh[ind + 1].CArr(), fMesh[ind + 2].CArr(),
00470                        norm.Arr());
00471    fNorm[ind] = norm;
00472    fNorm[ind + 1] = norm;
00473    fNorm[ind + 2] = norm;
00474    fNorm[ind + 3] = norm;
00475 }
00476 
00477 //______________________________________________________________________________
00478 void TCylinderSegMesh::Draw() const
00479 {
00480    //Cylinder segment is drawn as one quad strip and
00481    //two triangle fans
00482    //1. enabling vertex arrays
00483    glEnableClientState(GL_VERTEX_ARRAY);
00484    glEnableClientState(GL_NORMAL_ARRAY);
00485    //2. setting arrays
00486    glVertexPointer(3, GL_DOUBLE, sizeof(TGLVertex3), fMesh[0].CArr());
00487    glNormalPointer(GL_DOUBLE, sizeof(TGLVector3), fNorm[0].CArr());
00488    //3. draw quad strip
00489    glDrawArrays(GL_QUAD_STRIP, 0, 2 * (fLOD + 1) + 8);
00490    //4. draw top and bottom funs
00491    glDrawArrays(GL_TRIANGLE_FAN, 2 * (fLOD + 1) + 8, fLOD + 2);
00492    //      glDrawArrays(GL_TRIANGLE_FAN, 3 * (fLOD + 1) + 9, fLOD + 2);
00493    //5. disabling vertex arrays
00494    glDisableClientState(GL_VERTEX_ARRAY);
00495    glDisableClientState(GL_NORMAL_ARRAY);
00496 }
00497 
00498 
00499 //==============================================================================
00500 // TGLCylinder
00501 //==============================================================================
00502 
00503 //______________________________________________________________________________
00504 //
00505 // Implements a native ROOT-GL cylinder that can be rendered at
00506 // different levels of detail.
00507 
00508 ClassImp(TGLCylinder);
00509 
00510 //______________________________________________________________________________
00511 TGLCylinder::TGLCylinder(const TBuffer3DTube &buffer) :
00512    TGLLogicalShape(buffer)
00513 {
00514    // Copy out relevant parts of buffer - we create and delete mesh
00515    // parts on demand in DirectDraw() and they are DL cached
00516 
00517    fDLSize = 14;
00518 
00519    fR1 = buffer.fRadiusInner;
00520    fR2 = buffer.fRadiusOuter;
00521    fR3 = buffer.fRadiusInner;
00522    fR4 = buffer.fRadiusOuter;
00523    fDz = buffer.fHalfLength;
00524 
00525    fLowPlaneNorm = gLowNormalDefault;
00526    fHighPlaneNorm = gHighNormalDefault;
00527 
00528    switch (buffer.Type())
00529    {
00530       default:
00531       case TBuffer3DTypes::kTube:
00532       {
00533          fSegMesh = kFALSE;
00534          fPhi1 = 0;
00535          fPhi2 = 360;
00536          break;
00537       }
00538 
00539       case TBuffer3DTypes::kTubeSeg:
00540       case TBuffer3DTypes::kCutTube:
00541       {
00542          fSegMesh = kTRUE;
00543 
00544          const TBuffer3DTubeSeg * segBuffer = dynamic_cast<const TBuffer3DTubeSeg *>(&buffer);
00545          if (!segBuffer) {
00546             Error("TGLCylinder::TGLCylinder", "cannot cast TBuffer3D");
00547             return;
00548          }
00549 
00550          fPhi1 = segBuffer->fPhiMin;
00551          fPhi2 = segBuffer->fPhiMax;
00552          if (fPhi2 < fPhi1) fPhi2 += 360.;
00553          fPhi1 *= TMath::DegToRad();
00554          fPhi2 *= TMath::DegToRad();
00555 
00556          if (buffer.Type() == TBuffer3DTypes::kCutTube) {
00557             const TBuffer3DCutTube * cutBuffer = dynamic_cast<const TBuffer3DCutTube *>(&buffer);
00558             if (!cutBuffer) {
00559                Error("TGLCylinder::TGLCylinder", "cannot cast TBuffer3D");
00560                return;
00561             }
00562 
00563             for (UInt_t i =0; i < 3; i++) {
00564                fLowPlaneNorm[i] = cutBuffer->fLowPlaneNorm[i];
00565                fHighPlaneNorm[i] = cutBuffer->fHighPlaneNorm[i];
00566             }
00567          }
00568          break;
00569       }
00570    }
00571 }
00572 
00573 //______________________________________________________________________________
00574 TGLCylinder::~TGLCylinder()
00575 {
00576    //destructor
00577 }
00578 
00579 //______________________________________________________________________________
00580 UInt_t TGLCylinder::DLOffset(Short_t lod) const
00581 {
00582    // Return display-list offset for given LOD.
00583    // Calculation based on what is done in virtual QuantizeShapeLOD below.
00584 
00585    UInt_t  off = 0;
00586    if      (lod >= 100) off = 0;
00587    else if (lod <  10)  off = lod / 2;
00588    else                 off = lod / 10 + 4;
00589    return off;
00590 }
00591 
00592 //______________________________________________________________________________
00593 Short_t TGLCylinder::QuantizeShapeLOD(Short_t shapeLOD, Short_t combiLOD) const
00594 {
00595    // Factor in scene/viewer LOD and quantize.
00596 
00597    Int_t lod = ((Int_t)shapeLOD * (Int_t)combiLOD) / 100;
00598 
00599    if (lod >= 100)
00600    {
00601       lod = 100;
00602    }
00603    else if (lod > 10)
00604    {  // Round LOD above 10 to nearest 10
00605       Double_t quant = 0.1 * ((static_cast<Double_t>(lod)) + 0.5);
00606       lod            = 10  *   static_cast<Int_t>(quant);
00607    }
00608    else
00609    {  // Round LOD below 10 to nearest 2
00610       Double_t quant = 0.5 * ((static_cast<Double_t>(lod)) + 0.5);
00611       lod            = 2   *   static_cast<Int_t>(quant);
00612    }
00613    return static_cast<Short_t>(lod);
00614 }
00615 
00616 //______________________________________________________________________________
00617 void TGLCylinder::DirectDraw(TGLRnrCtx & rnrCtx) const
00618 {
00619    // Debug tracing
00620    if (gDebug > 4) {
00621       Info("TGLCylinder::DirectDraw", "this %ld (class %s) LOD %d",
00622            (Long_t)this, IsA()->GetName(), rnrCtx.ShapeLOD());
00623    }
00624 
00625    // As we are now support display list caching we can create, draw and
00626    // delete mesh parts of suitible LOD (quality) here - it will be cached
00627    // into a display list by base-class TGLLogicalShape::Draw(),
00628    // against our id and the LOD value. So this will only occur once
00629    // for a certain cylinder/LOD combination
00630    std::vector<TGLMesh *> meshParts;
00631 
00632    // Create mesh parts
00633    if (!fSegMesh) {
00634       meshParts.push_back(new TubeMesh   (rnrCtx.ShapeLOD(), fR1, fR2, fR3, fR4,
00635                                           fDz, fLowPlaneNorm, fHighPlaneNorm));
00636    } else {
00637       meshParts.push_back(new TubeSegMesh(rnrCtx.ShapeLOD(), fR1, fR2, fR3, fR4,
00638                                           fDz, fPhi1, fPhi2,
00639                                           fLowPlaneNorm, fHighPlaneNorm));
00640    }
00641 
00642    // Draw mesh parts
00643    for (UInt_t i = 0; i < meshParts.size(); ++i) meshParts[i]->Draw();
00644 
00645    // Delete mesh parts
00646    for (UInt_t i = 0; i < meshParts.size(); ++i) {
00647       delete meshParts[i];
00648       meshParts[i] = 0;//not to have invalid pointer for pseudo-destructor call :)
00649    }
00650 }

Generated on Tue Jul 5 14:18:06 2011 for ROOT_528-00b_version by  doxygen 1.5.1