How to create an embedded openGL viewer and draw in it

Dear rooters,

is it possible to create an embedded openGL viewer as it appears in EVE? And then how can I draw a geometry into it instead of normal canvas?

If I change colors of some volumes, how can I tell the embedded viewer to update?

Cheers, Jing

Hi Jing,

What are you actually trying to do, also on a larger scale?

Eve, in principle, contains the high-level interface to GL Viewers / Scenes. So, what you are trying to do, if I understand correctly, is to redo this interface in a simplified way. The implementation of this is in the following classes:

  1. TEveViewer – interface over GL viewer, it also has functions for creation of GL viewers;

  2. TEveScene – interface over GL scene; here you’ll see how a Pad is used to pass objects to GL scene;

  3. TEveGeoTopNode / TEveGeoNode – this is interface to TGeoPainter allowing you to display geometry hierarchy from some point downward.

If you change objects on the geometry side, you have to repaint the scene. In Eve, GL scene is directly told to take the new objects, see TEveScene::Repaint(). After that you still have to tell the viewer to redraw itself, TGLViewer::RequestDraw() should be ok.

I strongly suggest to use existing Eve interfaces. These can also be extended or made more flexible if needed.

Best,
Matevz

Dear Matevz,

[quote=“matevz”]Hi Jing,
What are you actually trying to do, also on a larger scale?
[/quote]
Thank you for asking. I am building up an event display for the XMASS dark matter experiment. The photo cathodes of inner PMT array are grouped as shown in the attached picture. I would like to assign different colors to the photo cathodes based on the energies recorded by the PMTs. For online event display, I don’t need to show tracks and hits (I may need to work on this later for reconstructed events). Changing colors of some nodes and redraw the viewer is all I wanna to.

I was trying to follow the example, tutorials/geom/runplugin.C. It didn’t work out very well because

  1. if all nodes share a single volume, I cannot build up a stand alone program due to the reason mentioned in this post: TGeoIteratorPlugin::fIterator is private

  2. I then initialized one volume for each node so that I can change the color of each node without affecting others by using

gGeoManager->cd("/.../.../...");
gGeoManager->GetCurrentNode()->GetVolume()->SetLineColor(kBlue); 

. But the viewer won’t be redrawn unless I click on it. I had used gGeoManager->GetGeomPainter()->ModifiedPad() after I changed colors. It didn’t work for some reason (It does work in runplugin.C example).

  1. I would like to show openGL viewer only. I set “Viewer3D.DefaultDrawOption: ogl” in my .rootrc. But an empty normal canvas will pop up together with the openGL viewer. This is quit confusing for a user of this event display. And this program would be run in different machines. I cannot change .rootrc in all of them. This is why I start to think of having an embedded openGL viewer and draw geometries in it.

Exactly. I didn’t start with EVE because I thought my application was very simple, I didn’t need something big as EVE. After having so many issues on building up my own event display, I turned back to EVE. That’s why I posted this How to get a TEveElement from EVE in command line the other day.

I guess this is the reason for my problem 3? A pad is created before a GL scene.

I guess this is the reason for my problem 2?

great. But where can I get the pointer to TGLViewer?

[quote=“matevz”]
I strongly suggest to use existing Eve interfaces. These can also be extended or made more flexible if needed.

Best,
Matevz[/quote]

If my simple solution won’t work out, I would love to use EVE. I guess I can at first import my geometry to EVE by following tutorials/eve/assembly.C and then use your trick How to get a TEveElement from EVE in command line to change colors. But how can I add buttons and menus in EVE main window to step through events (e.g. previous, next events)?

Sorry for such a long post.

Cheers, Jing


Dear Jing,

To start with, I will again propose to use Eve :slight_smile: If you want a simpler interface, you can always keep the standard eve window hidden and show only your GUI. As you application will become more complex, you will find yourself reimplementing many things that are already done.

An example of simple event navigation is in tutorials/eve/alice_vsd.C – it creates a new Tab with just buttons to go to next/previous event. This should be easy to extend.
To add menu entries, you can get TMenuBar via gEve->GetBrowser()->GetMenuBar() and then you can add your own menu-popus, as is done in TEveBrowser constructor. You will also need a ROOT class with ClassDef to connect signals from menu-pop to its member functions.

As you have already found out, geometry isn’t the best way of displaying digits. TEveGeoShape provides a way around that: you pass it the shape (can be taken from geometry) and set the transformation matrix. You are able to set its title (tooltip) and color as you want. For collections of digits there are also specialized objects: TEveQuadSet (2d) and TEveBoxSet (3d) (see demos quadset.C and boxset.C) but they only support a limited set of shapes.

Now … I find it a bit hard to answer to all your questions in a coherent manner: all the issues are somehow interconnected :slight_smile: If you want, we can go through step-by-step, but I think it is better to start at the beginning and work from basic things towards more complex ones.

However, I’d suggest you put your geometry file somewhere I can access it and tell me which geometry paths you want to show. Then I will create a small macro that will show these PMDs with random colors using TEveGeoShape. After that, you can take this code and modify it to show meaningful values and to support event navigation. What do you say?

A very similar thing is done in ALICE to display raw-data of ACORDE detector:
alisoft.cern.ch/viewvc/trunk/EVE … ot=AliRoot

