#include "Riostream.h"
#include "TAttLine.h"
#include "TGLScene.h"
#include "TGLCamera.h"
#include "TGLLogicalShape.h"
#include "TGLPhysicalShape.h"
#include "TGLStopwatch.h"
#include "TGLDisplayListCache.h"
#include "TGLClip.h"
#include "TGLIncludes.h"
#include "TError.h"
#include "TString.h"
#include "TClass.h" // For non-TObject reflection
#include "TGLViewer.h" // Only here for some draw style enums - remove these
#include "TColor.h" // moved to proper class
#include "TAtt3D.h"
#include <algorithm>
ClassImp(TGLScene)
TGLScene::TGLScene() :
fLock(kUnlocked), fDrawList(1000),
fDrawListValid(kFALSE),
fInSmartRefresh(kFALSE),
fBoundingBox(), fBoundingBoxValid(kFALSE),
fSelectedPhysical(0),
fClipPlane(0), fClipBox(0), fCurrentClip(0),
fTransManip(), fScaleManip(), fRotateManip()
{
fCurrentManip = &fTransManip;
}
TGLScene::~TGLScene()
{
TGLDisplayListCache::Instance().Purge();
ClearClips();
TakeLock(kModifyLock);
DestroyPhysicals(kTRUE);
DestroyLogicals();
ReleaseLock(kModifyLock);
}
void TGLScene::AdoptLogical(TGLLogicalShape & shape)
{
if (fLock != kModifyLock) {
Error("TGLScene::AdoptLogical", "expected ModifyLock");
return;
}
fLogicalShapes.insert(LogicalShapeMapValueType_t(shape.ID(), &shape));
}
Bool_t TGLScene::DestroyLogical(ULong_t ID)
{
if (ID == 0U) {
Error("TGLScene::DestroyLogical", "asked to destory non-unqiue 0 ID logical shape");
return kFALSE;
}
if (fLock != kModifyLock) {
Error("TGLScene::DestroyLogical", "expected ModifyLock");
return kFALSE;
}
LogicalShapeMapIt_t logicalIt = fLogicalShapes.find(ID);
if (logicalIt != fLogicalShapes.end()) {
const TGLLogicalShape * logical = logicalIt->second;
if (logical->Ref() == 0) {
fLogicalShapes.erase(logicalIt);
delete logical;
return kTRUE;
} else {
assert(kFALSE);
}
}
return kFALSE;
}
UInt_t TGLScene::DestroyLogicals()
{
UInt_t count = 0;
if (fLock != kModifyLock) {
Error("TGLScene::DestroyLogicals", "expected ModifyLock");
return count;
}
LogicalShapeMapIt_t logicalShapeIt = fLogicalShapes.begin();
const TGLLogicalShape * logicalShape;
while (logicalShapeIt != fLogicalShapes.end()) {
logicalShape = logicalShapeIt->second;
if (logicalShape) {
if (logicalShape->Ref() == 0) {
fLogicalShapes.erase(logicalShapeIt++);
delete logicalShape;
++count;
continue;
} else {
assert(kFALSE);
}
} else {
assert(kFALSE);
}
++logicalShapeIt;
}
return count;
}
TGLLogicalShape * TGLScene::FindLogical(ULong_t ID) const
{
if (ID == 0U) {
Error("TGLScene::FindLogical", "asked to find non-unqiue 0 ID logical shape");
return 0;
}
LogicalShapeMapCIt_t it = fLogicalShapes.find(ID);
if (it != fLogicalShapes.end()) {
return it->second;
} else {
if (fInSmartRefresh)
return FindLogicalSmartRefresh(ID);
else
return 0;
}
}
void TGLScene::AdoptPhysical(TGLPhysicalShape & shape)
{
if (fLock != kModifyLock) {
Error("TGLScene::AdoptPhysical", "expected ModifyLock");
return;
}
assert(fPhysicalShapes.find(shape.ID()) == fPhysicalShapes.end());
fPhysicalShapes.insert(PhysicalShapeMapValueType_t(shape.ID(), &shape));
fBoundingBoxValid = kFALSE;
fDrawList.push_back(&shape);
fDrawListValid = kFALSE;
}
Bool_t TGLScene::DestroyPhysical(ULong_t ID)
{
if (fLock != kModifyLock) {
Error("TGLScene::DestroyPhysical", "expected ModifyLock");
return kFALSE;
}
PhysicalShapeMapIt_t physicalIt = fPhysicalShapes.find(ID);
if (physicalIt != fPhysicalShapes.end()) {
TGLPhysicalShape * physical = physicalIt->second;
if (fSelectedPhysical == physical) {
if (fCurrentManip->GetAttached() == fSelectedPhysical) {
fCurrentManip->Attach(0);
}
fSelectedPhysical = 0;
}
fPhysicalShapes.erase(physicalIt);
fBoundingBoxValid = kFALSE;
DrawListIt_t drawIt = find(fDrawList.begin(), fDrawList.end(), physical);
if (drawIt != fDrawList.end()) {
*drawIt = 0;
fDrawListValid = kFALSE;
} else {
assert(kFALSE);
}
delete physical;
return kTRUE;
}
return kFALSE;
}
UInt_t TGLScene::DestroyPhysicals(Bool_t incModified, const TGLCamera * camera)
{
if (fLock != kModifyLock) {
Error("TGLScene::DestroyPhysicals", "expected ModifyLock");
return kFALSE;
}
UInt_t count = 0;
PhysicalShapeMapIt_t physicalShapeIt = fPhysicalShapes.begin();
const TGLPhysicalShape * physical;
while (physicalShapeIt != fPhysicalShapes.end()) {
physical = physicalShapeIt->second;
if (physical) {
if (incModified || (!incModified && !physical->IsModified())) {
if (!camera || (camera && !camera->OfInterest(physical->BoundingBox()))) {
fPhysicalShapes.erase(physicalShapeIt++);
DrawListIt_t drawIt = find(fDrawList.begin(), fDrawList.end(), physical);
if (drawIt != fDrawList.end()) {
*drawIt = 0;
} else {
assert(kFALSE);
}
if (fSelectedPhysical == physical) {
if (fCurrentManip->GetAttached() == fSelectedPhysical) {
fCurrentManip->Attach(0);
}
fSelectedPhysical = 0;
}
delete physical;
++count;
continue;
}
}
} else {
assert(kFALSE);
}
++physicalShapeIt;
}
if (count > 0) {
fBoundingBoxValid = kFALSE;
fDrawListValid = kFALSE;
}
return count;
}
TGLPhysicalShape * TGLScene::FindPhysical(ULong_t ID) const
{
PhysicalShapeMapCIt_t it = fPhysicalShapes.find(ID);
if (it != fPhysicalShapes.end()) {
return it->second;
} else {
return 0;
}
}
void TGLScene::BeginSmartRefresh()
{
fSmartRefreshCache.swap(fLogicalShapes);
LogicalShapeMapIt_t i = fSmartRefreshCache.begin();
while (i != fSmartRefreshCache.end()) {
if (i->second->KeepDuringSmartRefresh() == false) {
delete i->second;
fSmartRefreshCache.erase(i);
}
++i;
}
fInSmartRefresh = true;
}
void TGLScene::EndSmartRefresh()
{
fInSmartRefresh = false;
LogicalShapeMapIt_t i = fSmartRefreshCache.begin();
while (i != fSmartRefreshCache.end()) {
delete i->second;
++i;
}
fSmartRefreshCache.clear();
}
TGLLogicalShape * TGLScene::FindLogicalSmartRefresh(ULong_t ID) const
{
LogicalShapeMapIt_t it = fSmartRefreshCache.find(ID);
if (it != fSmartRefreshCache.end()) {
TGLLogicalShape* l_shape = it->second;
fSmartRefreshCache.erase(it);
LogicalShapeMap_t* lsm = const_cast<LogicalShapeMap_t*>(&fLogicalShapes);
lsm->insert(LogicalShapeMapValueType_t(l_shape->ID(), l_shape));
return l_shape;
} else {
return 0;
}
}
void TGLScene::Draw(const TGLCamera & camera, TGLDrawFlags sceneFlags,
Double_t timeout, Int_t axesType, const TGLVertex3 * reference,
Bool_t forSelect)
{
if (fLock != kDrawLock && fLock != kSelectLock) {
Error("TGLScene::Draw", "expected Draw or Select Lock");
}
ResetDrawStats(sceneFlags);
if (!fDrawListValid) {
SortDrawList();
}
if (fCurrentClip) {
} else {
}
UInt_t reqFullDraws = 1;
switch (sceneFlags.Style()) {
case (TGLDrawFlags::kFill):
case (TGLDrawFlags::kOutline): {
glEnable(GL_LIGHTING);
if (fCurrentClip) {
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_CULL_FACE);
}
if (sceneFlags.Style() == TGLDrawFlags::kFill) {
glClearColor(0.0, 0.0, 0.0, 1.0);
} else {
glClearColor(1.0, 1.0, 1.0, 1.0);
reqFullDraws = 2;
}
break;
}
case (TGLDrawFlags::kWireFrame): {
glDisable(GL_LIGHTING);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glClearColor(0.0, 0.0, 0.0, 1.0);
break;
}
default: {
assert(kFALSE);
}
}
for (UInt_t fullDraws = 0; fullDraws < reqFullDraws; fullDraws++) {
if (sceneFlags.Style() == TGLDrawFlags::kOutline) {
if (fullDraws == 0) {
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.f, 1.f);
} else {
glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_LIGHTING);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
}
Double_t fullDrawTimeout = timeout/reqFullDraws;
if (!fCurrentClip) {
DrawPass(camera, sceneFlags, fullDrawTimeout);
} else {
std::vector<TGLPlane> planeSet;
fCurrentClip->PlaneSet(planeSet);
for (std::vector<TGLPlane>::iterator it = planeSet.begin();
it != planeSet.end(); ) {
if (BoundingBox().Overlap(*it) == kOutside) {
it = planeSet.erase(it);
} else {
++it;
}
}
if (gDebug>2) {
Info("TGLScene::Draw()", "%d active clip planes", planeSet.size());
}
Int_t maxGLPlanes;
glGetIntegerv(GL_MAX_CLIP_PLANES, &maxGLPlanes);
UInt_t maxPlanes = maxGLPlanes;
UInt_t planeInd;
if (planeSet.size() < maxPlanes) {
maxPlanes = planeSet.size();
}
if (fCurrentClip->Mode() == TGLClip::kOutside) {
for (UInt_t i=0; i<maxPlanes; i++) {
planeSet[i].Negate();
glClipPlane(GL_CLIP_PLANE0+i, planeSet[i].CArr());
glEnable(GL_CLIP_PLANE0+i);
}
DrawPass(camera, sceneFlags, fullDrawTimeout, &planeSet);
}
else {
std::vector<TGLPlane> activePlanes;
for (planeInd=0; planeInd<maxPlanes; planeInd++) {
if (planeInd > 0) {
activePlanes[planeInd - 1].Negate();
glClipPlane(GL_CLIP_PLANE0+planeInd - 1, activePlanes[planeInd - 1].CArr());
}
activePlanes.push_back(planeSet[planeInd]);
glClipPlane(GL_CLIP_PLANE0+planeInd, activePlanes[planeInd].CArr());
glEnable(GL_CLIP_PLANE0+planeInd);
DrawPass(camera, sceneFlags, fullDrawTimeout/maxPlanes, &activePlanes);
}
}
for (planeInd=0; planeInd<maxPlanes; planeInd++) {
glDisable(GL_CLIP_PLANE0+planeInd);
}
}
}
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
glPolygonMode(GL_FRONT, GL_FILL);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
DrawGuides(camera, axesType, reference);
if (!forSelect) {
if (fCurrentClip && fCurrentManip->GetAttached() == fCurrentClip) {
TGLDrawFlags clipSceneFlags(TGLDrawFlags::kFill, sceneFlags.LOD());
fCurrentClip->Draw(fCurrentClip->CalcDrawFlags(camera, clipSceneFlags));
}
glClear(GL_DEPTH_BUFFER_BIT);
fCurrentManip->Draw(camera);
if (fSelectedPhysical) {
if (sceneFlags.Style() == TGLDrawFlags::kFill ||
sceneFlags.Style() == TGLDrawFlags::kWireFrame) {
glColor3d(1.0, 1.0, 1.0);
} else {
glColor3d(1.0, 0.0, 0.0);
}
if (sceneFlags.Style() == TGLDrawFlags::kFill ||
sceneFlags.Style() == TGLDrawFlags::kOutline) {
glDisable(GL_LIGHTING);
}
fSelectedPhysical->BoundingBox().Draw();
if (sceneFlags.Style() == TGLDrawFlags::kFill ||
sceneFlags.Style() == TGLDrawFlags::kOutline) {
glEnable(GL_LIGHTING);
}
}
}
DumpDrawStats();
}
void TGLScene::DrawPass(const TGLCamera & camera, const TGLDrawFlags & sceneFlags,
Double_t timeout, const std::vector<TGLPlane> * clipPlanes)
{
TGLStopwatch stopwatch;
if (timeout > 0.0 || gDebug > 2) {
stopwatch.Start();
}
Bool_t run = kTRUE;
const TGLPhysicalShape * drawShape;
Bool_t doSelected = (fSelectedPhysical != 0);
static DrawList_t transDrawList;
transDrawList.reserve(fDrawList.size() / 10);
transDrawList.clear();
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
Bool_t useFrustumCheck = (camera.FrustumOverlap(BoundingBox()) != kInside);
TGLDrawFlags shapeFlags;
DrawListIt_t drawIt;
for (drawIt = fDrawList.begin(); drawIt != fDrawList.end() && run;
++drawIt) {
drawShape = *drawIt;
if (!drawShape)
{
assert(kFALSE);
continue;
}
if (drawShape == fSelectedPhysical) {
doSelected = kFALSE;
}
Bool_t drawNeeded = kTRUE;
EOverlap overlap;
if (clipPlanes) {
for (UInt_t i = 0; i < clipPlanes->size(); ++i) {
overlap = drawShape->BoundingBox().Overlap((*clipPlanes)[i]);
if (overlap == kOutside) {
drawNeeded = kFALSE;
break;
}
}
}
if (drawNeeded && useFrustumCheck)
{
overlap = camera.FrustumOverlap(drawShape->BoundingBox());
drawNeeded = overlap == kInside || overlap == kPartial;
}
if (drawNeeded)
{
if (drawShape->IsTransparent()) {
transDrawList.push_back(drawShape);
continue;
}
shapeFlags = drawShape->CalcDrawFlags(camera, sceneFlags);
drawShape->Draw(shapeFlags);
UpdateDrawStats(*drawShape, shapeFlags);
}
if (timeout > 0.0 && fDrawStats.fOpaque > 0 && (fDrawStats.fOpaque % 50) == 0) {
Double_t opaqueTimeFraction = static_cast<Double_t>(fDrawStats.fOpaque) /
static_cast<Double_t>(transDrawList.size() + fDrawStats.fOpaque);
if (stopwatch.Lap() > (timeout * opaqueTimeFraction)) {
run = kFALSE;
}
}
}
if (doSelected) {
if (!fSelectedPhysical->IsTransparent()) {
shapeFlags = fSelectedPhysical->CalcDrawFlags(camera, sceneFlags);
fSelectedPhysical->Draw(shapeFlags);
UpdateDrawStats(*fSelectedPhysical, shapeFlags);
} else {
transDrawList.push_back(fSelectedPhysical);
}
}
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (drawIt = transDrawList.begin(); drawIt != transDrawList.end(); drawIt++) {
drawShape = *drawIt;
shapeFlags = drawShape->CalcDrawFlags(camera, sceneFlags);
drawShape->Draw(shapeFlags);
UpdateDrawStats(*drawShape, shapeFlags);
}
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
if (gDebug > 2) {
Info("TGLScene::DrawPass", "requested in %f msec, took %f msec", timeout, stopwatch.End());
}
}
void TGLScene::SortDrawList()
{
assert(!fDrawListValid);
TGLStopwatch stopwatch;
if (gDebug>2) {
stopwatch.Start();
}
fDrawList.reserve(fPhysicalShapes.size());
fDrawList.erase(remove(fDrawList.begin(), fDrawList.end(), static_cast<const TGLPhysicalShape *>(0)), fDrawList.end());
assert(fDrawList.size() == fPhysicalShapes.size());
sort(fDrawList.begin(), fDrawList.end(), TGLScene::ComparePhysicalVolumes);
if (gDebug>2) {
Info("TGLScene::SortDrawList", "sorting took %f msec", stopwatch.End());
}
fDrawListValid = kTRUE;
}
Bool_t TGLScene::ComparePhysicalVolumes(const TGLPhysicalShape * shape1, const TGLPhysicalShape * shape2)
{
return (shape1->BoundingBox().Volume() > shape2->BoundingBox().Volume());
}
void TGLScene::DrawGuides(const TGLCamera & camera, Int_t axesType, const TGLVertex3 * reference) const
{
if (fLock != kDrawLock && fLock != kSelectLock) {
Error("TGLScene::DrawMarkers", "expected Draw or Select Lock");
}
glDisable(GL_DEPTH_TEST);
if (reference) {
const Float_t referenceColor[4] = { 0.98, 0.45, 0.0, 1.0 };
TGLVector3 referenceSize = camera.ViewportDeltaToWorld(*reference, 3, 3);
TGLUtil::DrawSphere(*reference, referenceSize.Mag(), referenceColor);
}
if (axesType != TGLViewer::kAxesOrigin) {
glEnable(GL_DEPTH_TEST);
}
if (axesType == TGLViewer::kAxesNone) {
return;
}
const Float_t axesColors[][4] = {{0.5, 0.0, 0.0, 1.0},
{1.0, 0.0, 0.0, 1.0},
{0.0, 0.5, 0.0, 1.0},
{0.0, 1.0, 0.0, 1.0},
{0.0, 0.0, 0.5, 1.0},
{0.0, 0.0, 1.0, 1.0}};
TGLVector3 pixelVector = camera.ViewportDeltaToWorld(BoundingBox().Center(), 1, 1);
Double_t pixelSize = pixelVector.Mag();
Double_t min[3] = { BoundingBox().XMin(), BoundingBox().YMin(), BoundingBox().ZMin() };
Double_t max[3] = { BoundingBox().XMax(), BoundingBox().YMax(), BoundingBox().ZMax() };
for (UInt_t i = 0; i < 3; i++) {
TGLVertex3 start;
TGLVector3 vector;
if (axesType == TGLViewer::kAxesOrigin) {
start[(i+1)%3] = 0.0;
start[(i+2)%3] = 0.0;
} else {
start[(i+1)%3] = min[(i+1)%3];
start[(i+2)%3] = min[(i+2)%3];
}
vector[(i+1)%3] = 0.0;
vector[(i+2)%3] = 0.0;
if (min[i] < 0.0) {
if (max[i] > 0.0) {
start[i] = 0.0;
vector[i] = min[i];
} else {
start[i] = max[i];
vector[i] = min[i] - max[i];
}
TGLUtil::DrawLine(start, vector, TGLUtil::kLineHeadNone, pixelSize*2.5, axesColors[i*2]);
}
if (max[i] > 0.0) {
if (min[i] < 0.0) {
start[i] = 0.0;
vector[i] = max[i];
} else {
start[i] = min[i];
vector[i] = max[i] - min[i];
}
TGLUtil::DrawLine(start, vector, TGLUtil::kLineHeadNone, pixelSize*2.5, axesColors[i*2 + 1]);
}
}
if (axesType == TGLViewer::kAxesOrigin) {
Float_t white[4] = { 1.0, 1.0, 1.0, 1.0 };
TGLUtil::DrawSphere(TGLVertex3(0.0, 0.0, 0.0), pixelSize*2.0, white);
} else {
for (UInt_t j = 0; j < 3; j++) {
if (min[j] <= 0.0 && max[j] >= 0.0) {
TGLVertex3 zero;
zero[j] = 0.0;
zero[(j+1)%3] = min[(j+1)%3];
zero[(j+2)%3] = min[(j+2)%3];
TGLUtil::DrawSphere(zero, pixelSize*2.0, axesColors[j*2 + 1]);
}
}
}
static const UChar_t xyz[][8] = {{0x44, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0x44},
{0x10, 0x10, 0x10, 0x10, 0x10, 0x28, 0x44, 0x44},
{0x7c, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x7c}};
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
Double_t padPixels = 25.0;
glDisable(GL_LIGHTING);
for (UInt_t k = 0; k < 3; k++) {
TGLUtil::SetDrawColors(axesColors[k*2+1]);
TGLVertex3 minPos, maxPos;
if (axesType == TGLViewer::kAxesOrigin) {
minPos[(k+1)%3] = 0.0;
minPos[(k+2)%3] = 0.0;
} else {
minPos[(k+1)%3] = min[(k+1)%3];
minPos[(k+2)%3] = min[(k+2)%3];
}
maxPos = minPos;
minPos[k] = min[k];
maxPos[k] = max[k];
TGLVector3 axis = maxPos - minPos;
TGLVector3 axisViewport = camera.WorldDeltaToViewport(minPos, axis);
if (axisViewport.Mag() < 1) {
continue;
}
minPos -= camera.ViewportDeltaToWorld(minPos, padPixels*axisViewport.X()/axisViewport.Mag(),
padPixels*axisViewport.Y()/axisViewport.Mag());
axisViewport = camera.WorldDeltaToViewport(maxPos, -axis);
maxPos -= camera.ViewportDeltaToWorld(maxPos, padPixels*axisViewport.X()/axisViewport.Mag(),
padPixels*axisViewport.Y()/axisViewport.Mag());
DrawNumber(min[k], minPos);
DrawNumber(max[k], maxPos);
TGLVertex3 namePos = maxPos -
camera.ViewportDeltaToWorld(maxPos, padPixels*axisViewport.X()/axisViewport.Mag(),
padPixels*axisViewport.Y()/axisViewport.Mag());
glRasterPos3dv(namePos.CArr());
glBitmap(8, 8, 0.0, 4.0, 0.0, 0.0, xyz[k]);
}
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
}
void TGLScene::DrawNumber(Double_t num, const TGLVertex3 & center) const
{
if (fLock != kDrawLock && fLock != kSelectLock) {
Error("TGLScene::DrawNumber", "expected Draw or Select Lock");
}
static const UChar_t
digits[][8] = {{0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38},
{0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x10, 0x10},
{0x7c, 0x44, 0x20, 0x18, 0x04, 0x04, 0x44, 0x38},
{0x38, 0x44, 0x04, 0x04, 0x18, 0x04, 0x44, 0x38},
{0x04, 0x04, 0x04, 0x04, 0x7c, 0x44, 0x44, 0x44},
{0x7c, 0x44, 0x04, 0x04, 0x7c, 0x40, 0x40, 0x7c},
{0x7c, 0x44, 0x44, 0x44, 0x7c, 0x40, 0x40, 0x7c},
{0x20, 0x20, 0x20, 0x10, 0x08, 0x04, 0x44, 0x7c},
{0x38, 0x44, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38},
{0x7c, 0x44, 0x04, 0x04, 0x7c, 0x44, 0x44, 0x7c},
{0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00}};
TString str;
str+=Long_t(num);
Double_t xOffset = 3.5 * str.Length();
Double_t yOffset = 4.0;
glRasterPos3dv(center.CArr());
for (Ssiz_t i = 0, e = str.Length(); i < e; ++i) {
if (str[i] == '.') {
glBitmap(8, 8, xOffset, yOffset, 7.0, 0.0, digits[10]);
} else if (str[i] == '-') {
glBitmap(8, 8, xOffset, yOffset, 7.0, 0.0, digits[11]);
} else {
glBitmap(8, 8, xOffset, yOffset, 7.0, 0.0, digits[str[i] - '0']);
}
}
}
Bool_t TGLScene::Select(const TGLCamera & camera, const TGLDrawFlags & sceneFlags)
{
Bool_t changed = kFALSE;
if (fLock != kSelectLock) {
Error("TGLScene::Select", "expected SelectLock");
}
static std::vector<GLuint> selectBuffer;
selectBuffer.resize(fPhysicalShapes.size()*4);
glSelectBuffer(selectBuffer.size(), &selectBuffer[0]);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(0);
Draw(camera, sceneFlags, 0.0, TGLViewer::kAxesNone, 0, kTRUE);
Int_t hits = glRenderMode(GL_RENDER);
if (hits < 0) {
Error("TGLScene::Select", "selection buffer overflow");
return changed;
}
if (hits > 0) {
static std::vector<std::pair<UInt_t, Int_t> > sortedHits;
sortedHits.resize(hits);
Int_t i;
for (i = 0; i < hits; i++) {
assert(selectBuffer[i * 4] == 1);
sortedHits[i].first = selectBuffer[i * 4 + 1];
sortedHits[i].second = selectBuffer[i * 4 + 3];
}
std::sort(sortedHits.begin(), sortedHits.end());
TGLPhysicalShape * selected = 0;
for (i = 0; i < hits; i++) {
selected = FindPhysical(sortedHits[i].second);
if (!selected->IsTransparent()) {
break;
}
}
if (selected->IsTransparent()) {
selected = FindPhysical(sortedHits[0].second);
}
assert(selected);
if (selected != fSelectedPhysical) {
if (fSelectedPhysical) {
fSelectedPhysical->Select(kFALSE);
}
fSelectedPhysical = selected;
fSelectedPhysical->Select(kTRUE);
changed = kTRUE;
}
fCurrentManip->Attach(fSelectedPhysical);
} else {
if (fSelectedPhysical) {
fSelectedPhysical->Select(kFALSE);
fSelectedPhysical = 0;
changed = kTRUE;
}
if (fCurrentManip->GetAttached()) {
fCurrentManip->Attach(0);
changed = kTRUE;
}
}
return changed;
}
Bool_t TGLScene::SetSelectedColor(const Float_t color[17])
{
if (fSelectedPhysical) {
fSelectedPhysical->SetColor(color);
return kTRUE;
} else {
assert(kFALSE);
return kFALSE;
}
}
Bool_t TGLScene::SetColorOnSelectedFamily(const Float_t color[17])
{
if (fSelectedPhysical) {
if (TAttLine *test = dynamic_cast<TAttLine *>(fSelectedPhysical->GetLogical().GetExternal()))
test->SetLineColor(TColor::GetColor(color[0], color[1], color[2]));
TGLPhysicalShape * physical;
PhysicalShapeMapIt_t physicalShapeIt = fPhysicalShapes.begin();
while (physicalShapeIt != fPhysicalShapes.end()) {
physical = physicalShapeIt->second;
if (physical) {
if (physical->GetLogical().ID() == fSelectedPhysical->GetLogical().ID()) {
physical->SetColor(color);
}
} else {
assert(kFALSE);
}
++physicalShapeIt;
}
return kTRUE;
} else {
assert(kFALSE);
return kFALSE;
}
}
Bool_t TGLScene::SetSelectedGeom(const TGLVertex3 & trans, const TGLVector3 & scale)
{
if (fSelectedPhysical) {
fSelectedPhysical->SetTranslation(trans);
fSelectedPhysical->Scale(scale);
fBoundingBoxValid = kFALSE;
return kTRUE;
} else {
assert(kFALSE);
return kFALSE;
}
}
void TGLScene::SetupClips()
{
ClearClips();
fClipPlane = new TGLClipPlane(TGLVector3(0.0,-1.0,0.0),
BoundingBox().Center(),
BoundingBox().Extents().Mag()*5.0);
TGLVector3 halfLengths = BoundingBox().Extents() * 0.2501;
TGLVertex3 center = BoundingBox().Center() + halfLengths;
fClipBox = new TGLClipBox(halfLengths, center);
}
void TGLScene::ClearClips()
{
if (fCurrentManip->GetAttached() == fCurrentClip) {
fCurrentManip->Attach(0);
}
fCurrentClip = 0;
delete fClipPlane;
delete fClipBox;
}
void TGLScene::GetClipState(EClipType type, Double_t data[6]) const
{
if (type == kClipPlane) {
TGLPlaneSet_t planes;
fClipPlane->PlaneSet(planes);
data[0] = planes[0].A();
data[1] = planes[0].B();
data[2] = planes[0].C();
data[3] = planes[0].D();
} else if (type == kClipBox) {
const TGLBoundingBox & box = fClipBox->BoundingBox();
TGLVector3 ext = box.Extents();
data[0] = box.Center().X();
data[1] = box.Center().Y();
data[2] = box.Center().Z();
data[3] = box.Extents().X();
data[4] = box.Extents().Y();
data[5] = box.Extents().Z();
} else {
Error("TGLScene::GetClipState", "invalid clip type");
}
}
void TGLScene::SetClipState(EClipType type, const Double_t data[6])
{
switch (type) {
case(kClipNone): {
break;
}
case(kClipPlane): {
TGLPlane newPlane(data[0], data[1], data[2], data[3]);
fClipPlane->Set(newPlane);
break;
}
case(kClipBox): {
const TGLBoundingBox & currentBox = fClipBox->BoundingBox();
TGLVector3 shift(data[0] - currentBox.Center().X(),
data[1] - currentBox.Center().Y(),
data[2] - currentBox.Center().Z());
fClipBox->Translate(shift);
TGLVector3 currentScale = fClipBox->GetScale();
TGLVector3 newScale(data[3] / currentBox.Extents().X() * currentScale.X(),
data[4] / currentBox.Extents().Y() * currentScale.Y(),
data[5] / currentBox.Extents().Z() * currentScale.Z());
fClipBox->Scale(newScale);
break;
}
}
}
void TGLScene::GetCurrentClip(EClipType & type, Bool_t & edit) const
{
if (fCurrentClip == 0) {
type = kClipNone;
edit = kFALSE;
} else if (fCurrentClip == fClipPlane) {
type = kClipPlane;
edit = (fCurrentManip->GetAttached() == fCurrentClip);
} else if (fCurrentClip == fClipBox) {
type = kClipBox;
edit = (fCurrentManip->GetAttached() == fCurrentClip);
} else {
Error("TGLScene::GetCurrentClip" , "Unknown clip type");
type = kClipNone;
edit = kFALSE;
}
}
void TGLScene::SetCurrentClip(EClipType type, Bool_t edit)
{
if (!edit && fCurrentManip->GetAttached() == fCurrentClip) {
fCurrentManip->Attach(0);
}
switch (type) {
case(kClipNone): {
fCurrentClip = 0;
break;
}
case(kClipPlane): {
fCurrentClip = fClipPlane;
break;
}
case(kClipBox): {
fCurrentClip = fClipBox;
break;
}
default: {
Error("TGLScene::SetCurrentClip" , "Unknown clip type");
break;
}
}
if (edit) {
fCurrentManip->Attach(fCurrentClip);
fSelectedPhysical = 0;
}
}
void TGLScene::SetCurrentManip(EManipType type)
{
switch (type) {
case kManipTrans: {
fTransManip.Attach(fCurrentManip->GetAttached());
fCurrentManip = &fTransManip;
break;
}
case kManipScale: {
fScaleManip.Attach(fCurrentManip->GetAttached());
fCurrentManip = &fScaleManip;
break;
}
case kManipRotate: {
fRotateManip.Attach(fCurrentManip->GetAttached());
fCurrentManip = &fRotateManip;
break;
}
default: {
Error("TGLScene::SetCurrentManip", "invalid manipulator type");
break;
}
}
}
const TGLBoundingBox & TGLScene::BoundingBox() const
{
if (!fBoundingBoxValid) {
Double_t xMin, xMax, yMin, yMax, zMin, zMax;
xMin = xMax = yMin = yMax = zMin = zMax = 0.0;
PhysicalShapeMapCIt_t physicalShapeIt = fPhysicalShapes.begin();
const TGLPhysicalShape * physicalShape;
while (physicalShapeIt != fPhysicalShapes.end())
{
physicalShape = physicalShapeIt->second;
if (!physicalShape)
{
assert(kFALSE);
continue;
}
TGLBoundingBox box = physicalShape->BoundingBox();
if (physicalShapeIt == fPhysicalShapes.begin()) {
xMin = box.XMin(); xMax = box.XMax();
yMin = box.YMin(); yMax = box.YMax();
zMin = box.ZMin(); zMax = box.ZMax();
} else {
if (box.XMin() < xMin) { xMin = box.XMin(); }
if (box.XMax() > xMax) { xMax = box.XMax(); }
if (box.YMin() < yMin) { yMin = box.YMin(); }
if (box.YMax() > yMax) { yMax = box.YMax(); }
if (box.ZMin() < zMin) { zMin = box.ZMin(); }
if (box.ZMax() > zMax) { zMax = box.ZMax(); }
}
++physicalShapeIt;
}
fBoundingBox.SetAligned(TGLVertex3(xMin,yMin,zMin), TGLVertex3(xMax,yMax,zMax));
fBoundingBoxValid = kTRUE;
}
return fBoundingBox;
}
void TGLScene::Dump() const
{
std::cout << "Scene: " << fLogicalShapes.size() << " Logicals / " << fPhysicalShapes.size() << " Physicals " << std::endl;
}
UInt_t TGLScene::SizeOf() const
{
UInt_t size = sizeof(this);
std::cout << "Size: Scene Only " << size << std::endl;
LogicalShapeMapCIt_t logicalShapeIt = fLogicalShapes.begin();
const TGLLogicalShape * logicalShape;
while (logicalShapeIt != fLogicalShapes.end()) {
logicalShape = logicalShapeIt->second;
size += sizeof(*logicalShape);
++logicalShapeIt;
}
std::cout << "Size: Scene + Logical Shapes " << size << std::endl;
PhysicalShapeMapCIt_t physicalShapeIt = fPhysicalShapes.begin();
const TGLPhysicalShape * physicalShape;
while (physicalShapeIt != fPhysicalShapes.end()) {
physicalShape = physicalShapeIt->second;
size += sizeof(*physicalShape);
++physicalShapeIt;
}
std::cout << "Size: Scene + Logical Shapes + Physical Shapes " << size << std::endl;
return size;
}
void TGLScene::ResetDrawStats(const TGLDrawFlags & flags)
{
fDrawStats.fFlags = flags;
fDrawStats.fOpaque = 0;
fDrawStats.fTrans = 0;
fDrawStats.fPixelLOD = 0;
fDrawStats.fByShape.clear();
}
void TGLScene::UpdateDrawStats(const TGLPhysicalShape & shape, const TGLDrawFlags & flags)
{
if (shape.IsTransparent()) {
++fDrawStats.fTrans;
} else {
++fDrawStats.fOpaque;
}
if (flags.LOD() == TGLDrawFlags::kLODPixel) {
fDrawStats.fPixelLOD++;
}
if (gDebug>3) {
std::string shapeType = shape.GetLogical().IsA()->GetName();
typedef std::map<std::string, UInt_t>::iterator MapIt_t;
MapIt_t statIt = fDrawStats.fByShape.find(shapeType);
if (statIt == fDrawStats.fByShape.end()) {
statIt = fDrawStats.fByShape.insert(std::make_pair(shapeType, 0u)).first;
}
statIt->second++;
}
}
void TGLScene::DumpDrawStats()
{
if (gDebug>2) {
std::string style;
switch (fDrawStats.fFlags.Style()) {
case TGLDrawFlags::kFill: {
style = "Filled Polys";
break;
}
case TGLDrawFlags::kWireFrame: {
style = "Wireframe";
break;
}
case TGLDrawFlags::kOutline: {
style = "Outline";
break;
}
}
Info("TGLScene::DumpDrawStats()", "Drew scene (%s / %i LOD) - %i (Op %i Trans %i) %i pixel",
style.c_str(),
fDrawStats.fFlags.LOD(),
fDrawStats.fOpaque + fDrawStats.fTrans,
fDrawStats.fOpaque,
fDrawStats.fTrans,
fDrawStats.fPixelLOD);
}
if (gDebug>3) {
std::map<std::string, UInt_t>::const_iterator it = fDrawStats.fByShape.begin();
while (it != fDrawStats.fByShape.end()) {
std::cout << it->first << " (" << it->second << ")\t";
it++;
}
std::cout << std::endl;
}
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.