]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EVE/Reve/BoxSetGL.cxx
First big commit of the mchview program and its accompanying library,
[u/mrichter/AliRoot.git] / EVE / Reve / BoxSetGL.cxx
1 // $Header$
2
3 #include "BoxSetGL.h"
4 #include <Reve/BoxSet.h>
5
6 #include <TGLIncludes.h>
7 #include <TGLRnrCtx.h>
8 #include <TGLScene.h>
9 #include <TGLSelectRecord.h>
10 #include <TGLContext.h>
11
12 using namespace Reve;
13
14 //______________________________________________________________________________
15 // BoxSetGL
16 //
17 // A GL rendering class for BoxSet.
18 //
19
20 ClassImp(BoxSetGL)
21
22 //______________________________________________________________________________
23 BoxSetGL::BoxSetGL() : fM(0), fBoxDL(0)
24 {
25   // Default constructor.
26
27   // fDLCache = false; // Disable display list.
28 }
29
30 //______________________________________________________________________________
31 BoxSetGL::~BoxSetGL()
32 {
33   // Destructor. Noop.
34 }
35
36 /**************************************************************************/
37 // Protected methods
38 /**************************************************************************/
39
40 //______________________________________________________________________________
41 Int_t BoxSetGL::PrimitiveType() const
42 {
43   // Return GL primitive used to render the boxes, based on the
44   // render-mode specified in the model object.
45
46   return (fM->fRenderMode != DigitSet::RM_Line) ? GL_QUADS : GL_LINE_LOOP;
47 }
48
49 //______________________________________________________________________________
50 inline Bool_t BoxSetGL::SetupColor(const DigitSet::DigitBase& q) const
51 {
52   // Set GL color for given primitive.
53
54   if (fM->fValueIsColor)
55   {
56     glColor4ubv((UChar_t*) & q.fValue);
57     return kTRUE;
58   }
59   else
60   {
61     UChar_t c[4];
62     Bool_t visible = fM->fPalette->ColorFromValue(q.fValue, fM->fDefaultValue, c);
63     if (visible)
64       glColor4ubv(c);
65     return visible;
66   }
67 }
68
69 //______________________________________________________________________________
70 void BoxSetGL::MakeOriginBox(Float_t p[24], Float_t dx, Float_t dy, Float_t dz) const
71 {
72   // Fill array p to represent a box (0,0,0) - (dx,dy,dz).
73
74   // bottom
75   p[0] = 0;  p[1] = dy; p[2] = 0;  p += 3;
76   p[0] = dx; p[1] = dy; p[2] = 0;  p += 3;
77   p[0] = dx; p[1] = 0;  p[2] = 0;  p += 3;
78   p[0] = 0;  p[1] = 0;  p[2] = 0;  p += 3;
79   // top
80   p[0] = 0;  p[1] = dy; p[2] = dz; p += 3;
81   p[0] = dx; p[1] = dy; p[2] = dz; p += 3;
82   p[0] = dx; p[1] = 0;  p[2] = dz; p += 3;
83   p[0] = 0;  p[1] = 0;  p[2] = dz;
84 }
85
86 //______________________________________________________________________________
87 inline void BoxSetGL::RenderBox(const Float_t p[24]) const
88 {
89   // Render a box specified by points in array p.
90
91   // bottom: 0123
92   glNormal3f(0, 0, -1);
93   glVertex3fv(p);      glVertex3fv(p + 3);
94   glVertex3fv(p + 6);  glVertex3fv(p + 9);
95   // top:    7654
96   glNormal3f(0, 0, 1);
97   glVertex3fv(p + 21); glVertex3fv(p + 18);
98   glVertex3fv(p + 15); glVertex3fv(p + 12);
99   // back:  0451
100   glNormal3f(0, 1, 0);
101   glVertex3fv(p);      glVertex3fv(p + 12);
102   glVertex3fv(p + 15); glVertex3fv(p + 3);
103   // front:   3267
104   glNormal3f(0, -1, 0);
105   glVertex3fv(p + 9);   glVertex3fv(p + 6);
106   glVertex3fv(p + 18);  glVertex3fv(p + 21);
107   // left:    0374
108   glNormal3f(-1, 0, 0);
109   glVertex3fv(p);       glVertex3fv(p + 9);
110   glVertex3fv(p + 21);  glVertex3fv(p + 12);
111   // right:   1562
112   glNormal3f(1, 0, 0);
113   glVertex3fv(p + 3);   glVertex3fv(p + 15);
114   glVertex3fv(p + 18);  glVertex3fv(p + 6);
115 }
116
117 //______________________________________________________________________________
118 void BoxSetGL::MakeDisplayList() const
119 {
120   // Create a display-list for rendering a single box, based on the
121   // current box-type.
122   // Some box-types don't benefit from the display-list rendering and
123   // so display-list is not created.
124
125   if (fM->fBoxType == BoxSet::BT_AABox ||
126       fM->fBoxType == BoxSet::BT_AABoxFixedDim)
127   {
128     if (fBoxDL == 0)
129       fBoxDL = glGenLists(1);
130
131     Float_t p[24];
132     if (fM->fBoxType == BoxSet::BT_AABox)
133       MakeOriginBox(p, 1.0f, 1.0f, 1.0f);
134     else
135       MakeOriginBox(p, fM->fDefWidth, fM->fDefHeight, fM->fDefDepth);
136
137     glNewList(fBoxDL, GL_COMPILE);
138     glBegin(PrimitiveType());
139     RenderBox(p);
140     glEnd();
141     glEndList();
142   }
143 }
144
145 /**************************************************************************/
146 // Virtuals from base-classes
147 /**************************************************************************/
148
149 //______________________________________________________________________________
150 Bool_t BoxSetGL::ShouldDLCache(const TGLRnrCtx & rnrCtx) const
151 {
152   // Determines if display-list will be used for rendering.
153   // Virtual from TGLLogicalShape.
154
155   MakeDisplayList();
156
157   if (rnrCtx.DrawPass() == TGLRnrCtx::kPassOutlineLine)
158     return kFALSE;
159   return TGLObject::ShouldDLCache(rnrCtx);
160 }
161
162 //______________________________________________________________________________
163 void BoxSetGL::DLCacheDrop()
164 {
165   // Called when display lists have been destroyed externally and the
166   // internal display-list data needs to be cleare.
167   // Virtual from TGLLogicalShape.
168
169   fBoxDL = 0;
170   TGLObject::DLCacheDrop();
171 }
172
173 //______________________________________________________________________________
174 void BoxSetGL::DLCachePurge()
175 {
176   // Called when display-lists need to be returned to the system.
177   // Virtual from TGLLogicalShape.
178
179   static const Exc_t eH("BoxSetGL::DLCachePurge ");
180
181   if (fBoxDL == 0) return;
182   if (fScene)
183   {
184     fScene->GetGLCtxIdentity()->RegisterDLNameRangeToWipe(fBoxDL, 1);
185   }
186   else
187   {
188     Warning(eH, "Scene unknown, attempting direct deletion.");
189     glDeleteLists(fBoxDL, 1);
190   }
191   TGLObject::DLCachePurge();
192 }
193
194 /**************************************************************************/
195
196 //______________________________________________________________________________
197 Bool_t BoxSetGL::SetModel(TObject* obj, const Option_t* /*opt*/)
198 {
199   // Set model object.
200   // Virtual from TGLObject.
201
202   Bool_t isok = SetModelCheckClass(obj, Reve::BoxSet::Class());
203   fM = isok ? dynamic_cast<Reve::BoxSet*>(obj) : 0;
204   return isok;
205 }
206
207 //______________________________________________________________________________
208 void BoxSetGL::SetBBox()
209 {
210   // Fill the bounding-box data of the logical-shape.
211   // Virtual from TGLObject.
212
213   SetAxisAlignedBBox(fM->AssertBBox());
214 }
215
216 //______________________________________________________________________________
217 void BoxSetGL::DirectDraw(TGLRnrCtx & rnrCtx) const
218 {
219   // Actual rendering code.
220   // Virtual from TGLLogicalShape.
221
222   static const Exc_t eH("BoxSetGL::DirectDraw ");
223
224   if (rnrCtx.DrawPass() == TGLRnrCtx::kPassOutlineLine)
225     return;
226
227   BoxSet& mB = * fM;
228   // printf("BoxSetGL::DirectDraw N boxes %d\n", mB.fPlex.Size());
229   if(mB.fPlex.Size() == 0)
230     return;
231
232   glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
233   glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
234   glEnable(GL_COLOR_MATERIAL);
235
236   if (mB.fRenderMode == DigitSet::RM_Fill)
237     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
238   else if (mB.fRenderMode == DigitSet::RM_Line)
239     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
240
241   if (mB.fDisableLigting) glDisable(GL_LIGHTING);
242
243   if (rnrCtx.SecSelection()) glPushName(0);
244
245   Int_t boxSkip = 0;
246   if (rnrCtx.ShapeLOD() < 50)
247     boxSkip = 6 - (rnrCtx.ShapeLOD()+1)/10;
248
249   VoidCPlex::iterator bi(mB.fPlex);
250
251   switch (mB.fBoxType)
252   {
253
254     case BoxSet::BT_FreeBox:
255     {
256       GLenum primitiveType = PrimitiveType();
257       while (bi.next())
258       {
259         BoxSet::BFreeBox& b = * (BoxSet::BFreeBox*) bi();
260         if (SetupColor(b))
261         {
262           if (rnrCtx.SecSelection()) glLoadName(bi.index());
263           glBegin(primitiveType);
264           RenderBox(b.fVertices);
265           glEnd();
266         }
267         if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
268       }
269       break;
270     } // end case free-box
271
272     case BoxSet::BT_AABox:
273     {
274       glEnable(GL_NORMALIZE);
275       while (bi.next())
276       {
277         BoxSet::BAABox& b = * (BoxSet::BAABox*) bi();
278         if (SetupColor(b))
279         {
280           if (rnrCtx.SecSelection()) glLoadName(bi.index());
281           glPushMatrix();
282           glTranslatef(b.fA, b.fB, b.fC);
283           glScalef    (b.fW, b.fH, b.fD);
284           glCallList(fBoxDL);
285           glPopMatrix();
286         }
287         if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
288       }
289       break;
290     }
291
292     case BoxSet::BT_AABoxFixedDim:
293     {
294       while (bi.next())
295       {
296         BoxSet::BAABoxFixedDim& b = * (BoxSet::BAABoxFixedDim*) bi();
297         if (SetupColor(b))
298         {
299           if (rnrCtx.SecSelection()) glLoadName(bi.index());
300           glTranslatef(b.fA, b.fB, b.fC);
301           glCallList(fBoxDL);
302           glTranslatef(-b.fA, -b.fB, -b.fC);
303         }
304         if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
305       }
306       break;
307     }
308
309     default:
310     {
311       throw(eH + "unsupported box-type.");
312     }
313
314   } // end switch box-type
315
316   if (rnrCtx.SecSelection()) glPopName();
317
318   glPopAttrib();
319 }
320
321 /**************************************************************************/
322
323 //______________________________________________________________________________
324 void BoxSetGL::ProcessSelection(TGLRnrCtx & /*rnrCtx*/, TGLSelectRecord & rec)
325 {
326   // Processes secondary selection from TGLViewer.
327   // Calls TPointSet3D::PointSelected(Int_t) with index of selected
328   // point as an argument.
329
330   if (rec.GetN() < 2) return;
331   fM->DigitSelected(rec.GetItem(1));
332 }
333
334 //______________________________________________________________________________
335 void BoxSetGL::Render(TGLRnrCtx & rnrCtx)
336 {
337   // Interface for direct rendering from classes that include BoxSet
338   // as a member.
339
340   MakeDisplayList();
341   DirectDraw(rnrCtx);
342   glDeleteLists(fBoxDL, 1);
343   fBoxDL = 0;
344 }