Ogre 1.10 Mid-Term Report

With the 1.10.8 release, the 1.10 support cycle is approximately half way over, which is a good time to recap the features and switches that got introduced since the initial release.

Note that Ogre 1.10 is the only actively maintained release – all other branches have reached their end of life, so no bugfixes will be back-ported.

If you are still using Ogre 1.9 or even a previous release, you are encouraged to upgrade to 1.10.

But besides bugfixes, there were also some notable changes, which will be presented below.

Java component

Following the Python Component that got introduced with the initial 1.10 release, we now introduce the Java Component. Both of them share the same SWIG definitions, meaning they have the same API coverage.

This allows you to write pure Java applications that leverage Ogre – which is especially useful for Android development. Take a look on the updated AndroidJNI sample

OpenGL improvements

The existing Vertex Array Object (VAO) implementation in GL3+ and GLES2 was so broken that VAOs had to be updated each frame – essentially disabling them. From 1.10.7 on VAOs work as expected and give a performance boost of about 10%.

Thanks to a contribution by Jean-Baptiste Griffo the GL3+ RenderSystem got a StateCache (accompanying GLES2 and GL). We took it as a starting point to further improve and unify the State Cache implementations and indeed could eliminate various bugs inside the GLES2 and GL caches.

Deprecation of node-less positioning

Traditionally Ogre allowed you to place Cameras and Lights in the scene without attaching them to a SceneNode. This resulted in three different positioning APIs for Cameras, Lights and SceneNodes with slight inconsistencies ( Camera::move vs. SceneNode::translate ) and one big one:

SceneNodes & Cameras look into (0,0,-1) by default

whereas Lights look into (0,0,1)

To make things consistent, using the Camera and Light API for positioning is deprecated now. If you want to move away from the origin, you have to attach to a SceneNode (same as you would have to with Ogre 2.x).

The only exception is Light::setDirection , which you should call with (0,0,-1) to make Lights behave like the other Nodes.

We cannot go ahead and change the default direction for 1.10 as it would break existing applications.

Compile time switches

Lets turn to some more fundamental changes that change the API and thus are hidden behind CMake switches.

OGRE_THREAD_SUPPORT == 3

To quote Steve, who initially implemented threading in Ogre:

OGRE_THREAD_SUPPORT==1 where resource management is fully threaded, was hopelessly naive. It required too many locks, and also that the rendersystem was multi-threaded. OGRE_THREAD_SUPPORT==2 improved that by not requiring that the rendersystem was threaded, and just doing disk I/O in the background, but still, the whole process is still driven within the Resource class, which means the locks are still in place on Resource and by association SharedPtr and a bunch of other classes too.

OGRE_THREAD_SUPPORT==3 option. Setting this, Ogre core objects – most notably Resource – are not thread-safe. However the DefaultWorkQueue is threaded. This allows the Terrain and MeshLOD Components to be multi-threaded without the locking overhead in OgreMain. Therefore we introduce the newoption. Setting this, Ogre core objects – most notably Resource – are not thread-safe. However the DefaultWorkQueuethreaded. This allows the Terrain and MeshLOD Components to be multi-threaded without the locking overhead in OgreMain. See #454 for details

OGRE_USE_STD11

Setting this option, the custom SharedPtr and AtomicScalar types become merely aliases for std::shared_ptr and std::atomic which are both more portable and higher performance alternatives.

Also std::thread is used as the default threading provider.

OGRE_NODE_STORAGE_LEGACY

Traditionally Ogre uses (hash-)maps to store everything by name, including sub-nodes and attached MovableObjects. While this gives you O(log(N)) lookup, iteration performance is terrible as maps are spread all over the memory and thus trash the CPU caches.

However with rendering the most common operation is iterating (for e.g culling) over all children while lookup is only done for changing the state. Furthermore high-frequency lookups can be easily avoided by just storing the returned pointer.

OGRE_NODE_STORAGE_LEGACY=0 will use the cache friendly std::vector instead of maps. Naturally lookup by name becomes O(N) instead of O(log(N)) and the API changes. However this improves rendering performance by about 20% – bringing Ogre 1.x into 2.0 range when only a few nodes need updates. Settingwill use the cache friendlyinstead of maps. Naturally lookup by name becomesinstead ofand the API changes. However this improves rendering performance by about 20% – bringing Ogre 1.x into 2.0 range when only a few nodes need updates. See #440 for details

An outlook on Ogre 1.11

As the amount of possible configurations explodes with each switch we introduce, we are going to only allow one setting with Ogre 1.11 to keep things maintainable.

So rather think about the switches in terms of feature previews and not so much as options.

With Ogre 1.11 we will choose the following configuration: