#include "TGLViewer.h"
#include "TGLIncludes.h"
#include "TGLStopwatch.h"
#include "TGLDisplayListCache.h"
#include "TGLLogicalShape.h"
#include "TGLPhysicalShape.h"
#include "TGLObject.h"
#include "TGLStopwatch.h"
#include "TBuffer3D.h"
#include "TBuffer3DTypes.h"
#include "TGLFaceSet.h"
#include "TGLPolyLine.h"
#include "TGLPolyMarker.h"
#include "TGLCylinder.h"
#include "TGLSphere.h"
#include "TGLOutput.h"
#include "TVirtualPad.h" // Remove when pad removed - use signal
#include "TVirtualX.h"
#include "TColor.h"
#include "TError.h"
#include "TROOT.h"
#include "Buttons.h"
#include "GuiTypes.h"
#include "TVirtualGL.h"
#include "TGLRenderArea.h"
#include "TGLViewerEditor.h"
#include "KeySymbols.h"
#include "TContextMenu.h"
#include <TBaseClass.h>
ClassImp(TGLViewer)
TGLViewer::TGLViewer(TVirtualPad * pad, Int_t x, Int_t y,
UInt_t width, UInt_t height) :
fPad(pad),
fContextMenu(0),
fPerspectiveCameraXOZ(TGLVector3(1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)),
fPerspectiveCameraYOZ(TGLVector3(0.0, 1.0, 0.0), TGLVector3(1.0, 0.0, 0.0)),
fPerspectiveCameraXOY(TGLVector3(1.0, 0.0, 0.0), TGLVector3(0.0, 0.0,-1.0)),
fOrthoXOYCamera(TGLOrthoCamera::kXOY),
fOrthoXOZCamera(TGLOrthoCamera::kXOZ),
fOrthoZOYCamera(TGLOrthoCamera::kZOY),
fCurrentCamera(&fPerspectiveCameraXOZ),
fInternalRebuild(kFALSE),
fPostSceneBuildSetup(kFALSE),
fAcceptedAllPhysicals(kTRUE),
fForceAcceptAll(kFALSE),
fInternalPIDs(kFALSE),
fNextInternalPID(1),
fComposite(0), fCSLevel(0),
fAction(kCameraNone), fLastPos(0,0), fActiveButtonID(0),
fDrawFlags(TGLDrawFlags::kFill, TGLDrawFlags::kLODHigh),
fRedrawTimer(0),
fClearColor(1),
fLightState(kLightMask),
fAxesType(kAxesNone),
fReferenceOn(kFALSE),
fReferencePos(0.0, 0.0, 0.0),
fInitGL(kFALSE),
fSmartRefresh(kFALSE),
fDebugMode(kFALSE),
fAcceptedPhysicals(0),
fRejectedPhysicals(0),
fIsPrinting(kFALSE),
fGLWindow(0),
fGLDevice(-1),
fPadEditor(0),
fIgnoreSizesOnUpdate(kFALSE),
fResetCamerasOnUpdate(kTRUE),
fResetCamerasOnNextUpdate(kFALSE),
fResetCameraOnDoubleClick(kTRUE)
{
fRedrawTimer = new TGLRedrawTimer(*this);
SetViewport(x, y, width, height);
}
TGLViewer::TGLViewer(TVirtualPad * pad) :
fPad(pad),
fContextMenu(0),
fPerspectiveCameraXOZ(TGLVector3(1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)),
fPerspectiveCameraYOZ(TGLVector3(0.0, 1.0, 0.0), TGLVector3(1.0, 0.0, 0.0)),
fPerspectiveCameraXOY(TGLVector3(1.0, 0.0, 0.0), TGLVector3(0.0, 0.0,-1.0)),
fOrthoXOYCamera(TGLOrthoCamera::kXOY),
fOrthoXOZCamera(TGLOrthoCamera::kXOZ),
fOrthoZOYCamera(TGLOrthoCamera::kZOY),
fCurrentCamera(&fPerspectiveCameraXOZ),
fInternalRebuild(kFALSE),
fPostSceneBuildSetup(kFALSE),
fAcceptedAllPhysicals(kTRUE),
fForceAcceptAll(kFALSE),
fInternalPIDs(kFALSE),
fNextInternalPID(1),
fComposite(0), fCSLevel(0),
fAction(kCameraNone), fLastPos(0,0), fActiveButtonID(0),
fDrawFlags(TGLDrawFlags::kFill, TGLDrawFlags::kLODHigh),
fRedrawTimer(0),
fClearColor(1),
fLightState(kLightMask),
fAxesType(kAxesNone),
fReferenceOn(kFALSE),
fReferencePos(0.0, 0.0, 0.0),
fInitGL(kFALSE),
fSmartRefresh(kFALSE),
fDebugMode(kFALSE),
fAcceptedPhysicals(0),
fRejectedPhysicals(0),
fIsPrinting(kFALSE),
fGLWindow(0),
fGLDevice(fPad->GetGLDevice()),
fPadEditor(0),
fIgnoreSizesOnUpdate(kFALSE),
fResetCamerasOnUpdate(kTRUE),
fResetCamerasOnNextUpdate(kFALSE),
fResetCameraOnDoubleClick(kTRUE)
{
fRedrawTimer = new TGLRedrawTimer(*this);
if (fGLDevice != -1) {
Int_t viewport[4] = {0};
gGLManager->ExtractViewport(fGLDevice, viewport);
SetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
}
TGLViewer::~TGLViewer()
{
delete fContextMenu;
delete fRedrawTimer;
if (fPadEditor) fPadEditor = 0;
fPad->ReleaseViewer3D();
}
Bool_t TGLViewer::PreferLocalFrame() const
{
return kTRUE;
}
void TGLViewer::BeginScene()
{
if (!fScene.TakeLock(TGLScene::kModifyLock)) {
return;
}
UInt_t destroyedLogicals = 0;
UInt_t destroyedPhysicals = 0;
TGLStopwatch stopwatch;
if (gDebug>2 || fDebugMode) {
stopwatch.Start();
}
if (!fInternalRebuild)
{
fInternalPIDs = kFALSE;
fForceAcceptAll = kFALSE;
CurrentCamera().ResetInterest();
fPostSceneBuildSetup = kTRUE;
destroyedPhysicals = fScene.DestroyPhysicals(kTRUE);
if (fSmartRefresh) {
fScene.BeginSmartRefresh();
} else {
destroyedLogicals = fScene.DestroyLogicals();
}
TGLDisplayListCache::Instance().Purge();
} else {
destroyedPhysicals = fScene.DestroyPhysicals(kFALSE, &CurrentCamera());
}
fNextInternalPID = 1;
fAcceptedAllPhysicals = kTRUE;
fAcceptedPhysicals = 0;
fRejectedPhysicals = 0;
if (gDebug>2 || fDebugMode) {
Info("TGLViewer::BeginScene", "destroyed %d physicals %d logicals in %f msec",
destroyedPhysicals, destroyedLogicals, stopwatch.End());
fScene.Dump();
}
}
void TGLViewer::EndScene()
{
if (!fInternalRebuild) {
if (fSmartRefresh) {
fScene.EndSmartRefresh();
}
}
fScene.ReleaseLock(TGLScene::kModifyLock);
if (fPostSceneBuildSetup) {
PostSceneBuildSetup(fResetCamerasOnNextUpdate || fResetCamerasOnUpdate);
fResetCamerasOnNextUpdate = kFALSE;
}
if (!fInternalRebuild) {
RequestDraw();
} else {
fInternalRebuild = kFALSE;
fPostSceneBuildSetup = kFALSE;
}
if (gDebug>2 || fDebugMode) {
Info("TGLViewer::EndScene", "Added %d, rejected %d physicals, accepted all:%s", fAcceptedPhysicals,
fRejectedPhysicals, fAcceptedAllPhysicals ? "Yes":"No");
fScene.Dump();
}
}
Bool_t TGLViewer::RebuildScene()
{
if (fAcceptedAllPhysicals) {
if (fDebugMode) {
Info("TGLViewer::RebuildScene", "not required - all physicals previous accepted (FORCED anyway)");
}
else {
if (gDebug>3) {
Info("TGLViewer::RebuildScene", "not required - all physicals previous accepted");
}
return kFALSE;
}
}
if (!CurrentCamera().UpdateInterest(fDebugMode)) {
if (gDebug>3 || fDebugMode) {
Info("TGLViewer::RebuildScene", "not required - no camera interest change");
}
return kFALSE;
}
fRedrawTimer->Stop();
if (gDebug>3 || fDebugMode) {
Info("TGLViewer::RebuildScene", "required");
}
fInternalRebuild = kTRUE;
TGLStopwatch timer;
if (gDebug>2 || fDebugMode) {
timer.Start();
}
fPad->Paint();
if (gDebug>2 || fDebugMode) {
Info("TGLViewer::RebuildScene", "rebuild complete in %f", timer.End());
}
fRedrawTimer->RequestDraw(20, TGLDrawFlags::kLODMed);
return kTRUE;
}
Int_t TGLViewer::AddObject(const TBuffer3D & buffer, Bool_t * addChildren)
{
fInternalPIDs = kTRUE;
Int_t sections = AddObject(fNextInternalPID, buffer, addChildren);
return sections;
}
Int_t TGLViewer::AddObject(UInt_t physicalID, const TBuffer3D & buffer, Bool_t * addChildren)
{
if (physicalID == 0) {
Error("TGLViewer::AddObject", "0 physical ID reserved");
return TBuffer3D::kNone;
}
if (fInternalPIDs && physicalID != fNextInternalPID) {
Error("TGLViewer::AddObject", "invalid next physical ID - mix of internal + external IDs?");
return TBuffer3D::kNone;
}
if (addChildren) {
*addChildren = kTRUE;
}
if (fScene.CurrentLock() != TGLScene::kModifyLock) {
Error("TGLViewer::AddObject", "expected scene to be in mode modified locked");
return TBuffer3D::kNone;
}
if (fComposite) {
RootCsg::TBaseMesh *newMesh = RootCsg::ConvertToMesh(buffer);
fCSTokens.push_back(std::make_pair(static_cast<UInt_t>(TBuffer3D::kCSNoOp), newMesh));
return TBuffer3D::kNone;
}
TGLPhysicalShape * physical = fScene.FindPhysical(physicalID);
TGLLogicalShape * logical = 0;
if (buffer.fID) {
logical = fScene.FindLogical(reinterpret_cast<ULong_t>(buffer.fID));
if (logical == 0) {
logical = AttemptDirectRenderer(buffer.fID);
}
} else if (!fForceAcceptAll) {
fForceAcceptAll = kTRUE;
if (fNextInternalPID > 1) {
Error("TGLViewer::AddObject", "zero fID objects can't be mixed with non-zero ones");
}
}
static UInt_t lastPID = 0;
if (physicalID != lastPID) {
if (physical) {
if (!logical) {
Error("TGLViewer::AddObject", "cached physical with no assocaited cached logical");
}
if (addChildren && !fInternalPIDs) {
*addChildren = kTRUE;
}
if (fInternalPIDs) {
fNextInternalPID++;
}
return TBuffer3D::kNone;
}
else {
if (!fForceAcceptAll) {
TGLBoundingBox box;
if (logical) {
box = logical->BoundingBox();
}
else if (buffer.SectionsValid(TBuffer3D::kBoundingBox)) {
box.Set(buffer.fBBVertex);
} else if (buffer.SectionsValid(TBuffer3D::kRaw)) {
box.SetAligned(buffer.NbPnts(), buffer.fPnts);
}
if (!box.IsEmpty()) {
box.Transform(TGLMatrix(buffer.fLocalMaster));
Bool_t ignoreSize = fIgnoreSizesOnUpdate || !logical || logical->IgnoreSizeForOfInterest();
Bool_t ofInterest = CurrentCamera().OfInterest(box, ignoreSize);
if (addChildren &&!fInternalPIDs) {
*addChildren = ofInterest;
}
if (!ofInterest) {
++fRejectedPhysicals;
fAcceptedAllPhysicals = kFALSE;
if (fInternalPIDs) {
fNextInternalPID++;
}
return TBuffer3D::kNone;
}
}
}
}
Int_t extraSections = ValidateObjectBuffer(buffer,
logical == 0);
if (extraSections != TBuffer3D::kNone) {
return extraSections;
} else {
lastPID = physicalID;
}
}
if(lastPID != physicalID)
{
Error("TGLViewer::AddObject", "internal physical ID tracking error?");
}
if (physical) {
Error("TGLViewer::AddObject", "expecting to require physical");
return TBuffer3D::kNone;
}
if (!logical) {
logical = CreateNewLogical(buffer);
if (!logical) {
Error("TGLViewer::AddObject", "failed to create logical");
return TBuffer3D::kNone;
}
fScene.AdoptLogical(*logical);
}
physical = CreateNewPhysical(physicalID, buffer, *logical);
if (physical) {
fScene.AdoptPhysical(*physical);
++fAcceptedPhysicals;
if (gDebug>3 && fAcceptedPhysicals%1000 == 0) {
Info("TGLViewer::AddObject", "added %d physicals", fAcceptedPhysicals);
}
} else {
Error("TGLViewer::AddObject", "failed to create physical");
}
if (fInternalPIDs) {
fNextInternalPID++;
}
lastPID = 0;
return TBuffer3D::kNone;
}
Bool_t TGLViewer::OpenComposite(const TBuffer3D & buffer, Bool_t * addChildren)
{
if (fComposite) {
Error("TGLViewer::OpenComposite", "composite already open");
return kFALSE;
}
UInt_t extraSections = AddObject(buffer, addChildren);
if (extraSections != TBuffer3D::kNone) {
Error("TGLViewer::OpenComposite", "expected top level composite to not require extra buffer sections");
}
if (fComposite) {
return kTRUE;
} else {
return kFALSE;
}
}
void TGLViewer::CloseComposite()
{
if (fComposite) {
fCSLevel = 0;
RootCsg::TBaseMesh *resultMesh = BuildComposite();
fComposite->SetFromMesh(resultMesh);
delete resultMesh;
for (UInt_t i = 0; i < fCSTokens.size(); ++i) delete fCSTokens[i].second;
fCSTokens.clear();
fComposite = 0;
}
}
void TGLViewer::AddCompositeOp(UInt_t operation)
{
fCSTokens.push_back(std::make_pair(operation, (RootCsg::TBaseMesh *)0));
}
Int_t TGLViewer::ValidateObjectBuffer(const TBuffer3D & buffer, Bool_t includeRaw) const
{
if (!buffer.SectionsValid(TBuffer3D::kCore)) {
Error("TGLViewer::ValidateObjectBuffer", "kCore section of buffer should be filled always");
return TBuffer3D::kNone;
}
if (!includeRaw) {
return TBuffer3D::kNone;
}
Bool_t needRaw = kFALSE;
if (buffer.Type() != TBuffer3DTypes::kSphere &&
buffer.Type() != TBuffer3DTypes::kTube &&
buffer.Type() != TBuffer3DTypes::kTubeSeg &&
buffer.Type() != TBuffer3DTypes::kCutTube &&
buffer.Type() != TBuffer3DTypes::kComposite) {
needRaw = kTRUE;
}
else if (buffer.Type() == TBuffer3DTypes::kSphere) {
const TBuffer3DSphere * sphereBuffer = dynamic_cast<const TBuffer3DSphere *>(&buffer);
if (sphereBuffer) {
if (!sphereBuffer->IsSolidUncut()) {
needRaw = kTRUE;
}
} else {
Error("TGLViewer::ValidateObjectBuffer", "failed to cast buffer of type 'kSphere' to TBuffer3DSphere");
return TBuffer3D::kNone;
}
}
else if (!buffer.SectionsValid(TBuffer3D::kBoundingBox)) {
needRaw = kTRUE;
}
else if (!buffer.SectionsValid(TBuffer3D::kShapeSpecific) &&
buffer.Type() != TBuffer3DTypes::kComposite) {
needRaw = kTRUE;
}
else if (fComposite) {
needRaw = kTRUE;
}
if (needRaw && !buffer.SectionsValid(TBuffer3D::kRawSizes|TBuffer3D::kRaw)) {
return TBuffer3D::kRawSizes|TBuffer3D::kRaw;
} else {
return TBuffer3D::kNone;
}
}
TGLLogicalShape * TGLViewer::CreateNewLogical(const TBuffer3D & buffer) const
{
TGLLogicalShape * newLogical = 0;
switch (buffer.Type()) {
case TBuffer3DTypes::kLine:
newLogical = new TGLPolyLine(buffer);
break;
case TBuffer3DTypes::kMarker:
newLogical = new TGLPolyMarker(buffer);
break;
case TBuffer3DTypes::kSphere: {
const TBuffer3DSphere * sphereBuffer = dynamic_cast<const TBuffer3DSphere *>(&buffer);
if (sphereBuffer) {
if (sphereBuffer->IsSolidUncut()) {
newLogical = new TGLSphere(*sphereBuffer);
} else {
newLogical = new TGLFaceSet(buffer);
}
}
else {
Error("TGLViewer::CreateNewLogical", "failed to cast buffer of type 'kSphere' to TBuffer3DSphere");
}
break;
}
case TBuffer3DTypes::kTube:
case TBuffer3DTypes::kTubeSeg:
case TBuffer3DTypes::kCutTube: {
const TBuffer3DTube * tubeBuffer = dynamic_cast<const TBuffer3DTube *>(&buffer);
if (tubeBuffer)
{
newLogical = new TGLCylinder(*tubeBuffer);
}
else {
Error("TGLViewer::CreateNewLogical", "failed to cast buffer of type 'kTube/kTubeSeg/kCutTube' to TBuffer3DTube");
}
break;
}
case TBuffer3DTypes::kComposite: {
if (fComposite) {
Error("TGLViewer::CreateNewLogical", "composite already open");
}
fComposite = new TGLFaceSet(buffer);
newLogical = fComposite;
break;
}
default:
newLogical = new TGLFaceSet(buffer);
break;
}
return newLogical;
}
TGLPhysicalShape * TGLViewer::CreateNewPhysical(UInt_t ID,
const TBuffer3D & buffer,
const TGLLogicalShape & logical) const
{
Int_t colorIndex = buffer.fColor;
if (colorIndex <= 1) colorIndex = 42;
Float_t rgba[4] = { 0.0 };
TColor *rcol = gROOT->GetColor(colorIndex);
if (rcol) {
rcol->GetRGB(rgba[0], rgba[1], rgba[2]);
}
rgba[3] = 1.f - buffer.fTransparency / 100.f;
TGLPhysicalShape * newPhysical = new TGLPhysicalShape(ID, logical, buffer.fLocalMaster,
buffer.fReflection, rgba);
return newPhysical;
}
RootCsg::TBaseMesh *TGLViewer::BuildComposite()
{
const CSPart_t &currToken = fCSTokens[fCSLevel];
UInt_t opCode = currToken.first;
if (opCode != TBuffer3D::kCSNoOp) {
++fCSLevel;
RootCsg::TBaseMesh *left = BuildComposite();
RootCsg::TBaseMesh *right = BuildComposite();
switch (opCode) {
case TBuffer3D::kCSUnion:
return RootCsg::BuildUnion(left, right);
case TBuffer3D::kCSIntersection:
return RootCsg::BuildIntersection(left, right);
case TBuffer3D::kCSDifference:
return RootCsg::BuildDifference(left, right);
default:
Error("BuildComposite", "Wrong operation code %d\n", opCode);
return 0;
}
} else return fCSTokens[fCSLevel++].second;
}
void TGLViewer::InitGL()
{
if (fInitGL) {
Error("TGLViewer::InitGL", "GL already initialised");
}
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glClearColor(0.f, 0.f, 0.f, 1.f);
glClearDepth(1.0);
glMaterialf(GL_BACK, GL_SHININESS, 0.0);
glPolygonMode(GL_FRONT, GL_FILL);
glDisable(GL_BLEND);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
Float_t lmodelAmb[] = {0.5f, 0.5f, 1.f, 1.f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodelAmb);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
TGLUtil::CheckError("TGLViewer::InitGL");
fInitGL = kTRUE;
}
void TGLViewer::PostSceneBuildSetup(Bool_t resetCameras)
{
SetupCameras(resetCameras);
fScene.SetupClips();
fReferencePos.Set(fScene.BoundingBox().Center());
}
void TGLViewer::SetupCameras(Bool_t reset)
{
if (fScene.IsLocked()) {
Error("TGLViewer::SetupCameras", "expected kUnlocked, found %s", TGLScene::LockName(fScene.CurrentLock()));
return;
}
const TGLBoundingBox & box = fScene.BoundingBox();
if (!box.IsEmpty()) {
fPerspectiveCameraYOZ.Setup(box, reset);
fPerspectiveCameraXOZ.Setup(box, reset);
fPerspectiveCameraXOY.Setup(box, reset);
fOrthoXOYCamera.Setup(box, reset);
fOrthoXOZCamera.Setup(box, reset);
fOrthoZOYCamera.Setup(box, reset);
}
}
void TGLViewer::ResetCurrentCamera()
{
CurrentCamera().Reset();
}
void TGLViewer::UpdateScene()
{
fRedrawTimer->Stop();
fInternalRebuild = kFALSE;
fPad->Paint();
}
void TGLViewer::SetupLights()
{
const TGLBoundingBox & box = fScene.BoundingBox();
if (!box.IsEmpty()) {
Double_t lightRadius = box.Extents().Mag() * 2.9;
Double_t sideLightsZ, frontLightZ;
TGLOrthoCamera * orthoCamera = dynamic_cast<TGLOrthoCamera *>(fCurrentCamera);
if (orthoCamera) {
sideLightsZ =
fCurrentCamera->FrustumPlane(TGLCamera::kNear).DistanceTo(fCurrentCamera->FrustumCenter())*0.7;
frontLightZ = sideLightsZ;
} else {
TGLVector3 eyeVector = fCurrentCamera->EyePoint() - fCurrentCamera->FrustumCenter();
sideLightsZ = eyeVector.Mag() * -0.85;
frontLightZ = 0.0;
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
TGLVertex3 center = box.Center();
Float_t pos0[] = { center.X(), center.Y(), frontLightZ, 1.0 };
Float_t pos1[] = { center.X(), center.Y() + lightRadius, sideLightsZ, 1.0 };
Float_t pos2[] = { center.X(), center.Y() - lightRadius, sideLightsZ, 1.0 };
Float_t pos3[] = { center.X() - lightRadius, center.Y(), sideLightsZ, 1.0 };
Float_t pos4[] = { center.X() + lightRadius, center.Y(), sideLightsZ, 1.0 };
Float_t frontLightColor[] = {0.35, 0.35, 0.35, 1.0};
Float_t sideLightColor[] = {0.7, 0.7, 0.7, 1.0};
glLightfv(GL_LIGHT0, GL_POSITION, pos0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, frontLightColor);
glLightfv(GL_LIGHT1, GL_POSITION, pos1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, sideLightColor);
glLightfv(GL_LIGHT2, GL_POSITION, pos2);
glLightfv(GL_LIGHT2, GL_DIFFUSE, sideLightColor);
glLightfv(GL_LIGHT3, GL_POSITION, pos3);
glLightfv(GL_LIGHT3, GL_DIFFUSE, sideLightColor);
glLightfv(GL_LIGHT4, GL_POSITION, pos4);
glLightfv(GL_LIGHT4, GL_DIFFUSE, sideLightColor);
}
for (UInt_t light = 0; (1<<light) < kLightMask; light++) {
if ((1<<light) & fLightState) {
glEnable(GLenum(GL_LIGHT0 + light));
if (fDebugMode) {
glDisable(GL_LIGHTING);
Float_t yellow[4] = { 1.0, 1.0, 0.0, 1.0 };
Float_t position[4];
glGetLightfv(GLenum(GL_LIGHT0 + light), GL_POSITION, position);
Double_t size = fScene.BoundingBox().Extents().Mag() / 10.0;
TGLVertex3 dPosition(position[0], position[1], position[2]);
TGLUtil::DrawSphere(dPosition, size, yellow);
glEnable(GL_LIGHTING);
}
} else {
glDisable(GLenum(GL_LIGHT0 + light));
}
}
fCurrentCamera->Apply(fScene.BoundingBox());
}
void TGLViewer::RequestDraw(Short_t LOD)
{
fRedrawTimer->Stop();
if ((!fGLWindow || !gVirtualGL) && fGLDevice == -1) {
return;
}
if (!fScene.TakeLock(TGLScene::kDrawLock)) {
if (gDebug>3) {
Info("TGLViewer::RequestDraw", "scene drawlocked - requesting another draw");
}
fRedrawTimer->RequestDraw(100, LOD);
return;
}
fDrawFlags.SetLOD(LOD);
if (fGLDevice == -1)
gVirtualGL->DrawViewer(this);
else
gGLManager->DrawViewer(this);
}
void TGLViewer::DoDraw()
{
if (fScene.CurrentLock() != TGLScene::kDrawLock) {
if (!fScene.TakeLock(TGLScene::kDrawLock)) {
Error("TGLViewer::DoDraw", "scene is %s", TGLScene::LockName(fScene.CurrentLock()));
}
}
fRedrawTimer->Stop();
if (fGLDevice != -1) {
Int_t viewport[4] = {};
gGLManager->ExtractViewport(fGLDevice, viewport);
SetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
TGLStopwatch timer;
if (gDebug>2) {
timer.Start();
}
if (!fIsPrinting) PreDraw();
fCurrentCamera->Apply(fScene.BoundingBox());
if (!fScene.BoundingBox().IsEmpty()) {
Double_t sceneDrawTime = (fDrawFlags.LOD() == TGLDrawFlags::kLODHigh) ? 0.0 : 100.0;
SetupLights();
fScene.Draw(*fCurrentCamera, fDrawFlags, sceneDrawTime,
fAxesType, fReferenceOn ? &fReferencePos:0);
if (fDebugMode) {
glDisable(GL_LIGHTING);
CurrentCamera().DrawDebugAids();
glColor3d(0.0, 1.0, 0.0);
fScene.BoundingBox().Draw();
glDisable(GL_DEPTH_TEST);
Double_t size = fScene.BoundingBox().Extents().Mag() / 200.0;
static Float_t white[4] = {1.0, 1.0, 1.0, 1.0};
TGLUtil::DrawSphere(TGLVertex3(0.0, 0.0, 0.0), size, white);
static Float_t green[4] = {0.0, 1.0, 0.0, 1.0};
const TGLVertex3 & center = fScene.BoundingBox().Center();
TGLUtil::DrawSphere(center, size, green);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
}
}
PostDraw();
if (gDebug>2) {
Info("TGLViewer::DoDraw()", "Took %f msec", timer.End());
TGLDisplayListCache::Instance().Dump();
}
fScene.ReleaseLock(TGLScene::kDrawLock);
Bool_t redrawReq = kFALSE;
if (!fDebugMode) {
if (fDrawFlags.LOD() == TGLDrawFlags::kLODHigh) {
RebuildScene();
} else {
redrawReq = kTRUE;
}
} else {
redrawReq = fDrawFlags.LOD() != TGLDrawFlags::kLODHigh;
}
if (redrawReq) {
fRedrawTimer->RequestDraw(100, TGLDrawFlags::kLODHigh);
}
}
void TGLViewer::PreDraw()
{
MakeCurrent();
if (!fInitGL) {
InitGL();
}
Color_t ci = (fGLDevice != -1) ? gPad->GetFillColor() : fClearColor;
TColor *color = gROOT->GetColor(ci);
Float_t sc[3] = {1.f, 1.f, 1.f};
if (color)
color->GetRGB(sc[0], sc[1], sc[2]);
glClearColor(sc[0], sc[1], sc[2], 1.);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
TGLUtil::CheckError("TGLViewer::PreDraw");
}
void TGLViewer::PostDraw()
{
glFlush();
SwapBuffers();
TGLUtil::CheckError("TGLViewer::PostDraw");
}
void TGLViewer::MakeCurrent() const
{
if (fGLDevice == -1)
fGLWindow->MakeCurrent();
else gGLManager->MakeCurrent(fGLDevice);
}
void TGLViewer::SwapBuffers() const
{
if (fScene.CurrentLock() != TGLScene::kDrawLock &&
fScene.CurrentLock() != TGLScene::kSelectLock) {
Error("TGLViewer::SwapBuffers", "scene is %s", TGLScene::LockName(fScene.CurrentLock()));
}
if (fGLDevice == -1)
fGLWindow->SwapBuffers();
else {
gGLManager->ReadGLBuffer(fGLDevice);
gGLManager->Flush(fGLDevice);
gGLManager->MarkForDirectCopy(fGLDevice, kFALSE);
}
}
Bool_t TGLViewer::RequestSelect(UInt_t x, UInt_t y)
{
if (!fScene.TakeLock(TGLScene::kSelectLock)) {
return kFALSE;
}
TGLRect selectRect(x, y, 3, 3);
if (fGLDevice == -1)
return gVirtualGL->SelectViewer(this, &selectRect);
else
return gGLManager->SelectViewer(this, &selectRect);
}
Bool_t TGLViewer::DoSelect(const TGLRect & rect)
{
if (fScene.CurrentLock() != TGLScene::kSelectLock) {
Error("TGLViewer::Draw", "expected kSelectLock, found %s", TGLScene::LockName(fScene.CurrentLock()));
return kFALSE;
}
MakeCurrent();
TGLRect glRect(rect);
fCurrentCamera->WindowToViewport(glRect);
fCurrentCamera->Apply(fScene.BoundingBox(), &glRect);
Bool_t changed = fScene.Select(*fCurrentCamera, fDrawFlags);
fScene.ReleaseLock(TGLScene::kSelectLock);
return changed;
}
void TGLViewer::ApplySelection()
{
fScene.ApplySelection();
RequestDraw(TGLDrawFlags::kLODHigh);
SelectionChanged();
ClipChanged();
}
void TGLViewer::SetViewport(Int_t x, Int_t y, UInt_t width, UInt_t height)
{
if (fScene.IsLocked() && fGLDevice == -1) {
Error("TGLViewer::SetViewport", "expected kUnlocked, found %s", TGLScene::LockName(fScene.CurrentLock()));
return;
}
if (fViewport.X() == x && fViewport.Y() == y &&
fViewport.Width() == width && fViewport.Height() == height) {
return;
}
fViewport.Set(x, y, width, height);
fCurrentCamera->SetViewport(fViewport);
fRedrawTimer->RequestDraw(20, TGLDrawFlags::kLODMed);
if (gDebug>2) {
Info("TGLViewer::SetViewport", "updated - corner %d,%d dimensions %d,%d", x, y, width, height);
}
}
void TGLViewer::SetDrawStyle(TGLDrawFlags::EStyle drawStyle)
{
fDrawFlags.SetStyle(drawStyle);
RequestDraw();
}
void TGLViewer::SetCurrentCamera(ECameraType cameraType)
{
if (fScene.IsLocked()) {
Error("TGLViewer::SetCurrentCamera", "expected kUnlocked, found %s", TGLScene::LockName(fScene.CurrentLock()));
return;
}
switch(cameraType) {
case(kCameraPerspXOZ): {
fCurrentCamera = &fPerspectiveCameraXOZ;
break;
}
case(kCameraPerspYOZ): {
fCurrentCamera = &fPerspectiveCameraYOZ;
break;
}
case(kCameraPerspXOY): {
fCurrentCamera = &fPerspectiveCameraXOY;
break;
}
case(kCameraOrthoXOY): {
fCurrentCamera = &fOrthoXOYCamera;
break;
}
case(kCameraOrthoXOZ): {
fCurrentCamera = &fOrthoXOZCamera;
break;
}
case(kCameraOrthoZOY): {
fCurrentCamera = &fOrthoZOYCamera;
break;
}
default: {
Error("TGLViewer::SetCurrentCamera", "invalid camera type");
break;
}
}
fCurrentCamera->SetViewport(fViewport);
RefreshPadEditor(this);
RequestDraw(TGLDrawFlags::kLODHigh);
}
void TGLViewer::SetOrthoCamera(ECameraType camera, Double_t left, Double_t right,
Double_t top, Double_t bottom)
{
switch(camera) {
case(kCameraOrthoXOY): {
fOrthoXOYCamera.Configure(left, right, top, bottom);
if (fCurrentCamera == &fOrthoXOYCamera) {
RequestDraw(TGLDrawFlags::kLODHigh);
}
break;
}
case(kCameraOrthoXOZ): {
fOrthoXOZCamera.Configure(left, right, top, bottom);
if (fCurrentCamera == &fOrthoXOZCamera) {
RequestDraw(TGLDrawFlags::kLODHigh);
}
break;
}
case(kCameraOrthoZOY): {
fOrthoZOYCamera.Configure(left, right, top, bottom);
if (fCurrentCamera == &fOrthoZOYCamera) {
RequestDraw(TGLDrawFlags::kLODHigh);
}
break;
}
default: {
Error("TGLViewer::SetOrthoCamera", "invalid camera type");
break;
}
}
}
void TGLViewer::SetPerspectiveCamera(ECameraType camera, Double_t fov, Double_t dolly,
Double_t center[3], Double_t hRotate, Double_t vRotate)
{
switch(camera) {
case(kCameraPerspXOZ): {
fPerspectiveCameraXOZ.Configure(fov, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fPerspectiveCameraXOZ) {
RequestDraw(TGLDrawFlags::kLODHigh);
}
break;
}
case(kCameraPerspYOZ): {
fPerspectiveCameraYOZ.Configure(fov, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fPerspectiveCameraYOZ) {
RequestDraw(TGLDrawFlags::kLODHigh);
}
break;
}
case(kCameraPerspXOY): {
fPerspectiveCameraXOY.Configure(fov, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fPerspectiveCameraXOY) {
RequestDraw(TGLDrawFlags::kLODHigh);
}
break;
}
default: {
Error("TGLViewer::SetPerspectiveCamera", "invalid camera type");
break;
}
}
}
void TGLViewer::ToggleLight(ELight light)
{
if (light >= kLightMask) {
Error("TGLViewer::ToggleLight", "invalid light type");
return;
}
fLightState ^= light;
if (fGLDevice != -1)
gGLManager->MarkForDirectCopy(fGLDevice, kTRUE);
RequestDraw();
}
void TGLViewer::SetLight(ELight light, Bool_t on)
{
if (light >= kLightMask) {
Error("TGLViewer::ToggleLight", "invalid light type");
return;
}
if (on) {
fLightState |= light;
} else {
fLightState &= ~light;
}
RequestDraw();
}
void TGLViewer::GetGuideState(EAxesType & axesType, Bool_t & referenceOn, Double_t referencePos[3]) const
{
axesType = fAxesType;
referenceOn = fReferenceOn;
referencePos[0] = fReferencePos.X();
referencePos[1] = fReferencePos.Y();
referencePos[2] = fReferencePos.Z();
}
void TGLViewer::SetGuideState(EAxesType axesType, Bool_t referenceOn, const Double_t referencePos[3])
{
fAxesType = axesType;
fReferenceOn = referenceOn;
fReferencePos.Set(referencePos[0], referencePos[1], referencePos[2]);
if (fGLDevice != -1)
gGLManager->MarkForDirectCopy(fGLDevice, kTRUE);
RequestDraw();
}
void TGLViewer::SetSelectedColor(const Float_t color[17])
{
if (fScene.SetSelectedColor(color)) {
RequestDraw();
}
}
void TGLViewer::SetColorOnSelectedFamily(const Float_t color[17])
{
if (fScene.SetColorOnSelectedFamily(color)) {
RequestDraw();
}
}
void TGLViewer::SetSelectedGeom(const TGLVertex3 & trans, const TGLVector3 & scale)
{
if (fScene.SetSelectedGeom(trans, scale)) {
RequestDraw();
}
}
void TGLViewer::SelectionChanged()
{
Emit("SelectionChanged()");
}
void TGLViewer::ClipChanged()
{
Emit("ClipChanged()");
}
Int_t TGLViewer::DistancetoPrimitive(Int_t , Int_t )
{
gPad->SetSelected(this);
return 0;
}
void TGLViewer::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
Event_t eventSt;
eventSt.fX = px;
eventSt.fY = py;
eventSt.fState = 0;
if (event != kKeyPress) {
eventSt.fY -= Int_t((1 - gPad->GetHNDC() - gPad->GetYlowNDC()) * gPad->GetWh());
eventSt.fX -= Int_t(gPad->GetXlowNDC() * gPad->GetWw());
}
switch (event) {
case kMouseMotion:
eventSt.fCode = kMouseMotion;
eventSt.fType = kMotionNotify;
HandleMotion(&eventSt);
break;
case kButton1Down:
case kButton1Up:
{
eventSt.fCode = kButton1;
eventSt.fType = event == kButton1Down ? kButtonPress:kButtonRelease;
HandleButton(&eventSt);
}
break;
case kButton2Down:
case kButton2Up:
{
eventSt.fCode = kButton2;
eventSt.fType = event == kButton2Down ? kButtonPress:kButtonRelease;
HandleButton(&eventSt);
}
break;
case kButton3Down:
{
eventSt.fState = kKeyShiftMask;
eventSt.fCode = kButton1;
eventSt.fType = kButtonPress;
HandleButton(&eventSt);
}
break;
case kButton3Up:
{
eventSt.fCode = kButton3;
eventSt.fType = kButtonRelease;
HandleButton(&eventSt);
}
break;
case kButton1Double:
case kButton2Double:
case kButton3Double:
{
eventSt.fCode = kButton1Double ? kButton1 : kButton2Double ? kButton2 : kButton3;
eventSt.fType = kButtonDoubleClick;
HandleDoubleClick(&eventSt);
}
break;
case kButton1Motion:
case kButton2Motion:
case kButton3Motion:
{
eventSt.fCode = event == kButton1Motion ? kButton1 : event == kButton2Motion ? kButton2 : kButton3;
eventSt.fType = kMotionNotify;
HandleMotion(&eventSt);
}
break;
case kKeyPress:
{
eventSt.fType = kKeyRelease;
eventSt.fCode = py;
HandleKey(&eventSt);
}
break;
case 5:
if (CurrentCamera().Zoom(+50, kFALSE, kFALSE)) {
if (fGLDevice != -1) {
gGLManager->MarkForDirectCopy(fGLDevice, kTRUE);
gVirtualX->SetDrawMode(TVirtualX::kCopy);
}
RequestDraw();
}
break;
case 6:
if (CurrentCamera().Zoom(-50, kFALSE, kFALSE)) {
if (fGLDevice != -1) {
gGLManager->MarkForDirectCopy(fGLDevice, kTRUE);
gVirtualX->SetDrawMode(TVirtualX::kCopy);
}
RequestDraw();
}
break;
case 7:
eventSt.fState = kKeyShiftMask;
eventSt.fCode = kButton1;
eventSt.fType = kButtonPress;
HandleButton(&eventSt);
break;
default:
{
}
}
}
Bool_t TGLViewer::HandleEvent(Event_t *event)
{
if (event->fType == kFocusIn) {
if (fAction != kNone) {
Error("TGLViewer::HandleEvent", "active action at focus in");
}
fAction = kCameraNone;
}
if (event->fType == kFocusOut) {
fAction = kCameraNone;
}
return kTRUE;
}
Bool_t TGLViewer::HandleButton(Event_t * event)
{
if (fScene.IsLocked()) {
if (gDebug>2) {
Info("TGLViewer::HandleButton", "ignored - scene is %s", TGLScene::LockName(fScene.CurrentLock()));
}
return kFALSE;
}
if (fAction == kNone) {
if (fScene.HandleButton(*event, *fCurrentCamera)) {
RequestDraw();
return kTRUE;
}
}
if (fAction != kNone) {
if (event->fType == kButtonPress ||
(event->fType == kButtonRelease && event->fCode != fActiveButtonID)) {
return kFALSE;
}
}
if (event->fType == kButtonPress) {
Bool_t grabPointer = kFALSE;
fActiveButtonID = event->fCode;
switch(event->fCode) {
case(kButton1): {
if (event->fState & kKeyShiftMask) {
if (RequestSelect(event->fX, event->fY)) {
ApplySelection();
}
} else if (event->fState & kKeyControlMask) {
fScene.ActivateSecSelect();
RequestSelect(event->fX, event->fY);
if (fScene.GetNSecHits() > 0) {
TGLLogicalShape& lshape = const_cast<TGLLogicalShape&>
(fScene.GetSelectionResult()->GetLogical());
lshape.ProcessSelection(fScene.GetHitRecord(0).second, this, &fScene);
}
} else {
fAction = kCameraRotate;
grabPointer = kTRUE;
}
break;
}
case(kButton2): {
fAction = kCameraTruck;
grabPointer = kTRUE;
break;
}
case(kButton3): {
if (event->fState & kKeyShiftMask) {
RequestSelect(event->fX, event->fY);
const TGLPhysicalShape * selected = fScene.GetSelectionResult();
if (selected) {
if (!fContextMenu) {
fContextMenu = new TContextMenu("glcm", "GL Viewer Context Menu");
}
Int_t x, y;
Window_t childdum;
gVirtualX->TranslateCoordinates(fGLWindow->GetId(),
gClient->GetDefaultRoot()->GetId(),
event->fX, event->fY, x, y, childdum);
selected->InvokeContextMenu(*fContextMenu, x, y);
}
} else {
fAction = kCameraDolly;
grabPointer = kTRUE;
}
break;
}
}
}
else if (event->fType == kButtonRelease) {
switch(event->fCode) {
case(kButton4): {
if (CurrentCamera().Zoom(+50, kFALSE, kFALSE)) {
RequestDraw();
}
break;
}
case(kButton5): {
if (CurrentCamera().Zoom(-50, kFALSE, kFALSE)) {
RequestDraw();
}
break;
}
}
fAction = kCameraNone;
if (fGLDevice != -1)
gGLManager->MarkForDirectCopy(fGLDevice, kFALSE);
}
return kTRUE;
}
Bool_t TGLViewer::HandleDoubleClick(Event_t *event)
{
if (fScene.IsLocked()) {
if (gDebug>3) {
Info("TGLViewer::HandleDoubleClick", "ignored - scene is %s", TGLScene::LockName(fScene.CurrentLock()));
}
return kFALSE;
}
if (event->fCode != kButton4 && event->fCode != kButton5) {
if (fResetCameraOnDoubleClick) {
ResetCurrentCamera();
RequestDraw();
}
}
return kTRUE;
}
Bool_t TGLViewer::HandleConfigureNotify(Event_t *event)
{
if (fScene.IsLocked()) {
if (gDebug>3) {
Info("TGLViewer::HandleConfigureNotify", "ignored - scene is %s", TGLScene::LockName(fScene.CurrentLock()));
}
return kFALSE;
}
if (event) {
SetViewport(event->fX, event->fY, event->fWidth, event->fHeight);
}
return kTRUE;
}
Bool_t TGLViewer::HandleKey(Event_t *event)
{
if (fScene.IsLocked()) {
if (gDebug>3) {
Info("TGLViewer::HandleKey", "ignored - scene is %s", TGLScene::LockName(fScene.CurrentLock()));
}
return kFALSE;
}
char tmp[10] = {0};
UInt_t keysym = 0;
if (fGLDevice == -1)
gVirtualX->LookupString(event, tmp, sizeof(tmp), keysym);
else
keysym = event->fCode;
Bool_t redraw = kFALSE;
switch (keysym) {
case kKey_Plus:
case kKey_J:
case kKey_j:
redraw = CurrentCamera().Dolly(10, event->fState & kKeyControlMask,
event->fState & kKeyShiftMask);
break;
case kKey_Minus:
case kKey_K:
case kKey_k:
redraw = CurrentCamera().Dolly(-10, event->fState & kKeyControlMask,
event->fState & kKeyShiftMask);
break;
case kKey_R:
case kKey_r:
fDrawFlags.SetStyle(TGLDrawFlags::kFill);
if (fClearColor == 0) {
fClearColor = 1;
RefreshPadEditor(this);
}
redraw = kTRUE;
break;
case kKey_W:
case kKey_w:
fDrawFlags.SetStyle(TGLDrawFlags::kWireFrame);
if (fClearColor == 0) {
fClearColor = 1;
RefreshPadEditor(this);
}
redraw = kTRUE;
break;
case kKey_T:
case kKey_t:
fDrawFlags.SetStyle(TGLDrawFlags::kOutline);
if (fClearColor == 1) {
fClearColor = 0;
RefreshPadEditor(this);
}
redraw = kTRUE;
break;
case kKey_V:
case kKey_v:
fScene.SetCurrentManip(kManipTrans);
redraw = kTRUE;
break;
case kKey_X:
case kKey_x:
fScene.SetCurrentManip(kManipScale);
redraw = kTRUE;
break;
case kKey_C:
case kKey_c:
fScene.SetCurrentManip(kManipRotate);
redraw = kTRUE;
break;
case kKey_Up:
redraw = CurrentCamera().Truck(fViewport.CenterX(), fViewport.CenterY(), 0, 5);
break;
case kKey_Down:
redraw = CurrentCamera().Truck(fViewport.CenterX(), fViewport.CenterY(), 0, -5);
break;
case kKey_Left:
redraw = CurrentCamera().Truck(fViewport.CenterX(), fViewport.CenterY(), -5, 0);
break;
case kKey_Right:
redraw = CurrentCamera().Truck(fViewport.CenterX(), fViewport.CenterY(), 5, 0);
break;
case kKey_Home:
ResetCurrentCamera();
RequestDraw();
break;
case kKey_D:
case kKey_d:
fDebugMode = !fDebugMode;
redraw = kTRUE;
Info("OpenGL viewer debug mode : ", fDebugMode ? "ON" : "OFF");
break;
case kKey_Space:
if (fDebugMode) {
Info("OpenGL viewer FORCED rebuild", "");
RebuildScene();
}
default:;
}
if (redraw) {
if (fGLDevice != -1)
gGLManager->MarkForDirectCopy(fGLDevice, kTRUE);
RequestDraw();
}
return kTRUE;
}
Bool_t TGLViewer::HandleMotion(Event_t * event)
{
if (fScene.IsLocked()) {
if (gDebug>3) {
Info("TGLViewer::HandleMotion", "ignored - scene is %s", TGLScene::LockName(fScene.CurrentLock()));
}
return kFALSE;
}
if (!event) {
return kFALSE;
}
Bool_t processed = kFALSE;
Int_t xDelta = event->fX - fLastPos.fX;
Int_t yDelta = event->fY - fLastPos.fY;
if (fAction == kNone) {
MakeCurrent();
processed = fScene.HandleMotion(*event, *fCurrentCamera);
if (processed) {
SelectionChanged();
ClipChanged();
}
} else if (fAction == kCameraRotate) {
processed = CurrentCamera().Rotate(xDelta, -yDelta);
} else if (fAction == kCameraTruck) {
processed = CurrentCamera().Truck(event->fX, fViewport.Y() - event->fY, xDelta, -yDelta);
} else if (fAction == kCameraDolly) {
processed = CurrentCamera().Dolly(xDelta, event->fState & kKeyControlMask,
event->fState & kKeyShiftMask);
}
fLastPos.fX = event->fX;
fLastPos.fY = event->fY;
if (processed) {
if (fGLDevice != -1) {
gGLManager->MarkForDirectCopy(fGLDevice, kTRUE);
gVirtualX->SetDrawMode(TVirtualX::kCopy);
}
RequestDraw();
}
return kTRUE;
}
Bool_t TGLViewer::HandleExpose(Event_t *)
{
if (fScene.IsLocked()) {
if (gDebug>3) {
Info("TGLViewer::HandleExpose", "ignored - scene is %s", TGLScene::LockName(fScene.CurrentLock()));
}
return kFALSE;
}
RequestDraw(TGLDrawFlags::kLODHigh);
return kTRUE;
}
TClass* TGLViewer::FindDirectRendererClass(TClass* cls)
{
TString rnr( cls->GetName() );
rnr += "GL";
TClass* c = gROOT->GetClass(rnr);
if (c != 0)
return c;
TList* bases = cls->GetListOfBases();
if (bases == 0 || bases->IsEmpty())
return 0;
TIter next_base(bases);
TBaseClass* bc;
while ((bc = (TBaseClass*) next_base()) != 0) {
cls = bc->GetClassPointer();
if ((c = FindDirectRendererClass(cls)) != 0) {
return c;
}
}
return 0;
}
TGLLogicalShape* TGLViewer::AttemptDirectRenderer(TObject* id)
{
TClass* isa = id->IsA();
std::map<TClass*, TClass*>::iterator i = fDirectRendererMap.find(isa);
TClass* cls;
if (i != fDirectRendererMap.end()) {
cls = i->second;
} else {
cls = FindDirectRendererClass(isa);
fDirectRendererMap[isa] = cls;
}
TGLObject* rnr = 0;
if (cls != 0) {
rnr = reinterpret_cast<TGLObject*>(cls->New());
if (rnr) {
if (rnr->SetModel(id) == false) {
Warning("TGLViewer::AttemptDirectRenderer", "failed initializing direct rendering.");
delete rnr;
return 0;
}
rnr->SetBBox();
fScene.AdoptLogical(*rnr);
}
}
return rnr;
}
void TGLViewer::PrintObjects()
{
TGLOutput::Capture(*this);
}
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.