// @(#)root/gl:$Name: $:$Id: TGLScene.cxx,v 1.12 2005/06/23 15:08:45 brun Exp $
// Author: Richard Maunder 25/05/2005
// Parts taken from original TGLRender by Timur Pocheptsov
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
// TODO: Function descriptions
// TODO: Class def - same as header
#include "TGLScene.h"
#include "TGLCamera.h"
#include "TGLLogicalShape.h"
#include "TGLPhysicalShape.h"
#include "TGLStopwatch.h"
#include "TGLDisplayListCache.h"
#include "TGLIncludes.h"
#include "TError.h"
#include "TString.h"
#include "Riostream.h"
#include <algorithm>
ClassImp(TGLScene)
//______________________________________________________________________________
TGLScene::TGLScene() :
fLock(kUnlocked), fDrawList(1000),
fDrawListValid(kFALSE), fBoundingBox(), fBoundingBoxValid(kFALSE),
fLastDrawLOD(kHigh), fDrawMode(kFill), fSelectedPhysical(0)
{
}
//______________________________________________________________________________
TGLScene::~TGLScene()
{
TakeLock(kModifyLock);
DestroyPhysicals(kTRUE); // including modified
DestroyLogicals();
ReleaseLock(kModifyLock);
// Purge out the DL cache - when per drawable done no longer required
TGLDisplayListCache::Instance().Purge();
}
//TODO: Inline
//______________________________________________________________________________
void TGLScene::AdoptLogical(TGLLogicalShape & shape)
{
if (fLock != kModifyLock) {
Error("TGLScene::AdoptLogical", "expected ModifyLock");
return;
}
// TODO: Very inefficient check - disable
assert(fLogicalShapes.find(shape.ID()) == fLogicalShapes.end());
fLogicalShapes.insert(LogicalShapeMapValueType_t(shape.ID(), &shape));
}
//______________________________________________________________________________
Bool_t TGLScene::DestroyLogical(ULong_t ID)
{
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::DestroyAllLogicals", "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;
}
//TODO: Inline
//______________________________________________________________________________
TGLLogicalShape * TGLScene::FindLogical(ULong_t ID) const
{
LogicalShapeMapCIt_t it = fLogicalShapes.find(ID);
if (it != fLogicalShapes.end()) {
return it->second;
} else {
return 0;
}
}
//TODO: Inline
//______________________________________________________________________________
void TGLScene::AdoptPhysical(TGLPhysicalShape & shape)
{
if (fLock != kModifyLock) {
Error("TGLScene::AdoptPhysical", "expected ModifyLock");
return;
}
// TODO: Very inefficient check - disable
assert(fPhysicalShapes.find(shape.ID()) == fPhysicalShapes.end());
fPhysicalShapes.insert(PhysicalShapeMapValueType_t(shape.ID(), &shape));
fBoundingBoxValid = kFALSE;
// Add into draw list and mark for sorting
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) {
fSelectedPhysical = 0;
}
fPhysicalShapes.erase(physicalIt);
fBoundingBoxValid = kFALSE;
// Zero the draw list entry - will be erased as part of sorting
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) {
// Destroy any physical shape no longer of interest to camera
// If modified options allow this physical to be destoyed
if (incModified || (!incModified && !physical->IsModified())) {
// and no camera is passed, or it is no longer of interest
// to camera
if (!camera || (camera && !camera->OfInterest(physical->BoundingBox()))) {
// Then we can destroy it - remove from map
fPhysicalShapes.erase(physicalShapeIt++);
// Zero the draw list entry - will be erased as part of sorting
DrawListIt_t drawIt = find(fDrawList.begin(), fDrawList.end(), physical);
if (drawIt != fDrawList.end()) {
*drawIt = 0;
} else {
assert(kFALSE);
}
// Ensure if selected object this is cleared
if (fSelectedPhysical == physical) {
fSelectedPhysical = 0;
}
// Finally destroy actual object
delete physical;
++count;
continue; // Incremented the iterator during erase()
}
}
} else {
assert(kFALSE);
}
++physicalShapeIt;
}
if (count > 0) {
fBoundingBoxValid = kFALSE;
fDrawListValid = kFALSE;
}
return count;
}
//TODO: Inline
//______________________________________________________________________________
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::SetPhysicalsColorByLogical(ULong_t logicalID, const Float_t rgba[4])
{
if (fLock != kModifyLock) {
Error("TGLScene::SetPhysicalsColorByLogical", "expected ModifyLock");
return;
}
PhysicalShapeMapIt_t physicalShapeIt = fPhysicalShapes.begin();
TGLPhysicalShape * physical;
while (physicalShapeIt != fPhysicalShapes.end()) {
physical = physicalShapeIt->second;
if (physical) {
if (physical->GetLogical().ID() == logicalID) {
physical->SetColor(rgba);
}
} else {
assert(kFALSE);
}
++physicalShapeIt;
}
}
//______________________________________________________________________________
//TODO: Merge axes flag and LOD into general draw flag
UInt_t TGLScene::Draw(const TGLCamera & camera, UInt_t sceneLOD, Double_t timeout)
{
UInt_t drawn = 0;
if (fLock != kDrawLock && fLock != kSelectLock) {
Error("TGLScene::Draw", "expected Draw or Select Lock");
}
void (TGLPhysicalShape::*drawPtr)(UInt_t)const = &TGLPhysicalShape::Draw;
if (fDrawMode)
fDrawMode == kWireFrame ? drawPtr = &TGLPhysicalShape::DrawWireFrame :
drawPtr = &TGLPhysicalShape::DrawOutline;
TGLStopwatch stopwatch;
stopwatch.Start();
// If the scene bounding box is inside the camera frustum then
// no need to check individual shapes - everything is visible
Bool_t doFrustumCheck = (camera.FrustumOverlap(BoundingBox()) != kInside);
if (!fDrawListValid) {
SortDrawList();
}
// TODO: Tidy up draw loop to make this less complicated
// Step 1: Loop through the main sorted draw list
Bool_t run = kTRUE;
const TGLPhysicalShape * drawShape;
// Transparent list built on fly
static DrawList_t transDrawList;
transDrawList.reserve(fDrawList.size() / 10); // assume less 10% of total
transDrawList.clear();
// Opaque only objects drawn in first loop
// TODO: Sort front -> back for better performance
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
DrawListIt_t drawIt;
for (drawIt = fDrawList.begin(); drawIt != fDrawList.end() && run;
drawIt++) {
drawShape = *drawIt;
if (!drawShape)
{
assert(kFALSE);
continue;
}
// TODO: Do small skipping first? Probably cheaper than frustum check
// Profile relative costs? The frustum check could be done implictly
// from the LOD as we project all 8 verticies of the BB onto viewport
EOverlap frustumOverlap = kInside;
if (doFrustumCheck)
{
frustumOverlap = camera.FrustumOverlap(drawShape->BoundingBox());
}
if (frustumOverlap == kInside || frustumOverlap == kPartial)
{
// Collect transparent shapes for drawing at end
if (drawShape->IsTransparent()) {
transDrawList.push_back(drawShape);
continue;
}
// Get the shape draw quality
UInt_t shapeLOD = CalcPhysicalLOD(*drawShape, camera, sceneLOD);
//Draw, DrawWireFrame, DrawOutline
(drawShape->*drawPtr)(shapeLOD);
++drawn;
}
// Terminate the draw is over timeout
if (timeout > 0.0 && stopwatch.Lap() > timeout) {
run = kFALSE;
}
}
// Step 2: Deal with selected physical
if (fSelectedPhysical) {
// Draw now if non-transparent (may already have been done)
if (!fSelectedPhysical->IsTransparent()) {
UInt_t shapeLOD = CalcPhysicalLOD(*fSelectedPhysical, camera, sceneLOD);
(fSelectedPhysical->*drawPtr)(shapeLOD);
++drawn;
} else {
// Ensure transparent selected physical will get drawn
transDrawList.push_back(fSelectedPhysical);
}
}
// Step 3: Draw the filtered transparent objects with GL depth writing off
// blending on
// TODO: Sort to draw back to front with depth test off for better blending
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// We assume there are <<< of these than opaque so time will be negligible
// TODO: Record transparent % and reserve time for these
for (drawIt = transDrawList.begin(); drawIt != transDrawList.end(); drawIt++) {
drawShape = *drawIt;
UInt_t shapeLOD = CalcPhysicalLOD(*drawShape, camera, sceneLOD);
//Draw, DrawWireFrame, DrawOutline
(drawShape->*drawPtr)(shapeLOD);
++drawn;
}
// Reset these after transparent done
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
// Finally: Draw selected object bounding box
if (fSelectedPhysical) {
//BBOX is white for wireframe mode and fill,
//red for outlines
switch (fDrawMode) {
case kFill:
case kWireFrame :
glColor3d(1., 1., 1.);
break;
case kOutline:
glColor3d(1., 0., 0.);
break;
}
if (fDrawMode == kFill || fDrawMode == kOutline) {
glDisable(GL_LIGHTING);
}
glDisable(GL_DEPTH_TEST);
fSelectedPhysical->BoundingBox().Draw();
if (fDrawMode == kFill || fDrawMode == kOutline) {
glEnable(GL_LIGHTING);
}
glEnable(GL_DEPTH_TEST);
}
// Record this so that any Select() draw can be redone at same quality and ensure
// accuracy of picking
fLastDrawLOD = sceneLOD;
// TODO: Should record if full scene can be drawn at 100% in a target time (set on scene)
// Then timeout should not be passed - just bool if termination is permitted - which may
// be ignored if all can be done. Pass back bool to indicate if whole scene could be drawn
// at desired quality. Need a fixed target time so valid across multiple draws
return drawn;
}
//______________________________________________________________________________
void TGLScene::SortDrawList()
{
assert(!fDrawListValid);
TGLStopwatch stopwatch;
if (gDebug>2) {
stopwatch.Start();
}
fDrawList.reserve(fPhysicalShapes.size());
// Delete all zero (to-be-deleted) objects
fDrawList.erase(remove(fDrawList.begin(), fDrawList.end(), static_cast<const TGLPhysicalShape *>(0)), fDrawList.end());
assert(fDrawList.size() == fPhysicalShapes.size());
//TODO: partition the selected to front
// Sort by volume of shape bounding box
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::DrawAxes() const
{
if (fLock != kDrawLock && fLock != kSelectLock) {
Error("TGLScene::Draw", "expected Draw or Select Lock");
}
// Draw out the scene axes
// Taken directly from TGLRender by Timur Pocheptsov
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);
glPushAttrib(GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
const Double_t axeColors[][3] = {{1., 0., 0.}, // X axis red
{0., 1., 0.}, // Y axis green
{0., 0., 1.}};// Z axis blue
//glColor3dv(axeColors[3]);
const TGLBoundingBox & box = BoundingBox();
Double_t xmin = box.XMin(), xmax = box.XMax();
Double_t ymin = box.YMin(), ymax = box.YMax();
Double_t zmin = box.ZMin(), zmax = box.ZMax();
glBegin(GL_LINES);
glColor3dv(axeColors[0]);
glVertex3d(xmin, ymin, zmin);
glVertex3d(xmax, ymin, zmin);
glColor3dv(axeColors[1]);
glVertex3d(xmin, ymin, zmin);
glVertex3d(xmin, ymax, zmin);
glColor3dv(axeColors[2]);
glVertex3d(xmin, ymin, zmin);
glVertex3d(xmin, ymin, zmax);
glEnd();
// X label
glColor3dv(axeColors[0]);
glRasterPos3d(xmax, ymin + 12, zmin);
glBitmap(8, 8, 0., 0., 0., 0., xyz[0]);
DrawNumber(xmax, xmax, ymin, zmin, 9.);
DrawNumber(xmin, xmin, ymin, zmin, 0.);
// Y label
glColor3dv(axeColors[1]);
glRasterPos3d(xmin, ymax + 12, zmin);
glBitmap(8, 8, 0, 0, 12., 0, xyz[1]);
DrawNumber(ymax, xmin, ymax, zmin, 9.);
DrawNumber(ymin, xmin, ymin, zmin, 9.);
// Z label
glColor3dv(axeColors[2]);
glRasterPos3d(xmin, ymin, zmax);
glBitmap(8, 8, 0, 0, 0., 0, xyz[2]);
DrawNumber(zmax, xmin, ymin, zmax, 9.);
DrawNumber(zmin, xmin, ymin, zmin, -9.);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glPopAttrib();
}
//______________________________________________________________________________
void TGLScene::DrawNumber(Double_t num, Double_t x, Double_t y, Double_t z, Double_t yorig) const
{
if (fLock != kDrawLock && fLock != kSelectLock) {
Error("TGLScene::Draw", "expected Draw or Select Lock");
}
static const UChar_t
digits[][8] = {{0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38},//0
{0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x10, 0x10},//1
{0x7c, 0x44, 0x20, 0x18, 0x04, 0x04, 0x44, 0x38},//2
{0x38, 0x44, 0x04, 0x04, 0x18, 0x04, 0x44, 0x38},//3
{0x04, 0x04, 0x04, 0x04, 0x7c, 0x44, 0x44, 0x44},//4
{0x7c, 0x44, 0x04, 0x04, 0x7c, 0x40, 0x40, 0x7c},//5
{0x7c, 0x44, 0x44, 0x44, 0x7c, 0x40, 0x40, 0x7c},//6
{0x20, 0x20, 0x20, 0x10, 0x08, 0x04, 0x44, 0x7c},//7
{0x38, 0x44, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38},//8
{0x7c, 0x44, 0x04, 0x04, 0x7c, 0x44, 0x44, 0x7c},//9
{0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//.
{0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00}};//-
TString str;
str+=Long_t(num);
glRasterPos3i(Int_t(x), Int_t(y), Int_t(z));
for (Ssiz_t i = 0, e = str.Length(); i < e; ++i) {
if (str[i] == '.') {
glBitmap(8, 8, 0., yorig, 7., 0., digits[10]);
if (i + 1 < e)
glBitmap(8, 8, 0., yorig, 7., 0., digits[str[i + 1] - '0']);
break;
} else if (str[i] == '-') {
glBitmap(8, 8, 0., yorig, 7., 0., digits[11]);
} else {
glBitmap(8, 8, 0., yorig, 7., 0., digits[str[i] - '0']);
}
}
}
//______________________________________________________________________________
UInt_t TGLScene::CalcPhysicalLOD(const TGLPhysicalShape & shape, const TGLCamera & camera,
UInt_t sceneLOD) const
{
// Find diagonal pixel size of projected drawable BB, using camera
Double_t diagonal = static_cast<Double_t>(camera.ViewportSize(shape.BoundingBox()).Diagonal());
// TODO: Get real screen size - assuming 2000 pixel screen at present
// Calculate a non-linear sizing hint for this shape. Needs more experimenting with...
UInt_t sizeLOD = static_cast<UInt_t>(pow(diagonal,0.4) * 100.0 / pow(2000.0,0.4));
// Factor in scene quality
UInt_t shapeLOD = (sceneLOD * sizeLOD) / 100;
if (shapeLOD > 10) {
Double_t quant = ((static_cast<Double_t>(shapeLOD)) + 0.3) / 10;
shapeLOD = static_cast<UInt_t>(quant)*10;
} else {
Double_t quant = ((static_cast<Double_t>(shapeLOD)) + 0.3) / 3;
shapeLOD = static_cast<UInt_t>(quant)*3;
}
if (shapeLOD > 100) {
shapeLOD = 100;
}
return shapeLOD;
}
//______________________________________________________________________________
Bool_t TGLScene::Select(const TGLCamera & camera)
{
Bool_t redrawReq = kFALSE;
if (fLock != kSelectLock) {
Error("TGLScene::Draw", "expected SelectLock");
}
// Create the select buffer. This will work as we have a flat set of physical shapes.
// We only ever load a single name in TGLPhysicalShape::DirectDraw so any hit record always
// has same 4 GLuint format
static std::vector<GLuint> selectBuffer(fPhysicalShapes.size()*4);
glSelectBuffer(selectBuffer.size(), &selectBuffer[0]);
// Enter picking mode
glRenderMode(GL_SELECT);
glInitNames();
glPushName(0);
// Draw out scene at last visible quality
Draw(camera, kHigh, kFALSE); // No axes
// Retrieve the hit count and return to render
GLint hits = glRenderMode(GL_RENDER);
if (hits < 0) {
Error("TGLScene::Select", "selection buffer overflow");
} else if (hits > 0) {
// Every hit record has format (GLuint per item) - see above for selectBuffer
// for reason. Format is:
//
// no of names in name block (1 always)
// minDepth
// maxDepth
// name(s) (1 always)
assert(selectBuffer[0] == 1);
UInt_t minDepth = selectBuffer[1];
UInt_t minDepthName = selectBuffer[3];
// Find the nearest picked object
// TODO: Put back transparency picking stuff
for (Int_t i = 1; i < hits; ++i) {
assert(selectBuffer[i*4] == 1); // Single name per record
if (selectBuffer[i*4 + 1] < minDepth) {
minDepth = selectBuffer[i*4 + 1];
minDepthName = selectBuffer[i*4 + 3];
}
}
TGLPhysicalShape * selected = FindPhysical(minDepthName);
if (!selected) {
assert(kFALSE);
}
// Swap any selection
if (selected != fSelectedPhysical) {
if (fSelectedPhysical) {
fSelectedPhysical->Select(kFALSE);
}
fSelectedPhysical = selected;
fSelectedPhysical->Select(kTRUE);
redrawReq = kTRUE;
}
} else { // 0 hits
if (fSelectedPhysical) {
fSelectedPhysical->Select(kFALSE);
fSelectedPhysical = 0;
redrawReq = kTRUE;
}
}
return redrawReq;
}
//______________________________________________________________________________
void TGLScene::SelectedModified()
{
// External modification - no locking
// The selected object was modified external - our bounding box
// is potentially invalid
if (fSelectedPhysical && !BoundingBox().AlignedContains(fSelectedPhysical->BoundingBox())) {
fBoundingBoxValid = kFALSE;
}
}
//______________________________________________________________________________
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;
}
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.