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
25#include <stdexcept>
26
27// Clone from TGLUtil -- typedefs needed for portable tesselator function typedef.
28
29#ifndef CALLBACK
30#define CALLBACK
31#endif
32
33extern "C"
34{
35#if defined(__APPLE_CC__) && __APPLE_CC__ > 4000 && __APPLE_CC__ < 5450 && !defined(__INTEL_COMPILER)
36 typedef GLvoid (*tessfuncptr_t)(...);
37#elif defined(__linux__) || defined(__FreeBSD__) || defined( __OpenBSD__ ) || defined(__sun) || defined (__CYGWIN__) || defined (__APPLE__)
38 typedef GLvoid (*tessfuncptr_t)();
39#elif defined (WIN32)
40 typedef GLvoid (CALLBACK *tessfuncptr_t)();
41#else
42 #error "Error - need to define type tessfuncptr_t for this platform/compiler"
43#endif
44}
45
46/** \class TGLFaceSet
47\ingroup opengl
48Implements a native ROOT-GL representation of an arbitrary set of polygons.
49*/
50
51
53
54////////////////////////////////////////////////////////////////////////////////
55/// constructor
56
58 TGLLogicalShape(buffer),
59 fVertices(buffer.fPnts, buffer.fPnts + 3 * buffer.NbPnts()),
60 fNormals(0)
61{
62 fNbPols = buffer.NbPols();
63
64 if (fNbPols == 0) return;
65
66 Int_t *segs = buffer.fSegs;
67 Int_t *pols = buffer.fPols;
68
69 Int_t descSize = 0;
70
71 for (UInt_t i = 0, j = 1; i < fNbPols; ++i, ++j)
72 {
73 descSize += pols[j] + 1;
74 j += pols[j] + 1;
75 }
76
77 fPolyDesc.resize(descSize);
78
79 for (UInt_t numPol = 0, currInd = 0, j = 1; numPol < fNbPols; ++numPol)
80 {
81 Int_t segmentInd = pols[j] + j;
84 segmentInd--;
86 segmentInd--;
87 Int_t segEnds[] = {segs[s1 * 3 + 1], segs[s1 * 3 + 2],
88 segs[s2 * 3 + 1], segs[s2 * 3 + 2]};
89 Int_t numPnts[3] = {0};
90
91 if (segEnds[0] == segEnds[2]) {
92 numPnts[0] = segEnds[1], numPnts[1] = segEnds[0], numPnts[2] = segEnds[3];
93 } else if (segEnds[0] == segEnds[3]) {
94 numPnts[0] = segEnds[1], numPnts[1] = segEnds[0], numPnts[2] = segEnds[2];
95 } else if (segEnds[1] == segEnds[2]) {
96 numPnts[0] = segEnds[0], numPnts[1] = segEnds[1], numPnts[2] = segEnds[3];
97 } else {
98 numPnts[0] = segEnds[0], numPnts[1] = segEnds[1], numPnts[2] = segEnds[2];
99 }
100
101 fPolyDesc[currInd] = 3;
103 fPolyDesc[currInd++] = numPnts[0];
104 fPolyDesc[currInd++] = numPnts[1];
105 fPolyDesc[currInd++] = numPnts[2];
107
108 Int_t end = j + 1;
109 for (; segmentInd != end; segmentInd--) {
110 segEnds[0] = segs[pols[segmentInd] * 3 + 1];
111 segEnds[1] = segs[pols[segmentInd] * 3 + 2];
112 if (segEnds[0] == lastAdded) {
113 fPolyDesc[currInd++] = segEnds[1];
114 lastAdded = segEnds[1];
115 } else {
116 fPolyDesc[currInd++] = segEnds[0];
117 lastAdded = segEnds[0];
118 }
120 }
121 j += segmentCol + 2;
122 }
123
124 if (fgEnforceTriangles) {
126 }
128}
129
130////////////////////////////////////////////////////////////////////////////////
131/// Should only be done on an empty faceset object
132
133void TGLFaceSet::SetFromMesh(const RootCsg::TBaseMesh *mesh)
134{
135 assert(fNbPols == 0);
136
137 UInt_t nv = mesh->NumberOfVertices();
138 fVertices.reserve(3 * nv);
139 UInt_t i;
140
141 for (i = 0; i < nv; ++i) {
142 const Double_t *v = mesh->GetVertex(i);
143 fVertices.insert(fVertices.end(), v, v + 3);
144 }
145
146 fNbPols = mesh->NumberOfPolys();
147
148 UInt_t descSize = 0;
149
150 for (i = 0; i < fNbPols; ++i) descSize += mesh->SizeOfPoly(i) + 1;
151
152 fPolyDesc.reserve(descSize);
153
154 for (UInt_t polyIndex = 0; polyIndex < fNbPols; ++polyIndex) {
155 UInt_t polySize = mesh->SizeOfPoly(polyIndex);
156
157 fPolyDesc.push_back(polySize);
158
159 for(i = 0; i < polySize; ++i) fPolyDesc.push_back(mesh->GetVertexIndex(polyIndex, i));
160 }
161
162 if (fgEnforceTriangles) {
164 }
166}
167
168////////////////////////////////////////////////////////////////////////////////
169/// Use GLU tesselator to replace all polygons with N > 3 with triangles.
170/// After this call polygon descriptions are changed.
171/// New vertices are not expected -- exception is thrown if this is
172/// requested by the triangulator. Support for adding of new vertices can be
173/// provided.
174
176{
177 class TriangleCollector
178 {
179 protected:
180 Int_t fNTriangles;
181 Int_t fNVertices;
182 Int_t fV0, fV1;
183 GLenum fType;
184 std::vector<Int_t> fPolyDesc;
185
186 void add_triangle(Int_t v0, Int_t v1, Int_t v2)
187 {
188 fPolyDesc.push_back(3);
189 fPolyDesc.push_back(v0);
190 fPolyDesc.push_back(v1);
191 fPolyDesc.push_back(v2);
192 ++fNTriangles;
193 }
194
195 void process_vertex(Int_t vi)
196 {
197 ++fNVertices;
198
199 if (fV0 == -1) {
200 fV0 = vi;
201 return;
202 }
203 if (fV1 == -1) {
204 fV1 = vi;
205 return;
206 }
207
208 switch (fType)
209 {
210 case GL_TRIANGLES:
211 {
212 add_triangle(fV0, fV1, vi);
213 fV0 = fV1 = -1;
214 break;
215 }
217 {
218 if (fNVertices % 2 == 0)
219 add_triangle(fV1, fV0, vi);
220 else
221 add_triangle(fV0, fV1, vi);
222 fV0 = fV1;
223 fV1 = vi;
224 break;
225 }
226 case GL_TRIANGLE_FAN:
227 {
228 add_triangle(fV0, fV1, vi);
229 fV1 = vi;
230 break;
231 }
232 default:
233 {
234 throw std::runtime_error("TGLFaceSet::EnforceTriangles unexpected type in tess_vertex callback.");
235 }
236 }
237 }
238
239 public:
240 TriangleCollector(GLUtesselator* ts) :
241 fNTriangles(0), fNVertices(0), fV0(-1), fV1(-1), fType(GL_NONE)
242 {
247 }
248
249 Int_t GetNTrianlges() { return fNTriangles; }
250 std::vector<Int_t>& RefPolyDesc() { return fPolyDesc; }
251
252 static void tess_begin(GLenum type, TriangleCollector* tc)
253 {
254 tc->fNVertices = 0;
255 tc->fV0 = tc->fV1 = -1;
256 tc->fType = type;
257 }
258
259 static void tess_vertex(Int_t* vi, TriangleCollector* tc)
260 {
261 tc->process_vertex(*vi);
262 }
263
264 static void tess_combine(GLdouble /*coords*/[3], void* /*vertex_data*/[4],
265 GLfloat /*weight*/[4], void** /*outData*/,
266 TriangleCollector* /*tc*/)
267 {
268 throw std::runtime_error("TGLFaceSet::EnforceTriangles tesselator requested vertex combining -- not supported yet.");
269 }
270
271 static void tess_end(TriangleCollector* tc)
272 {
273 tc->fType = GL_NONE;
274 }
275 };
276
278 if (!tess) throw std::bad_alloc();
279
280 TriangleCollector tc(tess);
281
282 // Loop ...
283 const Double_t *pnts = &fVertices[0];
284 const Int_t *pols = &fPolyDesc[0];
285
286 for (UInt_t i = 0, j = 0; i < fNbPols; ++i)
287 {
288 Int_t npoints = pols[j++];
289
292
293 for (Int_t k = 0; k < npoints; ++k, ++j)
294 {
295 gluTessVertex(tess, (Double_t*) pnts + pols[j] * 3, (GLvoid*) &pols[j]);
296 }
297
300 }
301
303
304 fPolyDesc.swap(tc.RefPolyDesc());
305 fNbPols = tc.GetNTrianlges();
306}
307
308////////////////////////////////////////////////////////////////////////////////
309/// Debug tracing
310
312{
313 if (gDebug > 4) {
314 Info("TGLFaceSet::DirectDraw", "this %zd (class %s) LOD %d", (size_t)this, IsA()->GetName(), rnrCtx.ShapeLOD());
315 }
316
317 if (fNbPols == 0) return;
318
320 const Double_t *pnts = &fVertices[0];
321 const Double_t *normals = &fNormals[0];
322 const Int_t *pols = &fPolyDesc[0];
323
324 for (UInt_t i = 0, j = 0; i < fNbPols; ++i) {
325 Int_t npoints = pols[j++];
326
327 if (tessObj && npoints > 4) {
330 glNormal3dv(normals + i * 3);
331
332 for (Int_t k = 0; k < npoints; ++k, ++j) {
333 gluTessVertex(tessObj, (Double_t *)pnts + pols[j] * 3, (Double_t *)pnts + pols[j] * 3);
334 }
336 } else {
338 glNormal3dv(normals + i * 3);
339
340 for (Int_t k = 0; k < npoints; ++k, ++j) {
341 glVertex3dv(pnts + pols[j] * 3);
342 }
343 glEnd();
344 }
345 }
346}
347
348////////////////////////////////////////////////////////////////////////////////
349/// CheckPoints
350
352{
353 const Double_t * p1 = &fVertices[source[0] * 3];
354 const Double_t * p2 = &fVertices[source[1] * 3];
355 const Double_t * p3 = &fVertices[source[2] * 3];
356 Int_t retVal = 1;
357
358 if (Eq(p1, p2)) {
359 dest[0] = source[0];
360 if (!Eq(p1, p3) ) {
361 dest[1] = source[2];
362 retVal = 2;
363 }
364 } else if (Eq(p1, p3)) {
365 dest[0] = source[0];
366 dest[1] = source[1];
367 retVal = 2;
368 } else {
369 dest[0] = source[0];
370 dest[1] = source[1];
371 retVal = 2;
372 if (!Eq(p2, p3)) {
373 dest[2] = source[2];
374 retVal = 3;
375 }
376 }
377
378 return retVal;
379}
380
381////////////////////////////////////////////////////////////////////////////////
382/// test equality
383
385{
386 Double_t dx = TMath::Abs(p1[0] - p2[0]);
387 Double_t dy = TMath::Abs(p1[1] - p2[1]);
388 Double_t dz = TMath::Abs(p1[2] - p2[2]);
389 return dx < 1e-10 && dy < 1e-10 && dz < 1e-10;
390}
391
392////////////////////////////////////////////////////////////////////////////////
393/// CalculateNormals
394
396{
397 fNormals.resize(3 *fNbPols);
398 if (fNbPols == 0) return;
399 Double_t *pnts = &fVertices[0];
400 for (UInt_t i = 0, j = 0; i < fNbPols; ++i) {
401 Int_t polEnd = fPolyDesc[j] + j + 1;
402 Int_t norm[] = {fPolyDesc[j + 1], fPolyDesc[j + 2], fPolyDesc[j + 3]};
403 j += 4;
405 if (check == 3) {
406 TMath::Normal2Plane(pnts + norm[0] * 3, pnts + norm[1] * 3,
407 pnts + norm[2] * 3, &fNormals[i * 3]);
408 j = polEnd;
409 continue;
410 }
411 while (j < (UInt_t)polEnd) {
412 norm[ngood++] = fPolyDesc[j++];
413 if (ngood == 3) {
415 if (ngood == 3) {
416 TMath::Normal2Plane(pnts + norm[0] * 3, pnts + norm[1] * 3,
417 pnts + norm[2] * 3, &fNormals[i * 3]);
418 j = polEnd;
419 break;
420 }
421 }
422 }
423 }
424}
425
426////////////////////////////////////////////////////////////////////////////////
427/// Get current state of static flag EnforceTriangles.
428
433
434////////////////////////////////////////////////////////////////////////////////
435/// Set state of static flag EnforceTriangles.
436/// When this is set, all tesselations will be automatically converted into
437/// triangle-only meshes.
438/// This is needed to export TGeo shapes and CSG meshes to external
439/// triangle-mesh libraries that can not handle arbitrary polygons.
440
#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:77
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
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:627
segment * segs
Definition X3DBuffer.c:23
Generic 3D primitive description class.
Definition TBuffer3D.h:18
Int_t * fPols
Definition TBuffer3D.h:115
UInt_t NbPols() const
Definition TBuffer3D.h:82
Int_t * fSegs
Definition TBuffer3D.h:114
void EnforceTriangles()
Use GLU tesselator to replace all polygons with N > 3 with triangles.
UInt_t fNbPols
Definition TGLFaceSet.h:28
static void SetEnforceTriangles(Bool_t e)
Set state of static flag EnforceTriangles.
std::vector< Int_t > fPolyDesc
Definition TGLFaceSet.h:27
std::vector< Double_t > fNormals
Definition TGLFaceSet.h:26
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:25
static Bool_t Eq(const Double_t *p1, const Double_t *p2)
test equality
static Bool_t fgEnforceTriangles
Definition TGLFaceSet.h:30
TClass * IsA() const override
Definition TGLFaceSet.h:55
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:1299
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:124