00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TGLScenePad.h"
00013
00014 #include "TGLViewer.h"
00015 #include "TGLLogicalShape.h"
00016 #include "TGLPhysicalShape.h"
00017 #include "TGLObject.h"
00018 #include "TGLStopwatch.h"
00019 #include "TBuffer3D.h"
00020 #include "TBuffer3DTypes.h"
00021
00022 #include "TGLFaceSet.h"
00023 #include "TGLPolyLine.h"
00024 #include "TGLPolyMarker.h"
00025 #include "TGLCylinder.h"
00026 #include "TGLSphere.h"
00027
00028 #include "TVirtualPad.h"
00029 #include "TAtt3D.h"
00030 #include "TClass.h"
00031 #include "TList.h"
00032 #include "TMath.h"
00033
00034 #include "TGLPlot3D.h"
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 ClassImp(TGLScenePad)
00045
00046
00047
00048 TGLScenePad::TGLScenePad(TVirtualPad* pad) :
00049 TVirtualViewer3D(),
00050 TGLScene(),
00051
00052 fPad (pad),
00053 fInternalPIDs (kFALSE),
00054 fNextInternalPID (1),
00055 fLastPID (0),
00056 fAcceptedPhysicals (0),
00057 fComposite (0),
00058 fCSLevel (0),
00059 fSmartRefresh (kFALSE)
00060 {
00061
00062 }
00063
00064
00065
00066
00067
00068
00069
00070 void TGLScenePad::AddHistoPhysical(TGLLogicalShape* log)
00071 {
00072
00073
00074 Double_t how = ((Double_t) gPad->GetWh()) / gPad->GetWw();
00075
00076 Double_t lw = gPad->GetAbsWNDC();
00077 Double_t lh = gPad->GetAbsHNDC() * how;
00078 Double_t lm = TMath::Min(lw, lh);
00079
00080 const TGLBoundingBox& bb = log->BoundingBox();
00081
00082
00083 Double_t size = TMath::Sqrt(3) * (bb.XMax() - bb.XMin());
00084 Double_t scale = lm / size;
00085 TGLVector3 scaleVec(scale, scale, scale);
00086
00087 Double_t tx = gPad->GetAbsXlowNDC() + lw;
00088 Double_t ty = gPad->GetAbsYlowNDC() * how + lh;
00089 TGLVector3 transVec(0, ty, tx);
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 TGLMatrix mat;
00105 mat.Scale(scaleVec);
00106 mat.Translate(transVec);
00107 mat.RotateLF(3, 2, TMath::PiOver2());
00108 mat.RotateLF(1, 3, TMath::DegToRad()*gPad->GetTheta());
00109 mat.RotateLF(1, 2, TMath::DegToRad()*(gPad->GetPhi() - 90));
00110 Float_t rgba[4] = { 1, 1, 1, 1};
00111 TGLPhysicalShape* phys = new TGLPhysicalShape
00112 (fNextInternalPID++, *log, mat, false, rgba);
00113 AdoptPhysical(*phys);
00114
00115
00116
00117 }
00118
00119
00120 void TGLScenePad::SubPadPaint(TVirtualPad* pad)
00121 {
00122
00123
00124 TVirtualPad *padsav = gPad;
00125 TVirtualViewer3D *vv3dsav = pad->GetViewer3D();
00126 gPad = pad;
00127 pad->SetViewer3D(this);
00128
00129 TList *prims = pad->GetListOfPrimitives();
00130 TObjOptLink *lnk = (prims) ? (TObjOptLink*)prims->FirstLink() : 0;
00131 while (lnk)
00132 {
00133 ObjectPaint(lnk->GetObject(), lnk->GetOption());
00134 lnk = (TObjOptLink*)lnk->Next();
00135 }
00136
00137 pad->SetViewer3D(vv3dsav);
00138 gPad = padsav;
00139 }
00140
00141
00142
00143 void TGLScenePad::ObjectPaint(TObject* obj, Option_t* opt)
00144 {
00145
00146
00147
00148
00149 TGLPlot3D* log = TGLPlot3D::CreatePlot(obj, opt, gPad);
00150 if (log)
00151 {
00152 AdoptLogical(*log);
00153 AddHistoPhysical(log);
00154 }
00155 else if (obj->InheritsFrom(TAtt3D::Class()))
00156 {
00157
00158 obj->Paint(opt);
00159 }
00160 else if (obj->InheritsFrom(TVirtualPad::Class()))
00161 {
00162 SubPadPaint(dynamic_cast<TVirtualPad*>(obj));
00163 }
00164 else
00165 {
00166
00167 obj->Paint(opt);
00168 }
00169 }
00170
00171
00172 void TGLScenePad::PadPaintFromViewer(TGLViewer* viewer)
00173 {
00174
00175
00176
00177 Bool_t sr = fSmartRefresh;
00178 fSmartRefresh = viewer->GetSmartRefresh();
00179
00180 PadPaint(fPad);
00181
00182 fSmartRefresh = sr;
00183 }
00184
00185
00186 void TGLScenePad::PadPaint(TVirtualPad* pad)
00187 {
00188
00189
00190
00191
00192
00193 if (pad != fPad)
00194 {
00195 Error("TGLScenePad::PadPaint", "Mismatch between pad argument and data-member!");
00196 return;
00197 }
00198
00199 BeginScene();
00200 SubPadPaint(fPad);
00201 EndScene();
00202 }
00203
00204
00205
00206
00207
00208
00209
00210 void TGLScenePad::BeginScene()
00211 {
00212
00213
00214
00215
00216
00217
00218
00219 if (gDebug>2) {
00220 Info("TGLScenePad::BeginScene", "entering.");
00221 }
00222
00223 if ( ! BeginUpdate()) {
00224 Error("TGLScenePad::BeginScene", "could not take scene lock.");
00225 return;
00226 }
00227
00228 UInt_t destroyedLogicals = 0;
00229 UInt_t destroyedPhysicals = 0;
00230
00231 TGLStopwatch stopwatch;
00232 if (gDebug > 2) {
00233 stopwatch.Start();
00234 }
00235
00236
00237
00238
00239 destroyedPhysicals = DestroyPhysicals();
00240 if (fSmartRefresh) {
00241 destroyedLogicals = BeginSmartRefresh();
00242 } else {
00243 destroyedLogicals = DestroyLogicals();
00244 }
00245
00246
00247 fInternalPIDs = kFALSE;
00248
00249
00250 fNextInternalPID = 1;
00251 fLastPID = 0;
00252
00253
00254 fAcceptedPhysicals = 0;
00255
00256 if (gDebug > 2) {
00257 Info("TGLScenePad::BeginScene", "destroyed %d physicals %d logicals in %f msec",
00258 destroyedPhysicals, destroyedLogicals, stopwatch.End());
00259 DumpMapSizes();
00260 }
00261 }
00262
00263
00264 void TGLScenePad::EndScene()
00265 {
00266
00267
00268
00269
00270 if (fSmartRefresh) {
00271 EndSmartRefresh();
00272 }
00273
00274 EndUpdate();
00275
00276 if (gDebug > 2) {
00277 Info("TGLScenePad::EndScene", "Accepted %d physicals", fAcceptedPhysicals);
00278 DumpMapSizes();
00279 }
00280 }
00281
00282
00283 Int_t TGLScenePad::AddObject(const TBuffer3D& buffer, Bool_t* addChildren)
00284 {
00285
00286
00287
00288
00289
00290 fInternalPIDs = kTRUE;
00291 Int_t sections = AddObject(fNextInternalPID, buffer, addChildren);
00292 return sections;
00293 }
00294
00295
00296 Int_t TGLScenePad::AddObject(UInt_t physicalID, const TBuffer3D& buffer, Bool_t* addChildren)
00297 {
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 if (physicalID == 0) {
00316 Error("TGLScenePad::AddObject", "0 physical ID reserved");
00317 return TBuffer3D::kNone;
00318 }
00319
00320
00321 if (fInternalPIDs && physicalID != fNextInternalPID) {
00322 Error("TGLScenePad::AddObject", "invalid next physical ID - mix of internal + external IDs?");
00323 return TBuffer3D::kNone;
00324 }
00325
00326
00327 if (addChildren)
00328 *addChildren = kTRUE;
00329
00330
00331 if (CurrentLock() != kModifyLock) {
00332 Error("TGLScenePad::AddObject", "expected scene to be modify-locked.");
00333 return TBuffer3D::kNone;
00334 }
00335
00336
00337
00338
00339
00340 if (fComposite) {
00341 RootCsg::TBaseMesh *newMesh = RootCsg::ConvertToMesh(buffer);
00342
00343 fCSTokens.push_back(std::make_pair(static_cast<UInt_t>(TBuffer3D::kCSNoOp), newMesh));
00344 return TBuffer3D::kNone;
00345 }
00346
00347
00348 TGLPhysicalShape *physical = FindPhysical(physicalID);
00349 TGLLogicalShape *logical = 0;
00350
00351
00352
00353 if (buffer.fID)
00354 {
00355 logical = FindLogical(buffer.fID);
00356 if (!logical)
00357 logical = AttemptDirectRenderer(buffer.fID);
00358 }
00359
00360
00361 if (physicalID != fLastPID)
00362 {
00363
00364
00365 if (physical)
00366 {
00367
00368 if (!logical) {
00369 Error("TGLScenePad::AddObject", "cached physical with no assocaited cached logical");
00370 }
00371
00372
00373
00374 if (fInternalPIDs)
00375 ++fNextInternalPID;
00376
00377 return TBuffer3D::kNone;
00378 }
00379
00380
00381 Bool_t includeRaw = (logical == 0);
00382 Int_t extraSections = ValidateObjectBuffer(buffer, includeRaw);
00383 if (extraSections != TBuffer3D::kNone)
00384 return extraSections;
00385
00386 fLastPID = physicalID;
00387 }
00388
00389 if (fLastPID != physicalID) {
00390 Error("TGLScenePad::AddObject", "internal physical ID tracking error?");
00391 }
00392
00393
00394 if (physical) {
00395 Error("TGLScenePad::AddObject", "expecting to require physical");
00396 return TBuffer3D::kNone;
00397 }
00398
00399
00400 if (!logical)
00401 {
00402 logical = CreateNewLogical(buffer);
00403 if (!logical) {
00404 Error("TGLScenePad::AddObject", "failed to create logical");
00405 return TBuffer3D::kNone;
00406 }
00407
00408 AdoptLogical(*logical);
00409 }
00410
00411
00412 physical = CreateNewPhysical(physicalID, buffer, *logical);
00413
00414 if (physical)
00415 {
00416 AdoptPhysical(*physical);
00417 buffer.fPhysicalID = physicalID;
00418 ++fAcceptedPhysicals;
00419 if (gDebug>3 && fAcceptedPhysicals%1000 == 0) {
00420 Info("TGLScenePad::AddObject", "added %d physicals", fAcceptedPhysicals);
00421 }
00422 }
00423 else
00424 {
00425 Error("TGLScenePad::AddObject", "failed to create physical");
00426 }
00427
00428
00429 if (fInternalPIDs)
00430 fNextInternalPID++;
00431
00432 return TBuffer3D::kNone;
00433 }
00434
00435
00436 Bool_t TGLScenePad::OpenComposite(const TBuffer3D& buffer, Bool_t* addChildren)
00437 {
00438
00439
00440
00441
00442 if (fComposite) {
00443 Error("TGLScenePad::OpenComposite", "composite already open");
00444 return kFALSE;
00445 }
00446 UInt_t extraSections = AddObject(buffer, addChildren);
00447 if (extraSections != TBuffer3D::kNone) {
00448 Error("TGLScenePad::OpenComposite", "expected top level composite to not require extra buffer sections");
00449 }
00450
00451
00452
00453 if (fComposite) {
00454 return kTRUE;
00455 } else {
00456 return kFALSE;
00457 }
00458 }
00459
00460
00461 void TGLScenePad::CloseComposite()
00462 {
00463
00464
00465
00466
00467
00468 if (fComposite) {
00469
00470 fCSLevel = 0;
00471
00472 RootCsg::TBaseMesh *resultMesh = BuildComposite();
00473 fComposite->SetFromMesh(resultMesh);
00474 delete resultMesh;
00475 for (UInt_t i = 0; i < fCSTokens.size(); ++i) delete fCSTokens[i].second;
00476 fCSTokens.clear();
00477 fComposite = 0;
00478 }
00479 }
00480
00481
00482 void TGLScenePad::AddCompositeOp(UInt_t operation)
00483 {
00484
00485
00486
00487
00488 fCSTokens.push_back(std::make_pair(operation, (RootCsg::TBaseMesh *)0));
00489 }
00490
00491
00492
00493
00494
00495 Int_t TGLScenePad::ValidateObjectBuffer(const TBuffer3D& buffer, Bool_t includeRaw) const
00496 {
00497
00498
00499
00500
00501
00502
00503
00504 if (!buffer.SectionsValid(TBuffer3D::kCore)) {
00505 Error("TGLScenePad::ValidateObjectBuffer", "kCore section of buffer should be filled always");
00506 return TBuffer3D::kNone;
00507 }
00508
00509
00510 if (!includeRaw) {
00511 return TBuffer3D::kNone;
00512 }
00513
00514
00515 Bool_t needRaw = kFALSE;
00516
00517
00518
00519
00520 if (buffer.Type() != TBuffer3DTypes::kSphere &&
00521 buffer.Type() != TBuffer3DTypes::kTube &&
00522 buffer.Type() != TBuffer3DTypes::kTubeSeg &&
00523 buffer.Type() != TBuffer3DTypes::kCutTube &&
00524 buffer.Type() != TBuffer3DTypes::kComposite)
00525 {
00526 needRaw = kTRUE;
00527 }
00528
00529
00530 else if (buffer.Type() == TBuffer3DTypes::kSphere)
00531 {
00532 const TBuffer3DSphere * sphereBuffer = dynamic_cast<const TBuffer3DSphere *>(&buffer);
00533 if (sphereBuffer) {
00534 if (!sphereBuffer->IsSolidUncut()) {
00535 needRaw = kTRUE;
00536 }
00537 } else {
00538 Error("TGLScenePad::ValidateObjectBuffer", "failed to cast buffer of type 'kSphere' to TBuffer3DSphere");
00539 return TBuffer3D::kNone;
00540 }
00541 }
00542
00543 else if (!buffer.SectionsValid(TBuffer3D::kBoundingBox))
00544 {
00545 needRaw = kTRUE;
00546 }
00547
00548 else if (!buffer.SectionsValid(TBuffer3D::kShapeSpecific) &&
00549 buffer.Type() != TBuffer3DTypes::kComposite)
00550 {
00551 needRaw = kTRUE;
00552 }
00553
00554 else if (fComposite)
00555 {
00556 needRaw = kTRUE;
00557 }
00558
00559 if (needRaw && !buffer.SectionsValid(TBuffer3D::kRawSizes|TBuffer3D::kRaw)) {
00560 return TBuffer3D::kRawSizes|TBuffer3D::kRaw;
00561 } else {
00562 return TBuffer3D::kNone;
00563 }
00564 }
00565
00566
00567 TGLLogicalShape* TGLScenePad::CreateNewLogical(const TBuffer3D& buffer) const
00568 {
00569
00570 TGLLogicalShape * newLogical = 0;
00571
00572 if (buffer.fColor == 1)
00573 const_cast<TBuffer3D&>(buffer).fColor = 42;
00574
00575 switch (buffer.Type())
00576 {
00577 case TBuffer3DTypes::kLine:
00578 newLogical = new TGLPolyLine(buffer);
00579 break;
00580 case TBuffer3DTypes::kMarker:
00581 newLogical = new TGLPolyMarker(buffer);
00582 break;
00583 case TBuffer3DTypes::kSphere:
00584 {
00585 const TBuffer3DSphere * sphereBuffer = dynamic_cast<const TBuffer3DSphere *>(&buffer);
00586 if (sphereBuffer)
00587 {
00588
00589
00590 if (sphereBuffer->IsSolidUncut() && !buffer.SectionsValid(TBuffer3D::kRawSizes|TBuffer3D::kRaw))
00591 {
00592 newLogical = new TGLSphere(*sphereBuffer);
00593 } else {
00594 newLogical = new TGLFaceSet(buffer);
00595 }
00596 } else {
00597 Error("TGLScenePad::CreateNewLogical", "failed to cast buffer of type 'kSphere' to TBuffer3DSphere");
00598 }
00599 break;
00600 }
00601 case TBuffer3DTypes::kTube:
00602 case TBuffer3DTypes::kTubeSeg:
00603 case TBuffer3DTypes::kCutTube:
00604 {
00605 const TBuffer3DTube * tubeBuffer = dynamic_cast<const TBuffer3DTube *>(&buffer);
00606 if (tubeBuffer)
00607 {
00608
00609 if (!buffer.SectionsValid(TBuffer3D::kRawSizes|TBuffer3D::kRaw)) {
00610 newLogical = new TGLCylinder(*tubeBuffer);
00611 } else {
00612 newLogical = new TGLFaceSet(buffer);
00613 }
00614 } else {
00615 Error("TGLScenePad::CreateNewLogical", "failed to cast buffer of type 'kTube/kTubeSeg/kCutTube' to TBuffer3DTube");
00616 }
00617 break;
00618 }
00619 case TBuffer3DTypes::kComposite:
00620 {
00621
00622
00623 if (fComposite)
00624 {
00625 Error("TGLScenePad::CreateNewLogical", "composite already open");
00626 }
00627 fComposite = new TGLFaceSet(buffer);
00628 newLogical = fComposite;
00629 break;
00630 }
00631 default:
00632 newLogical = new TGLFaceSet(buffer);
00633 break;
00634 }
00635
00636 return newLogical;
00637 }
00638
00639
00640 TGLPhysicalShape*
00641 TGLScenePad::CreateNewPhysical(UInt_t ID, const TBuffer3D& buffer,
00642 const TGLLogicalShape& logical) const
00643 {
00644
00645
00646
00647
00648
00649
00650 Int_t colorIndex = buffer.fColor;
00651 if (colorIndex < 0) colorIndex = 42;
00652 Float_t rgba[4];
00653 TGLScene::RGBAFromColorIdx(rgba, colorIndex, buffer.fTransparency);
00654 return new TGLPhysicalShape(ID, logical, buffer.fLocalMaster,
00655 buffer.fReflection, rgba);
00656 }
00657
00658
00659 RootCsg::TBaseMesh* TGLScenePad::BuildComposite()
00660 {
00661
00662 const CSPart_t &currToken = fCSTokens[fCSLevel];
00663 UInt_t opCode = currToken.first;
00664
00665 if (opCode != TBuffer3D::kCSNoOp) {
00666 ++fCSLevel;
00667 RootCsg::TBaseMesh *left = BuildComposite();
00668 RootCsg::TBaseMesh *right = BuildComposite();
00669
00670 switch (opCode) {
00671 case TBuffer3D::kCSUnion:
00672 return RootCsg::BuildUnion(left, right);
00673 case TBuffer3D::kCSIntersection:
00674 return RootCsg::BuildIntersection(left, right);
00675 case TBuffer3D::kCSDifference:
00676 return RootCsg::BuildDifference(left, right);
00677 default:
00678 Error("BuildComposite", "Wrong operation code %d\n", opCode);
00679 return 0;
00680 }
00681 } else return fCSTokens[fCSLevel++].second;
00682 }
00683
00684
00685 TGLLogicalShape* TGLScenePad::AttemptDirectRenderer(TObject* id)
00686 {
00687
00688
00689
00690
00691 TClass* cls = TGLObject::GetGLRenderer(id->IsA());
00692 if (cls == 0)
00693 return 0;
00694
00695 TGLObject* rnr = reinterpret_cast<TGLObject*>(cls->New());
00696 if (rnr) {
00697 Bool_t status;
00698 try
00699 {
00700 status = rnr->SetModel(id);
00701 }
00702 catch (std::exception&)
00703 {
00704 status = kFALSE;
00705 }
00706 if (!status)
00707 {
00708 Warning("TGLScenePad::AttemptDirectRenderer", "failed initializing direct rendering.");
00709 delete rnr;
00710 return 0;
00711 }
00712 rnr->SetBBox();
00713 AdoptLogical(*rnr);
00714 }
00715 return rnr;
00716 }