00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TGLViewerBase.h"
00013
00014 #include "TGLSceneBase.h"
00015 #include "TGLSceneInfo.h"
00016
00017 #include "TGLRnrCtx.h"
00018 #include "TGLCamera.h"
00019 #include "TGLClip.h"
00020 #include "TGLOverlay.h"
00021 #include "TGLSelectBuffer.h"
00022 #include "TGLSelectRecord.h"
00023 #include "TGLAnnotation.h"
00024 #include "TGLUtil.h"
00025
00026 #include "TGLContext.h"
00027 #include "TGLIncludes.h"
00028
00029 #include <algorithm>
00030 #include <stdexcept>
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 ClassImp(TGLViewerBase);
00048
00049
00050 TGLViewerBase::TGLViewerBase() :
00051 fRnrCtx (0),
00052 fCamera (0),
00053 fClip (0),
00054 fLOD (TGLRnrCtx::kLODHigh),
00055 fStyle (TGLRnrCtx::kFill),
00056 fWFLineW (1),
00057 fOLLineW (1),
00058
00059 fResetSceneInfosOnRender (kFALSE),
00060 fChanged (kFALSE)
00061 {
00062
00063
00064 fRnrCtx = new TGLRnrCtx(this);
00065 }
00066
00067
00068 TGLViewerBase::~TGLViewerBase()
00069 {
00070
00071
00072 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
00073 {
00074 (*i)->GetScene()->RemoveViewer(this);
00075 delete *i;
00076 }
00077
00078 DeleteOverlayElements(TGLOverlayElement::kAll);
00079
00080 delete fRnrCtx;
00081 }
00082
00083
00084 const char* TGLViewerBase::LockIdStr() const
00085 {
00086
00087
00088 return "TGLViewerBase";
00089 }
00090
00091
00092
00093
00094
00095
00096 TGLViewerBase::SceneInfoList_i
00097 TGLViewerBase::FindScene(TGLSceneBase* scene)
00098 {
00099
00100
00101 SceneInfoList_i i = fScenes.begin();
00102 while (i != fScenes.end() && (*i)->GetScene() != scene) ++i;
00103 return i;
00104 }
00105
00106
00107 TGLSceneInfo* TGLViewerBase::AddScene(TGLSceneBase* scene)
00108 {
00109
00110
00111 SceneInfoList_i i = FindScene(scene);
00112 if (i == fScenes.end()) {
00113 TGLSceneInfo* sinfo = scene->CreateSceneInfo(this);
00114 fScenes.push_back(sinfo);
00115 scene->AddViewer(this);
00116 Changed();
00117 return sinfo;
00118 } else {
00119 Warning("TGLViewerBase::AddScene", "scene '%s' already in the list.",
00120 scene->GetName());
00121 return 0;
00122 }
00123 }
00124
00125
00126 void TGLViewerBase::RemoveScene(TGLSceneBase* scene)
00127 {
00128
00129
00130 SceneInfoList_i i = FindScene(scene);
00131 if (i != fScenes.end()) {
00132 delete *i;
00133 fScenes.erase(i);
00134 scene->RemoveViewer(this);
00135 Changed();
00136 } else {
00137 Warning("TGLViewerBase::RemoveScene", "scene '%s' not found.",
00138 scene->GetName());
00139 }
00140 }
00141
00142
00143 void TGLViewerBase::RemoveAllScenes()
00144 {
00145
00146
00147 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
00148 {
00149 TGLSceneInfo * sinfo = *i;
00150 sinfo->GetScene()->RemoveViewer(this);
00151 delete sinfo;
00152 }
00153 fScenes.clear();
00154 Changed();
00155 }
00156
00157
00158 void TGLViewerBase::SceneDestructing(TGLSceneBase* scene)
00159 {
00160
00161
00162
00163
00164 SceneInfoList_i i = FindScene(scene);
00165 if (i != fScenes.end()) {
00166 delete *i;
00167 fScenes.erase(i);
00168 Changed();
00169 } else {
00170 Warning("TGLViewerBase::SceneDestructing", "scene not found.");
00171 }
00172 }
00173
00174
00175 TGLSceneInfo* TGLViewerBase::GetSceneInfo(TGLSceneBase* scene)
00176 {
00177
00178
00179 SceneInfoList_i i = FindScene(scene);
00180 if (i != fScenes.end())
00181 return *i;
00182 else
00183 return 0;
00184 }
00185
00186
00187 TGLLogicalShape* TGLViewerBase::FindLogicalInScenes(TObject* id)
00188 {
00189
00190
00191
00192 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
00193 {
00194 TGLLogicalShape *lshp = (*i)->GetScene()->FindLogical(id);
00195 if (lshp)
00196 return lshp;
00197 }
00198 return 0;
00199 }
00200
00201
00202 void TGLViewerBase::AddOverlayElement(TGLOverlayElement* el)
00203 {
00204
00205
00206 fOverlay.push_back(el);
00207 Changed();
00208 }
00209
00210
00211 void TGLViewerBase::RemoveOverlayElement(TGLOverlayElement* el)
00212 {
00213
00214
00215 OverlayElmVec_i it = std::find(fOverlay.begin(), fOverlay.end(), el);
00216 if (it != fOverlay.end())
00217 fOverlay.erase(it);
00218 Changed();
00219 }
00220
00221
00222 void TGLViewerBase::DeleteOverlayAnnotations()
00223 {
00224
00225
00226 DeleteOverlayElements(TGLOverlayElement::kAnnotation);
00227 }
00228
00229
00230 void TGLViewerBase::DeleteOverlayElements(TGLOverlayElement::ERole role)
00231 {
00232
00233
00234 OverlayElmVec_t ovl;
00235 fOverlay.swap(ovl);
00236
00237 for (OverlayElmVec_i i = ovl.begin(); i != ovl.end(); ++i)
00238 {
00239 if (role == TGLOverlayElement::kAll || (*i)->GetRole() == role)
00240 delete *i;
00241 else
00242 fOverlay.push_back(*i);
00243 }
00244
00245 Changed();
00246 }
00247
00248
00249
00250
00251
00252
00253 void TGLViewerBase::ResetSceneInfos()
00254 {
00255
00256
00257
00258
00259
00260 SceneInfoList_i i = fScenes.begin();
00261 while (i != fScenes.end())
00262 {
00263 (*i)->ResetSceneStamp();
00264 ++i;
00265 }
00266 }
00267
00268
00269 void TGLViewerBase::MergeSceneBBoxes(TGLBoundingBox& bbox)
00270 {
00271
00272
00273 bbox.SetEmpty();
00274 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
00275 {
00276 TGLSceneInfo * sinfo = *i;
00277 if (sinfo->GetActive())
00278 {
00279 sinfo->SetupTransformsAndBBox();
00280 bbox.MergeAligned(sinfo->GetTransformedBBox());
00281 }
00282 }
00283 }
00284
00285
00286
00287
00288
00289
00290 void TGLViewerBase::SetupClipObject()
00291 {
00292
00293
00294 if (fClip)
00295 {
00296 fClip->Setup(fOverallBoundingBox);
00297 }
00298 }
00299
00300
00301 void TGLViewerBase::PreRender()
00302 {
00303
00304
00305
00306 TGLContextIdentity* cid = TGLContextIdentity::GetCurrent();
00307 if (cid == 0)
00308 {
00309
00310
00311
00312
00313
00314 }
00315 else
00316 {
00317 if (cid != fRnrCtx->GetGLCtxIdentity())
00318 {
00319 if (fRnrCtx->GetGLCtxIdentity() != 0)
00320 Warning("TGLViewerBase::PreRender", "Switching to another GL context; maybe you should use context-sharing.");
00321 fRnrCtx->SetGLCtxIdentity(cid);
00322 }
00323 }
00324
00325 fRnrCtx->SetCamera (fCamera);
00326 fRnrCtx->SetViewerLOD (fLOD);
00327 fRnrCtx->SetViewerStyle (fStyle);
00328 fRnrCtx->SetViewerWFLineW (fWFLineW);
00329 fRnrCtx->SetViewerOLLineW (fOLLineW);
00330 fRnrCtx->SetViewerClip (fClip);
00331
00332 if (fResetSceneInfosOnRender)
00333 {
00334 ResetSceneInfos();
00335 fResetSceneInfosOnRender = kFALSE;
00336 }
00337
00338 fOverallBoundingBox.SetEmpty();
00339 SceneInfoList_t locked_scenes;
00340 for (SceneInfoList_i i=fScenes.begin(); i!=fScenes.end(); ++i)
00341 {
00342 TGLSceneInfo *sinfo = *i;
00343 TGLSceneBase *scene = sinfo->GetScene();
00344 if (sinfo->GetActive())
00345 {
00346 if ( ! fRnrCtx->Selection() || scene->GetSelectable())
00347 {
00348 if ( ! sinfo->GetScene()->TakeLock(kDrawLock))
00349 {
00350 Warning("TGLViewerBase::PreRender", "locking of scene '%s' failed, skipping.",
00351 sinfo->GetScene()->GetName());
00352 continue;
00353 }
00354 locked_scenes.push_back(sinfo);
00355 }
00356 sinfo->SetupTransformsAndBBox();
00357 fOverallBoundingBox.MergeAligned(sinfo->GetTransformedBBox());
00358 }
00359 }
00360
00361 fCamera->Apply(fOverallBoundingBox, fRnrCtx->GetPickRectangle());
00362 SetupClipObject();
00363
00364
00365
00366 fVisScenes.clear();
00367 for (SceneInfoList_i i=locked_scenes.begin(); i!=locked_scenes.end(); ++i)
00368 {
00369 TGLSceneInfo * sinfo = *i;
00370 const TGLBoundingBox & bbox = sinfo->GetTransformedBBox();
00371 Bool_t visp = (!bbox.IsEmpty() && fCamera->FrustumOverlap(bbox) != kOutside);
00372 sinfo->ViewCheck(visp);
00373 if (visp) {
00374 fRnrCtx->SetSceneInfo(sinfo);
00375 sinfo->GetScene()->PreDraw(*fRnrCtx);
00376 if (sinfo->IsVisible()) {
00377 fVisScenes.push_back(sinfo);
00378 } else {
00379 sinfo->GetScene()->PostDraw(*fRnrCtx);
00380 sinfo->GetScene()->ReleaseLock(kDrawLock);
00381 }
00382 fRnrCtx->SetSceneInfo(0);
00383 } else {
00384 sinfo->GetScene()->ReleaseLock(kDrawLock);
00385 }
00386 }
00387 }
00388
00389
00390 void TGLViewerBase::SubRenderScenes(SubRender_foo render_foo)
00391 {
00392
00393
00394
00395 Int_t nScenes = fVisScenes.size();
00396
00397 for (Int_t i = 0; i < nScenes; ++i)
00398 {
00399 TGLSceneInfo* sinfo = fVisScenes[i];
00400 TGLSceneBase* scene = sinfo->GetScene();
00401 fRnrCtx->SetSceneInfo(sinfo);
00402 glPushName(i);
00403 scene->PreRender(*fRnrCtx);
00404 (scene->*render_foo)(*fRnrCtx);
00405 scene->PostRender(*fRnrCtx);
00406 glPopName();
00407 fRnrCtx->SetSceneInfo(0);
00408 }
00409 }
00410
00411
00412 void TGLViewerBase::Render()
00413 {
00414
00415
00416
00417
00418
00419
00420
00421 RenderNonSelected();
00422 glClear(GL_DEPTH_BUFFER_BIT);
00423 RenderSelected();
00424 }
00425
00426
00427 void TGLViewerBase::RenderNonSelected()
00428 {
00429
00430
00431 SubRenderScenes(&TGLSceneBase::RenderOpaque);
00432
00433 TGLCapabilityEnabler blend(GL_BLEND, kTRUE);
00434 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00435 glDepthMask(GL_FALSE);
00436
00437 SubRenderScenes(&TGLSceneBase::RenderTransp);
00438
00439 glDepthMask(GL_TRUE);
00440
00441 TGLUtil::CheckError("TGLViewerBase::RenderNonSelected - pre exit check");
00442 }
00443
00444
00445 void TGLViewerBase::RenderSelected()
00446 {
00447
00448
00449 SubRenderScenes(&TGLSceneBase::RenderSelOpaque);
00450
00451 TGLCapabilityEnabler blend(GL_BLEND, kTRUE);
00452 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00453 glDepthMask(GL_FALSE);
00454
00455 SubRenderScenes(&TGLSceneBase::RenderSelTransp);
00456
00457 glDepthMask(GL_TRUE);
00458
00459 TGLUtil::CheckError("TGLViewerBase::RenderSelected - pre exit check");
00460 }
00461
00462
00463 void TGLViewerBase::RenderOverlay(Int_t state, Bool_t selection)
00464 {
00465
00466
00467 Int_t nOvl = fOverlay.size();
00468 for (Int_t i = 0; i < nOvl; ++i)
00469 {
00470 TGLOverlayElement* el = fOverlay[i];
00471 if (el->GetState() & state)
00472 {
00473 if (selection) glPushName(i);
00474 el->Render(*fRnrCtx);
00475 if (selection) glPopName();
00476 }
00477 }
00478 }
00479
00480
00481 void TGLViewerBase::PostRender()
00482 {
00483
00484
00485
00486 for (SceneInfoVec_i i = fVisScenes.begin(); i != fVisScenes.end(); ++i)
00487 {
00488 TGLSceneInfo* sinfo = *i;
00489 fRnrCtx->SetSceneInfo(sinfo);
00490 sinfo->GetScene()->PostDraw(*fRnrCtx);
00491 fRnrCtx->SetSceneInfo(0);
00492 sinfo->GetScene()->ReleaseLock(kDrawLock);
00493 }
00494 fChanged = kFALSE;
00495 }
00496
00497
00498 void TGLViewerBase::PreRenderOverlaySelection()
00499 {
00500
00501
00502
00503
00504
00505 fCamera->Apply(fOverallBoundingBox, fRnrCtx->GetPickRectangle());
00506 }
00507
00508
00509 void TGLViewerBase::PostRenderOverlaySelection()
00510 {
00511
00512
00513 }
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 Bool_t TGLViewerBase::ResolveSelectRecord(TGLSelectRecord& rec, Int_t recIdx)
00530 {
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 TGLSelectBuffer* sb = fRnrCtx->GetSelectBuffer();
00541 if (recIdx >= sb->GetNRecords())
00542 return kFALSE;
00543
00544 sb->SelectRecord(rec, recIdx);
00545 UInt_t sceneIdx = rec.GetItem(0);
00546 if (sceneIdx >= fVisScenes.size())
00547 return kFALSE;
00548
00549 TGLSceneInfo* sinfo = fVisScenes[sceneIdx];
00550 rec.SetSceneInfo(sinfo);
00551 return sinfo->GetScene()->ResolveSelectRecord(rec, 1);
00552 }
00553
00554
00555 Bool_t TGLViewerBase::FindClosestRecord(TGLSelectRecord& rec, Int_t& recIdx)
00556 {
00557
00558
00559
00560
00561 TGLSelectBuffer* sb = fRnrCtx->GetSelectBuffer();
00562
00563 while (recIdx < sb->GetNRecords())
00564 {
00565 if (ResolveSelectRecord(rec, recIdx))
00566 return kTRUE;
00567 ++recIdx;
00568 }
00569 return kFALSE;
00570 }
00571
00572
00573 Bool_t TGLViewerBase::FindClosestOpaqueRecord(TGLSelectRecord& rec, Int_t& recIdx)
00574 {
00575
00576
00577
00578
00579 TGLSelectBuffer* sb = fRnrCtx->GetSelectBuffer();
00580
00581 while (recIdx < sb->GetNRecords())
00582 {
00583 if (ResolveSelectRecord(rec, recIdx) && ! rec.GetTransparent())
00584 return kTRUE;
00585 ++recIdx;
00586 }
00587 return kFALSE;
00588 }
00589
00590
00591 Bool_t TGLViewerBase::FindClosestOverlayRecord(TGLOvlSelectRecord& rec,
00592 Int_t & recIdx)
00593 {
00594
00595
00596
00597
00598 TGLSelectBuffer* sb = fRnrCtx->GetSelectBuffer();
00599
00600 while (recIdx < sb->GetNRecords())
00601 {
00602 sb->SelectRecord(rec, recIdx);
00603 if (rec.GetItem(0) < fOverlay.size())
00604 {
00605 rec.SetOvlElement(fOverlay[rec.GetItem(0)]);
00606 rec.NextPos();
00607 return kTRUE;
00608 }
00609 ++recIdx;
00610 }
00611 return kFALSE;
00612 }