From $ROOTSYS/tutorials/gl/glViewerLOD.C

//To set the Level Of Details when rendering geometry shapes
//Author: Richard Maunder

void glViewerLOD(Int_t reqNodes = 1000, Bool_t randomDist = kTRUE,
                 Bool_t reqSpheres = kTRUE, Bool_t reqTubes = kTRUE)
{
   TGeoManager * geom = new TGeoManager("LODTest", "GL viewer LOD test");
   geom->SetNsegments(4); // Doesn't matter keep low
   TGeoMaterial *matEmptySpace = new TGeoMaterial("EmptySpace", 0, 0, 0);
   TGeoMaterial *matSolid      = new TGeoMaterial("Solid"    , .938, 1., 10000.);

   TGeoMedium *medEmptySpace = new TGeoMedium("Empty", 1, matEmptySpace);
   TGeoMedium *medSolid      = new TGeoMedium("Solid", 1, matSolid);

   Double_t sizeBase = 20.0;
   Double_t worldRadius;
   if (randomDist) {
      worldRadius = pow(reqNodes,.5)*sizeBase;
   } else {
      worldRadius = pow(reqNodes,.3)*sizeBase;
   }

   TGeoVolume *top = geom->MakeBox
      ("WORLD", medEmptySpace, worldRadius, worldRadius, worldRadius);
   geom->SetTopVolume(top);

   gRandom->SetSeed();

   // Create random number of unique sphere shapes - up to 25% of
   // total placed sphere requested
   UInt_t volumeCount = gRandom->Integer(reqNodes/4)+1;
   TGeoVolume ** volumes = new TGeoVolume *[volumeCount];
   TGeoVolume * volume;

   Double_t dummy;

   for (UInt_t i = 0; i < volumeCount; i++) {
      char name[128];
      sprintf(name, "Volume_%d", i);

      // Random volume shape
      Int_t type = -1;
      if (reqSpheres && reqTubes) {
         type = gRandom->Integer(2);
         if (type == 1)
            type += gRandom->Integer(3);
      }
      else if(reqSpheres)
         type = 0;
      else if(reqTubes)
         type = 1 + gRandom->Integer(3);

      // Random dimensions
      Double_t rMin = gRandom->Rndm() * sizeBase;
      Double_t rMax = rMin + gRandom->Rndm() * sizeBase * 2.0;
      Double_t dz   = pow(gRandom->Rndm(),2.0) * sizeBase * 15.0;
      Double_t phi1 = gRandom->Rndm() * 90.0;
      Double_t phi2 = phi1 + gRandom->Rndm() * 270.0;

      // Pick random color (not black)
      Int_t color = gRandom->Integer(50);
      if (color == kBlack) color += 1;

      switch (type) {
        case 0: {
            // GL viewer only supports solid spheres (0. inner radius)
            volumes[i] = geom->MakeSphere(name,  medSolid,  0., rMax);
            printf("Volume %d : Color %d, Sphere, Radius %f\n", i, color, rMax);
            break;
         }
         case 1: {
            volumes[i] = geom->MakeTube(name,  medSolid,  rMin, rMax, dz);
            printf("Volume %d : Color %d, Tube, Inner Radius %f, "
                   "Outer Radius %f, Length %f\n",
                   i, color, rMin, rMax, dz);
            break;
         }
         case 2: {
            volumes[i] = geom->MakeTubs(name,  medSolid,  rMin, rMax, dz,
                                        phi1, phi2);
            printf("Volume %d : Color %d, Tube Seg, Inner Radius %f, "
                   "Outer Radius %f, Length %f, Phi1 %f, Phi2 %f\n",
                   i, color, rMin, rMax, dz, phi1, phi2);
            break;
         }
         case 3: {
            Double_t n1[3], n2[3];
            n1[0] = gRandom->Rndm()*.5;
            n1[1] = gRandom->Rndm()*.5; n1[2] = -1.0 + gRandom->Rndm()*.5;
            n2[0] = gRandom->Rndm()*.5;
            n2[1] = gRandom->Rndm()*.5; n2[2] =  1.0 - gRandom->Rndm()*.5;

            volumes[i] = geom->MakeCtub(name,  medSolid,  rMin, rMax, dz,
                                        phi1, phi2, n1[0], n1[1], n1[2],
                                        n2[0], n2[1], n2[2]);
            printf("Volume %d : Color %d, Cut Tube, Inner Radius %f, "
                   "Outer Radius %f, Length %f, Phi1 %f, Phi2 %f, "
                   "n1 (%f,%f,%f), n2 (%f,%f,%f)\n",
                   i, color, rMin, rMax, dz, phi1, phi2,
                   n1[0], n1[1], n1[2], n2[0], n2[1], n2[2]);
            break;
         }
         default: {
            assert(kFALSE);
         }
      }

      volumes[i]->SetLineColor(color);
   }

   printf("\nCreated %d volumes\n\n", volumeCount);

   // Scatter reqSpheres placed sphere randomly in space
   Double_t x, y, z;
   for (i = 0; i < reqNodes; i++) {
      // Pick random volume
      UInt_t useVolume = gRandom->Integer(volumeCount);

      TGeoTranslation * trans;
      TGeoRotation * rot;
      if (randomDist) {
         // Random translation
         gRandom->Rannor(x, y);
         gRandom->Rannor(z,dummy);
         trans = new TGeoTranslation(x*worldRadius, y*worldRadius, z*worldRadius);

         // Random rotation
         gRandom->Rannor(x, y);
         gRandom->Rannor(z,dummy);
         rot = new TGeoRotation("rot", x*360.0, y*360.0, z*360.0);
      } else {
         UInt_t perSide = pow(reqNodes,1.0/3.0)+0.5;
         Double_t distance = sizeBase*5.0;
         UInt_t xi, yi, zi;
         zi = i / (perSide*perSide);
         yi = (i / perSide) % perSide;
         xi = i % perSide;
         trans = new TGeoTranslation(xi*distance,yi*distance,zi*distance);
         rot = new TGeoRotation("rot",0.0, 0.0, 0.0);
      }
      top->AddNode(volumes[useVolume], i, new TGeoCombiTrans(*trans, *rot));
      //printf("Added node %d (Volume %d)\n", i, useVolume);
   }
   geom->CloseGeometry();
   top->Draw("ogl");
}
 glViewerLOD.C:1
 glViewerLOD.C:2
 glViewerLOD.C:3
 glViewerLOD.C:4
 glViewerLOD.C:5
 glViewerLOD.C:6
 glViewerLOD.C:7
 glViewerLOD.C:8
 glViewerLOD.C:9
 glViewerLOD.C:10
 glViewerLOD.C:11
 glViewerLOD.C:12
 glViewerLOD.C:13
 glViewerLOD.C:14
 glViewerLOD.C:15
 glViewerLOD.C:16
 glViewerLOD.C:17
 glViewerLOD.C:18
 glViewerLOD.C:19
 glViewerLOD.C:20
 glViewerLOD.C:21
 glViewerLOD.C:22
 glViewerLOD.C:23
 glViewerLOD.C:24
 glViewerLOD.C:25
 glViewerLOD.C:26
 glViewerLOD.C:27
 glViewerLOD.C:28
 glViewerLOD.C:29
 glViewerLOD.C:30
 glViewerLOD.C:31
 glViewerLOD.C:32
 glViewerLOD.C:33
 glViewerLOD.C:34
 glViewerLOD.C:35
 glViewerLOD.C:36
 glViewerLOD.C:37
 glViewerLOD.C:38
 glViewerLOD.C:39
 glViewerLOD.C:40
 glViewerLOD.C:41
 glViewerLOD.C:42
 glViewerLOD.C:43
 glViewerLOD.C:44
 glViewerLOD.C:45
 glViewerLOD.C:46
 glViewerLOD.C:47
 glViewerLOD.C:48
 glViewerLOD.C:49
 glViewerLOD.C:50
 glViewerLOD.C:51
 glViewerLOD.C:52
 glViewerLOD.C:53
 glViewerLOD.C:54
 glViewerLOD.C:55
 glViewerLOD.C:56
 glViewerLOD.C:57
 glViewerLOD.C:58
 glViewerLOD.C:59
 glViewerLOD.C:60
 glViewerLOD.C:61
 glViewerLOD.C:62
 glViewerLOD.C:63
 glViewerLOD.C:64
 glViewerLOD.C:65
 glViewerLOD.C:66
 glViewerLOD.C:67
 glViewerLOD.C:68
 glViewerLOD.C:69
 glViewerLOD.C:70
 glViewerLOD.C:71
 glViewerLOD.C:72
 glViewerLOD.C:73
 glViewerLOD.C:74
 glViewerLOD.C:75
 glViewerLOD.C:76
 glViewerLOD.C:77
 glViewerLOD.C:78
 glViewerLOD.C:79
 glViewerLOD.C:80
 glViewerLOD.C:81
 glViewerLOD.C:82
 glViewerLOD.C:83
 glViewerLOD.C:84
 glViewerLOD.C:85
 glViewerLOD.C:86
 glViewerLOD.C:87
 glViewerLOD.C:88
 glViewerLOD.C:89
 glViewerLOD.C:90
 glViewerLOD.C:91
 glViewerLOD.C:92
 glViewerLOD.C:93
 glViewerLOD.C:94
 glViewerLOD.C:95
 glViewerLOD.C:96
 glViewerLOD.C:97
 glViewerLOD.C:98
 glViewerLOD.C:99
 glViewerLOD.C:100
 glViewerLOD.C:101
 glViewerLOD.C:102
 glViewerLOD.C:103
 glViewerLOD.C:104
 glViewerLOD.C:105
 glViewerLOD.C:106
 glViewerLOD.C:107
 glViewerLOD.C:108
 glViewerLOD.C:109
 glViewerLOD.C:110
 glViewerLOD.C:111
 glViewerLOD.C:112
 glViewerLOD.C:113
 glViewerLOD.C:114
 glViewerLOD.C:115
 glViewerLOD.C:116
 glViewerLOD.C:117
 glViewerLOD.C:118
 glViewerLOD.C:119
 glViewerLOD.C:120
 glViewerLOD.C:121
 glViewerLOD.C:122
 glViewerLOD.C:123
 glViewerLOD.C:124
 glViewerLOD.C:125
 glViewerLOD.C:126
 glViewerLOD.C:127
 glViewerLOD.C:128
 glViewerLOD.C:129
 glViewerLOD.C:130
 glViewerLOD.C:131
 glViewerLOD.C:132
 glViewerLOD.C:133
 glViewerLOD.C:134
 glViewerLOD.C:135
 glViewerLOD.C:136
 glViewerLOD.C:137
 glViewerLOD.C:138
 glViewerLOD.C:139
 glViewerLOD.C:140
 glViewerLOD.C:141
 glViewerLOD.C:142
 glViewerLOD.C:143
 glViewerLOD.C:144
 glViewerLOD.C:145
 glViewerLOD.C:146
 glViewerLOD.C:147