Custom mainloop without OS specific window management?

Problems building or running the engine, queries about how to use features etc.
Baalzamon
Gnoblar
Posts: 16
Joined: Sun Nov 27, 2005 11:23 am

Custom mainloop without OS specific window management?

Post by Baalzamon »

Hi,

first of all, this is what I want to achive:

I want an encapsulation of the Ogre Engine so I can create my own mainloop without dealing with the OS dependent windows programming.

I searched the forum and the tutorials, but I only found suggestions and examples that implement PeekMessage etc. for Windows-OS. But what to do on a *unix-Plattform?

I thought Ogre is plattform independent? Do I have to use OS specific window management outside of Ogre, in my own code to achive this?

This is (roughly) what I thought about, please not the run() method:

Code: Select all

class videoDevice
{
  videoDevice()
  {
    Root* root = new Ogre::root();
     // do all the Ogre initialisation here
  }

  virtual ~videoDevice()
  {
    delete root;
  }

  bool run()
  {
    // return true if the renderSystem is running which means, 
    // no 'exit' Button has been pressed (like 'close window', 'exit key' etc.)
    // something like root->isRunning() would be nice. :) 
    // I could achive this with PeekMessage etc. but then I had to do a
    // distinction of cases on the OS. But that's what I _don't_ want to
    // do in my own code.
  }

  void drawAll()
  {
    root->renderOneFrame();
    // Do all the render dependent stuff here
  }
};
So my main will look like this:

Code: Select all

main()
{
  videoDevice* device = new videoDevice();

  while(device->run())
  {
    device->drawAll();
  }
}
I really don't want to care about OS specific programming, and as I said, I thought Ogre would take of this for me. But as it seems it takes only care when I use the startRendering() method.

I think my problem is that Ogre has no isRunning() method, which indicates if the RenderSystem(? don't know if that is really what I want to check) is still running and catches the OS specific window close commands for me.

Hope you get the point. ;)
Every help is appreciated.

Regards,
Baalzamon
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 67

Post by sinbad »

I think this patch my be useful to you:

http://sourceforge.net/tracker/index.ph ... tid=302997

If it is, please test and let us know how it goes. Posting a note on the patch of your testing results will help us evaluate it.
User avatar
pjcast
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2543
Joined: Fri Oct 24, 2003 2:53 am
Location: San Diego, Ca
x 2

Post by pjcast »

The patch adds a void messagePump(RenderWindow* rw); method to platform manage that either startRendering will call, or you can call yourself if not using the Ogre render loop. This way, OS specific events are removed from client code.. It would be awesome if you could help test that patch.. as it has been sitting there for some time, and I fear it might not be compatiable with Ogre head anymore :/
Have a question about Input? Video? WGE? Come on over... http://www.wreckedgames.com/forum/
Baalzamon
Gnoblar
Posts: 16
Joined: Sun Nov 27, 2005 11:23 am

Post by Baalzamon »

Hi, sorry for the delayed reply. :(

I downloaded and applied the patch, using the minGW patch tool. There were no Problems except for one file, ./RenderSystems/GL/src/GLX/OgreGLXWindow.cpp.

The output of the patching process you might be interessted in:

Code: Select all

Hunk #1 succeeded at 66 with fuzz 2 (offset -5 lines).
Hunk #2 succeeded at 621 (offset -26 lines).
Hunk #7 FAILED at 374.
Hunk #8 succeeded at 402 (offset 7 lines).
Hunk #9 FAILED at 455.
2 out of 9 hunks FAILED -- saving rejects to ./RenderSystems/GL/src/GLX/OgreGLXWindow.cpp.rej
Anyway, here is the output of the OgreGLXWindows.cpp.rej:

Code: Select all

***************
*** 363,378 ****
      mContext = new GLXContext(mDisplay, mWindow, mGlxContext);
  }

  void GLXWindow::destroy(void)
  {
-     // Unregister and destroy OGRE GLContext
-     delete mContext;

-     // Destroy GL context
    if(mGlxContext)
      glXDestroyContext(mDisplay, mGlxContext);
    if(mWindow)
      XDestroyWindow(mDisplay, mWindow);
    mWindow = 0;
    mGlxContext = 0;
    mActive = false;
--- 374,393 ----
      mContext = new GLXContext(mDisplay, mWindow, mGlxContext);
  }

