For most of our code we want to do a 1:1 port and thus not much explanation is required. However there are two systems that will highly benefit from a redesign:
- With the OSG stateset system, properties can now be applied to the node hierarchy, instead of having to collect parent properties for each renderable.
- Setting visibility flags (node mask) and render queue group (render bin) can be done on the node hierarchy instead of on the renderables only. This means we no longer need the "mEntities" "mParticleSystems" vectors in ObjectScene. Same applies to the environment map effect for enchanted objects, we can do that on the hierarchy too.
- Skinned body parts should be attached directly to the character skeleton instead of a manually updated child skeleton (performance improvement).
- No static geometry batching. The inherent problems (lighting issues, enable/disable issues, and increased loading time) will be gone with it. The new renderer has a much lower batch cost, so we will not need any form of batching, at least not for the 1.0 release.
- Get rid of mesh names and skeleton names (loading time improvement).
- Node filtering should be done while traversing the hierarchy, i.e. not create filtered meshes at all, instead of just hiding the created meshes (loading time improvement).
- Node transform should not be baked into the meshes. This will allow for more accurate transparency-sorting so we can finally enable alpha blending again.
- Creating multiple instances of the same NIF file should be overhauled. Currently we have to parse the file again for every instance that is created. I expect this change to greatly reduce loading time.
The idea is to use the OSG defined copy constructor for a scene graph, which allows detailed control over deep vs. shallow copy for each component. A shallow copy should be used, except for anything that has a controller attached to it.
As a bonus, we do not need to implement resource sharing (for geometry, etc), because the shallow copy behaviour takes care of that automatically.
- Controllers should be part of the scene graph (as UpdateCallbacks), thus updated automatically, and alleviating copy-constructor problems with the various target pointers we used to have in the controller classes. Storing these pointers is not needed anymore, because the NodeVisitor will give them to us.
The main bonus is that we can finally have anonymous (unnamed) resources, e.g. for the savegame screenshot, loading screen FBO, character preview textures, font textures, video textures, local map and world map textures. Anonymous resources would bypass the resource manager entirely, so we don't have to worry about name collisions.
All data directories and BSAs should be merged into a single file tree for improved performance. Currently we are using a separate Archive for each and have to search them in order, which is slow.
The resource manager should track when a resource was last used so it can be clever when deciding which resources to unload.
In fact some of the Ogre resource managers we have currently implemented (skeleton manager, collision shape manager) don't have unloading implemented at all, so porting them to the new manager we would benefit from lower memory usage automatically.
So far about the design goals, here is the roadmap.
1. Standalone components
- [done] Port ConstrainedFileDataStream to use an std::istream so that OSG's image loaders can interface with it
- [done] Port BSAFile
- [done] Port NIF reader
- [done] Port ESM reader
- [done] Create the new NIF loader
- [done] Geometry
- [done] StateSets
- [done] Controllers
- [done] Skinning (RigGeometry)
- [done] Vertex morphing (MorphGeometry)
- [done] Particles
- [done] Billboard nodes
- [done] Scene utilities
- [done] Load filtered parts onto an existing skeleton
- [done] Investigate StateSet caching
- [in progress] Create the new resource system
- [done] Virtual file system
- [done] Scene object (NIF) template manager
- [in progress] Texture manager
- [in progress] Collision shape manager
- [done - thanks to Chris for help] MyGUI backend
- [done - thanks to Chris for help] SDL2 GraphicsWindow
- [done] Video player
- [done] stub Ogre-related code so we can gradually port it over
- [done] sky renderer
- [done] terrain renderer (just the basic 3x3 grid for now, distant terrain should be added later)
- [done] lighting (directional lights can be created as an osg::Light, for point lights we need to collect the closest lights for a particular sub-graph)
- [done] Animation, character controller
- [done] Camera, player controls
- [done] GUI
- [done] Inventory preview
- [done] Physics
- [done] Local map, fog of war, world map
- [done] Basic water and ripple particles
3. Further porting
- [not started] shader pipeline
- Note OSG supports "shader composition", so we should not need an extra library like Shiny again: http://forum.openscenegraph.org/viewtopic.php?t=14680
- [not started] shadows
- [not started] water reflections
- unrelated to OSG, but I also want to try replicating the original MW water shader, i.e. cubemapping, a normal map for rain drops, and re-add the ripple normal map effect, which will look much better with a cubemap.
- [done] OpenCS
- [done] Launcher
4. Bonus improvements
- NPC width
Thanks to the new skeleton system we can now properly scale NPCs on their X and Y axes for the authentic Morrowind look. I already tried this with the NIF loader test app and it's working.
- Try out hardware skinning and hardware vertex morphing
To begin with we will be using software skinning/morphing like the Ogre branch did. Getting hardware skinning to work would be a bonus performance improvement. I never got this to work with Ogre, because it hit the limit on the number of bones it was able to pass to the shader at a time. AFAIK the problem was that even bones not used for skinning contributed towards the limit. osgAnimation does not appear to have this problem, so we should give HW skinning a try.
- Render the loading screen in a separate thread
OpenMW has both the loading screen and the actual loading procedure happening in the same thread. This is of course problematic because the rendering blocks the loading procedure. Doing the loading and loading screen rendering from independent threads should reduce loading times, and also allow us to increase the loading screen "fps", i.e. have it look smoother, with no performance penalty.
I *think* that is already done, or rather, not an issue in the first place. With the default threading mode, osgViewer uses a separate graphics thread for OpenGL calls, which goes on drawing (and swapping) while the main thread is already running the next frame's update (or in the case of the loading screen, loading stuff).
- Background cell loading
The new NIF loader should make it much easier to implement background loading of cells. Creating an OSG scene graph seems to be inherently thread-safe, so long as that scene graph is not connected to the root node yet. The OpenGL objects (textures, geometry) for the disconnected scene graph can be uploaded gradually over several frames using osg's IncrementalCompileOperation.
OSG seems to have built-in raycasting support, so we would be able to get rid of the Bullet raycasting shapes. If I understand correctly, raycasting against a skinned mesh also works, so we could get rid of the selection buffer used for the inventory preview and use raycasting instead. Should be much faster, because we do not have to copy the selection buffer from the GPU to the CPU.
- Camera relative rendering
Experiment with camera-relative rendering to fix the large world precision issues.
- Get rid of boost
With Ogre gone we will no longer need the boost libraries. We are still using filesystem and shared_ptr in a lot of places though. Switching to C++11 would be a migration path.