OpenGL rendering on juce windows

Hi,

I’m working on a new version of a program I have been working for some time already (http://www.demopaja.org). As for the new version I have been searching and evaluating a cross platform GUI librarys. My main platform is Windows and I really would like to port the app to run on a Mac too.

My options at the moment are more or less JUCE or wxWidgets, I just dont like wxWidgets, and JUCE would allow me to create just the kind of UI I want. Still evaluating it, but it looks very promising and fits the way I like to work creating UI.

I have one major problem/concern regarding JUCE, though. My application is all about hardware accelerated 3D rendering, Direct3D or OpenGL (on Windows both, on Mac OGL). The JUCE architecture seemed to hide the underlying platform so well, that I’m not sure the amount of work that it requires to get that working.

All I need is to have one window where I can render my stuff (the new layout will be somewhat similar than the old one, see the link above). This window needs to have a native window handle as it is required by the rendering API setup.

To keep it short :)… my questions is, is it possible and how much effort it would require to have a OpenGL rendering window inside the main window? As that 3D rendering window will take most of the screen space I would also like not to render anything that lies under that 3D rendering window.

Thanks in advance,

–mikko

Someone else I know was thining of using it for openGL, though it’s not something I know much about. I wouldn’t have thought it’d be too hard to do though - you can easily get a window handle from a component to use directly, and I’ve done something similar with QuickTime. If you want to have a go, I’ll happily help you get it working.

Hi memon and jules,

I also tried to create my own dialog window with opengl support.
I succeeded but i had problems with the refresh of the screen.

The original paint of the component was interfering with my opengl swapbuffers routine. (so jules, if you have a solution for this let me know).

You can the native handle from a juce component. so it will return a HWND for windows and something elsei forgot for the mac.

i eventually ended up creating a native windows opengl window and a mac (carbon) opengl window.
For the rest of the interface i just use Juce.

another option is using glut for your rendering window, the problem is though that it interferes with Juce, so the interface will run very slow…

cheers
edwin

It’ll probably involve a bit of messing about in the win32/mac native code to get the refresh working nicely. Why not post your code so we can have a look?

In my case one solution I have been thinking is to have four windows native. One at tbe bottom which acts like a container for the three latter ones, then one native window for the left pane and one for the bottom pane.

The container window would be dummy and it would not contain no drawing code at all, not even to clear the window. Also the opengl window should not be cleared or anything should not be drawn into that area.

That way the configuration would be similar is it would be in normal win32 app (maybe similar config would work in Mac too). I could use JUCE to the UI in the two smaller windows and still render nicely into the “main” window with OGL.

I will try this as soon as I get back home.

Hi jules,memon

i created a small opengl juce test application…
next to the main juce window, a juce dialog with opengl support is created.
you will see a spinning cube, but it flickers a lot…

http://www.resolume.com/download/juceopengltest.zip

hope we can fix it, would be very nice, i can cook you up the mac equivalent as well…

cheers
Edwin de Koning

p.s i used to code everything in delphi, so my c++ experience is limited to translating to and from delphi code.

To get rid of the flickering you can add the following code at the top of the handlePaintMessage (juce_Win32_windowing.cpp).

// Just handle the wm paint, and return. if( ownerWindow->getDoNotPaint() ) { PAINTSTRUCT paintStruct; HDC dc = BeginPaint (hW, &paintStruct); // Note this can immediately generate a WM_NCPAINT Graphics imageGraphics (*paintingBuffer, 0, 0, 0, 0, 0, 0); try { ownerWindow->handlePaint (imageGraphics); } catch (...) {} EndPaint (hW, &paintStruct); return; }

You of course need to add getDoNotPaint() and setDoNotPaint() to the native window class too. That was just quick hack to get it going. Other than that the JUCE window class (the win32 window class) seems to have most of the flags already which are used by any opengl app. I usually also add CS_HREDRAW | CS_VREDRAW flags to the class style. Those styles forces the whole window to redraw if the size changes. Not completely sure, but I think they caused some problem with overlapping windows (i.e. juce dialog under the opengl fialog).

Also in your example there you seemed to flip the buffer twice on paint(), and also the ValidateRect(hWnd,NULL); is not necessary, as the begin paint in above piece of code handles that. That free(glwindow) is really dangerous… create with ‘new’, free with ‘delete’… always :slight_smile:

I tried to make a component but it seems that ogl does not co-exists very well with GDI. I event masked the update the same way as the quicktime component does, but did not help.

Once I have more time I will try following:
[list]- add a flag to the component class indicating masking ála the quicktime masking

  • allow a child component to have own native window (this will make a lot of things easier with opengl and d3d)[/list]
    I have to still check out what opengl initialisation requires on Mac. I will post my findings here as I progress.

Very interesting, I’ll probably have a go at getting this working…

one quick question, (as someone who’s never done any openGL before): to get the project to build, I had to replace

with

…because those are the headers I’ve got in the platform sdk. Why do you have different ones?

Hi Jules,

nice that you are having a look into this, an opengl dialog component would be a nice addition to your JUCE system.
You don’t need the glut.h…that was my fault, glut is the platform independant GUI framework of opengl. With glut it’s very easy to create opengl windows and have support for mouse, keys timers etc…

i will try out your modifications to the code…
i will to do this coming monday and i will try to send you the mac code as well…

yes i saw that i flipped the buffer twice, i corrected that allready…
i did not know that calling free was dangerous, in delphi it is the right and safest way to go.

thanx for the help,
cheers
Edwin

[/quote]

Hi Jules,
i could not resist and added the modifications.
and it works!!!..cool…but you knew that allready :wink:

this is wicked
cheers
Edwin

Memon,
sorry sorry…i thought jules posted the code…
my apologies…so all the credits go to you…

cheers
Edwin

ok guys, probably best not to spend too much of your time on this any more - I got a bit carried away here, and I’ve got a clean, working implementation almost ready.

It lets you create a GL component anywhere inside a normal component, and picks up mouse, keyboard, etc messages that go there too. Very nifty. Needed a few cunning tricks to get it to work, but it looks good!

Haven’t looked at mac support yet, but I’ll post this soon and let you have a go.

:shock: :smiley: !!!

crumbz0rs!

here’s an appetizer for you…

http://www.rawmaterialsoftware.com/juce/downloads/jucedemo_gl.exe

:shock: :shock: :shock: :shock: :shock:

:!:

jules you are a genius.

Thanks Jules!

My priority is to get D3D working, but I think the OpenGL component should get me good head start… and an idea of “the right way” to do it :slight_smile:

I ment that mixing and matching malloc/free (the C way) and new/delete (the C++ way) is dangerous. For VC++ it works with simple classes, since internally it uses malloc (or the windows api allocation function) anyway, but the destructor of the class is not called, and there may be some other interesting side effects too with virtual methods and such. For example on my computer your example was always crashing at exit.

Another thing is that if you allocate an array with new: char* test = new char[100], you have to use the array delete operator to delete it: delete [] test. Not very intuitive for someone just getting used to c++ :wink:

:shock: Wow! Thanks Jules! This’ll be a very useful component :D.

  • Niall.

does this mean T3 will just be a deathmatch mode? because i personally think that taking the single-player story out ruined the quake series…