#include "TGLViewer.h"
#include "TGLIncludes.h"
#include "TGLStopwatch.h"
#include "TGLRnrCtx.h"
#include "TGLSelectBuffer.h"
#include "TGLLightSet.h"
#include "TGLClip.h"
#include "TGLManipSet.h"
#include "TGLScenePad.h"
#include "TGLLogicalShape.h"
#include "TGLPhysicalShape.h"
#include "TGLObject.h"
#include "TGLStopwatch.h"
#include "TBuffer3D.h"
#include "TBuffer3DTypes.h"
#include "TGLOutput.h"
#include "TVirtualPad.h"
#include "TAtt3D.h"
#include "TVirtualX.h"
#include "TMath.h"
#include "TColor.h"
#include "TError.h"
#include "TClass.h"
#include "TROOT.h"
#include "Buttons.h"
#include "GuiTypes.h"
#include "TVirtualGL.h"
#include "TGLWidget.h"
#include "TGLViewerEditor.h"
#include "KeySymbols.h"
#include "TContextMenu.h"
ClassImp(TGLViewer)
TGLViewer::TGLViewer(TVirtualPad * pad, Int_t x, Int_t y,
Int_t width, Int_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(TGLVector3( 0.0, 0.0, 1.0), TGLVector3(0.0, 1.0, 0.0)),
fOrthoXOZCamera(TGLVector3( 0.0,-1.0, 0.0), TGLVector3(0.0, 0.0, 1.0)),
fOrthoZOYCamera(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)),
fCurrentCamera(&fPerspectiveCameraXOZ),
fLightSet (0),
fClipSet (0),
fSelectedPShapeRef (0),
fCurrentOvlElm (0),
fPushAction(kPushStd), fAction(kDragNone), fLastPos(0,0), fActiveButtonID(0),
fRedrawTimer(0),
fMaxSceneDrawTimeHQ(5000),
fMaxSceneDrawTimeLQ(100),
fClearColor(1),
fAxesType(TGLUtil::kAxesNone),
fAxesDepthTest(kTRUE),
fReferenceOn(kFALSE),
fReferencePos(0.0, 0.0, 0.0),
fDrawCameraCenter(kFALSE),
fCameraMarkup(0),
fInitGL(kFALSE),
fSmartRefresh(kFALSE),
fDebugMode(kFALSE),
fIsPrinting(kFALSE),
fGLWindow(0),
fGLDevice(-1),
fGLCtxId(0),
fIgnoreSizesOnUpdate(kFALSE),
fResetCamerasOnUpdate(kTRUE),
fResetCamerasOnNextUpdate(kFALSE),
fResetCameraOnDoubleClick(kTRUE)
{
InitSecondaryObjects();
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(TGLVector3( 0.0, 0.0, 1.0), TGLVector3(0.0, 1.0, 0.0)),
fOrthoXOZCamera(TGLVector3( 0.0,-1.0, 0.0), TGLVector3(0.0, 0.0, 1.0)),
fOrthoZOYCamera(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)),
fCurrentCamera(&fPerspectiveCameraXOZ),
fLightSet (0),
fClipSet (0),
fSelectedPShapeRef (0),
fCurrentOvlElm (0),
fPushAction(kPushStd), fAction(kDragNone), fLastPos(0,0), fActiveButtonID(0),
fRedrawTimer(0),
fMaxSceneDrawTimeHQ(5000),
fMaxSceneDrawTimeLQ(100),
fClearColor(1),
fAxesType(TGLUtil::kAxesNone),
fAxesDepthTest(kTRUE),
fReferenceOn(kFALSE),
fReferencePos(0.0, 0.0, 0.0),
fDrawCameraCenter(kFALSE),
fCameraMarkup(0),
fInitGL(kFALSE),
fSmartRefresh(kFALSE),
fDebugMode(kFALSE),
fIsPrinting(kFALSE),
fGLWindow(0),
fGLDevice(fPad->GetGLDevice()),
fGLCtxId(0),
fIgnoreSizesOnUpdate(kFALSE),
fResetCamerasOnUpdate(kTRUE),
fResetCamerasOnNextUpdate(kFALSE),
fResetCameraOnDoubleClick(kTRUE)
{
InitSecondaryObjects();
if (fGLDevice != -1) {
fGLCtxId = new TGLContextIdentity;
fGLCtxId->AddRef(0);
Int_t viewport[4] = {0};
gGLManager->ExtractViewport(fGLDevice, viewport);
SetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
}
void TGLViewer::InitSecondaryObjects()
{
fLightSet = new TGLLightSet;
fClipSet = new TGLClipSet; fOverlay.push_back(fClipSet);
fSelectedPShapeRef = new TGLManipSet; fOverlay.push_back(fSelectedPShapeRef);
fSelectedPShapeRef->SetDrawBBox(kTRUE);
fCameraMarkup = new TGLCameraMarkupStyle;
fRedrawTimer = new TGLRedrawTimer(*this);
}
TGLViewer::~TGLViewer()
{
delete fLightSet;
delete fClipSet;
delete fSelectedPShapeRef;
delete fCameraMarkup;
delete fContextMenu;
delete fRedrawTimer;
if (fPad)
fPad->ReleaseViewer3D();
if (fGLDevice != -1)
fGLCtxId->Release(0);
}
void TGLViewer::PadPaint(TVirtualPad* pad)
{
TGLScenePad* scenepad = 0;
for (SceneInfoList_i si = fScenes.begin(); si != fScenes.end(); ++si)
{
scenepad = dynamic_cast<TGLScenePad*>((*si)->GetScene());
if (scenepad && scenepad->GetPad() == pad)
break;
scenepad = 0;
}
if (scenepad == 0)
{
scenepad = new TGLScenePad(pad);
AddScene(scenepad);
}
scenepad->PadPaintFromViewer(this);
PostSceneBuildSetup(fResetCamerasOnNextUpdate || fResetCamerasOnUpdate);
fResetCamerasOnNextUpdate = kFALSE;
RequestDraw();
}
void TGLViewer::UpdateScene()
{
fRedrawTimer->Stop();
for (SceneInfoList_i si = fScenes.begin(); si != fScenes.end(); ++si)
{
TGLScenePad* scenepad = dynamic_cast<TGLScenePad*>((*si)->GetScene());
if (scenepad)
scenepad->PadPaintFromViewer(this);
}
PostSceneBuildSetup(fResetCamerasOnNextUpdate || fResetCamerasOnUpdate);
fResetCamerasOnNextUpdate = kFALSE;
RequestDraw();
}
void TGLViewer::ResetCurrentCamera()
{
MergeSceneBBoxes(fOverallBoundingBox);
CurrentCamera().Setup(fOverallBoundingBox, kTRUE);
}
void TGLViewer::SetupCameras(Bool_t reset)
{
if (IsLocked()) {
Error("TGLViewer::SetupCameras", "expected kUnlocked, found %s", LockName(CurrentLock()));
return;
}
const TGLBoundingBox & box = fOverallBoundingBox;
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::PostSceneBuildSetup(Bool_t resetCameras)
{
MergeSceneBBoxes(fOverallBoundingBox);
SetupCameras(resetCameras);
fReferencePos.Set(fOverallBoundingBox.Center());
RefreshPadEditor(this);
}
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::RequestDraw(Short_t LOD)
{
fRedrawTimer->Stop();
if (!fGLWindow && fGLDevice == -1) {
fRedrawTimer->RequestDraw(100, LOD);
return;
}
if ( ! TakeLock(kDrawLock)) {
if (gDebug>3) {
Info("TGLViewer::RequestDraw", "viewer locked - requesting another draw.");
}
fRedrawTimer->RequestDraw(100, LOD);
return;
}
fLOD = LOD;
if (!gVirtualX->IsCmdThread())
gROOT->ProcessLineFast(Form("((TGLViewer *)0x%x)->DoDraw()", this));
else
DoDraw();
}
void TGLViewer::PreRender()
{
fCamera = fCurrentCamera;
fClip = fClipSet->GetCurrentClip();
if (fGLDevice != -1)
{
fRnrCtx->SetGLCtxIdentity(fGLCtxId);
fGLCtxId->DeleteDisplayLists();
}
TGLViewerBase::PreRender();
fLightSet->StdSetupLights(fOverallBoundingBox, *fCamera, fDebugMode);
fClipSet->SetupClips(fOverallBoundingBox);
}
void TGLViewer::DoDraw()
{
fRedrawTimer->Stop();
if (CurrentLock() != kDrawLock) {
if ( ! TakeLock(kDrawLock)) {
Error("TGLViewer::DoDraw", "viewer is %s", LockName(CurrentLock()));
return;
}
}
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();
}
fRnrCtx->SetRenderTimeout(fLOD == TGLRnrCtx::kLODHigh ?
fMaxSceneDrawTimeHQ :
fMaxSceneDrawTimeLQ);
if (!fIsPrinting) PreDraw();
PreRender();
Render();
DrawGuides();
glClear(GL_DEPTH_BUFFER_BIT);
RenderOverlay();
DrawCameraMarkup();
DrawDebugInfo();
PostRender();
PostDraw();
ReleaseLock(kDrawLock);
if (gDebug>2) {
Info("TGLViewer::DoDraw()", "Took %f msec", timer.End());
}
if (CurrentCamera().UpdateInterest(kFALSE)) {
ResetSceneInfos();
fRedrawTimer->RequestDraw(0, fLOD);
}
if (fLOD != TGLRnrCtx::kLODHigh &&
(fAction < kDragCameraRotate || fAction > kDragCameraDolly))
{
fRedrawTimer->RequestDraw(100, TGLRnrCtx::kLODHigh);
}
}
void TGLViewer::DrawGuides()
{
Bool_t disabled = kFALSE;
if (fReferenceOn)
{
glDisable(GL_DEPTH_TEST);
TGLUtil::DrawReferenceMarker(*fCamera, fReferencePos);
disabled = kTRUE;
}
if (fDrawCameraCenter)
{
glDisable(GL_DEPTH_TEST);
Float_t radius = fCamera->ViewportDeltaToWorld(TGLVertex3(fCamera->GetCenterVec()), 3, 3).Mag();
const Float_t rgba[4] = { 0, 1, 1, 1.0 };
TGLUtil::DrawSphere(fCamera->GetCenterVec(), radius, rgba);
disabled = kTRUE;
}
if(fAxesDepthTest && disabled)
{
glEnable(GL_DEPTH_TEST);
disabled = kFALSE;
}
else if (fAxesDepthTest == kFALSE && disabled == kFALSE)
{
glDisable(GL_DEPTH_TEST);
disabled = kTRUE;
}
TGLUtil::DrawSimpleAxes(*fCamera, fOverallBoundingBox, fAxesType);
if(disabled)
glEnable(GL_DEPTH_TEST);
}
void TGLViewer::DrawCameraMarkup()
{
if (fCameraMarkup && fCameraMarkup->Show())
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
const TGLRect& vp = fRnrCtx->RefCamera().RefViewport();
gluOrtho2D(0., vp.Width(), 0., vp.Height());
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDisable(GL_LIGHTING);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glDisable(GL_DEPTH_TEST);
fRnrCtx->RefCamera().Markup(fCameraMarkup);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
}
void TGLViewer::DrawDebugInfo()
{
if (fDebugMode)
{
glDisable(GL_LIGHTING);
CurrentCamera().DrawDebugAids();
glColor3d(0.0, 1.0, 0.0);
fOverallBoundingBox.Draw();
glDisable(GL_DEPTH_TEST);
Double_t size = fOverallBoundingBox.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 = fOverallBoundingBox.Center();
TGLUtil::DrawSphere(center, size, green);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
}
}
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 ( ! IsDrawOrSelectLock()) {
Error("TGLViewer::SwapBuffers", "viewer is %s", LockName(CurrentLock()));
}
if (fGLDevice == -1)
fGLWindow->SwapBuffers();
else {
gGLManager->ReadGLBuffer(fGLDevice);
gGLManager->Flush(fGLDevice);
gGLManager->MarkForDirectCopy(fGLDevice, kFALSE);
}
}
Bool_t TGLViewer::RequestSelect(Int_t x, Int_t y, Bool_t trySecSel)
{
if ( ! TakeLock(kSelectLock)) {
return kFALSE;
}
if (!gVirtualX->IsCmdThread())
return Bool_t(gROOT->ProcessLineFast(Form("((TGLViewer *)0x%x)->DoSelect(%d, %d, %s)", this, x, y, trySecSel ? "kTRUE" : "kFALSE")));
else
return DoSelect(x, y, trySecSel);
}
Bool_t TGLViewer::DoSelect(Int_t x, Int_t y, Bool_t trySecSel)
{
if (CurrentLock() != kSelectLock) {
Error("TGLViewer::DoSelect", "expected kSelectLock, found %s", LockName(CurrentLock()));
return kFALSE;
}
MakeCurrent();
fRnrCtx->BeginSelection(x, y, 3);
glRenderMode(GL_SELECT);
PreRender();
Render();
PostRender();
Int_t nHits = glRenderMode(GL_RENDER);
fRnrCtx->EndSelection(nHits);
if (gDebug > 0) Info("TGLViewer::DoSelect", "Primary select nHits=%d.", nHits);
if (nHits > 0)
{
Int_t idx = 0;
if (FindClosestRecord(fSelRec, idx))
{
if (fSelRec.GetTransparent())
{
TGLSelectRecord opaque;
if (FindClosestOpaqueRecord(opaque, ++idx))
fSelRec = opaque;
}
if (gDebug > 1) fSelRec.Print();
}
} else {
fSelRec.Reset();
}
if ( ! trySecSel)
{
ReleaseLock(kSelectLock);
return ! TGLSelectRecord::AreSameSelectionWise(fSelRec, fCurrentSelRec);
}
{
if ( nHits < 1 || ! fSelRec.GetSceneInfo() || ! fSelRec.GetPhysShape() ||
! fSelRec.GetPhysShape()->GetLogical()->SupportsSecondarySelect())
{
if (gDebug > 0)
Info("TGLViewer::DoSelect", "Skipping secondary selection "
"(nPrimHits=%d, sinfo=0x%lx, pshape=0x%lx).\n",
nHits, fSelRec.GetSceneInfo(), fSelRec.GetPhysShape());
ReleaseLock(kSelectLock);
fSecSelRec.Reset();
return kFALSE;
}
TGLSceneInfo* sinfo = fSelRec.GetSceneInfo();
TGLSceneBase* scene = sinfo->GetScene();
TGLPhysicalShape* pshp = fSelRec.GetPhysShape();
SceneInfoList_t foo;
foo.push_back(sinfo);
fScenes.swap(foo);
fRnrCtx->BeginSelection(x, y, 3);
fRnrCtx->SetSecSelection(kTRUE);
glRenderMode(GL_SELECT);
PreRender();
fRnrCtx->SetSceneInfo(sinfo);
scene->PreRender(*fRnrCtx);
fRnrCtx->SetDrawPass(TGLRnrCtx::kPassFill);
fRnrCtx->SetShapeLOD(TGLRnrCtx::kLODHigh);
glPushName(pshp->ID());
pshp->Draw(*fRnrCtx);
glPopName();
scene->PostRender(*fRnrCtx);
fRnrCtx->SetSceneInfo(0);
PostRender();
Int_t nSecHits = glRenderMode(GL_RENDER);
fRnrCtx->EndSelection(nSecHits);
fScenes.swap(foo);
if (gDebug > 0) Info("TGLViewer::DoSelect", "Secondary select nSecHits=%d.", nSecHits);
ReleaseLock(kSelectLock);
if (nSecHits > 0)
{
fSecSelRec = fSelRec;
fSecSelRec.SetRawOnly(fRnrCtx->GetSelectBuffer()->RawRecord(0));
if (gDebug > 1) fSecSelRec.Print();
return kTRUE;
} else {
fSecSelRec.Reset();
return kFALSE;
}
}
}
void TGLViewer::ApplySelection()
{
fCurrentSelRec = fSelRec;
TGLPhysicalShape * selPhys = fSelRec.GetPhysShape();
fSelectedPShapeRef->SetPShape(selPhys);
SelectionChanged();
RequestDraw(TGLRnrCtx::kLODHigh);
}
Bool_t TGLViewer::RequestOverlaySelect(Int_t x, Int_t y)
{
if ( ! TakeLock(kSelectLock)) {
return kFALSE;
}
if (!gVirtualX->IsCmdThread())
return Bool_t(gROOT->ProcessLineFast(Form("((TGLViewer *)0x%x)->DoSelect(%d, %d)", this, x, y)));
else
return DoOverlaySelect(x, y);
}
Bool_t TGLViewer::DoOverlaySelect(Int_t x, Int_t y)
{
if (CurrentLock() != kSelectLock) {
Error("TGLViewer::DoOverlaySelect", "expected kSelectLock, found %s", LockName(CurrentLock()));
return kFALSE;
}
MakeCurrent();
fRnrCtx->BeginSelection(x, y, 3);
glRenderMode(GL_SELECT);
PreRenderOverlaySelection();
RenderOverlay();
PostRenderOverlaySelection();
Int_t nHits = glRenderMode(GL_RENDER);
fRnrCtx->EndSelection(nHits);
TGLOverlayElement * selElm = 0;
if (nHits > 0)
{
Int_t idx = 0;
while (idx < nHits && FindClosestOverlayRecord(fOvlSelRec, idx))
{
TGLOverlayElement* el = fOvlSelRec.GetOvlElement();
if (el == fCurrentOvlElm)
{
if (el->MouseStillInside(fOvlSelRec))
{
selElm = el;
break;
}
}
else if (el->MouseEnter(fOvlSelRec))
{
selElm = el;
break;
}
}
}
else
{
fOvlSelRec.Reset();
}
ReleaseLock(kSelectLock);
if (fCurrentOvlElm != selElm)
{
if (fCurrentOvlElm) fCurrentOvlElm->MouseLeave();
fCurrentOvlElm = selElm;
return kTRUE;
}
else
{
return kFALSE;
}
}
void TGLViewer::SetViewport(Int_t x, Int_t y, Int_t width, Int_t height)
{
if (IsLocked() && fGLDevice == -1) {
Error("TGLViewer::SetViewport", "expected kUnlocked, found %s", LockName(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);
if (gDebug>2) {
Info("TGLViewer::SetViewport", "updated - corner %d,%d dimensions %d,%d", x, y, width, height);
}
}
TGLCamera& TGLViewer::RefCamera(ECameraType cameraType)
{
switch(cameraType) {
case kCameraPerspXOZ:
return fPerspectiveCameraXOZ;
case kCameraPerspYOZ:
return fPerspectiveCameraYOZ;
case kCameraPerspXOY:
return fPerspectiveCameraXOY;
case kCameraOrthoXOY:
return fOrthoXOYCamera;
case kCameraOrthoXOZ:
return fOrthoXOZCamera;
case kCameraOrthoZOY:
return fOrthoZOYCamera;
default:
Error("TGLViewer::SetCurrentCamera", "invalid camera type");
return *fCurrentCamera;
}
}
void TGLViewer::SetCurrentCamera(ECameraType cameraType)
{
if (IsLocked()) {
Error("TGLViewer::SetCurrentCamera", "expected kUnlocked, found %s", LockName(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(TGLRnrCtx::kLODHigh);
}
void TGLViewer::SetOrthoCamera(ECameraType camera,
Double_t zoom, Double_t dolly,
Double_t center[3],
Double_t hRotate, Double_t vRotate)
{
switch(camera) {
case kCameraOrthoXOY: {
fOrthoXOYCamera.Configure(zoom, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fOrthoXOYCamera) {
RequestDraw(TGLRnrCtx::kLODHigh);
}
break;
}
case kCameraOrthoXOZ: {
fOrthoXOZCamera.Configure(zoom, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fOrthoXOZCamera) {
RequestDraw(TGLRnrCtx::kLODHigh);
}
break;
}
case kCameraOrthoZOY: {
fOrthoZOYCamera.Configure(zoom, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fOrthoZOYCamera) {
RequestDraw(TGLRnrCtx::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(TGLRnrCtx::kLODHigh);
}
break;
}
case kCameraPerspYOZ: {
fPerspectiveCameraYOZ.Configure(fov, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fPerspectiveCameraYOZ) {
RequestDraw(TGLRnrCtx::kLODHigh);
}
break;
}
case kCameraPerspXOY: {
fPerspectiveCameraXOY.Configure(fov, dolly, center, hRotate, vRotate);
if (fCurrentCamera == &fPerspectiveCameraXOY) {
RequestDraw(TGLRnrCtx::kLODHigh);
}
break;
}
default: {
Error("TGLViewer::SetPerspectiveCamera", "invalid camera type");
break;
}
}
}
void TGLViewer::GetGuideState(Int_t & axesType, Bool_t & axesDepthTest, Bool_t & referenceOn, Double_t referencePos[3]) const
{
axesType = fAxesType;
axesDepthTest = fAxesDepthTest;
referenceOn = fReferenceOn;
referencePos[0] = fReferencePos.X();
referencePos[1] = fReferencePos.Y();
referencePos[2] = fReferencePos.Z();
}
void TGLViewer::SetGuideState(Int_t axesType, Bool_t axesDepthTest, Bool_t referenceOn, const Double_t referencePos[3])
{
fAxesType = axesType;
fAxesDepthTest = axesDepthTest;
fReferenceOn = referenceOn;
if (referencePos)
fReferencePos.Set(referencePos[0], referencePos[1], referencePos[2]);
if (fGLDevice != -1)
gGLManager->MarkForDirectCopy(fGLDevice, kTRUE);
RequestDraw();
}
void TGLViewer::SetDrawCameraCenter(Bool_t x)
{
fDrawCameraCenter = x;
RequestDraw();
}
const TGLPhysicalShape * TGLViewer::GetSelected() const
{
return fSelectedPShapeRef->GetPShape();
}
void TGLViewer::SelectionChanged()
{
Emit("SelectionChanged()");
}
void TGLViewer::OverlayDragFinished()
{
Emit("OverlayDragFinished()");
}
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 = kGKeyPress;
eventSt.fCode = py;
HandleKey(&eventSt);
}
break;
case 6:
if (CurrentCamera().Zoom(+50, kFALSE, kFALSE)) {
if (fGLDevice != -1) {
gGLManager->MarkForDirectCopy(fGLDevice, kTRUE);
gVirtualX->SetDrawMode(TVirtualX::kCopy);
}
RequestDraw();
}
break;
case 5:
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 = kDragNone;
}
if (event->fType == kFocusOut) {
fAction = kDragNone;
}
return kTRUE;
}
Bool_t TGLViewer::HandleButton(Event_t * event)
{
if (IsLocked()) {
if (gDebug>2) {
Info("TGLViewer::HandleButton", "ignored - viewer is %s", LockName(CurrentLock()));
}
return kFALSE;
}
if (event->fType == kButtonPress)
{
if (fAction != kNone)
return kFALSE;
if (fPushAction == kPushCamCenter)
{
fPushAction = kPushStd;
RequestSelect(event->fX, event->fY);
if (fSelRec.GetN() > 0)
{
TGLVector3 v(event->fX, event->fY, 0.5*fSelRec.GetMinZ());
fCurrentCamera->WindowToViewport(v);
v = fCurrentCamera->ViewportToWorld(v);
fCurrentCamera->SetExternalCenter(kTRUE);
fCurrentCamera->SetCenterVec(v.X(), v.Y(), v.Z());
RequestDraw();
}
RefreshPadEditor(this);
return kTRUE;
}
Bool_t grabPointer = kFALSE;
Bool_t handled = kFALSE;
fActiveButtonID = event->fCode;
if (fAction == kDragNone && fCurrentOvlElm)
{
if (fCurrentOvlElm->Handle(*fRnrCtx, fOvlSelRec, event))
{
handled = kTRUE;
grabPointer = kTRUE;
fAction = kDragOverlay;
RequestDraw();
}
}
if ( ! handled)
{
switch(event->fCode)
{
case kButton1:
{
if (event->fState & kKeyShiftMask) {
if (RequestSelect(event->fX, event->fY)) {
ApplySelection();
handled = kTRUE;
} else {
SelectionChanged();
}
} else if (event->fState & kKeyControlMask) {
RequestSelect(event->fX, event->fY, kTRUE);
if (fSecSelRec.GetPhysShape() != 0) {
TGLLogicalShape& lshape = const_cast<TGLLogicalShape&>
(*fSecSelRec.GetPhysShape()->GetLogical());
lshape.ProcessSelection(*fRnrCtx, fSecSelRec);
handled = kTRUE;
}
}
if ( ! handled) {
fAction = kDragCameraRotate;
grabPointer = kTRUE;
}
break;
}
case kButton2:
{
fAction = kDragCameraTruck;
grabPointer = kTRUE;
break;
}
case kButton3:
{
if (event->fState & kKeyShiftMask) {
RequestSelect(event->fX, event->fY);
const TGLPhysicalShape * selected = fSelRec.GetPhysShape();
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 = kDragCameraDolly;
grabPointer = kTRUE;
}
break;
}
}
}
}
else if (event->fType == kButtonRelease)
{
if (fAction == kDragOverlay)
{
fCurrentOvlElm->Handle(*fRnrCtx, fOvlSelRec, event);
OverlayDragFinished();
if (RequestOverlaySelect(event->fX, event->fY))
RequestDraw();
}
else if (fAction >= kDragCameraRotate && fAction <= kDragCameraDolly)
{
RequestDraw(TGLRnrCtx::kLODHigh);
}
switch(event->fCode) {
case kButton5: {
if (CurrentCamera().Zoom(+50, kFALSE, kFALSE)) {
RequestDraw();
}
break;
}
case kButton4: {
if (CurrentCamera().Zoom(-50, kFALSE, kFALSE)) {
RequestDraw();
}
break;
}
}
fAction = kDragNone;
if (fGLDevice != -1)
gGLManager->MarkForDirectCopy(fGLDevice, kFALSE);
}
return kTRUE;
}
Bool_t TGLViewer::HandleDoubleClick(Event_t *event)
{
if (IsLocked()) {
if (gDebug>3) {
Info("TGLViewer::HandleDoubleClick", "ignored - viewer is %s", LockName(CurrentLock()));
}
return kFALSE;
}
if (event->fCode != kButton4 && event->fCode != kButton5) {
if (fResetCameraOnDoubleClick) {
ResetCurrentCamera();
RequestDraw();
}
}
return kTRUE;
}
Bool_t TGLViewer::HandleConfigureNotify(Event_t *event)
{
if (IsLocked()) {
if (gDebug > 0) {
Info("TGLViewer::HandleConfigureNotify", "ignored - viewer is %s", LockName(CurrentLock()));
}
return kFALSE;
}
if (event) {
SetViewport(event->fX, event->fY, event->fWidth, event->fHeight);
RequestDraw(TGLRnrCtx::kLODMed);
}
return kTRUE;
}
Bool_t TGLViewer::HandleKey(Event_t *event)
{
if (IsLocked()) {
if (gDebug>3) {
Info("TGLViewer::HandleKey", "ignored - viewer is %s", LockName(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;
fRnrCtx->SetEventKeySym(keysym);
Bool_t redraw = kFALSE;
if (fCurrentOvlElm && fCurrentOvlElm->Handle(*fRnrCtx, fOvlSelRec, event))
{
redraw = kTRUE;
}
else
{
switch (keysym)
{
case kKey_R:
case kKey_r:
SetStyle(TGLRnrCtx::kFill);
if (fClearColor == 0) {
fClearColor = 1;
RefreshPadEditor(this);
}
redraw = kTRUE;
break;
case kKey_W:
case kKey_w:
SetStyle(TGLRnrCtx::kWireFrame);
if (fClearColor == 0) {
fClearColor = 1;
RefreshPadEditor(this);
}
redraw = kTRUE;
break;
case kKey_T:
case kKey_t:
SetStyle(TGLRnrCtx::kOutline);
if (fClearColor == 1) {
fClearColor = 0;
RefreshPadEditor(this);
}
redraw = kTRUE;
break;
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_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();
redraw = kTRUE;
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", "");
UpdateScene();
}
default:;
}
}
if (redraw) {
if (fGLDevice != -1)
gGLManager->MarkForDirectCopy(fGLDevice, kTRUE);
RequestDraw();
}
return kTRUE;
}
Bool_t TGLViewer::HandleMotion(Event_t * event)
{
if (IsLocked()) {
if (gDebug>3) {
Info("TGLViewer::HandleMotion", "ignored - viewer is %s", LockName(CurrentLock()));
}
return kFALSE;
}
assert (event);
Bool_t processed = kFALSE, changed = kFALSE;
Short_t lod = TGLRnrCtx::kLODMed;
Int_t xDelta = event->fX - fLastPos.fX;
Int_t yDelta = event->fY - fLastPos.fY;
Bool_t mod1 = event->fState & kKeyControlMask;
Bool_t mod2 = event->fState & kKeyShiftMask;
if (fAction == kDragNone)
{
changed = RequestOverlaySelect(event->fX, event->fY);
if (fCurrentOvlElm)
processed = fCurrentOvlElm->Handle(*fRnrCtx, fOvlSelRec, event);
lod = TGLRnrCtx::kLODHigh;
} else if (fAction == kDragCameraRotate) {
processed = CurrentCamera().Rotate(xDelta, -yDelta, mod1, mod2);
} else if (fAction == kDragCameraTruck) {
processed = CurrentCamera().Truck(xDelta, -yDelta, mod1, mod2);
} else if (fAction == kDragCameraDolly) {
processed = CurrentCamera().Dolly(xDelta, mod1, mod2);
} else if (fAction == kDragOverlay) {
processed = fCurrentOvlElm->Handle(*fRnrCtx, fOvlSelRec, event);
}
fLastPos.fX = event->fX;
fLastPos.fY = event->fY;
if (processed || changed) {
if (fGLDevice != -1) {
gGLManager->MarkForDirectCopy(fGLDevice, kTRUE);
gVirtualX->SetDrawMode(TVirtualX::kCopy);
}
RequestDraw(lod);
}
return processed;
}
Bool_t TGLViewer::HandleExpose(Event_t * event)
{
if (event->fCount != 0) return kTRUE;
if (IsLocked()) {
if (gDebug > 0) {
Info("TGLViewer::HandleExpose", "ignored - viewer is %s", LockName(CurrentLock()));
}
return kFALSE;
}
fRedrawTimer->RequestDraw(20, TGLRnrCtx::kLODHigh);
return kTRUE;
}
void TGLViewer::Repaint()
{
if (IsLocked()) {
if (gDebug > 0) {
Info("TGLViewer::HandleExpose", "ignored - viewer is %s", LockName(CurrentLock()));
}
return;
}
fRedrawTimer->RequestDraw(20, TGLRnrCtx::kLODHigh);
}
void TGLViewer::PrintObjects()
{
TGLOutput::Capture(*this);
}
Last update: Thu Jan 17 08:52:29 2008
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.