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)();
40 typedef GLvoid (CALLBACK *tessfuncptr_t)();
42 #error "Error - need to define type tessfuncptr_t for this platform/compiler"
53 Bool_t TGLFaceSet::fgEnforceTriangles = kFALSE;
58 TGLFaceSet::TGLFaceSet(
const TBuffer3D & buffer) :
59 TGLLogicalShape(buffer),
60 fVertices(buffer.fPnts, buffer.fPnts + 3 * buffer.NbPnts()),
63 fNbPols = buffer.NbPols();
65 if (fNbPols == 0)
return;
67 Int_t *segs = buffer.fSegs;
68 Int_t *pols = buffer.fPols;
72 for (UInt_t i = 0, j = 1; i < fNbPols; ++i, ++j)
74 descSize += pols[j] + 1;
78 fPolyDesc.resize(descSize);
80 for (UInt_t numPol = 0, currInd = 0, j = 1; numPol < fNbPols; ++numPol)
82 Int_t segmentInd = pols[j] + j;
83 Int_t segmentCol = pols[j];
84 Int_t s1 = pols[segmentInd];
86 Int_t s2 = pols[segmentInd];
88 Int_t segEnds[] = {segs[s1 * 3 + 1], segs[s1 * 3 + 2],
89 segs[s2 * 3 + 1], segs[s2 * 3 + 2]};
90 Int_t numPnts[3] = {0};
92 if (segEnds[0] == segEnds[2]) {
93 numPnts[0] = segEnds[1], numPnts[1] = segEnds[0], numPnts[2] = segEnds[3];
94 }
else if (segEnds[0] == segEnds[3]) {
95 numPnts[0] = segEnds[1], numPnts[1] = segEnds[0], numPnts[2] = segEnds[2];
96 }
else if (segEnds[1] == segEnds[2]) {
97 numPnts[0] = segEnds[0], numPnts[1] = segEnds[1], numPnts[2] = segEnds[3];
99 numPnts[0] = segEnds[0], numPnts[1] = segEnds[1], numPnts[2] = segEnds[2];
102 fPolyDesc[currInd] = 3;
103 Int_t sizeInd = currInd++;
104 fPolyDesc[currInd++] = numPnts[0];
105 fPolyDesc[currInd++] = numPnts[1];
106 fPolyDesc[currInd++] = numPnts[2];
107 Int_t lastAdded = numPnts[2];
110 for (; segmentInd != end; segmentInd--) {
111 segEnds[0] = segs[pols[segmentInd] * 3 + 1];
112 segEnds[1] = segs[pols[segmentInd] * 3 + 2];
113 if (segEnds[0] == lastAdded) {
114 fPolyDesc[currInd++] = segEnds[1];
115 lastAdded = segEnds[1];
117 fPolyDesc[currInd++] = segEnds[0];
118 lastAdded = segEnds[0];
120 ++fPolyDesc[sizeInd];
125 if (fgEnforceTriangles) {
134 void TGLFaceSet::SetFromMesh(
const RootCsg::TBaseMesh *mesh)
136 assert(fNbPols == 0);
138 UInt_t nv = mesh->NumberOfVertices();
139 fVertices.reserve(3 * nv);
142 for (i = 0; i < nv; ++i) {
143 const Double_t *v = mesh->GetVertex(i);
144 fVertices.insert(fVertices.end(), v, v + 3);
147 fNbPols = mesh->NumberOfPolys();
151 for (i = 0; i < fNbPols; ++i) descSize += mesh->SizeOfPoly(i) + 1;
153 fPolyDesc.reserve(descSize);
155 for (UInt_t polyIndex = 0; polyIndex < fNbPols; ++polyIndex) {
156 UInt_t polySize = mesh->SizeOfPoly(polyIndex);
158 fPolyDesc.push_back(polySize);
160 for(i = 0; i < polySize; ++i) fPolyDesc.push_back(mesh->GetVertexIndex(polyIndex, i));
163 if (fgEnforceTriangles) {
176 void TGLFaceSet::EnforceTriangles()
178 class TriangleCollector
185 std::vector<Int_t> fPolyDesc;
187 void add_triangle(Int_t v0, Int_t v1, Int_t v2)
189 fPolyDesc.push_back(3);
190 fPolyDesc.push_back(v0);
191 fPolyDesc.push_back(v1);
192 fPolyDesc.push_back(v2);
196 void process_vertex(Int_t vi)
213 add_triangle(fV0, fV1, vi);
217 case GL_TRIANGLE_STRIP:
219 if (fNVertices % 2 == 0)
220 add_triangle(fV1, fV0, vi);
222 add_triangle(fV0, fV1, vi);
227 case GL_TRIANGLE_FAN:
229 add_triangle(fV0, fV1, vi);
235 throw std::runtime_error(
"TGLFaceSet::EnforceTriangles unexpected type in tess_vertex callback.");
241 TriangleCollector(GLUtesselator* ts) :
242 fNTriangles(0), fNVertices(0), fV0(-1), fV1(-1), fType(GL_NONE)
244 gluTessCallback(ts, (GLenum)GLU_TESS_BEGIN_DATA, (tessfuncptr_t)((
void*)tess_begin));
245 gluTessCallback(ts, (GLenum)GLU_TESS_VERTEX_DATA, (tessfuncptr_t)((
void*)tess_vertex));
246 gluTessCallback(ts, (GLenum)GLU_TESS_COMBINE_DATA, (tessfuncptr_t)((
void*)tess_combine));
247 gluTessCallback(ts, (GLenum)GLU_TESS_END_DATA, (tessfuncptr_t)((
void*)tess_end));
250 Int_t GetNTrianlges() {
return fNTriangles; }
251 std::vector<Int_t>& RefPolyDesc() {
return fPolyDesc; }
253 static void tess_begin(GLenum type, TriangleCollector* tc)
256 tc->fV0 = tc->fV1 = -1;
260 static void tess_vertex(Int_t* vi, TriangleCollector* tc)
262 tc->process_vertex(*vi);
265 static void tess_combine(GLdouble [3],
void* [4],
266 GLfloat [4],
void** ,
269 throw std::runtime_error(
"TGLFaceSet::EnforceTriangles tesselator requested vertex combining -- not supported yet.");
272 static void tess_end(TriangleCollector* tc)
278 GLUtesselator *tess = gluNewTess();
279 if (!tess)
throw std::bad_alloc();
281 TriangleCollector tc(tess);
284 const Double_t *pnts = &fVertices[0];
285 const Int_t *pols = &fPolyDesc[0];
287 for (UInt_t i = 0, j = 0; i < fNbPols; ++i)
289 Int_t npoints = pols[j++];
291 gluTessBeginPolygon(tess, &tc);
292 gluTessBeginContour(tess);
294 for (Int_t k = 0; k < npoints; ++k, ++j)
296 gluTessVertex(tess, (Double_t*) pnts + pols[j] * 3, (GLvoid*) &pols[j]);
299 gluTessEndContour(tess);
300 gluTessEndPolygon(tess);
305 fPolyDesc.swap(tc.RefPolyDesc());
306 fNbPols = tc.GetNTrianlges();
312 void TGLFaceSet::DirectDraw(TGLRnrCtx & rnrCtx)
const
315 Info(
"TGLFaceSet::DirectDraw",
"this %ld (class %s) LOD %d", (Long_t)
this, IsA()->GetName(), rnrCtx.ShapeLOD());
318 if (fNbPols == 0)
return;
320 GLUtesselator *tessObj = TGLUtil::GetDrawTesselator3dv();
321 const Double_t *pnts = &fVertices[0];
322 const Double_t *normals = &fNormals[0];
323 const Int_t *pols = &fPolyDesc[0];
325 for (UInt_t i = 0, j = 0; i < fNbPols; ++i) {
326 Int_t npoints = pols[j++];
328 if (tessObj && npoints > 4) {
329 gluBeginPolygon(tessObj);
330 gluNextContour(tessObj, (GLenum)GLU_UNKNOWN);
331 glNormal3dv(normals + i * 3);
333 for (Int_t k = 0; k < npoints; ++k, ++j) {
334 gluTessVertex(tessObj, (Double_t *)pnts + pols[j] * 3, (Double_t *)pnts + pols[j] * 3);
336 gluEndPolygon(tessObj);
339 glNormal3dv(normals + i * 3);
341 for (Int_t k = 0; k < npoints; ++k, ++j) {
342 glVertex3dv(pnts + pols[j] * 3);
352 Int_t TGLFaceSet::CheckPoints(
const Int_t *source, Int_t *dest)
const
354 const Double_t * p1 = &fVertices[source[0] * 3];
355 const Double_t * p2 = &fVertices[source[1] * 3];
356 const Double_t * p3 = &fVertices[source[2] * 3];
365 }
else if (Eq(p1, p3)) {
385 Bool_t TGLFaceSet::Eq(
const Double_t *p1,
const Double_t *p2)
387 Double_t dx = TMath::Abs(p1[0] - p2[0]);
388 Double_t dy = TMath::Abs(p1[1] - p2[1]);
389 Double_t dz = TMath::Abs(p1[2] - p2[2]);
390 return dx < 1e-10 && dy < 1e-10 && dz < 1e-10;
396 void TGLFaceSet::CalculateNormals()
398 fNormals.resize(3 *fNbPols);
399 if (fNbPols == 0)
return;
400 Double_t *pnts = &fVertices[0];
401 for (UInt_t i = 0, j = 0; i < fNbPols; ++i) {
402 Int_t polEnd = fPolyDesc[j] + j + 1;
403 Int_t norm[] = {fPolyDesc[j + 1], fPolyDesc[j + 2], fPolyDesc[j + 3]};
405 Int_t check = CheckPoints(norm, norm), ngood = check;
407 TMath::Normal2Plane(pnts + norm[0] * 3, pnts + norm[1] * 3,
408 pnts + norm[2] * 3, &fNormals[i * 3]);
412 while (j < (UInt_t)polEnd) {
413 norm[ngood++] = fPolyDesc[j++];
415 ngood = CheckPoints(norm, norm);
417 TMath::Normal2Plane(pnts + norm[0] * 3, pnts + norm[1] * 3,
418 pnts + norm[2] * 3, &fNormals[i * 3]);
430 Bool_t TGLFaceSet::GetEnforceTriangles()
432 return fgEnforceTriangles;
442 void TGLFaceSet::SetEnforceTriangles(Bool_t e)
444 fgEnforceTriangles = e;