// @(#)root/gl:$Name: $:$Id: TGLRender.cxx,v 1.16 2004/11/24 14:48:02 brun Exp $
// Author: Timur Pocheptsov 03/08/2004
/*************************************************************************
* Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
#ifdef GDK_WIN32
#include "Windows4Root.h"
#endif
#include <algorithm>
#include <utility>
#include <vector>
#include <GL/gl.h>
#include <GL/glu.h>
#include "Rstrstream.h"
#include "TError.h"
#include "TGLSceneObject.h"
#include "TGLRender.h"
#include "TGLCamera.h"
ClassImp(TGLRender)
namespace std {} using namespace std;
const UChar_t gXyz[][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}};
const UChar_t gDigits[][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}};//-
//______________________________________________________________________________
TGLRender::TGLRender()
{
fGLObjects.SetOwner(kTRUE);
fGLCameras.SetOwner(kTRUE);
fGLInit = kFALSE;
fAllActive = kTRUE;
fIsPicking = kFALSE;
fBoxInList = kFALSE;
fActiveCam = 0;
fDList = 0;
fPlaneEqn[0] = 1.;
fPlaneEqn[1] = fPlaneEqn[2] = fPlaneEqn[3] = 0.;
fClipping = kFALSE;
fSelected = 0;
fFirstT = 0;
fSelectedObj = 0;
fSelectionBox = 0;
fPxs = kFALSE;
fAxes = kFALSE;
}
//______________________________________________________________________________
TGLRender::~TGLRender()
{
if (fDList)
glDeleteLists(fDList, 1);
}
//______________________________________________________________________________
void TGLRender::Traverse()
{
if (!fGLInit) {
fGLInit = kTRUE;
Init();
}
if (!fDList) {
if (!(fDList = glGenLists(1))) {
Error("TGLRender::Traverse", "could not create gl list");
return;
}
BuildGLList();
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Int_t start = 0, end = fGLCameras.GetEntriesFast();
if (!fAllActive) {
start = fActiveCam;
end = start + 1;
}
for (; start < end; ++start) {
TGLCamera *currCam = (TGLCamera *)fGLCameras.At(start);
currCam->TurnOn();
if (fClipping) {
glClipPlane(GL_CLIP_PLANE0, fPlaneEqn);
}
RunGLList();
if (fSelectionBox) {
fSelectionBox->DrawBox();
}
if(fAxes) DrawAxes();
}
}
//______________________________________________________________________________
void TGLRender::SetActive(UInt_t ncam)
{
fActiveCam = ncam;
fAllActive = kFALSE;
}
//______________________________________________________________________________
void TGLRender::AddNewObject(TGLSceneObject *newobject)
{
fGLObjects.AddLast(newobject);
}
//______________________________________________________________________________
void TGLRender::AddNewCamera(TGLCamera *newcamera)
{
fGLCameras.AddLast(newcamera);
}
//______________________________________________________________________________
TGLSceneObject *TGLRender::SelectObject(Int_t x, Int_t y, Int_t cam)
{
TGLCamera *actCam = (TGLCamera *)fGLCameras.At(cam);
static std::vector<UInt_t>selectBuff(fGLObjects.GetEntriesFast() * 4);
std::vector<std::pair<UInt_t, Int_t> >objNames;
glSelectBuffer(selectBuff.size(), &selectBuff[0]);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
actCam->TurnOn(x, y);
RunGLList();
Int_t hits = glRenderMode(GL_RENDER);
if (hits < 0) {
Error("TGLRender::SelectObject", "selection buffer overflow");
} else if (hits > 0) {
objNames.resize(hits);
for (Int_t i = 0; i < hits; ++i) {
//object's "depth"
objNames[i].first = selectBuff[i * 4 + 1];
//object's name
objNames[i].second = selectBuff[i * 4 + 3];
}
std::sort(objNames.begin(), objNames.end());
UInt_t chosen = 0;
TGLSceneObject *hitObject = 0;
for (Int_t j = 0; j < hits; ++j) {
chosen = objNames[j].second;
hitObject = (TGLSceneObject *)fGLObjects.At(chosen - 1);
if (!hitObject->IsTransparent())
break;
}
if (hitObject->IsTransparent()) {
chosen = objNames[0].second;
hitObject = (TGLSceneObject *)fGLObjects.At(chosen - 1);
}
if (fSelected != chosen) {
fSelected = chosen;
fSelectedObj = hitObject;
fSelectionBox = fSelectedObj->GetBox();
Traverse();
}
} else if (fSelected) {
fSelected = 0;
fSelectedObj = 0;
fSelectionBox = 0;
Traverse();
}
return fSelectedObj;
}
//______________________________________________________________________________
void TGLRender::MoveSelected(Double_t x, Double_t y, Double_t z)
{
if (!fIsPicking) {
fIsPicking = kTRUE;
}
fSelectedObj->Shift(x, y, z);
fSelectionBox->Shift(x, y, z);
}
//______________________________________________________________________________
void TGLRender::SetPlane(const Double_t *n)
{
fPlaneEqn[0] = n[0];
fPlaneEqn[1] = n[1];
fPlaneEqn[2] = n[2];
fPlaneEqn[3] = n[3];
}
//______________________________________________________________________________
void TGLRender::EndMovement()
{
if (fIsPicking) {
fIsPicking = kFALSE;
glDeleteLists(fDList, 1);
if (!(fDList = glGenLists(1))) {
Error("TGLSceneGraph::EndMovement", "could not create display list");
return;
}
fFirstT = 0;
BuildGLList();
}
}
//______________________________________________________________________________
void TGLRender::BuildGLList(Bool_t exec)
{
glNewList(fDList, exec ? GL_COMPILE_AND_EXECUTE : GL_COMPILE);
Bool_t isTr = kFALSE;
if (fSelectedObj && !(isTr = fSelectedObj->IsTransparent())) {
fSelectedObj->GLDraw();
}
for (Int_t i = 0, e = fGLObjects.GetEntriesFast(); i < e; ++i) {
TGLSceneObject *currObj = (TGLSceneObject *)fGLObjects.At(i);
if (currObj->IsTransparent() && currObj != fSelectedObj) {
currObj->SetNextT(fFirstT);
fFirstT = currObj;
} else if (currObj != fSelectedObj) {
currObj->GLDraw();
}
}
if (isTr)
fSelectedObj->GLDraw();
while (fFirstT) {
fFirstT->GLDraw();
fFirstT = fFirstT->GetNextT();
}
glEndList();
}
//______________________________________________________________________________
void TGLRender::RunGLList()
{
glCallList(fDList);
}
//______________________________________________________________________________
void TGLRender::Invalidate()
{
if(fDList)
glDeleteLists(fDList, 1);
if (!(fDList = glGenLists(1))) {
Error("TGLSceneGraph::EndMovement", "could not create display list");
return;
}
fFirstT = 0;
BuildGLList();
}
//______________________________________________________________________________
void TGLRender::SetAxes(const PDD_t &x, const PDD_t &y, const PDD_t &z)
{
fAxeD[0] = x;
fAxeD[1] = y;
fAxeD[2] = z;
}
//______________________________________________________________________________
void PrintNumber(Double_t x, Double_t y, Double_t z, Double_t num, Double_t ys)
{
#ifdef R__SSTREAM
ostringstream ss;
#else
ostrstream ss;
#endif
ss<<num;
std::string str(ss.str());
glRasterPos3d(x, y, z);
for (UInt_t i = 0, e = str.length(); i < e; ++i) {
if (str[i] == '.') {
glBitmap(8, 8, 0., ys, 7., 0., gDigits[10]);
if (i + 1 < e)
glBitmap(8, 8, 0., ys, 7., 0., gDigits[str[i + 1] - '0']);
break;
} else if (str[i] == '-') {
glBitmap(8, 8, 0., ys, 7., 0., gDigits[11]);
} else {
glBitmap(8, 8, 0., ys, 7., 0., gDigits[str[i] - '0']);
}
}
}
//______________________________________________________________________________
void TGLRender::DrawAxes()
{
if (!fPxs) {
fPxs = kTRUE;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
glPushAttrib(GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
const Double_t axeColors[][3] = {{1., 0., 0.},
{0., 1., 0.},
{0., 0., 1.}};
//white axes
glDisable(GL_LIGHTING);
glColor3dv(axeColors[3]);
glBegin(GL_LINES);
glColor3dv(axeColors[0]);
glVertex3d(fAxeD[0].first, fAxeD[1].first, fAxeD[2].first);
glVertex3d(fAxeD[0].second, fAxeD[1].first, fAxeD[2].first);
glColor3dv(axeColors[1]);
glVertex3d(fAxeD[0].first, fAxeD[1].first, fAxeD[2].first);
glVertex3d(fAxeD[0].first, fAxeD[1].second, fAxeD[2].first);
glColor3dv(axeColors[2]);
glVertex3d(fAxeD[0].first, fAxeD[1].first, fAxeD[2].first);
glVertex3d(fAxeD[0].first, fAxeD[1].first, fAxeD[2].second);
glEnd();
glColor3dv(axeColors[0]);
glRasterPos3d(fAxeD[0].second, fAxeD[1].first + 12, fAxeD[2].first);
glBitmap(8, 8, 0., 0., 0., 0., gXyz[0]);
PrintNumber(fAxeD[0].second, fAxeD[1].first, fAxeD[2].first, fAxeD[0].second, 9.);
PrintNumber(fAxeD[0].first, fAxeD[1].first, fAxeD[2].first, fAxeD[0].first, 0.);
glColor3dv(axeColors[1]);
glRasterPos3d(fAxeD[0].first, fAxeD[1].second + 12, fAxeD[2].first);
glBitmap(8, 8, 0, 0, 12., 0, gXyz[1]);
PrintNumber(fAxeD[0].first, fAxeD[1].second, fAxeD[2].first, fAxeD[1].second, 9.);
PrintNumber(fAxeD[0].first, fAxeD[1].first, fAxeD[2].first, fAxeD[1].first, 9.);
glColor3dv(axeColors[2]);
glRasterPos3d(fAxeD[0].first, fAxeD[1].first, fAxeD[2].second);
glBitmap(8, 8, 0, 0, 0., 0, gXyz[2]);
PrintNumber(fAxeD[0].first, fAxeD[1].first, fAxeD[2].second, fAxeD[2].second, 9.);
PrintNumber(fAxeD[0].first, fAxeD[1].first, fAxeD[2].first, fAxeD[2].first, -9.);
glEnable(GL_LIGHTING);
glPopAttrib();
}
void TGLRender::SetFamilyColor(const Float_t *newColor)
{
if (TObject *ro = fSelectedObj->GetRealObject()) {
TString famName = ro->GetName();
for (Int_t i = 0, e = fGLObjects.GetEntriesFast(); i < e; ++i) {
TObject *obj = ((TGLSceneObject *)fGLObjects[i])->GetRealObject();
if (obj && obj->GetName() == famName)
((TGLSceneObject *)fGLObjects[i])->SetColor(newColor);
}
} else fSelectedObj->SetColor(newColor);
}
void TGLRender::Init()
{
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);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glClearColor(0., 0., 0., 0.);
glClearDepth(1.);
}
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.