c++iossdl-2ogre

SDL 2.0.3 with Ogre 1.9.0 and IOS


I am trying to integrate SDL 2.0.3 to work Ogre 1.9.0 for window and events handling, it works fine under Linux but I am having issues under IOS 7.1.

I cannot get any input or window events from SDL. I am using the wmInfo.info.uikit.window to get the handle and then I pass it to Ogre. The only thing I am not sure is if I am getting the GL context properly. I can get only one event when I start SDL with Ogre SDL_APP_DIDENTERFOREGROUND. Is there anything special I need to do for the IOS.

I would really appreciate any help as I am stuck on the problems above.

Also I am working under OSX and IOS 7.1 simulator. Below are my changes to the original Ogre iOS template.

SDL and Ogre initialization:

//SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
    printf("Could not initialize SDL\n");
    return 1;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_EGL, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

SDL_DisplayMode displayMode;
SDL_GetDesktopDisplayMode(0, &displayMode);

/* create window and renderer */
SDL_Window* window = SDL_CreateWindow(NULL, 0, 0, displayMode.w, displayMode.h,    SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE);

SDL_GLContext glContext = SDL_GL_CreateContext(window);

SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(window,&wmInfo);

m_pLog = Ogre::LogManager::getSingleton().createLog("OgreLogfile.log", true, true, false);
m_pLog->setDebugOutputEnabled(true);

String pluginsPath;
m_pRoot = new Ogre::Root(pluginsPath, Ogre::macBundlePath() + "/ogre.cfg");
m_StaticPluginLoader.load();

m_pRenderWnd = m_pRoot->initialise(false, wndTitle);

size_t winHandle = reinterpret_cast<size_t>(wmInfo.info.uikit.window);
size_t glHandle = reinterpret_cast<size_t>(glContext);

Ogre::NameValuePairList params;
params["externalWindowHandle"] = Ogre::StringConverter::toString((unsigned long)winHandle);
params["externalGLContext"] =   Ogre::StringConverter::toString((unsigned long)glHandle);
params["externalGLControl"] = String("True");

m_pRenderWnd = m_pRoot->createRenderWindow("", displayMode.w/2, displayMode.h/2, false,  &params);

My main loop:

DemoApp demo;
demo.startDemo();

bool done = false;

SDL_Event event;

double mStartTime;
double mLastFrameTime;

while (!done)
{

  mStartTime = OgreFramework::getSingletonPtr()->m_pTimer->getMillisecondsCPU();
  OgreFramework::getSingletonPtr()->updateOgre(mLastFrameTime);
  OgreFramework::getSingletonPtr()->m_pRoot->renderOneFrame();
  mLastFrameTime = OgreFramework::getSingletonPtr()->m_pTimer->getMillisecondsCPU() - mStartTime;


    while (SDL_PollEvent(&event))
    {
        switch (event.type)
        {
            case SDL_FINGERMOTION:
                SDL_Log("Finger Motion");
                break;

            case SDL_FINGERDOWN:
                SDL_Log("Finger Down");
                break;

            case SDL_FINGERUP:
                SDL_Log("Finger Up");
                break;

            case SDL_QUIT:
                done = true;
                break;

            case SDL_APP_DIDENTERFOREGROUND:
                SDL_Log("SDL_APP_DIDENTERFOREGROUND");
                break;

            case SDL_APP_DIDENTERBACKGROUND:
                SDL_Log("SDL_APP_DIDENTERBACKGROUND");
                break;

            case SDL_APP_LOWMEMORY:
                SDL_Log("SDL_APP_LOWMEMORY");
                break;

            case SDL_APP_TERMINATING:
                SDL_Log("SDL_APP_TERMINATING");
                break;

            case SDL_APP_WILLENTERBACKGROUND:
                SDL_Log("SDL_APP_WILLENTERBACKGROUND");
                break;

            case SDL_APP_WILLENTERFOREGROUND:
                SDL_Log("SDL_APP_WILLENTERFOREGROUND");
                break;

            case SDL_WINDOWEVENT:
            {
                switch (event.window.event)
                {

                    case SDL_WINDOWEVENT_RESIZED:
                    {
                        SDL_Log("Window %d resized to %dx%d", event.window.windowID, event.window.data1, event.window.data2);

                        break;
                    }
                }
            }
        }
    }

Solution

  • I realize this question is a few years old now, but I had the same problem and I hope my solution is of some use to others.

    The problem is that you are replacing SDL's UIView (SDL_uikitview) with Ogre's UIView (OgreEAGL2View) and so you are no longer going to receive any touch input or any of the features implemented via SDL_uikitviewcontroller or SDL_uikitview. This replacement is taking place inside the GLES2 RenderSystem (specifically in OgreEAGL2Window.mm)

    The way I solved this for myself is to create my own UIViewController and UIView, and then put that view behind SDL's view. You can then receive touch input from SDL's view, while rendering into Ogre's view. This will require creating an Objective-C compilation unit and the code would look something like:

    #include "OgreEAGL2View.h"
    #import <UIKit/UIWindow.h>
    #import <UIKit/UIDevice.h>
    // other includes
    
    // call this from your C++ framework
    // pass it your startup params
    void setupMyiOSViews(Ogre::NameValuePairList &params)
    {
        // grab the UIWindow (you must have called SDL_createwindow before calling this)
        SDL_SysWMinfo wmInfo;
        SDL_Window *sdlWindow;
        SDL_VERSION(&wmInfo.version);
        SDL_GetWindowWMInfo(sdlWindow, &wmInfo);
        UIWindow *w = wmInfo.info.uikit.window;
    
        // get a rectangle with the screen dimensions
        CGRect rect = [[UIScreen mainScreen] applicationFrame];
        // instantiate a view controller of Ogre's subclass of UIViewController
        EAGL2ViewController *myViewController = [[EAGL2ViewController alloc] init];
        // instantiate a view of Ogre's subclass of UIView
        EAGL2View *myView = [[EAGL2View alloc] initWithFrame:rect];
        // make sure it's not transparent
        myView.opaque = YES;
        // attach the view to the viewcontroller
        myViewController.view = myView;
        // add the view to the current window
        [w addSubview:myView];
        // put the view *behind* the SDL view
        [w sendSubviewToBack:myView];
    
        // add the window, viewcontroller, and view to the proper parameters
        // UIWindow maps to param: externalWindowHandle
        // UIViewController maps to param: externalViewControllerHandle
        // UIView maps to param: externalViewHandle
        Ogre::String str_w = Ogre::StringConverter::toString((unsigned long)w);
        Ogre::String str_vc = Ogre::StringConverter::toString((unsigned long)myViewController);
        Ogre::String str_v = Ogre::StringConverter::toString((unsigned long)myView);
    
        params["externalWindowHandle"] = str_w;
        params["externalViewControllerHandle"] = str_vc;
        params["externalViewHandle"] = str_v;
    
        Ogre::LogManager::getSingleton().logMessage("externalWindowHandle: " + str_w);
        Ogre::LogManager::getSingleton().logMessage("externalViewControllerHandle: " + str_vc);
        Ogre::LogManager::getSingleton().logMessage("externalViewHandle: " + str_v);
    
    // now pass params into Ogre::Root::createRenderWindow
    }
    

    Note that there is no need to even create and context with SDL. Ogre will now be rendering into it's own view and viewcontroller