00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "TGLScene.h"
00015 #include "TGLRnrCtx.h"
00016 #include "TGLObject.h"
00017 #include "TGLSelectRecord.h"
00018 #include "TGLLogicalShape.h"
00019 #include "TGLPhysicalShape.h"
00020 #include "TGLCamera.h"
00021 #include "TGLContext.h"
00022 #include "TGLIncludes.h"
00023
00024 #include <TColor.h>
00025 #include <TROOT.h>
00026 #include <TClass.h>
00027
00028 #include <algorithm>
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 TGLScene::TSceneInfo::TSceneInfo(TGLViewerBase* view, TGLScene* scene) :
00047 TGLSceneInfo (view, scene),
00048 fMinorStamp (0),
00049 fOpaqueCnt (0),
00050 fTranspCnt (0),
00051 fAsPixelCnt (0)
00052 {
00053
00054 }
00055
00056
00057 TGLScene::TSceneInfo::~TSceneInfo()
00058 {
00059
00060 }
00061
00062
00063 void TGLScene::TSceneInfo::ClearDrawElementVec(DrawElementVec_t& vec,
00064 Int_t maxSize)
00065 {
00066
00067
00068
00069 if (vec.capacity() > (size_t) maxSize) {
00070 DrawElementVec_t foo;
00071 foo.reserve((size_t) maxSize);
00072 vec.swap(foo);
00073 } else {
00074 vec.clear();
00075 }
00076 }
00077
00078
00079 void TGLScene::TSceneInfo::ClearDrawElementPtrVec(DrawElementPtrVec_t& vec,
00080 Int_t maxSize)
00081 {
00082
00083
00084
00085 if (vec.capacity() > (size_t) maxSize) {
00086 DrawElementPtrVec_t foo;
00087 foo.reserve((size_t) maxSize);
00088 vec.swap(foo);
00089 } else {
00090 vec.clear();
00091 }
00092 }
00093
00094
00095 void TGLScene::TSceneInfo::ClearAfterRebuild()
00096 {
00097
00098
00099
00100
00101 Int_t maxSize = (Int_t) fShapesOfInterest.size();
00102
00103 ClearDrawElementVec(fVisibleElements, maxSize);
00104 }
00105
00106
00107 void TGLScene::TSceneInfo::ClearAfterUpdate()
00108 {
00109
00110
00111
00112
00113 Int_t maxSize = (Int_t) fShapesOfInterest.size();
00114
00115 ClearDrawElementPtrVec(fOpaqueElements, maxSize);
00116 ClearDrawElementPtrVec(fTranspElements, maxSize);
00117 ClearDrawElementPtrVec(fSelOpaqueElements, maxSize);
00118 ClearDrawElementPtrVec(fSelTranspElements, maxSize);
00119
00120 fMinorStamp = 0;
00121 }
00122
00123
00124 void TGLScene::TSceneInfo::Lodify(TGLRnrCtx& ctx)
00125 {
00126
00127
00128 for (DrawElementVec_i i = fVisibleElements.begin(); i != fVisibleElements.end(); ++i)
00129 i->fPhysical->QuantizeShapeLOD(i->fPixelLOD, ctx.CombiLOD(), i->fFinalLOD);
00130 }
00131
00132
00133 void TGLScene::TSceneInfo::PreDraw()
00134 {
00135
00136
00137
00138 if (fMinorStamp < fScene->GetMinorStamp())
00139 {
00140 fOpaqueElements.clear();
00141 fTranspElements.clear();
00142 fSelOpaqueElements.clear();
00143 fSelTranspElements.clear();
00144
00145 for (DrawElementVec_i i = fVisibleElements.begin(); i != fVisibleElements.end(); ++i)
00146 {
00147 if (i->fPhysical->IsSelected())
00148 {
00149 if (i->fPhysical->IsTransparent())
00150 fSelTranspElements.push_back(&*i);
00151 else
00152 fSelOpaqueElements.push_back(&*i);
00153 } else {
00154 if (i->fPhysical->IsTransparent())
00155 fTranspElements.push_back(&*i);
00156 else
00157 fOpaqueElements.push_back(&*i);
00158 }
00159 }
00160 fMinorStamp = fScene->GetMinorStamp();
00161 }
00162 }
00163
00164
00165 void TGLScene::TSceneInfo::PostDraw()
00166 {
00167
00168 }
00169
00170
00171 void TGLScene::TSceneInfo::ResetDrawStats()
00172 {
00173
00174
00175 fOpaqueCnt = 0;
00176 fTranspCnt = 0;
00177 fAsPixelCnt = 0;
00178 fByShapeCnt.clear();
00179 }
00180
00181
00182 void TGLScene::TSceneInfo::UpdateDrawStats(const TGLPhysicalShape& shape,
00183 Short_t lod)
00184 {
00185
00186
00187
00188 if (shape.IsTransparent()) {
00189 ++fTranspCnt;
00190 } else {
00191 ++fOpaqueCnt;
00192 }
00193
00194 if (lod == TGLRnrCtx::kLODPixel) {
00195 ++fAsPixelCnt;
00196 }
00197
00198
00199 if (gDebug>3) {
00200
00201 TClass* logIsA = shape.GetLogical()->IsA();
00202 std::map<TClass*, UInt_t>::iterator it = fByShapeCnt.find(logIsA);
00203 if (it == fByShapeCnt.end()) {
00204
00205 it = fByShapeCnt.insert(std::make_pair(logIsA, 0u)).first;
00206 }
00207
00208 it->second++;
00209 }
00210 }
00211
00212
00213 void TGLScene::TSceneInfo::DumpDrawStats()
00214 {
00215
00216
00217 if (gDebug>2)
00218 {
00219 TString out;
00220
00221 out += Form("Drew scene (%s / %i LOD) - %i (Op %i Trans %i) %i pixel\n",
00222 TGLRnrCtx::StyleName(LastStyle()), LastLOD(),
00223 fOpaqueCnt + fTranspCnt, fOpaqueCnt, fTranspCnt, fAsPixelCnt);
00224 out += Form("\tInner phys nums: physicals=%d, of_interest=%lu, visible=%lu, op=%lu, trans=%lu",
00225 ((TGLScene*)fScene)->GetMaxPhysicalID(),
00226 (ULong_t)fShapesOfInterest.size(), (ULong_t)fVisibleElements.size(),
00227 (ULong_t)fOpaqueElements.size(), (ULong_t)fTranspElements.size());
00228
00229
00230 if (gDebug>3)
00231 {
00232 out += "\n\tStatistics by shape:\n";
00233 std::map<TClass*, UInt_t>::const_iterator it = fByShapeCnt.begin();
00234 while (it != fByShapeCnt.end()) {
00235 out += Form("\t%-20s %u\n", it->first->GetName(), it->second);
00236 it++;
00237 }
00238 }
00239 Info("TGLScene::DumpDrawStats()", "%s",out.Data());
00240 }
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 ClassImp(TGLScene);
00275
00276
00277 TGLScene::TGLScene() :
00278 TGLSceneBase(),
00279 fGLCtxIdentity(0),
00280 fInSmartRefresh(kFALSE),
00281 fLastPointSizeScale (0),
00282 fLastLineWidthScale (0)
00283 {}
00284
00285
00286 TGLScene::~TGLScene()
00287 {
00288
00289 TakeLock(kModifyLock);
00290 ReleaseGLCtxIdentity();
00291 DestroyPhysicals();
00292 DestroyLogicals();
00293 if (fGLCtxIdentity)
00294 fGLCtxIdentity->ReleaseClient();
00295 ReleaseLock(kModifyLock);
00296 }
00297
00298
00299
00300
00301
00302
00303 void TGLScene::ReleaseGLCtxIdentity()
00304 {
00305
00306
00307
00308 if (fGLCtxIdentity == 0) return;
00309
00310 if (fGLCtxIdentity->IsValid())
00311 {
00312
00313 LogicalShapeMapIt_t lit = fLogicalShapes.begin();
00314 while (lit != fLogicalShapes.end()) {
00315 lit->second->DLCachePurge();
00316 ++lit;
00317 }
00318 }
00319 else
00320 {
00321
00322 LogicalShapeMapIt_t lit = fLogicalShapes.begin();
00323 while (lit != fLogicalShapes.end()) {
00324 lit->second->DLCacheDrop();
00325 ++lit;
00326 }
00327 }
00328 fGLCtxIdentity->ReleaseClient();
00329 fGLCtxIdentity = 0;
00330 }
00331
00332
00333
00334
00335
00336
00337
00338 TGLScene::TSceneInfo* TGLScene::CreateSceneInfo(TGLViewerBase* view)
00339 {
00340
00341
00342
00343
00344 return new TSceneInfo(view, this);
00345 }
00346
00347
00348 inline Bool_t TGLScene::ComparePhysicalVolumes(const TGLPhysicalShape* shape1,
00349 const TGLPhysicalShape* shape2)
00350 {
00351
00352
00353
00354 return (shape1->BoundingBox().Volume() > shape2->BoundingBox().Volume());
00355 }
00356
00357
00358 inline Bool_t TGLScene::ComparePhysicalDiagonals(const TGLPhysicalShape* shape1,
00359 const TGLPhysicalShape* shape2)
00360 {
00361
00362
00363
00364 return (shape1->BoundingBox().Diagonal() > shape2->BoundingBox().Diagonal());
00365 }
00366
00367
00368 void TGLScene::RebuildSceneInfo(TGLRnrCtx& rnrCtx)
00369 {
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
00380 if (sinfo == 0 || sinfo->GetScene() != this) {
00381 Error("TGLScene::RebuildSceneInfo", "Scene mismatch.");
00382 return;
00383 }
00384
00385 TGLSceneBase::RebuildSceneInfo(rnrCtx);
00386
00387 if (sinfo->fShapesOfInterest.capacity() > fPhysicalShapes.size()) {
00388 ShapeVec_t foo;
00389 foo.reserve(fPhysicalShapes.size());
00390 sinfo->fShapesOfInterest.swap(foo);
00391 } else {
00392 sinfo->fShapesOfInterest.clear();
00393 }
00394
00395 PhysicalShapeMapIt_t pit = fPhysicalShapes.begin();
00396 while (pit != fPhysicalShapes.end())
00397 {
00398 TGLPhysicalShape * pshp = pit->second;
00399 const TGLLogicalShape * lshp = pshp->GetLogical();
00400 if (rnrCtx.GetCamera()->OfInterest(pshp->BoundingBox(),
00401 lshp->IgnoreSizeForOfInterest()))
00402 {
00403 sinfo->fShapesOfInterest.push_back(pshp);
00404 }
00405 ++pit;
00406 }
00407
00408 std::sort(sinfo->fShapesOfInterest.begin(), sinfo->fShapesOfInterest.end(),
00409 TGLScene::ComparePhysicalDiagonals);
00410
00411 sinfo->ClearAfterRebuild();
00412 }
00413
00414
00415 void TGLScene::UpdateSceneInfo(TGLRnrCtx& rnrCtx)
00416 {
00417
00418
00419
00420
00421
00422
00423 TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
00424 if (sinfo == 0 || sinfo->GetScene() != this) {
00425 Error("TGLScene::UpdateSceneInfo", "Scene mismatch.");
00426 return;
00427 }
00428
00429
00430
00431 TGLSceneBase::UpdateSceneInfo(rnrCtx);
00432
00433 if (!sinfo->IsVisible())
00434 return;
00435
00436 sinfo->fVisibleElements.clear();
00437
00438
00439
00440 Int_t checkCount = 0;
00441 Bool_t timerp = rnrCtx.IsStopwatchRunning();
00442 sinfo->ResetUpdateTimeouted();
00443
00444 for (ShapeVec_i phys=sinfo->fShapesOfInterest.begin();
00445 phys!=sinfo->fShapesOfInterest.end();
00446 ++phys, ++checkCount)
00447 {
00448 const TGLPhysicalShape * drawShape = *phys;
00449
00450
00451
00452
00453
00454
00455 Bool_t drawNeeded = kTRUE;
00456
00457
00458
00459
00460 if (sinfo->ClipMode() == TGLSceneInfo::kClipOutside)
00461 {
00462
00463 std::vector<TGLPlane>::iterator pi = sinfo->ClipPlanes().begin();
00464 while (pi != sinfo->ClipPlanes().end())
00465 {
00466 if (drawShape->BoundingBox().Overlap(*pi) == kOutside)
00467 {
00468 drawNeeded = kFALSE;
00469 break;
00470 }
00471 ++pi;
00472 }
00473 }
00474 else if (sinfo->ClipMode() == TGLSceneInfo::kClipInside)
00475 {
00476
00477 std::vector<TGLPlane>::iterator pi = sinfo->ClipPlanes().begin();
00478 size_t cnt = 0;
00479 while (pi != sinfo->ClipPlanes().end())
00480 {
00481 EOverlap ovlp = drawShape->BoundingBox().Overlap(*pi);
00482 if (ovlp == kOutside)
00483 break;
00484 else if (ovlp == kInside)
00485 ++cnt;
00486 ++pi;
00487 }
00488 if (cnt == sinfo->ClipPlanes().size())
00489 drawNeeded = kFALSE;
00490 }
00491
00492
00493
00494 if (drawNeeded)
00495 {
00496 std::vector<TGLPlane>::iterator pi = sinfo->FrustumPlanes().begin();
00497 while (pi != sinfo->FrustumPlanes().end())
00498 {
00499 if (drawShape->BoundingBox().Overlap(*pi) == kOutside)
00500 {
00501 drawNeeded = kFALSE;
00502 break;
00503 }
00504 ++pi;
00505 }
00506 }
00507
00508
00509 if (drawNeeded)
00510 {
00511 DrawElement_t de(drawShape);
00512 drawShape->CalculateShapeLOD(rnrCtx, de.fPixelSize, de.fPixelLOD);
00513 sinfo->fVisibleElements.push_back(de);
00514 }
00515
00516
00517
00518 if (timerp && (checkCount % 5000) == 0 && rnrCtx.HasStopwatchTimedOut())
00519 {
00520 sinfo->UpdateTimeouted();
00521 if (rnrCtx.ViewerLOD() == TGLRnrCtx::kLODHigh)
00522 Warning("TGLScene::UpdateSceneInfo",
00523 "Timeout reached, not all elements processed.");
00524 break;
00525 }
00526 }
00527
00528 sinfo->ClearAfterUpdate();
00529
00530
00531
00532
00533 }
00534
00535
00536 void TGLScene::LodifySceneInfo(TGLRnrCtx& rnrCtx)
00537 {
00538
00539
00540
00541 TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
00542 if (sinfo == 0 || sinfo->GetScene() != this) {
00543 Error("TGLScene::LodifySceneInfo", "Scene mismatch.");
00544 return;
00545 }
00546
00547 TGLSceneBase::LodifySceneInfo(rnrCtx);
00548
00549 sinfo->Lodify(rnrCtx);
00550 }
00551
00552
00553
00554
00555
00556
00557
00558 void TGLScene::PreDraw(TGLRnrCtx& rnrCtx)
00559 {
00560
00561
00562
00563
00564
00565 TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
00566 if (sinfo == 0 || sinfo->GetScene() != this) {
00567 TGLSceneInfo* si = rnrCtx.GetSceneInfo();
00568 Error("TGLScene::PreDraw", "%s", Form("SceneInfo mismatch (0x%lx, '%s').",
00569 (ULong_t)si, si ? si->IsA()->GetName() : "<>"));
00570 return;
00571 }
00572
00573
00574 TGLSceneBase::PreDraw(rnrCtx);
00575
00576 TGLContextIdentity* cid = rnrCtx.GetGLCtxIdentity();
00577 if (cid != fGLCtxIdentity)
00578 {
00579 ReleaseGLCtxIdentity();
00580 fGLCtxIdentity = cid;
00581 fGLCtxIdentity->AddClientRef();
00582 }
00583 else
00584 {
00585 if (fLastPointSizeScale != TGLUtil::GetPointSizeScale() ||
00586 fLastLineWidthScale != TGLUtil::GetLineWidthScale())
00587 {
00588
00589 LogicalShapeMapIt_t lit = fLogicalShapes.begin();
00590 while (lit != fLogicalShapes.end()) {
00591 lit->second->DLCacheClear();
00592 ++lit;
00593 }
00594 }
00595 }
00596 fLastPointSizeScale = TGLUtil::GetPointSizeScale();
00597 fLastLineWidthScale = TGLUtil::GetLineWidthScale();
00598
00599 sinfo->PreDraw();
00600
00601
00602 sinfo->ResetDrawStats();
00603 }
00604
00605
00606 void TGLScene::RenderOpaque(TGLRnrCtx& rnrCtx)
00607 {
00608
00609
00610 TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
00611 if (!sinfo->fOpaqueElements.empty())
00612 RenderAllPasses(rnrCtx, sinfo->fOpaqueElements, kTRUE);
00613 }
00614
00615
00616 void TGLScene::RenderTransp(TGLRnrCtx& rnrCtx)
00617 {
00618
00619
00620 TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
00621 if (!sinfo->fTranspElements.empty())
00622 RenderAllPasses(rnrCtx, sinfo->fTranspElements, kTRUE);
00623 }
00624
00625
00626 void TGLScene::RenderSelOpaque(TGLRnrCtx& rnrCtx)
00627 {
00628
00629
00630 TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
00631 if (!sinfo->fSelOpaqueElements.empty())
00632 RenderAllPasses(rnrCtx, sinfo->fSelOpaqueElements, kFALSE);
00633 }
00634
00635
00636 void TGLScene::RenderSelTransp(TGLRnrCtx& rnrCtx)
00637 {
00638
00639
00640 TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
00641 if (!sinfo->fSelTranspElements.empty())
00642 RenderAllPasses(rnrCtx, sinfo->fSelTranspElements, kFALSE);
00643 }
00644
00645
00646 void TGLScene::PostDraw(TGLRnrCtx& rnrCtx)
00647 {
00648
00649
00650
00651
00652 TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
00653
00654 if (gDebug)
00655 sinfo->DumpDrawStats();
00656
00657 sinfo->PostDraw();
00658
00659 TGLSceneBase::PostDraw(rnrCtx);
00660 }
00661
00662
00663 void TGLScene::RenderAllPasses(TGLRnrCtx& rnrCtx,
00664 DrawElementPtrVec_t& elVec,
00665 Bool_t check_timeout)
00666 {
00667
00668
00669
00670
00671
00672 TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
00673 assert(sinfo != 0);
00674
00675 Short_t sceneStyle = rnrCtx.SceneStyle();
00676
00677
00678 Int_t reqPasses = 1;
00679
00680 Short_t rnrPass[2];
00681 rnrPass[0] = rnrPass[1] = TGLRnrCtx::kPassUndef;
00682
00683 switch (sceneStyle)
00684 {
00685 case TGLRnrCtx::kFill:
00686 case TGLRnrCtx::kOutline:
00687 {
00688 glEnable(GL_LIGHTING);
00689 if (sinfo->ShouldClip()) {
00690
00691 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
00692 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00693 glDisable(GL_CULL_FACE);
00694 }
00695
00696
00697 if (sceneStyle == TGLRnrCtx::kOutline) {
00698 reqPasses = 2;
00699 rnrPass[0] = TGLRnrCtx::kPassOutlineFill;
00700 rnrPass[1] = TGLRnrCtx::kPassOutlineLine;
00701 } else {
00702 rnrPass[0] = TGLRnrCtx::kPassFill;
00703 }
00704 break;
00705 }
00706 case TGLRnrCtx::kWireFrame:
00707 {
00708 rnrPass[0] = TGLRnrCtx::kPassWireFrame;
00709 glDisable(GL_LIGHTING);
00710 glDisable(GL_CULL_FACE);
00711 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00712 break;
00713 }
00714 default:
00715 {
00716 assert(kFALSE);
00717 }
00718 }
00719
00720 for (Int_t i = 0; i < reqPasses; ++i)
00721 {
00722
00723
00724
00725 Short_t pass = rnrPass[i];
00726 rnrCtx.SetDrawPass(pass);
00727
00728 if (pass == TGLRnrCtx::kPassOutlineFill)
00729 {
00730
00731 glEnable(GL_POLYGON_OFFSET_FILL);
00732 glPolygonOffset(0.5f, 0.5f);
00733 }
00734 else if (pass == TGLRnrCtx::kPassOutlineLine)
00735 {
00736
00737 TGLUtil::LineWidth(rnrCtx.SceneOLLineW());
00738 glDisable(GL_POLYGON_OFFSET_FILL);
00739 glDisable(GL_LIGHTING);
00740
00741
00742
00743
00744
00745
00746
00747 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00748 }
00749 else if (pass == TGLRnrCtx::kPassWireFrame)
00750 {
00751 TGLUtil::LineWidth(rnrCtx.SceneWFLineW());
00752 }
00753
00754
00755 if ( ! sinfo->ShouldClip())
00756 {
00757 RenderElements(rnrCtx, elVec, check_timeout);
00758 }
00759 else
00760 {
00761
00762 TGLPlaneSet_t & planeSet = sinfo->ClipPlanes();
00763
00764 if (gDebug > 3)
00765 {
00766 Info("TGLScene::RenderAllPasses()",
00767 "%ld active clip planes", (Long_t)planeSet.size());
00768 }
00769
00770 Int_t maxGLPlanes;
00771 glGetIntegerv(GL_MAX_CLIP_PLANES, &maxGLPlanes);
00772 UInt_t maxPlanes = maxGLPlanes;
00773 UInt_t planeInd;
00774 if (planeSet.size() < maxPlanes) {
00775 maxPlanes = planeSet.size();
00776 }
00777
00778 if (sinfo->ClipMode() == TGLSceneInfo::kClipOutside)
00779 {
00780
00781
00782 for (UInt_t ii=0; ii<maxPlanes; ii++) {
00783 glClipPlane(GL_CLIP_PLANE0+ii, planeSet[ii].CArr());
00784 glEnable(GL_CLIP_PLANE0+ii);
00785 }
00786
00787
00788
00789 RenderElements(rnrCtx, elVec, check_timeout);
00790 }
00791 else
00792 {
00793
00794
00795
00796 std::vector<TGLPlane> activePlanes;
00797 for (planeInd=0; planeInd<maxPlanes; planeInd++)
00798 {
00799 activePlanes.push_back(planeSet[planeInd]);
00800 TGLPlane& p = activePlanes.back();
00801 p.Negate();
00802 glClipPlane(GL_CLIP_PLANE0+planeInd, p.CArr());
00803 glEnable(GL_CLIP_PLANE0+planeInd);
00804
00805
00806
00807 RenderElements(rnrCtx, elVec, check_timeout, &activePlanes);
00808
00809 p.Negate();
00810 glClipPlane(GL_CLIP_PLANE0+planeInd, p.CArr());
00811 }
00812 }
00813
00814 for (planeInd=0; planeInd<maxPlanes; planeInd++) {
00815 glDisable(GL_CLIP_PLANE0+planeInd);
00816 }
00817 }
00818 }
00819
00820
00821 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
00822 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00823 glEnable(GL_CULL_FACE);
00824 glEnable(GL_LIGHTING);
00825 }
00826
00827
00828 void TGLScene::RenderElements(TGLRnrCtx& rnrCtx,
00829 DrawElementPtrVec_t& elVec,
00830 Bool_t check_timeout,
00831 const TGLPlaneSet_t* clipPlanes)
00832 {
00833
00834
00835
00836
00837 TSceneInfo* sinfo = dynamic_cast<TSceneInfo*>(rnrCtx.GetSceneInfo());
00838 assert(sinfo != 0);
00839
00840 Int_t drawCount = 0;
00841
00842 for (DrawElementPtrVec_i i = elVec.begin(); i != elVec.end(); ++i)
00843 {
00844 const TGLPhysicalShape * drawShape = (*i)->fPhysical;
00845
00846 Bool_t drawNeeded = kTRUE;
00847
00848
00849 if (clipPlanes && IsOutside(drawShape->BoundingBox(), *clipPlanes))
00850 drawNeeded = kFALSE;
00851
00852
00853 if (drawNeeded)
00854 {
00855 rnrCtx.SetShapeLOD((*i)->fFinalLOD);
00856 rnrCtx.SetShapePixSize((*i)->fPixelSize);
00857 glPushName(drawShape->ID());
00858 drawShape->Draw(rnrCtx);
00859 glPopName();
00860 ++drawCount;
00861 sinfo->UpdateDrawStats(*drawShape, rnrCtx.ShapeLOD());
00862 }
00863
00864
00865
00866 if (check_timeout && (drawCount % 2000) == 0 &&
00867 rnrCtx.HasStopwatchTimedOut())
00868 {
00869 if (rnrCtx.ViewerLOD() == TGLRnrCtx::kLODHigh)
00870 Warning("TGLScene::RenderElements",
00871 "Timeout reached, not all elements rendered.");
00872 break;
00873 }
00874 }
00875 }
00876
00877
00878
00879
00880
00881
00882
00883 Bool_t TGLScene::ResolveSelectRecord(TGLSelectRecord& rec, Int_t curIdx)
00884 {
00885
00886
00887
00888
00889
00890
00891 if (curIdx >= rec.GetN())
00892 return kFALSE;
00893
00894 TGLPhysicalShape* pshp = FindPhysical(rec.GetItem(curIdx));
00895 if (pshp)
00896 {
00897 rec.SetTransparent(pshp->IsTransparent());
00898 rec.SetPhysShape(pshp);
00899 rec.SetObject(pshp->GetLogical()->GetExternal());
00900 rec.SetSpecific(0);
00901 return kTRUE;
00902 }
00903 return kFALSE;
00904 }
00905
00906
00907
00908
00909
00910
00911
00912 void TGLScene::CalcBoundingBox() const
00913 {
00914
00915
00916
00917 Double_t xMin, xMax, yMin, yMax, zMin, zMax;
00918 xMin = xMax = yMin = yMax = zMin = zMax = 0.0;
00919 PhysicalShapeMapCIt_t physicalShapeIt = fPhysicalShapes.begin();
00920 const TGLPhysicalShape * physicalShape;
00921 while (physicalShapeIt != fPhysicalShapes.end())
00922 {
00923 physicalShape = physicalShapeIt->second;
00924 if (!physicalShape)
00925 {
00926 assert(kFALSE);
00927 continue;
00928 }
00929 const TGLBoundingBox& box = physicalShape->BoundingBox();
00930 if (physicalShapeIt == fPhysicalShapes.begin()) {
00931 xMin = box.XMin(); xMax = box.XMax();
00932 yMin = box.YMin(); yMax = box.YMax();
00933 zMin = box.ZMin(); zMax = box.ZMax();
00934 } else {
00935 if (box.XMin() < xMin) { xMin = box.XMin(); }
00936 if (box.XMax() > xMax) { xMax = box.XMax(); }
00937 if (box.YMin() < yMin) { yMin = box.YMin(); }
00938 if (box.YMax() > yMax) { yMax = box.YMax(); }
00939 if (box.ZMin() < zMin) { zMin = box.ZMin(); }
00940 if (box.ZMax() > zMax) { zMax = box.ZMax(); }
00941 }
00942 ++physicalShapeIt;
00943 }
00944 fBoundingBox.SetAligned(TGLVertex3(xMin,yMin,zMin), TGLVertex3(xMax,yMax,zMax));
00945 fBoundingBoxValid = kTRUE;
00946 }
00947
00948
00949
00950
00951
00952
00953 void TGLScene::AdoptLogical(TGLLogicalShape& shape)
00954 {
00955
00956
00957
00958 if (fLock != kModifyLock) {
00959 Error("TGLScene::AdoptLogical", "expected ModifyLock");
00960 return;
00961 }
00962
00963 shape.fScene = this;
00964 fLogicalShapes.insert(LogicalShapeMapValueType_t(shape.ID(), &shape));
00965 }
00966
00967
00968 Bool_t TGLScene::DestroyLogical(TObject* logid, Bool_t mustFind)
00969 {
00970
00971
00972
00973
00974
00975
00976 if (fLock != kModifyLock) {
00977 Error("TGLScene::DestroyLogical", "expected ModifyLock");
00978 return kFALSE;
00979 }
00980
00981 LogicalShapeMapIt_t lit = fLogicalShapes.find(logid);
00982
00983 if (lit == fLogicalShapes.end()) {
00984 if (mustFind)
00985 Error("TGLScene::DestroyLogical", "logical not found in map.");
00986 return kFALSE;
00987 }
00988
00989 TGLLogicalShape * logical = lit->second;
00990 UInt_t phid;
00991 while ((phid = logical->UnrefFirstPhysical()) != 0)
00992 {
00993 PhysicalShapeMapIt_t pit = fPhysicalShapes.find(phid);
00994 if (pit != fPhysicalShapes.end())
00995 DestroyPhysicalInternal(pit);
00996 else
00997 Warning("TGLScene::DestroyLogical", "an attached physical not found in map.");
00998 }
00999 assert(logical->Ref() == 0);
01000 fLogicalShapes.erase(lit);
01001 delete logical;
01002 InvalidateBoundingBox();
01003 IncTimeStamp();
01004 return kTRUE;
01005 }
01006
01007
01008 Int_t TGLScene::DestroyLogicals()
01009 {
01010
01011
01012
01013 if (fLock != kModifyLock) {
01014 Error("TGLScene::DestroyLogicals", "expected ModifyLock");
01015 return 0;
01016 }
01017
01018 Int_t count = 0;
01019 LogicalShapeMapIt_t logicalShapeIt = fLogicalShapes.begin();
01020 const TGLLogicalShape * logicalShape;
01021 while (logicalShapeIt != fLogicalShapes.end()) {
01022 logicalShape = logicalShapeIt->second;
01023 if (logicalShape) {
01024 if (logicalShape->Ref() == 0) {
01025 fLogicalShapes.erase(logicalShapeIt++);
01026 delete logicalShape;
01027 ++count;
01028 continue;
01029 } else {
01030 assert(kFALSE);
01031 }
01032 } else {
01033 assert(kFALSE);
01034 }
01035 ++logicalShapeIt;
01036 }
01037
01038 return count;
01039 }
01040
01041
01042 TGLLogicalShape * TGLScene::FindLogical(TObject* logid) const
01043 {
01044
01045
01046
01047 LogicalShapeMapCIt_t lit = fLogicalShapes.find(logid);
01048 if (lit != fLogicalShapes.end()) {
01049 return lit->second;
01050 } else {
01051 if (fInSmartRefresh)
01052 return FindLogicalSmartRefresh(logid);
01053 else
01054 return 0;
01055 }
01056 }
01057
01058
01059
01060
01061
01062
01063
01064 void TGLScene::AdoptPhysical(TGLPhysicalShape & shape)
01065 {
01066
01067
01068 if (fLock != kModifyLock) {
01069 Error("TGLScene::AdoptPhysical", "expected ModifyLock");
01070 return;
01071 }
01072
01073 assert(fPhysicalShapes.find(shape.ID()) == fPhysicalShapes.end());
01074
01075 fPhysicalShapes.insert(PhysicalShapeMapValueType_t(shape.ID(), &shape));
01076
01077 InvalidateBoundingBox();
01078 IncTimeStamp();
01079 }
01080
01081
01082 void TGLScene::DestroyPhysicalInternal(PhysicalShapeMapIt_t pit)
01083 {
01084
01085
01086
01087
01088 delete pit->second;
01089 fPhysicalShapes.erase(pit);
01090 }
01091
01092
01093 Bool_t TGLScene::DestroyPhysical(UInt_t phid)
01094 {
01095
01096
01097
01098 if (fLock != kModifyLock) {
01099 Error("TGLScene::DestroyPhysical", "expected ModifyLock.");
01100 return kFALSE;
01101 }
01102
01103 PhysicalShapeMapIt_t pit = fPhysicalShapes.find(phid);
01104
01105 if (pit == fPhysicalShapes.end()) {
01106 Error("TGLScene::DestroyPhysical::UpdatePhysical", "physical not found.");
01107 return kFALSE;
01108 }
01109
01110 DestroyPhysicalInternal(pit);
01111
01112 InvalidateBoundingBox();
01113
01114 return kTRUE;
01115 }
01116
01117
01118 Int_t TGLScene::DestroyPhysicals()
01119 {
01120
01121
01122 if (fLock != kModifyLock) {
01123 Error("TGLScene::DestroyPhysicals", "expected ModifyLock");
01124 return 0;
01125 }
01126
01127
01128
01129 UInt_t count = 0;
01130
01131 LogicalShapeMapIt_t lit = fLogicalShapes.begin();
01132 while (lit != fLogicalShapes.end())
01133 {
01134 TGLLogicalShape *lshp = lit->second;
01135 if (lshp && lshp->Ref() != 0)
01136 {
01137 count += lshp->Ref();
01138 lshp->DestroyPhysicals();
01139 }
01140 ++lit;
01141 }
01142
01143 assert (count == fPhysicalShapes.size());
01144 fPhysicalShapes.clear();
01145
01146 if (count > 0) {
01147 InvalidateBoundingBox();
01148 IncTimeStamp();
01149 }
01150
01151 return count;
01152 }
01153
01154
01155 TGLPhysicalShape* TGLScene::FindPhysical(UInt_t phid) const
01156 {
01157
01158
01159
01160 PhysicalShapeMapCIt_t pit = fPhysicalShapes.find(phid);
01161 return (pit != fPhysicalShapes.end()) ? pit->second : 0;
01162 }
01163
01164
01165 UInt_t TGLScene::GetMaxPhysicalID()
01166 {
01167
01168
01169
01170 if (fPhysicalShapes.empty()) return 0;
01171 return (--fPhysicalShapes.end())->first;
01172 }
01173
01174
01175
01176
01177
01178
01179
01180 Bool_t TGLScene::BeginUpdate()
01181 {
01182
01183
01184 Bool_t ok = TakeLock(kModifyLock);
01185 return ok;
01186 }
01187
01188
01189 void TGLScene::EndUpdate(Bool_t minorChange, Bool_t sceneChanged, Bool_t updateViewers)
01190 {
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204 if (minorChange)
01205 IncMinorStamp();
01206
01207 if (sceneChanged)
01208 IncTimeStamp();
01209
01210 ReleaseLock(kModifyLock);
01211
01212 if (updateViewers)
01213 TagViewersChanged();
01214 }
01215
01216
01217 void TGLScene::UpdateLogical(TObject* logid)
01218 {
01219
01220
01221
01222 if (fLock != kModifyLock) {
01223 Error("TGLScene::UpdateLogical", "expected ModifyLock");
01224 return;
01225 }
01226
01227 TGLLogicalShape* log = FindLogical(logid);
01228
01229 if (log == 0) {
01230 Error("TGLScene::UpdateLogical", "logical not found");
01231 return;
01232 }
01233
01234 log->DLCacheClear();
01235 log->UpdateBoundingBox();
01236 }
01237
01238
01239 void TGLScene::UpdatePhysical(UInt_t phid, Double_t* trans, UChar_t* col)
01240 {
01241
01242
01243 if (fLock != kModifyLock) {
01244 Error("TGLScene::UpdatePhysical", "expected ModifyLock");
01245 return;
01246 }
01247
01248 TGLPhysicalShape* phys = FindPhysical(phid);
01249
01250 if (phys == 0) {
01251 Error("TGLScene::UpdatePhysical", "physical not found");
01252 return;
01253 }
01254
01255 if (trans) phys->SetTransform(trans);
01256 if (col) phys->SetDiffuseColor(col);
01257 }
01258
01259
01260 void TGLScene::UpdatePhysical(UInt_t phid, Double_t* trans, Color_t cidx, UChar_t transp)
01261 {
01262
01263
01264 if (fLock != kModifyLock) {
01265 Error("TGLScene::UpdatePhysical", "expected ModifyLock");
01266 return;
01267 }
01268
01269 TGLPhysicalShape* phys = FindPhysical(phid);
01270
01271 if (phys == 0) {
01272 Error("TGLScene::UpdatePhysical", "physical not found");
01273 return;
01274 }
01275
01276 if (trans)
01277 phys->SetTransform(trans);
01278 if (cidx >= 0) {
01279 Float_t rgba[4];
01280 RGBAFromColorIdx(rgba, cidx, transp);
01281 phys->SetDiffuseColor(rgba);
01282 }
01283 }
01284
01285
01286 void TGLScene::UpdatePhysioLogical(TObject* logid, Double_t* trans, UChar_t* col)
01287 {
01288
01289
01290
01291 if (fLock != kModifyLock) {
01292 Error("TGLScene::UpdatePhysioLogical", "expected ModifyLock");
01293 return;
01294 }
01295
01296 TGLLogicalShape* log = FindLogical(logid);
01297
01298 if (log == 0) {
01299 Error("TGLScene::UpdatePhysioLogical", "logical not found");
01300 return;
01301 }
01302
01303 if (log->Ref() != 1) {
01304 Warning("TGLScene::UpdatePhysioLogical", "expecting a single physical (%d).", log->Ref());
01305 }
01306
01307 TGLPhysicalShape* phys = log->fFirstPhysical;
01308 if (trans) phys->SetTransform(trans);
01309 if (col) phys->SetDiffuseColor(col);
01310 }
01311
01312
01313 void TGLScene::UpdatePhysioLogical(TObject* logid, Double_t* trans, Color_t cidx, UChar_t transp)
01314 {
01315
01316
01317
01318 if (fLock != kModifyLock) {
01319 Error("TGLScene::UpdatePhysioLogical", "expected ModifyLock");
01320 return;
01321 }
01322
01323 TGLLogicalShape* log = FindLogical(logid);
01324
01325 if (log == 0) {
01326 Error("TGLScene::UpdatePhysioLogical", "logical not found");
01327 return;
01328 }
01329
01330 if (log->Ref() != 1) {
01331 Warning("TGLScene::UpdatePhysioLogical", "expecting a single physical (%d).", log->Ref());
01332 }
01333
01334 TGLPhysicalShape* phys = log->fFirstPhysical;
01335 if (trans)
01336 phys->SetTransform(trans);
01337 if (cidx >= 0) {
01338 Float_t rgba[4];
01339 RGBAFromColorIdx(rgba, cidx, transp);
01340 phys->SetDiffuseColor(rgba);
01341 }
01342 }
01343
01344
01345
01346
01347
01348
01349
01350 UInt_t TGLScene::BeginSmartRefresh()
01351 {
01352
01353
01354
01355 fSmartRefreshCache.swap(fLogicalShapes);
01356
01357 UInt_t count = 0;
01358 LogicalShapeMapIt_t i = fSmartRefreshCache.begin();
01359 while (i != fSmartRefreshCache.end()) {
01360 if (i->second->KeepDuringSmartRefresh() == kFALSE) {
01361 LogicalShapeMapIt_t j = i++;
01362 delete j->second;
01363 fSmartRefreshCache.erase(j);
01364 ++count;
01365 } else {
01366 ++i;
01367 }
01368 }
01369 fInSmartRefresh = kTRUE;
01370 return count;
01371 }
01372
01373
01374 void TGLScene::EndSmartRefresh()
01375 {
01376
01377
01378 fInSmartRefresh = kFALSE;
01379
01380 LogicalShapeMapIt_t i = fSmartRefreshCache.begin();
01381 while (i != fSmartRefreshCache.end()) {
01382 delete i->second;
01383 ++i;
01384 }
01385 fSmartRefreshCache.clear();
01386 }
01387
01388
01389 TGLLogicalShape * TGLScene::FindLogicalSmartRefresh(TObject* ID) const
01390 {
01391
01392
01393
01394 LogicalShapeMapIt_t it = fSmartRefreshCache.find(ID);
01395 if (it != fSmartRefreshCache.end())
01396 {
01397 TGLLogicalShape* l_shape = it->second;
01398 fSmartRefreshCache.erase(it);
01399 if (l_shape->IsA() != TGLObject::GetGLRenderer(ID->IsA()))
01400 {
01401 Warning("TGLScene::FindLogicalSmartRefresh", "Wrong renderer-type found in cache.");
01402 delete l_shape;
01403 return 0;
01404 }
01405
01406
01407
01408 LogicalShapeMap_t* lsm = const_cast<LogicalShapeMap_t*>(&fLogicalShapes);
01409 lsm->insert(LogicalShapeMapValueType_t(l_shape->ID(), l_shape));
01410 l_shape->DLCacheClear();
01411 l_shape->UpdateBoundingBox();
01412 return l_shape;
01413 } else {
01414 return 0;
01415 }
01416 }
01417
01418
01419
01420
01421
01422
01423
01424 UInt_t TGLScene::SizeOfScene() const
01425 {
01426
01427
01428
01429
01430 UInt_t size = sizeof(*this);
01431
01432 printf("Size: Scene Only %u\n", size);
01433
01434 LogicalShapeMapCIt_t logicalShapeIt = fLogicalShapes.begin();
01435 const TGLLogicalShape * logicalShape;
01436 while (logicalShapeIt != fLogicalShapes.end()) {
01437 logicalShape = logicalShapeIt->second;
01438 size += sizeof(*logicalShape);
01439 ++logicalShapeIt;
01440 }
01441
01442 printf("Size: Scene + Logical Shapes %u\n", size);
01443
01444 PhysicalShapeMapCIt_t physicalShapeIt = fPhysicalShapes.begin();
01445 const TGLPhysicalShape * physicalShape;
01446 while (physicalShapeIt != fPhysicalShapes.end()) {
01447 physicalShape = physicalShapeIt->second;
01448 size += sizeof(*physicalShape);
01449 ++physicalShapeIt;
01450 }
01451
01452 printf("Size: Scene + Logical Shapes + Physical Shapes %u\n", size);
01453
01454 return size;
01455 }
01456
01457
01458 void TGLScene::DumpMapSizes() const
01459 {
01460
01461
01462 printf("Scene: %u Logicals / %u Physicals\n",
01463 (UInt_t) fLogicalShapes.size(), (UInt_t) fPhysicalShapes.size());
01464 }
01465
01466
01467 void TGLScene::RGBAFromColorIdx(Float_t rgba[4], Color_t ci, Char_t transp)
01468 {
01469
01470
01471 TColor* c = gROOT->GetColor(ci);
01472 if(c) c->GetRGB(rgba[0], rgba[1], rgba[2]);
01473 else rgba[0] = rgba[1] = rgba[2] = 0.5;
01474 rgba[3] = 1.0f - transp/100.0f;
01475 }
01476
01477
01478 Bool_t TGLScene::IsOutside(const TGLBoundingBox & box,
01479 const TGLPlaneSet_t & planes)
01480 {
01481
01482
01483 for (TGLPlaneSet_ci p=planes.begin(); p!=planes.end(); ++p)
01484 if (box.Overlap(*p) == kOutside)
01485 return kTRUE;
01486 return kFALSE;
01487 }