Editor's Note

It's been a good while since we published the first part, and the delay in bringing you the second part is all Beyond3D's. We've had Roderic's series in mostly complete form for ages, and we've just not had the time to work with him to get it into shape. Apologies to Roderic especially for that, as he hunted recently for his new job. Good luck at Funcom!

In this part of the article series, Roderic talks about scene management and its specific implementation in his engine technology. What he describes is an elegant optimised implementation of understood techniques, pulling together ideas and application using accessible design patterns, to make them easy to consume in code. Enjoy part 2.

Scene Management

Scene management is central to a 3D engine, as it's a feature of the engine that the user will have to deal with daily. A usual way to handle scene management is through what's called (and often inaccurately) a scene graph: a hierarchical (The torch is in the hand of the hero), spatial (An orc is near the hero), and stateful (The flame of the torch is alpha blended) structure.

The issue with that structure is that it tries to be a jack of all trades, and becomes a master of none. There have been a lot of discussions on the Internet about that problem, and the general consensus seems to be that über scenegraphs should be discarded (¹). Some modern games also have no scene graph at all, nor any hierarchical structure to represent the scene. Although this might work well for a single given title, if an engine is to be used on many titles and provide functionality to ease the work of its user, having a hierarchical tree is something you would want nonetheless, if only because of the transformations (location and orientation) of the objects.

Take the torch in the hand of the Hero example above; when the hand moves, so must the torch, and if it's a child node of the hand node in the hierarchical tree, it'll happen automatically. The problem with the omnipotent (or über) scene graph is that by trying to solve all problems at once, it's usually not good at solving any of those sub problems well. Two nearby objects may be in different branchs of the scene graph because they are parts of two unrelated hierarchies. Also consider two objects having the same rendering properties...

As an example, imagine the following scene. Two warriors are fighting each other with magic swords, both using particle effects to show they are magic. Obviously the two swords will be hitting each other, so very close from one another (close spatial relationship), but each being in the hand of a different character, they'll belong to two different hierarchies (foreign hierarchical relationship) and the particles used to show off the magic essence of the sword are identical (identical rendering properties), yet duplicated.

Where a single structure can't solve all the problems at once efficiently, it can solve a single problem, which naturally leads to wanting specialised structures for each kind of relationship, just like a recent article on the subject (²) suggests. Using that article naming scheme, the engine's structures will be views, and data will be objects. That result in an engine having the following views:

  • A scene tree, which is the hierarchical view of the world (for handling hierarchical animation).
  • A spatial graph, which is the spatial view of the world (for grouping nearby objects together, for culling).
  • A render graph, which is the state optimal view of the world (for grouping objects by states, such as shaders, materials, etc).

Seen from the engine writer's perspective, this all sounds good. You have different structures for different tasks, each specialised for optimal performance, but from the user's point of view, it seems rather cumbersome to have to manage three structures all at once.

Fortunately, it's not a burden to the user, as it's hidden, and although the user will be warned about the internals of the engine, he'll have a single interface and tree to manage; the SceneTree. Objects will be automatically inserted into the SpatialGraph and the RenderGraph, when they are created. Reusing the example above example, the swords will be in the same spatial node (SpatialGraph), and since they are touching each other, they will be in their correct hierarchy for animation (SceneTree), and they will have particle systems sharing the same effect (RenderGraph).