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) {