4 #include "RGBAPalette.h"
5 #include "RGTopFrame.h"
10 #include <TBuffer3DTypes.h>
11 #include <TGeometry.h>
12 #include <TVirtualPad.h>
13 #include <TVirtualViewer3D.h>
21 /**************************************************************************/
23 /**************************************************************************/
26 void Quad::ColorFromIdx(Color_t ci)
28 TColor* c = gROOT->GetColor(ci);
30 UChar_t *x = (UChar_t*) &color;
31 x[0] = (UChar_t)(255*c->GetRed()); x[1] = (UChar_t)(255*c->GetGreen());
32 x[2] = (UChar_t)(255*c->GetBlue()); x[3] = 255;
36 Quad::Quad(TRandom& rnd, Float_t origin, Float_t size) : color(0)
38 ColorFromIdx(Int_t(30*rnd.Rndm()));
39 Float_t x = 2*origin*(rnd.Rndm() - 0.5);
40 Float_t y = 2*origin*(rnd.Rndm() - 0.5);
41 Float_t z = 2*origin*(rnd.Rndm() - 0.5);
42 Float_t* p = vertices;
43 for(int i=0; i<4; ++i) {
44 p[0] = x + 2*size*(rnd.Rndm() - 0.5);
45 p[1] = y + 2*size*(rnd.Rndm() - 0.5);
46 p[2] = z + 2*size*(rnd.Rndm() - 0.5);
51 /**************************************************************************/
53 /**************************************************************************/
54 ClassImp(Reve::OldQuadSet)
57 OldQuadSet::OldQuadSet(const Text_t* n, const Text_t* t) :
63 void OldQuadSet::Test(Int_t nquads)
66 fQuads.resize(nquads);
67 for(Int_t i=0; i<nquads; ++i) {
68 new (&fQuads[i]) Quad(rnd, 10, 2);
72 void OldQuadSet::Paint(Option_t* )
74 TBuffer3D buffer(TBuffer3DTypes::kGeneric);
79 buffer.fTransparency = 0;
80 buffer.fLocalFrame = fTrans;
82 memcpy(buffer.fLocalMaster, fMatrix, 16*sizeof(Double_t));
83 buffer.SetSectionsValid(TBuffer3D::kCore);
85 // We fill kCore on first pass and try with viewer
86 Int_t reqSections = gPad->GetViewer3D()->AddObject(buffer);
87 if (reqSections == TBuffer3D::kNone) {
88 // printf("OldQuadSet::Paint viewer was happy with Core buff3d.\n");
92 if (reqSections & TBuffer3D::kRawSizes) {
93 Int_t nbPnts = fQuads.size()*4;
94 Int_t nbSegs = nbPnts;
95 if (!buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, fQuads.size(), fQuads.size()*6)) {
98 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
101 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
104 for (std::vector<Quad>::iterator i=fQuads.begin(); i!=fQuads.end(); ++i) {
105 for (Int_t k = 0; k < 12; k++ ){
106 buffer.fPnts[pidx] = (*i).vertices[k];
113 for (Int_t q = 0; q < (Int_t)fQuads.size(); ++q) {
114 for (Int_t s = 0; s < 4; ++s ) {
115 buffer.fSegs[3*sidx ] = 4;
116 buffer.fSegs[3*sidx+1] = sidx;
118 buffer.fSegs[3*sidx+2] = q*4;
120 buffer.fSegs[3*sidx+2] = sidx + 1;
126 for (Int_t q = 0; q < (Int_t)fQuads.size(); ++q) {
127 buffer.fPols[6*q] = fQuads[q].color;
128 buffer.fPols[6*q +1] = 4;
129 buffer.fPols[6*q +2] = 4*q + 0;
130 buffer.fPols[6*q +3] = 4*q + 1;
131 buffer.fPols[6*q +4] = 4*q + 2;
132 buffer.fPols[6*q +5] = 4*q + 3;
135 buffer.SetSectionsValid(TBuffer3D::kRaw);
139 gPad->GetViewer3D()->AddObject(buffer);
142 /**************************************************************************/
144 void OldQuadSet::ComputeBBox()
151 for(std::vector<Quad>::iterator q=fQuads.begin(); q!=fQuads.end(); ++q) {
152 Float_t* p = q->vertices;
153 for(int i=0; i<4; ++i, p+=3)
157 // printf("%s BBox is x(%f,%f), y(%f,%f), z(%f,%f)\n", GetName(),
158 // fBBox[0], fBBox[1], fBBox[2], fBBox[3], fBBox[4], fBBox[5]);
161 /**************************************************************************/
162 /**************************************************************************/
163 /**************************************************************************/
164 /**************************************************************************/
166 //__________________________________________________________________________
169 // Supports various internal formats that result in rendering of a
170 // set of rectangular objects.
172 // Names of internal structures and their variables use fixed
173 // assignment to x, z, y coordinates; the render types can override
174 // this convention and impose Y as a fixed coordinate.
175 // For quad modes the deltas are expected to be positive.
176 // For line modes negative deltas are ok.
178 ClassImp(Reve::QuadSet)
180 QuadSet::QuadSet(const Text_t* n, const Text_t* t) :
185 fDefaultValue(kMinInt),
186 fValueIsColor(kFALSE),
191 fDefWidth(1), fDefHeight(1), fDefCoord(0),
195 fRenderMode(RM_Fill),
196 fDisableLigting(kTRUE),
197 fEmitSignals(kFALSE),
201 QuadSet::QuadSet(QuadType_e quadType, Bool_t valIsCol, Int_t chunkSize,
202 const Text_t* n, const Text_t* t) :
207 fDefaultValue(valIsCol ? 0 : kMinInt),
208 fValueIsColor(valIsCol),
210 fPlex(SizeofAtom(quadType), chunkSize),
213 fDefWidth(1), fDefHeight(1), fDefCoord(0),
217 fRenderMode(RM_Fill),
218 fDisableLigting(kTRUE),
219 fEmitSignals(kFALSE),
231 void QuadSet::ReleaseIds()
233 VoidCPlex::iterator qi(fPlex);
235 QuadBase& q = * (QuadBase*) qi();
236 if (q.fId.GetObject()) {
237 delete q.fId.GetObject();
243 /**************************************************************************/
245 Int_t QuadSet::SizeofAtom(QuadSet::QuadType_e qt)
247 static const Exc_t eH("QuadSet::SizeofAtom ");
250 case QT_Undef: return 0;
251 case QT_FreeQuad: return sizeof(QFreeQuad);
252 case QT_RectangleXY: return sizeof(QRect);
253 case QT_RectangleXYFixedDim: return sizeof(QRectFixDim);
254 case QT_RectangleXZFixedY:
255 case QT_RectangleXYFixedZ: return sizeof(QRectFixC);
256 case QT_RectangleXZFixedDimY:
257 case QT_RectangleXYFixedDimZ: return sizeof(QRectFixDimC);
258 case QT_LineXZFixedY:
259 case QT_LineXYFixedZ: return sizeof(QLineFixC);
261 case QT_HexagonYX: return sizeof(QHex);
262 default: throw(eH + "unexpected atom type.");
267 /**************************************************************************/
269 void QuadSet::Reset(QuadSet::QuadType_e quadType, Bool_t valIsCol, Int_t chunkSize)
271 fQuadType = quadType;
272 fValueIsColor = valIsCol;
273 fDefaultValue = valIsCol ? 0 : kMinInt;
276 fPlex.Reset(SizeofAtom(fQuadType), chunkSize);
279 void QuadSet::RefitPlex()
281 // Instruct underlying memory allocator to regroup itself into a
282 // contiguous memory chunk.
287 /**************************************************************************/
289 void QuadSet::ScanMinMaxValues(Int_t& min, Int_t& max)
291 if (fValueIsColor || fPlex.Size() == 0) return;
294 for (Int_t c=0; c<fPlex.VecSize(); ++c)
296 Char_t* a = fPlex.Chunk(c);
297 Int_t n = fPlex.NAtoms(c);
300 Int_t v = ((QuadBase*)a)->fValue;
301 if (v < min) min = v;
302 if (v > max) max = v;
310 /**************************************************************************/
312 void QuadSet::SetMainColor(Color_t color)
315 fFrame->SetFrameColor(color);
316 fFrame->UpdateBackPtrItems();
321 void QuadSet::SetFrame(FrameBox* b)
323 if (fFrame == b) return;
324 if (fFrame) fFrame->DecRefCount(this);
327 fFrame->IncRefCount(this);
328 SetMainColorPtr(fFrame->PtrFrameColor());
334 void QuadSet::SetPalette(RGBAPalette* p)
336 if (fPalette == p) return;
337 if (fPalette) fPalette->DecRefCount();
339 if (fPalette) fPalette->IncRefCount();
342 RGBAPalette* QuadSet::AssertPalette()
345 fPalette = new RGBAPalette;
346 if (!fValueIsColor) {
348 ScanMinMaxValues(min, max);
349 fPalette->SetLimits(min, max);
350 fPalette->SetMinMax(min, max);
356 /**************************************************************************/
358 QuadSet::QuadBase* QuadSet::NewQuad()
360 fLastQuad = new (fPlex.NewAtom()) QuadBase(fDefaultValue);
364 void QuadSet::AddQuad(Float_t* verts)
366 static const Exc_t eH("QuadSet::AddQuad ");
368 if (fQuadType != QT_FreeQuad)
369 throw(eH + "expect free quad-type.");
371 QFreeQuad* fq = (QFreeQuad*) NewQuad();
372 memcpy(fq->fVertices, verts, sizeof(fq->fVertices));
375 void QuadSet::AddQuad(Float_t x, Float_t y)
377 AddQuad(x, y, fDefCoord, fDefWidth, fDefHeight);
380 void QuadSet::AddQuad(Float_t x, Float_t y, Float_t z)
382 AddQuad(x, y, z, fDefWidth, fDefHeight);
385 void QuadSet::AddQuad(Float_t x, Float_t y, Float_t w, Float_t h)
387 AddQuad(x, y, fDefCoord, w, h);
390 void QuadSet::AddQuad(Float_t x, Float_t y, Float_t z, Float_t w, Float_t h)
392 static const Exc_t eH("QuadSet::AddAAQuad ");
394 QOrigin& fq = * (QOrigin*) NewQuad();
395 fq.fX = x; fq.fY = y;
398 case QT_RectangleXY: {
399 QRect& q = (QRect&) fq;
400 q.fZ = z; q.fW = w; q.fH = h;
403 case QT_RectangleXYFixedDim: {
404 QRectFixDim& q = (QRectFixDim&) fq;
408 case QT_RectangleXZFixedY:
409 case QT_RectangleXYFixedZ: {
410 QRectFixC& q = (QRectFixC&) fq;
414 case QT_RectangleXZFixedDimY:
415 case QT_RectangleXYFixedDimZ: {
419 throw(eH + "expect axis-aligned quad-type.");
423 void QuadSet::AddLine(Float_t x, Float_t y, Float_t w, Float_t h)
425 static const Exc_t eH("QuadSet::AddLine ");
427 QOrigin& fq = * (QOrigin*) NewQuad();
428 fq.fX = x; fq.fY = y;
431 case QT_LineXZFixedY:
432 case QT_LineXYFixedZ: {
433 QLineFixC& q = (QLineFixC&) fq;
434 q.fDx = w; q.fDy = h;
438 throw(eH + "expect line quad-type.");
442 void QuadSet::AddHexagon(Float_t x, Float_t y, Float_t z, Float_t r)
444 static const Exc_t eH("QuadSet::AddHexagon ");
446 QOrigin& fq = * (QOrigin*) NewQuad();
447 fq.fX = x; fq.fY = y;
452 QHex& q = (QHex&) fq;
457 throw(eH + "expect line quad-type.");
461 /**************************************************************************/
463 void QuadSet::QuadValue(Int_t value)
465 fLastQuad->fValue = value;
468 void QuadSet::QuadColor(Color_t ci)
470 ColorFromIdx(ci, (UChar_t*) & fLastQuad->fValue, kTRUE);
473 void QuadSet::QuadColor(UChar_t r, UChar_t g, UChar_t b, UChar_t a)
475 UChar_t* x = (UChar_t*) & fLastQuad->fValue;
476 x[0] = r; x[1] = g; x[2] = b; x[3] = a;
479 /**************************************************************************/
481 void QuadSet::QuadId(TObject* id)
486 /**************************************************************************/
488 void QuadSet::QuadSelected(Int_t idx)
491 CtrlClicked(this, idx);
493 QuadBase* qb = GetQuad(idx);
494 TObject* obj = qb->fId.GetObject();
495 printf("QuadSet::QuadSelected idx=%d, value=%d, obj=0x%lx\n",
496 idx, qb->fValue, (ULong_t)obj);
502 void QuadSet::CtrlClicked(QuadSet* qs, Int_t idx)
505 args[0] = (Long_t) qs;
506 args[1] = (Long_t) idx;
508 Emit("CtrlClicked(Reve::Track*, Int_t)", args);
511 /**************************************************************************/
512 /**************************************************************************/
514 void QuadSet::ComputeBBox()
516 // Fill bounding-box information in base-class TAttBBox (virtual method).
517 // If member 'FrameBox* fFrame' is set, frame's corners are used as bbox.
519 static const Exc_t eH("QuadSet::ComputeBBox ");
524 Int_t n = fFrame->GetFrameSize() / 3;
525 Float_t *bbps = fFrame->GetFramePoints();
526 for (int i=0; i<n; ++i, bbps+=3)
527 BBoxCheckPoint(bbps);
531 if(fPlex.Size() == 0) {
537 if (fQuadType == QT_RectangleXYFixedZ ||
538 fQuadType == QT_RectangleXYFixedDimZ)
540 fBBox[4] = fDefCoord;
541 fBBox[5] = fDefCoord;
543 else if (fQuadType == QT_RectangleXZFixedY ||
544 fQuadType == QT_RectangleXZFixedDimY)
546 fBBox[2] = fDefCoord;
547 fBBox[3] = fDefCoord;
550 VoidCPlex::iterator qi(fPlex);
558 const Float_t* p = ((QFreeQuad*) qi())->fVertices;
559 BBoxCheckPoint(p); p += 3;
560 BBoxCheckPoint(p); p += 3;
561 BBoxCheckPoint(p); p += 3;
570 QRect& q = * (QRect*) qi();
571 if(q.fX < fBBox[0]) fBBox[0] = q.fX;
572 if(q.fX + q.fW > fBBox[1]) fBBox[1] = q.fX + q.fW;
573 if(q.fY < fBBox[2]) fBBox[2] = q.fY;
574 if(q.fY + q.fH > fBBox[3]) fBBox[3] = q.fY + q.fH;
575 if(q.fZ < fBBox[4]) fBBox[4] = q.fZ;
576 if(q.fZ > fBBox[5]) fBBox[5] = q.fZ;
581 case QT_RectangleXYFixedDim:
583 const Float_t& w = fDefWidth;
584 const Float_t& h = fDefHeight;
586 QRectFixDim& q = * (QRectFixDim*) qi();
587 if(q.fX < fBBox[0]) fBBox[0] = q.fX;
588 if(q.fX + w > fBBox[1]) fBBox[1] = q.fX + w;
589 if(q.fY < fBBox[2]) fBBox[2] = q.fY;
590 if(q.fY + h > fBBox[3]) fBBox[3] = q.fY + h;
591 if(q.fZ < fBBox[4]) fBBox[4] = q.fZ;
592 if(q.fZ > fBBox[5]) fBBox[5] = q.fZ;
597 case QT_RectangleXYFixedZ:
600 QRectFixC& q = * (QRectFixC*) qi();
601 if(q.fX < fBBox[0]) fBBox[0] = q.fX;
602 if(q.fX + q.fW > fBBox[1]) fBBox[1] = q.fX + q.fW;
603 if(q.fY < fBBox[2]) fBBox[2] = q.fY;
604 if(q.fY + q.fH > fBBox[3]) fBBox[3] = q.fY + q.fH;
609 case QT_RectangleXZFixedY:
612 QRectFixC& q = * (QRectFixC*) qi();
613 if(q.fX < fBBox[0]) fBBox[0] = q.fX;
614 if(q.fX + q.fW > fBBox[1]) fBBox[1] = q.fX + q.fW;
615 if(q.fY < fBBox[4]) fBBox[4] = q.fY;
616 if(q.fY + q.fH > fBBox[5]) fBBox[5] = q.fY + q.fH;
621 case QT_RectangleXYFixedDimZ:
623 const Float_t& w = fDefWidth;
624 const Float_t& h = fDefHeight;
626 QRectFixDimC& q = * (QRectFixDimC*) qi();
627 if(q.fX < fBBox[0]) fBBox[0] = q.fX;
628 if(q.fX + w > fBBox[1]) fBBox[1] = q.fX + w;
629 if(q.fY < fBBox[2]) fBBox[2] = q.fY;
630 if(q.fY + h > fBBox[3]) fBBox[3] = q.fY + h;
635 case QT_RectangleXZFixedDimY:
637 const Float_t& w = fDefWidth;
638 const Float_t& h = fDefHeight;
640 QRectFixDimC& q = * (QRectFixDimC*) qi();
641 if(q.fX < fBBox[0]) fBBox[0] = q.fX;
642 if(q.fX + w > fBBox[1]) fBBox[1] = q.fX + w;
643 if(q.fY < fBBox[4]) fBBox[4] = q.fY;
644 if(q.fY + h > fBBox[5]) fBBox[5] = q.fY + h;
649 case QT_LineXYFixedZ:
652 QLineFixC& q = * (QLineFixC*) qi();
653 BBoxCheckPoint(q.fX, q.fY, fDefCoord);
654 BBoxCheckPoint(q.fX + q.fDx, q.fY + q.fDy, fDefCoord);
659 case QT_LineXZFixedY:
662 QLineFixC& q = * (QLineFixC*) qi();
663 BBoxCheckPoint(q.fX, fDefCoord, q.fY);
664 BBoxCheckPoint(q.fX + q.fDx, fDefCoord, q.fY + q.fDy);
669 // Ignore 'slight' difference, assume square box for both cases.
674 QHex& q = * (QHex*) qi();
675 BBoxCheckPoint(q.fX-q.fR, q.fY-q.fR, q.fZ);
676 BBoxCheckPoint(q.fX+q.fR, q.fY+q.fR, q.fZ);
682 throw(eH + "unsupported quad-type.");
685 } // end switch quad-type
686 } // end if frame ... else ...
688 #if ROOT_VERSION_CODE <= ROOT_VERSION(5,14,0)
689 { // Resize bounding box so that it does not have 0 volume.
690 // This should be done in TAttBBox (via method AssertMinExtents(epsilon)).
691 // Or handled more gracefully in TGLViewer.
692 static const Float_t eps = 1e-3;
693 for (Int_t i=0; i<6; i+=2) {
694 if (fBBox[i+1] - fBBox[i] < eps) {
695 Float_t b = 0.5*(fBBox[i] + fBBox[i+1]);
696 fBBox[i] = b - 0.5*eps;
697 fBBox[i+1] = b + 0.5*eps;
702 AssertBBoxExtents(0.001);
706 /**************************************************************************/
708 void QuadSet::Paint(Option_t* /*option*/)
710 static const Exc_t eH("QuadSet::Paint ");
712 TBuffer3D buff(TBuffer3DTypes::kGeneric);
717 buff.fTransparency = 0;
718 fHMTrans.SetBuffer3D(buff);
719 buff.SetSectionsValid(TBuffer3D::kCore);
721 Int_t reqSections = gPad->GetViewer3D()->AddObject(buff);
722 if (reqSections != TBuffer3D::kNone)
723 Error(eH, "only direct GL rendering supported.");
726 /**************************************************************************/