+ //-------------------------------------------------------------------------------------------------//
  void GLXWindow::destroy(void)
  {
+   // Unregister and destroy OGRE GLContext
+   delete mContext;

+   // Destroy GL context
    if(mGlxContext)
      glXDestroyContext(mDisplay, mGlxContext);
+
    if(mWindow)
      XDestroyWindow(mDisplay, mWindow);
+
+   mContext = 0;
    mWindow = 0;
    mGlxContext = 0;
    mActive = false;
***************
*** 434,546 ****
      break;
    case ConfigureNotify:
      if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
-       // Not for me
        break;
-         resized(event.xconfigure.width,  event.xconfigure.height);
      break;
    case MapNotify:
      if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
-       // Not for me
        break;
      // Window was mapped to the screen
-     exposed(true);
      break;
    case UnmapNotify:
      if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
-       // Not for me
        break;
      // Window was unmapped from the screen (user switched
      // to another workspace, for example)
-         exposed(false);
      break;
    }
  }

- void GLXWindow::exposed(bool active)
- {
-     mActive = active;
- }
  void GLXWindow::resized(size_t width, size_t height)
  {
-     // Check if the window size really changed
-     if(mWidth == width && mHeight == height)
-         return;
-     mWidth = width;
-     mHeight = height;
-
-     for (ViewportList::iterator it = mViewportList.begin();
-                     it != mViewportList.end(); ++it) {
-         (*it).second->_updateDimensions();
-     }
- }
- /// Pure virtual destructor must be defined
- GLXWindowInterface::~GLXWindowInterface()
- {
  }

  void GLXWindow::getCustomAttribute( const String& name, void* pData )
  {
-     if( name == "GLCONTEXT" ) {
-         *static_cast<GLXContext**>(pData) = mContext;
-         return;
-     } else if( name == "GLXWINDOW" ) {
      *static_cast<Window*>(pData) = mWindow;
      return;
-   } else if( name == "GLXDISPLAY" ) {
      *static_cast<Display**>(pData) = mDisplay;
      return;
-   } else if( name == "GLXWINDOWINTERFACE" ) {
-     *static_cast<GLXWindowInterface**>(pData) = this;
-     return;
    }
  }

-
-
  void GLXWindow::writeContentsToFile(const String& filename)
  {
-         ImageCodec::ImageData* imgData = new ImageCodec::ImageData;
-         imgData->width = mWidth;
-        imgData->height = mHeight;
-      imgData->format = PF_BYTE_RGB;
-
-       // Allocate buffer
-         uchar* pBuffer = new uchar[mWidth * mHeight * 3];
-
-      // Read pixels
-      // I love GL: it does all the locking & colour conversion for us
-        glReadPixels(0,0, mWidth-1, mHeight-1, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
-
-         // Wrap buffer in a memory stream
-         DataStreamPtr stream(new MemoryDataStream(pBuffer, mWidth * mHeight * 3, false));
-
-        // Need to flip the read data over in Y though
-      Image img;
-      img.loadRawData(stream, mWidth, mHeight, PF_BYTE_RGB );
-       img.flipAroundX();
-
-         MemoryDataStreamPtr streamFlipped(new MemoryDataStream(img.getData(), stream->size(), false));
-
-         // Get codec
-       size_t pos = filename.find_last_of(".");
-        String extension;
-       if( pos == String::npos )
-           OGRE_EXCEPT(
-             Exception::ERR_INVALIDPARAMS,
-          "Unable to determine image type for '" + filename + "' - invalid extension.",
-           "SDLWindow::writeContentsToFile" );
-
-        while( pos != filename.length() - 1 )
-           extension += filename[++pos];
-
-      // Get the codec
-        Codec * pCodec = Codec::getCodec(extension);
-
-       // Write out
-        Codec::CodecDataPtr codecDataPtr(imgData);
-      pCodec->codeToFile(streamFlipped, filename, codecDataPtr);

-         delete [] pBuffer;
  }

  }
--- 455,560 ----
      break;
    case ConfigureNotify:
      if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
        break;
+
+     resized(event.xconfigure.width,  event.xconfigure.height);
      break;
    case MapNotify:
      if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
        break;
+
      // Window was mapped to the screen
+     mActive = true;
      break;
    case UnmapNotify:
      if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
        break;