It is really good to see ROOT gl / eve also used in XMASS!

Cheers,
Matevz

PS: I will be away next week.

[quote=“matevz”]Dear Jing,
To start with, I will again propose to use Eve :slight_smile: If you want a simpler interface, you can always keep the standard eve window hidden and show only your GUI. As you application will become more complex, you will find yourself reimplementing many things that are already done.
[/quote]

Dear matevz, you are absolutely right. If everything works fine, we shall also show liquid Xe level, temperature distribution, source position, muon veto PMTs, etc. It will get more and more complex. A little worry is that EVE is developed for HEP experiment, where the requirement is a bit different.

Thank you for pointing it out.

for XMASS, at least two shapes are needed: hexagon, circle for 3D display.

Sorry, too many questions :stuck_out_tongue:

I would say ROOT developers are the best in the world :smiley: Attached please find a simplified version of our inner PMT array. Some PMTs are missing. But it won’t affect coding.

I will check that. Thanks.

It is really good to have EVE to start with!

[quote=“matevz”]
Cheers,
Matevz

PS: I will be away next week.[/quote]

Take your time. I will figure out something simple for the first several days of running.

Cheers, Jing
PMTs.C (5.39 KB)

Dear Jing,

I slightly modified your original:
[list=]
[] close geometry with “i” option: this allows me to get unique ids of nodes in the geometry and use them to extract PMT information (shape, transformation matrix).
[
] comment out drawing
[/list]

Then I wrote two macros (both use PMTs.C to create geometry).

PMTs_geom.C: draw geometry using TEveGeoTopNode

PMTs_digis.C: Draw radom digits on every PMT.

As you will see, I extract all PMTs and their ids from the geometry. In real life, you will need some kind of mapping between actual channel id and geometry-path — or just channel id - transformation matrix, since you know what kind of shape belongs to given id. In this case you don’t need geometry at all.

Cheers,
Matevz
PMTs_digis.C (2.29 KB)
PMTs_geom.C (666 Bytes)
PMTs.C (5.3 KB)

Dear Matevz,

thanks a lot! I think I got the idea. I have some further questions, but I guess it is better to open some other threads rather than making this one super long.

Cheers, Jing

Dear Matevz,

I’ll have to continue this post. I followed your examples to create my own event display. I have the following function executed every 1 second:

{
   gEve->GetViewers()->DeleteAnnotations();
   gEve->GetCurrentEvent()->DestroyElements();

   TEveElementList *hits = new TEveElementList("test event");

   const Int_t nColors = gStyle->GetNumberOfColors();
   const Int_t maxNPEs = 50;

   for (UInt_t ihit=0; ihit<25; ihit++) {
      Int_t id = gRandom->Integer(641);
      UShort_t nPEs = gRandom->Integer(49);

      TEveGeoShape* hit = new TEveGeoShape(Form("PMT %d",id),
            Form("PMT:%d, nPEs:%d",id,nPEs));

      hit->SetMainColor(gStyle->GetColorPalette(nColors * nPEs/maxNPEs));

      hit->SetMainTransparency(70); // To make shapes transparent
      hit->SetPickable(kTRUE);

      gGeoManager->cd(Form("/sphere_1/PMT_%d",id));
      TGeoMatrix *trans = (TGeoMatrix*) gGeoManager->GetCurrentMatrix();
      hit->RefMainTrans().SetFrom(*trans);
      hit->SetShape((TGeoShape*) gGeoManager->GetCurrentVolume()->GetShape()->Clone());

      hits->AddElement(hit);
   }

   // Add to default / event scene.
   gEve->AddElement(hits);

   gEve->Redraw3D(kFALSE,kTRUE);
}

The first two sentences are added to remove the previous event, otherwise events will overlap each other. However, the program crashed here:

Is it possible for you to figure out the problem with the above information?

If I do want to keep previous events for later use, how can I show a new event without showing the previous one?

Cheers, Jing

Dear Jing,

  1. About the crash … it is impossible to help you without more information. Are there some errors before the crash? You should run the program under debugger and examine the program state (call-stack, function arguments, local variables) at the point of error.

  2. You can in principle keep eve elements for later usage. In your case, that would probably be the “hits” containe. You shoud:
    a) call hits->IncDenyDestroy() to prevent automatic destruction;
    b) remove your “hits” container from current event using TEveElement::RemoveElement() and store it somewhere you can access it later
    c) when you want to delete it, call hits->DecDenyDestroy()

Cheers,
Matevz

Dear Matevz,

the crash is due to a stupid mistake. I call gEve->GetCurrentEvent()->DestroyElements(); at the beginning of the function. At the first time the function is called, there is no event at all, gEve->GetCurrentEvent() returns zero. I simply copied the codes from tutorials/eve without thinking. Sorry about it.

Cheers, Jing

Check Questions about Qt and Root
and Using OpenGL in a compiled program
You may find it useful

[quote=“fine”]Check Questions about Qt and Root
and Using OpenGL in a compiled program
You may find it useful[/quote]

Dear Fine,

thank you for the suggestion, yes, I noticed your QT GUI, and it looks promising. But in our computational environment not all machines have QT installed. I would have to live without it.

Cheers, Jing