Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGLFaceSet.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Timur Pocheptsov 03/08/2004
3// NOTE: This code moved from obsoleted TGLSceneObject.h / .cxx - see these
4// attic files for previous CVS history
5
6/*************************************************************************
7 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
14#include "TGLFaceSet.h"
15#include "TGLRnrCtx.h"
16#include "TGLIncludes.h"
17
18#include "TBuffer3D.h"
19#include "TMath.h"
20
21// For debug tracing
22#include "TClass.h"
23#include "TError.h"
24#define ROOT_CsgOps_cxx
25#include "CsgOps.h"
26
27#include <stdexcept>
28
29// Clone from TGLUtil -- typedefs needed for portable tesselator function typedef.
30
31#ifndef CALLBACK
32#define CALLBACK
33#endif
34
35extern "C"
36{
37#if defined(__APPLE_CC__) && __APPLE_CC__ > 4000 && __APPLE_CC__ < 5450 && !defined(__INTEL_COMPILER)
38 typedef GLvoid (*tessfuncptr_t)(...);
39#elif defined(__linux__) || defined(__FreeBSD__) || defined( __OpenBSD__ ) || defined(__sun) || defined (__CYGWIN__) || defined (__APPLE__)
40 typedef GLvoid (*tessfuncptr_t)();
41#elif defined (WIN32)
42 typedef GLvoid (CALLBACK *tessfuncptr_t)();
43#else
44 #error "Error - need to define type tessfuncptr_t for this platform/compiler"
45#endif
46}
47
48/** \class TGLFaceSet
49\ingroup opengl
50Implements a native ROOT-GL representation of an arbitrary set of polygons.
51*/
52
53
55
56////////////////////////////////////////////////////////////////////////////////
57/// constructor
58
60 TGLLogicalShape(buffer),
61 fVertices(buffer.fPnts, buffer.fPnts + 3 * buffer.NbPnts()),
62 fNormals(0)
63{
64 fNbPols = buffer.NbPols();
65
66 if (fNbPols == 0) return;
67
68 Int_t *segs = buffer.fSegs;
69 Int_t *pols = buffer.fPols;
70
71 Int_t descSize = 0;
72
73 for (UInt_t i = 0, j = 1; i < fNbPols; ++i, ++j)
74 {
75 descSize += pols[j] + 1;
76 j += pols[j] + 1;
77 }
78
79 fPolyDesc.resize(descSize);
80
81 for (UInt_t numPol = 0, currInd = 0, j = 1; numPol < fNbPols; ++numPol)
82 {
83 Int_t segmentInd = pols[j] + j;
86 segmentInd--;
88 segmentInd--;
89 Int_t segEnds[] = {segs[s1 * 3 + 1], segs[s1 * 3 + 2],
90 segs[s2 * 3 + 1], segs[s2 * 3 + 2]};
91 Int_t numPnts[3] = {0};
92
93 if (segEnds[0] == segEnds[2]) {
94 numPnts[0] = segEnds[1], numPnts[1] = segEnds[0], numPnts[2] = segEnds[3];
95 } else if (segEnds[0] == segEnds[3]) {
96 numPnts[0] = segEnds[1], numPnts[1] = segEnds[0], numPnts[2] = segEnds[2];
97 } else if (segEnds[1] == segEnds[2]) {
98 numPnts[0] = segEnds[0], numPnts[1] = segEnds[1], numPnts[2] = segEnds[3];
99 } else {
100 numPnts[0] = segEnds[0], numPnts[1] = segEnds[1], numPnts[2] = segEnds[2];
101 }
102
103 fPolyDesc[currInd] = 3;
105 fPolyDesc[currInd++] = numPnts[0];
106 fPolyDesc[currInd++] = numPnts[1];
107 fPolyDesc[currInd++] = numPnts[2];
109
110 Int_t end = j + 1;
111 for (; segmentInd != end; segmentInd--) {
112 segEnds[0] = segs[pols[segmentInd] * 3 + 1];
113 segEnds[1] = segs[pols[segmentInd] * 3 + 2];
114 if (segEnds[0] == lastAdded) {
115 fPolyDesc[currInd++] = segEnds[1];
116 lastAdded = segEnds[1];
117 } else {
118 fPolyDesc[currInd++] = segEnds[0];
119 lastAdded = segEnds[0];
120 }
122 }
123 j += segmentCol + 2;
124 }
125
126 if (fgEnforceTriangles) {
128 }
130}
131
132////////////////////////////////////////////////////////////////////////////////
133/// Should only be done on an empty faceset object
134
135void TGLFaceSet::SetFromMesh(const RootCsg::TBaseMesh *mesh)
136{
137 assert(fNbPols == 0);
138
139 UInt_t nv = mesh->NumberOfVertices();
140 fVertices.reserve(3 * nv);
141 UInt_t i;
142
143 for (i = 0; i < nv; ++i) {
144 const Double_t *v = mesh->GetVertex(i);
145 fVertices.insert(fVertices.end(), v, v + 3);
146 }
147
148 fNbPols = mesh->NumberOfPolys();
149
150 UInt_t descSize = 0;
151
152 for (i = 0; i < fNbPols; ++i) descSize += mesh->SizeOfPoly(i) + 1;
153
154 fPolyDesc.reserve(descSize);
155
156 for (UInt_t polyIndex = 0; polyIndex < fNbPols; ++polyIndex) {
157 UInt_t polySize = mesh->SizeOfPoly(polyIndex);
158
159 fPolyDesc.push_back(polySize);
160
161 for(i = 0; i < polySize; ++i) fPolyDesc.push_back(mesh->GetVertexIndex(polyIndex, i));
162 }
163
164 if (fgEnforceTriangles) {
166 }
168}
169
170////////////////////////////////////////////////////////////////////////////////
171/// Use GLU tesselator to replace all polygons with N > 3 with triangles.
172/// After this call polygon descriptions are changed.
173/// New vertices are not expected -- exception is thrown if this is
174/// requested by the triangulator. Support for adding of new vertices can be
175/// provided.
176
178{
179 class TriangleCollector
180 {
181 protected:
182 Int_t fNTriangles;
183 Int_t fNVertices;
184 Int_t fV0, fV1;
185 GLenum fType;
186 std::vector<Int_t> fPolyDesc;
187
188 void add_triangle(Int_t v0, Int_t v1, Int_t v2)
189 {
190 fPolyDesc.push_back(3);
191 fPolyDesc.push_back(v0);
192 fPolyDesc.push_back(v1);
193 fPolyDesc.push_back(v2);
194 ++fNTriangles;
195 }
196
197 void process_vertex(Int_t vi)
198 {
199 ++fNVertices;
200
201 if (fV0 == -1) {
202 fV0 = vi;
203 return;
204 }
205 if (fV1 == -1) {
206 fV1 = vi;
207 return;
208 }
209
210 switch (fType)
211 {
212 case GL_TRIANGLES:
213 {
214 add_triangle(fV0, fV1, vi);
215 fV0 = fV1 = -1;
216 break;
217 }
219 {
220 if (fNVertices % 2 == 0)
221 add_triangle(fV1, fV0, vi);
222 else
223 add_triangle(fV0, fV1, vi);
224 fV0 = fV1;
225 fV1 = vi;
226 break;
227 }
228 case GL_TRIANGLE_FAN:
229 {
230 add_triangle(fV0, fV1, vi);
231 fV1 = vi;
232 break;
233 }
234 default:
235 {
236 throw std::runtime_error("TGLFaceSet::EnforceTriangles unexpected type in tess_vertex callback.");
237 }
238 }
239 }
240
241 public:
242 TriangleCollector(GLUtesselator* ts) :
243 fNTriangles(0), fNVertices(0), fV0(-1), fV1(-1), fType(GL_NONE)
244 {
249 }
250
251 Int_t GetNTrianlges() { return fNTriangles; }
252 std::vector<Int_t>& RefPolyDesc() { return fPolyDesc; }
253
254 static void tess_begin(GLenum type, TriangleCollector* tc)
255 {
256 tc->fNVertices = 0;
257 tc->fV0 = tc->fV1 = -1;
258 tc->fType = type;
259 }
260
261 static void tess_vertex(Int_t* vi, TriangleCollector* tc)
262 {
263 tc->process_vertex(*vi);
264 }
265
266 static void tess_combine(GLdouble /*coords*/[3], void* /*vertex_data*/[4],
267 GLfloat /*weight*/[4], void** /*outData*/,
268 TriangleCollector* /*tc*/)
269 {
270 throw std::runtime_error("TGLFaceSet::EnforceTriangles tesselator requested vertex combining -- not supported yet.");
271 }
272
273 static void tess_end(TriangleCollector* tc)
274 {
275 tc->fType = GL_NONE;
276 }
277 };
278
280 if (!tess) throw std::bad_alloc();
281
282 TriangleCollector tc(tess);
283
284 // Loop ...
285 const Double_t *pnts = &fVertices[0];
286 const Int_t *pols = &fPolyDesc[0];
287
288 for (UInt_t i = 0, j = 0; i < fNbPols; ++i)
289 {
290 Int_t npoints = pols[j++];
291
294
295 for (Int_t k = 0; k < npoints; ++k, ++j)
296 {
297 gluTessVertex(tess, (Double_t*) pnts + pols[j] * 3, (GLvoid*) &pols[j]);
298 }
299
302 }
303
305
306 fPolyDesc.swap(tc.RefPolyDesc());
307 fNbPols = tc.GetNTrianlges();
308}
309
310////////////////////////////////////////////////////////////////////////////////
311/// Debug tracing
312
314{
315 if (gDebug > 4) {
316 Info("TGLFaceSet::DirectDraw", "this %zd (class %s) LOD %d", (size_t)this, IsA()->GetName(), rnrCtx.ShapeLOD());
317 }
318
319 if (fNbPols == 0) return;
320
322 const Double_t *pnts = &fVertices[0];
323 const Double_t *normals = &fNormals[0];
324 const Int_t *pols = &fPolyDesc[0];
325
326 for (UInt_t i = 0, j = 0; i < fNbPols; ++i) {
327 Int_t npoints = pols[j++];
328
329 if (tessObj && npoints > 4) {
332 glNormal3dv(normals + i * 3);
333
334 for (Int_t k = 0; k < npoints; ++k, ++j) {
335 gluTessVertex(tessObj, (Double_t *)pnts + pols[j] * 3, (Double_t *)pnts + pols[j] * 3);
336 }
338 } else {
340 glNormal3dv(normals + i * 3);
341
342 for (Int_t k = 0; k < npoints; ++k, ++j) {
343 glVertex3dv(pnts + pols[j] * 3);
344 }
345 glEnd();
346 }
347 }
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// CheckPoints
352
354{
355 const Double_t * p1 = &fVertices[source[0] * 3];
356 const Double_t * p2 = &fVertices[source[1] * 3];
357 const Double_t * p3 = &fVertices[source[2] * 3];
358 Int_t retVal = 1;
359
360 if (Eq(p1, p2)) {
361 dest[0] = source[0];
362 if (!Eq(p1, p3) ) {
363 dest[1] = source[2];
364 retVal = 2;
365 }
366 } else if (Eq(p1, p3)) {
367 dest[0] = source[0];
368 dest[1] = source[1];
369 retVal = 2;
370 } else {
371 dest[0] = source[0];
372 dest[1] = source[1];
373 retVal = 2;
374 if (!Eq(p2, p3)) {
375 dest[2] = source[2];
376 retVal = 3;
377 }
378 }
379
380 return retVal;
381}
382
383////////////////////////////////////////////////////////////////////////////////
384/// test equality
385
387{
388 Double_t dx = TMath::Abs(p1[0] - p2[0]);
389 Double_t dy = TMath::Abs(p1[1] - p2[1]);
390 Double_t dz = TMath::Abs(p1[2] - p2[2]);
391 return dx < 1e-10 && dy < 1e-10 && dz < 1e-10;
392}
393
394////////////////////////////////////////////////////////////////////////////////
395/// CalculateNormals
396
398{
399 fNormals.resize(3 *fNbPols);
400 if (fNbPols == 0) return;
401 Double_t *pnts = &fVertices[0];
402 for (UInt_t i = 0, j = 0; i < fNbPols; ++i) {
403 Int_t polEnd = fPolyDesc[j] + j + 1;
404 Int_t norm[] = {fPolyDesc[j + 1], fPolyDesc[j + 2], fPolyDesc[j + 3]};
405 j += 4;
407 if (check == 3) {
408 TMath::Normal2Plane(pnts + norm[0] * 3, pnts + norm[1] * 3,
409 pnts + norm[2] * 3, &fNormals[i * 3]);
410 j = polEnd;
411 continue;
412 }
413 while (j < (UInt_t)polEnd) {
414 norm[ngood++] = fPolyDesc[j++];
415 if (ngood == 3) {
417 if (ngood == 3) {
418 TMath::Normal2Plane(pnts + norm[0] * 3, pnts + norm[1] * 3,
419 pnts + norm[2] * 3, &fNormals[i * 3]);
420 j = polEnd;
421 break;
422 }
423 }
424 }
425 }
426}
427
428////////////////////////////////////////////////////////////////////////////////
429/// Get current state of static flag EnforceTriangles.
430
435
436////////////////////////////////////////////////////////////////////////////////
437/// Set state of static flag EnforceTriangles.
438/// When this is set, all tesselations will be automatically converted into
439/// triangle-only meshes.
440/// This is needed to export TGeo shapes and CSG meshes to external
441/// triangle-mesh libraries that can not handle arbitrary polygons.
442
#define s1(x)
Definition RSha256.hxx:91
#define e(i)
Definition RSha256.hxx:103
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:78
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
#define CALLBACK
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t dest
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:792
Generic 3D primitive description class.
Definition TBuffer3D.h:18
Int_t * fPols
Definition TBuffer3D.h:124
UInt_t NbPols() const
Definition TBuffer3D.h:91
Int_t * fSegs
Definition TBuffer3D.h:123
void EnforceTriangles()
Use GLU tesselator to replace all polygons with N > 3 with triangles.
UInt_t fNbPols
Definition TGLFaceSet.h:30
static void SetEnforceTriangles(Bool_t e)
Set state of static flag EnforceTriangles.
std::vector< Int_t > fPolyDesc
Definition TGLFaceSet.h:29
std::vector< Double_t > fNormals
Definition TGLFaceSet.h:28
Int_t CheckPoints(const Int_t *source, Int_t *dest) const
CheckPoints.
void SetFromMesh(const RootCsg::TBaseMesh *m)
Should only be done on an empty faceset object.
void DirectDraw(TGLRnrCtx &rnrCtx) const override
Debug tracing.
TGLFaceSet(const TBuffer3D &buffer)
constructor
void CalculateNormals()
CalculateNormals.
std::vector< Double_t > fVertices
Definition TGLFaceSet.h:27
static Bool_t Eq(const Double_t *p1, const Double_t *p2)
test equality
static Bool_t fgEnforceTriangles
Definition TGLFaceSet.h:32
TClass * IsA() const override
Definition TGLFaceSet.h:57
static Bool_t GetEnforceTriangles()
Get current state of static flag EnforceTriangles.
Abstract logical shape - a GL 'drawable' - base for all shapes - faceset sphere etc.
The TGLRnrCtx class aggregates data for a given redering context as needed by various parts of the RO...
Definition TGLRnrCtx.h:41
static GLUtesselator * GetDrawTesselator3dv()
Returns a tesselator for direct drawing when using 3-vertices with double precision.
Definition TGLUtil.cxx:1531
T * Normal2Plane(const T v1[3], const T v2[3], const T v3[3], T normal[3])
Calculates a normal vector of a plane.
Definition TMath.h:1305
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122