+
      // Window was unmapped from the screen (user switched
      // to another workspace, for example)
+     mActive = false;
      break;
    }
  }

+ //-------------------------------------------------------------------------------------------------//
  void GLXWindow::resized(size_t width, size_t height)
  {
+   // Check if the window size really changed
+   if(mWidth == width && mHeight == height)
+     return;
+
+   mWidth = width;
+   mHeight = height;
+
+   for (ViewportList::iterator it = mViewportList.begin();  it != mViewportList.end(); ++it)
+     (*it).second->_updateDimensions();
  }

+ //-------------------------------------------------------------------------------------------------//
  void GLXWindow::getCustomAttribute( const String& name, void* pData )
  {
+   if( name == "GLCONTEXT" )
+   {
+     *static_cast<GLXContext**>(pData) = mContext;
+     return;
+   }
+   else if( name == "GLXWINDOW" )
+   {
      *static_cast<Window*>(pData) = mWindow;
      return;
+   }
+   else if( name == "GLXDISPLAY" )
+   {
      *static_cast<Display**>(pData) = mDisplay;
      return;
    }
  }

+ //-------------------------------------------------------------------------------------------------//
  void GLXWindow::writeContentsToFile(const String& filename)
  {
+   ImageCodec::ImageData* imgData = new ImageCodec::ImageData;
+   imgData->width = mWidth;
+   imgData->height = mHeight;
+   imgData->format = PF_BYTE_RGB;
+
+   // Allocate buffer
+   uchar* pBuffer = new uchar[mWidth * mHeight * 3];
+
+   // Read pixels
+   // I love GL: it does all the locking & colour conversion for us
+   glReadPixels(0,0, mWidth-1, mHeight-1, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
+
+   // Wrap buffer in a memory stream
+   DataStreamPtr stream(new MemoryDataStream(pBuffer, mWidth * mHeight * 3, false));
+
+   // Need to flip the read data over in Y though
+   Image img;
+   img.loadRawData(stream, mWidth, mHeight, PF_BYTE_RGB );
+   img.flipAroundX();
+
+   MemoryDataStreamPtr streamFlipped(new MemoryDataStream(img.getData(), stream->size(), false));
+
+   // Get codec
+   size_t pos = filename.find_last_of(".");
+   String extension;
+   if( pos == String::npos )
+     OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Unable to determine image type for '"
+       + filename + "' - invalid extension.", "SDLWindow::writeContentsToFile" );
+
+   while( pos != filename.length() - 1 )
+     extension += filename[++pos];
+
+   // Get the codec
+   Codec * pCodec = Codec::getCodec(extension);
+
+   // Write out
+   Codec::CodecDataPtr codecDataPtr(imgData);
+   pCodec->codeToFile(streamFlipped, filename, codecDataPtr);

+   delete [] pBuffer;
  }

  }
+
I used the Ogre Build 1.0.6 to patch ageinst. And while I'm still stuck on a Windows machine right now, I recompiled the necessary files and as far as I can see everything runs fine, for a Win32 Platform. :)

Now, in my example above the run() method looks like:

Code: Select all

bool run() 
  {
    Ogre::PlatformManager::getSingleton().messagePump(rWindow);
    return !rWindow->isClosed();
  }
Thanks a lot for that little piece of code. :D This was quite was I was looking for.

Regards,
Baalzamon
User avatar
alphageek
Gnome
Posts: 365
Joined: Mon Jan 03, 2005 11:56 am

Post by alphageek »

I applied this patch. OgreGLXWindow.cpp patching failed, but all else was fine.

Ogre compiles fine (I am going to stick my head in the sand about the GLXWindow issue above), and everything works as expected.

"M4d pr0pz" to pjcast.


Edit: my situation is exactly the same as the guy above: 1.0.6, with the same patch output.
Axiomatic: action-packed space shooter
TaskScheduler 0.3
User avatar
pjcast
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2543
Joined: Fri Oct 24, 2003 2:53 am
Location: San Diego, Ca
x 2

Post by pjcast »

Yeah, the patch (as reported by _Xavier_) still applies cleanly to cvs head.. But conflicts with 1.0.6 and below with GLX. Not an issue probably, as I expect only Dagon will have these changes applied.
Have a question about Input? Video? WGE? Come on over... http://www.wreckedgames.com/forum/