My implementation was way before Jules implemented the new OpenGL code. So it created a real frankenstein using different frameworks! (Juce for the keyboard and mouse tracking, Ogre for the rendering and NUI for the 2d UI elements). I can't see why it shouldn't be possible to use JUCE nowadays.
The way I did it was like this... And I wouldn't do it this way now with the new classes, but it should give an idea... I'm embarassed to post this code, as its real hacky... but if it helps people
class SMOgreView : public Component
{
public:
SMOgreView();
virtual ~SMOgreView();
void initOgre();
Ogre::RenderWindow *getRenderWindow();
void resized();
void makeOgreCurrent(); // need to do this before loading any textures or rendering (any gl calls)
private:
void *ogreView; // Type is OgreView on mac (an NSView sub class)
void *ogreContext;
};
Then it did something like this(this was the mac implementation of void SMOgreView::initOgre())
// I just throw a regular old NSView in...
ogreView=[[OgreView alloc]initWithFrame:NSMakeRect(0, 0, getWidth(),getHeight())];
ComponentPeer *componentPeer=getPeer();
jassert(componentPeer);
NSView* const peer = (NSView*) (componentPeer->getNativeHandle());
if (peer != 0)
{
[peer addSubview: (OgreView*)ogreView];
}
// Before CreateRenderWindow is called, it MUST be in a window.
// If I use an NSViewComponent then is starts calling resize...
Ogre::NameValuePairList misc;
misc["macAPI"] = "cocoa";
misc["externalWindowHandle"] = Ogre::StringConverter::toString((size_t)ogreView);
// Create the window and load the params
Ogre::Root::getSingleton().createRenderWindow("LaunchPad", 0, 0, false, &misc);
On windows it was just....
void SMOgreView::initOgre()
{
// maybe I put a JUCE openGL component in here and external context it?
// http://www.ogre3d.org/docs/api/html/classOgre_1_1Root.html
ComponentPeer *componentPeer=getPeer();
jassert(componentPeer);
HWND windowHandle=(HWND)(componentPeer->getNativeHandle());
// Before CreateRenderWindow is called, it MUST be in a window.
Ogre::NameValuePairList misc;
misc["externalWindowHandle"] = Ogre::StringConverter::toString((size_t)windowHandle);
// Create the window and load the params
ogreView=Ogre::Root::getSingleton().createRenderWindow("Launch Pad", 0, 0, false, &misc);
ogreContext = wglGetCurrentContext(); //If the calling thread has a current OpenGL rendering context, wglGetCurrentContext returns a handle to that rendering context. Otherwise, the return value is NULL -- The current OpenGL rendering context of a thread is associated with a device context by means of the wglMakeCurrent function. You can use the wglGetCurrentDC function to obtain a handle to the device context associated with the current OpenGL rendering context
jassert(ogreContext);
winDC=wglGetCurrentDC();//obtains a handle to the device context that is associated with the current OpenGL rendering context of the calling thread...If the calling thread has a current OpenGL rendering context, the function returns a handle to the device context associated with that rendering context by means of the wglMakeCurrent function. Otherwise, the return value is NULL.
jassert(winDC);
}
This view pimpl was then added to this Component...
class SMOgreComponent : public Component, public Ogre::FrameListener, private Timer,public ApplicationCommandTarget, public Ogre::RenderTargetListener, public SMNotificationListener, public ActionListener
Then I had to manually fix rendering after Ogre was done with the context...
void SMOgreComponent::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
{
#if defined(_MACOSX_)
GLboolean appleStorage;
glGetBooleanv(GL_UNPACK_CLIENT_STORAGE_APPLE,&appleStorage);
#endif
#if 1
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPolygonMode(GL_FRONT, GL_FILL);
#endif
glPushMatrix();
Ogre::RenderSystem *d_renderSystem=Ogre::Root::getSingleton().getRenderSystem();
// initialise render settings
#if 1
d_renderSystem->_setWorldMatrix(Ogre::Matrix4::IDENTITY);
d_renderSystem->_setViewMatrix(Ogre::Matrix4::IDENTITY);
d_renderSystem->_setProjectionMatrix(Ogre::Matrix4::IDENTITY);
#endif
d_renderSystem->setLightingEnabled(false);
d_renderSystem->_setDepthBufferParams(false, false);
d_renderSystem->_setDepthBias(0, 0);
d_renderSystem->_setCullingMode(Ogre::CULL_NONE);
d_renderSystem->_setFog(Ogre::FOG_NONE);
d_renderSystem->_setColourBufferWriteEnabled(true, true, true, true);
d_renderSystem->unbindGpuProgram(Ogre::GPT_FRAGMENT_PROGRAM);
d_renderSystem->unbindGpuProgram(Ogre::GPT_VERTEX_PROGRAM);
d_renderSystem->setShadingType(Ogre::SO_GOURAUD);
//d_renderSystem->_setPolygonMode(Ogre::PM_SOLID);
// enable alpha blending
d_renderSystem->_setSceneBlending(Ogre::SBF_SOURCE_ALPHA,
Ogre::SBF_ONE_MINUS_SOURCE_ALPHA);
#if 1
Ogre::TextureUnitState::UVWAddressingMode d_uvwAddressMode;
d_uvwAddressMode.u = Ogre::TextureUnitState::TAM_CLAMP;
d_uvwAddressMode.v = Ogre::TextureUnitState::TAM_CLAMP;
d_uvwAddressMode.w = Ogre::TextureUnitState::TAM_CLAMP;
Ogre::LayerBlendModeEx d_colourBlendMode;
d_colourBlendMode.blendType = Ogre::LBT_COLOUR;
d_colourBlendMode.source1 = Ogre::LBS_TEXTURE;
d_colourBlendMode.source2 = Ogre::LBS_DIFFUSE;
d_colourBlendMode.operation = Ogre::LBX_MODULATE;
Ogre::LayerBlendModeEx d_alphaBlendMode;
d_alphaBlendMode.blendType = Ogre::LBT_ALPHA;
d_alphaBlendMode.source1 = Ogre::LBS_TEXTURE;
d_alphaBlendMode.source2 = Ogre::LBS_DIFFUSE;
d_alphaBlendMode.operation = Ogre::LBX_MODULATE;
d_renderSystem->_setTextureCoordCalculation(0, Ogre::TEXCALC_NONE);
d_renderSystem->_setTextureCoordSet(0, 0);
d_renderSystem->_setTextureUnitFiltering(0, Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_POINT);
d_renderSystem->_setTextureAddressingMode(0, d_uvwAddressMode);
d_renderSystem->_setTextureMatrix(0, Ogre::Matrix4::IDENTITY);
d_renderSystem->_setAlphaRejectSettings(Ogre::CMPF_ALWAYS_PASS, 0, false);
d_renderSystem->_setTextureBlendMode(0, d_colourBlendMode);
d_renderSystem->_setTextureBlendMode(0, d_alphaBlendMode);
d_renderSystem->_disableTextureUnitsFrom(1);
#endif
if (nuiBridge)
{
#if JUCE_MAC
// on windows i just killed vbo
glBindBuffer(GL_ARRAY_BUFFER_ARB, 0); // works with 1.5
#endif
nuiBridge->callDisplay(); // THIS RENDERS the 2d UI elements!
}
glPopMatrix();
#if 1
glPopAttrib();
glPopClientAttrib();
#endif
#if defined(_MACOSX_)
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, appleStorage);
#endif
}