30 using namespace ROOT::Experimental;
31 namespace REX = ROOT::Experimental;
38 Bool_t REX::REveGeoPolyShape::fgAutoEnforceTriangles = kTRUE;
39 Bool_t REX::REveGeoPolyShape::fgAutoCalculateNormals = kFALSE;
41 void REveGeoPolyShape::SetAutoEnforceTriangles(Bool_t f) { fgAutoEnforceTriangles = f; }
42 Bool_t REveGeoPolyShape::GetAutoEnforceTriangles() {
return fgAutoEnforceTriangles; }
43 void REveGeoPolyShape::SetAutoCalculateNormals(Bool_t f) { fgAutoCalculateNormals = f; }
44 Bool_t REveGeoPolyShape::GetAutoCalculateNormals() {
return fgAutoCalculateNormals; }
49 std::unique_ptr<RootCsg::TBaseMesh> MakeGeoMesh(TGeoMatrix *matr, TGeoShape *shape)
51 TGeoCompositeShape *comp =
dynamic_cast<TGeoCompositeShape *
> (shape);
53 std::unique_ptr<RootCsg::TBaseMesh> res;
56 std::unique_ptr<TBuffer3D> b3d(shape->MakeBuffer3D());
59 Double_t *v = b3d->fPnts;
61 for (UInt_t i = 0; i < b3d->NbPnts(); ++i) {
65 matr->LocalToMaster(buf, &v[i*3]);
69 res.reset(RootCsg::ConvertToMesh(*b3d.get()));
71 auto node = comp->GetBoolNode();
73 TGeoHMatrix mleft, mright;
74 if (matr) { mleft = *matr; mright = *matr; }
76 mleft.Multiply(node->GetLeftMatrix());
77 auto left = MakeGeoMesh(&mleft, node->GetLeftShape());
79 mright.Multiply(node->GetRightMatrix());
80 auto right = MakeGeoMesh(&mright, node->GetRightShape());
82 if (node->IsA() == TGeoUnion::Class()) res.reset(RootCsg::BuildUnion(left.get(), right.get()));
83 if (node->IsA() == TGeoIntersection::Class()) res.reset(RootCsg::BuildIntersection(left.get(), right.get()));
84 if (node->IsA() == TGeoSubtraction::Class()) res.reset(RootCsg::BuildDifference(left.get(), right.get()));
93 void REveGeoPolyShape::BuildFromComposite(TGeoCompositeShape *cshape, Int_t n_seg)
95 fOrigin[0] = cshape->GetOrigin()[0];
96 fOrigin[1] = cshape->GetOrigin()[1];
97 fOrigin[2] = cshape->GetOrigin()[2];
98 fDX = cshape->GetDX();
99 fDY = cshape->GetDY();
100 fDZ = cshape->GetDZ();
102 REveGeoManagerHolder gmgr(REveGeoShape::GetGeoManager(), n_seg);
104 auto mesh = MakeGeoMesh(
nullptr, cshape);
106 Int_t nv = mesh->NumberOfVertices();
107 fVertices.reserve(3 * nv);
109 for (Int_t i = 0; i < nv; ++i) {
110 auto v = mesh->GetVertex(i);
111 fVertices.insert(fVertices.end(), v, v + 3);
114 fNbPols = mesh->NumberOfPolys();
118 for (Int_t i = 0; i < fNbPols; ++i) descSize += mesh->SizeOfPoly(i) + 1;
120 fPolyDesc.reserve(descSize);
122 for (Int_t polyIndex = 0; polyIndex < fNbPols; ++polyIndex) {
123 Int_t polySize = mesh->SizeOfPoly(polyIndex);
125 fPolyDesc.push_back(polySize);
127 for (Int_t i = 0; i < polySize; ++i)
128 fPolyDesc.push_back(mesh->GetVertexIndex(polyIndex, i));
131 if (fgAutoEnforceTriangles) EnforceTriangles();
132 if (fgAutoCalculateNormals) CalculateNormals();
138 void REveGeoPolyShape::BuildFromShape(TGeoShape *shape, Int_t n_seg)
140 TGeoBBox *box =
dynamic_cast<TGeoBBox *
> (shape);
143 fOrigin[0] = box->GetOrigin()[0];
144 fOrigin[1] = box->GetOrigin()[1];
145 fOrigin[2] = box->GetOrigin()[2];
151 REveGeoManagerHolder gmgr(REveGeoShape::GetGeoManager(), n_seg);
153 std::unique_ptr<TBuffer3D> b3d(shape->MakeBuffer3D());
155 SetFromBuff3D(*b3d.get());
160 void REveGeoPolyShape::FillRenderData(REveRenderData &rd)
164 rd.Reserve(fVertices.size(), fNormals.size(), 2 + fNbPols * 3);
166 for (
auto &v: fVertices)
169 for (
auto &n: fNormals)
172 rd.PushI(REveRenderData::GL_TRIANGLES);
176 for (Int_t i = 0, j = 0; i < fNbPols; ++i) {
177 assert(fPolyDesc[j] == 3);
179 rd.PushI(fPolyDesc[j + 1], fPolyDesc[j + 2], fPolyDesc[j + 3]);
180 j += 1 + fPolyDesc[j];
188 void REveGeoPolyShape::SetFromBuff3D(
const TBuffer3D& buffer)
190 fNbPols = (Int_t) buffer.NbPols();
192 if (fNbPols == 0)
return;
194 fVertices.insert(fVertices.end(), buffer.fPnts, buffer.fPnts + 3 * buffer.NbPnts());
196 Int_t *segs = buffer.fSegs;
197 Int_t *pols = buffer.fPols;
201 for (Int_t i = 0, j = 1; i < fNbPols; ++i, ++j)
203 descSize += pols[j] + 1;
207 fPolyDesc.resize(descSize);
209 for (Int_t numPol = 0, currInd = 0, j = 1; numPol < fNbPols; ++numPol)
211 Int_t segmentInd = pols[j] + j;
212 Int_t segmentCol = pols[j];
213 Int_t s1 = pols[segmentInd];
215 Int_t s2 = pols[segmentInd];
217 Int_t segEnds[] = {segs[s1 * 3 + 1], segs[s1 * 3 + 2],
218 segs[s2 * 3 + 1], segs[s2 * 3 + 2]};
221 if (segEnds[0] == segEnds[2]) {
222 numPnts[0] = segEnds[1]; numPnts[1] = segEnds[0]; numPnts[2] = segEnds[3];
223 }
else if (segEnds[0] == segEnds[3]) {
224 numPnts[0] = segEnds[1]; numPnts[1] = segEnds[0]; numPnts[2] = segEnds[2];
225 }
else if (segEnds[1] == segEnds[2]) {
226 numPnts[0] = segEnds[0]; numPnts[1] = segEnds[1]; numPnts[2] = segEnds[3];
228 numPnts[0] = segEnds[0]; numPnts[1] = segEnds[1]; numPnts[2] = segEnds[2];
231 fPolyDesc[currInd] = 3;
232 Int_t sizeInd = currInd++;
233 fPolyDesc[currInd++] = numPnts[0];
234 fPolyDesc[currInd++] = numPnts[1];
235 fPolyDesc[currInd++] = numPnts[2];
236 Int_t lastAdded = numPnts[2];
239 for (; segmentInd != end; segmentInd--) {
240 segEnds[0] = segs[pols[segmentInd] * 3 + 1];
241 segEnds[1] = segs[pols[segmentInd] * 3 + 2];
242 if (segEnds[0] == lastAdded) {
243 fPolyDesc[currInd++] = segEnds[1];
244 lastAdded = segEnds[1];
246 fPolyDesc[currInd++] = segEnds[0];
247 lastAdded = segEnds[0];
249 ++fPolyDesc[sizeInd];
254 if (fgAutoEnforceTriangles) EnforceTriangles();
255 if (fgAutoCalculateNormals) CalculateNormals();
265 void REveGeoPolyShape::EnforceTriangles()
267 EveGlu::TriangleCollector tc;
269 tc.ProcessData(fVertices, fPolyDesc, fNbPols);
271 fPolyDesc.swap(tc.RefPolyDesc());
272 fNbPols = tc.GetNTrianlges();
278 void REveGeoPolyShape::CalculateNormals()
280 fNormals.resize(3 * fNbPols);
281 if (fNbPols == 0)
return;
282 Double_t *pnts = &fVertices[0];
283 for (Int_t i = 0, j = 0; i < fNbPols; ++i)
285 Int_t polEnd = fPolyDesc[j] + j + 1;
286 Int_t norm[] = {fPolyDesc[j + 1], fPolyDesc[j + 2], fPolyDesc[j + 3]};
288 Int_t check = CheckPoints(norm, norm);
291 TMath::Normal2Plane(pnts + norm[0] * 3, pnts + norm[1] * 3,
292 pnts + norm[2] * 3, &fNormals[i * 3]);
298 norm[ngood++] = fPolyDesc[j++];
300 ngood = CheckPoints(norm, norm);
302 TMath::Normal2Plane(pnts + norm[0] * 3, pnts + norm[1] * 3,
303 pnts + norm[2] * 3, &fNormals[i * 3]);
315 Int_t REveGeoPolyShape::CheckPoints(
const Int_t *source, Int_t *dest)
const
317 const Double_t * p1 = &fVertices[source[0] * 3];
318 const Double_t * p2 = &fVertices[source[1] * 3];
319 const Double_t * p3 = &fVertices[source[2] * 3];
328 }
else if (Eq(p1, p3)) {
348 Bool_t REveGeoPolyShape::Eq(
const Double_t *p1,
const Double_t *p2)
350 Double_t dx = TMath::Abs(p1[0] - p2[0]);
351 Double_t dy = TMath::Abs(p1[1] - p2[1]);
352 Double_t dz = TMath::Abs(p1[2] - p2[2]);
353 return (dx < 1e-10) && (dy < 1e-10) && (dz < 1e-10);
359 void REveGeoPolyShape::FillBuffer3D(TBuffer3D& b, Int_t reqSections, Bool_t)
const
361 if (reqSections & TBuffer3D::kCore)
364 b.ClearSectionsValid();
366 b.fID =
const_cast<REveGeoPolyShape*
>(
this);
369 b.fLocalFrame = kFALSE;
370 b.fReflection = kTRUE;
372 b.SetSectionsValid(TBuffer3D::kCore);
375 if ((reqSections & TBuffer3D::kRawSizes) || (reqSections & TBuffer3D::kRaw))
377 Int_t nvrt = fVertices.size() / 3;
380 std::map<Edge_t, Int_t> edges;
382 const Int_t *pd = &fPolyDesc[0];
383 for (Int_t i = 0; i < fNbPols; ++i) {
386 for (Int_t j = 0; j < nv; ++j) {
387 Edge_t e(pd[j], (j != nv - 1) ? pd[j + 1] : pd[0]);
388 if (edges.find(e) == edges.end()) {
389 edges.insert(std::make_pair(e, 0));
396 b.SetRawSizes(nvrt, 3*nvrt, nseg, 3*nseg, fNbPols, fNbPols+fPolyDesc.size());
398 memcpy(b.fPnts, &fVertices[0],
sizeof(Double_t)*fVertices.size());
400 Int_t si = 0, scnt = 0;
401 for (
auto &edge : edges) {
403 b.fSegs[si++] = edge.first.fI;
404 b.fSegs[si++] = edge.first.fJ;
405 edge.second = scnt++;
410 for (Int_t i = 0; i < fNbPols; ++i) {
415 for (Int_t j = 0; j < nv; ++j) {
416 b.fPols[pi++] = edges[Edge_t(pd[j], (j != nv - 1) ? pd[j + 1] : pd[0])];
421 b.SetSectionsValid(TBuffer3D::kRawSizes | TBuffer3D::kRaw);
428 const TBuffer3D& REveGeoPolyShape::GetBuffer3D(Int_t reqSections, Bool_t localFrame)
const
430 static TBuffer3D buf(TBuffer3DTypes::kGeneric);
432 FillBuffer3D(buf, reqSections, localFrame);
440 TBuffer3D *REveGeoPolyShape::MakeBuffer3D()
const
442 auto *buf =
new TBuffer3D(TBuffer3DTypes::kGeneric);
444 FillBuffer3D(*buf, TBuffer3D::kCore | TBuffer3D::kRawSizes | TBuffer3D::kRaw, kFALSE);