What is the relationship between NodeMemoryManagers and ObjectMemoryManagers?
They're pretty much siblings. The thing is that multiple Objects may be attached to the same SceneNode. If we had the relationship that 1 SceneNode = 1 MovableObject then we would be able to merge SceneNode and MovableObject classes, as well as merge NodeMemoryManager and ObjectMemoryManager into one. But we don't.
If I were to do this again; I'd have 1 SceneNode = 1 MovableObject (the most common case) with no ability to do parent/child relationships; and only reserve parent/child node with relationships as the exception with an extra performance cost (since they're pretty rare in practice).
Now, NodeMemoryManagers tell OgreNext how to update transforms (i.e. position + rotation + scale) and propagate derived transforms from parent to children nodes. And that's pretty much it.
However ObjectMemoryManagers tell OgreNext:
- What MovableObjects need their AABB updated (i.e. local_aabb * transform). The transform was already updated in the NodeMemoryManagers its node lives in.
- What MovableObjects should go into frustum culling.
So basically:
- If you forgot to include a NodeMemoryManagers but included ObjectMemoryManagers; the transform won't be properly updated; which means the AABB will be in the wrong place when considering frustum culling
- If you forgot to include ObjectMemoryManagers, the objects in it won't be rendered.
Initially, when implementing the portal system, I thought each zone should have its own NodeMemoryManager and only the visible zones (NodeMemoryManagers) would get sent to mNodeMemoryManagerUpdateList in SceneManager::highLevelCull().
It sounds about correct that each zone should have both its own NodeMemoryManager & ObjectMemoryManagers. But you need to send both in highLevelCull (highLevelCull is virtual on purpose, so that you can control which ones get sent).
You could also have one NodeMemoryManager for the whole thing, and have one ObjectMemoryManagers per zone.
What are the way current renderers deal with the visibility issue? I assume UE5, CryEngine etc. don't only use frustum culling to limit the number of renderer objects. I read somewhere that Source 2 from Valve uses some sort of Octree to deal with visibility but I don't remember finding a lot of details…
Ever since Culling the Battlefield got released; most tree-based solutions got thrown out the window.
Turns out a big cache friendly array is much faster than "smart" tree solutions from the 90's and a few early 2000's. Brute force won. Specially in the era of SIMD and 16-core multithreading.
Also shadow maps make things even more complicated because you have multiple cameras to worry about (which makes portals quite inconvenient because you end up including a lot more portals than you'd hope for).
For rendering, "high level" solutions still make sense at very huge scales (e.g. somewhere between 1000 to 10.000 objects per node). Having 5 objects per node is way too much overhead.
At least that's for outdoor rendering. For indoor rendering; again brute force wins most of the time; but in some cases with lots of small MovableObjects behind furniture and walls, engines have resorted to depth-based culling (aka occlusion culling) either by using a low resolution SW rasterizer (another project) or by using a reprojected depth buffer (slides) from the previous frame (CryTek does this for its Crysis titles, however reprojected depth buffers are imprecise and can lead to false positive/negatives for a single frame if moving too much).