PCZSceneManager in Ogre-Next

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


Hotshot5000
OGRE Contributor
OGRE Contributor
Posts: 233
Joined: Thu Oct 14, 2010 12:30 pm
x 58

PCZSceneManager in Ogre-Next

Post by Hotshot5000 »

I was looking around for a portal system for rendering to separate parts of the scene that need not to be rendered and I remembered that back in Ogre 1.7 days there was this PCZSceneManager that did exactly that. Searching for it in Ogre-Next yielded no results.

  1. Is there a particular reason why it was removed?
  2. Does it not fit with the current Ogre 2.x rendering technology?
  3. If PCZSceneManager shouldn't be used then what would a better solution be for only rendering parts of the scene instead of just relying on frustum culling?
User avatar
Zonder
Ogre Magi
Posts: 1172
Joined: Mon Aug 04, 2008 7:51 pm
Location: Manchester - England
x 76

Re: PCZSceneManager in Ogre-Next

Post by Zonder »

I suspect this is just one of them no one has needed it, so no one has contributed it.

There are 10 types of people in the world: Those who understand binary, and those who don't...
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5429
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1337

Re: PCZSceneManager in Ogre-Next

Post by dark_sylinc »

As Zonder said, even in 1.x the PCZ SceneManager received little love as it is a niche tech.

When Ogre 1.x transitioned to Ogre 2.0 (which has now become OgreNext) a the SceneManager was revamped in its internal workings, including Nodes and MovableObjects. This allowed better cache friendliness and multithreading. "Changes: Objects, Scene & Nodes" and "Technical Overview" cover the overview of these changes.

As a result, all the other SceneManagers stopped working. Since there has been no interest in other SceneManagers aside from the default one, the current default SceneManager is the only one working.

Hotshot5000
OGRE Contributor
OGRE Contributor
Posts: 233
Joined: Thu Oct 14, 2010 12:30 pm
x 58

Re: PCZSceneManager in Ogre-Next

Post by Hotshot5000 »

I managed to get PCZSceneManager to work with Ogre 2.1 (why 2.1? Because that is the version that is used by the game I'm working on).

For testing I instantiated around 100 objects and I discovered that the fps tanked to one digit (around 4-5 fps) as over 90% of the CPU time was spent in Camera::isVisible(Aabb box). Frustum::updateFrustumPlanes(void) is hilariously bad because of the mParentNode->_getDerivedOrientationUpdated() call.

But anyway, I don't really care about the was PCZSceneManager was doing things in 2007, so I was thinking of a more modern approach.

Right now there is a NodeArrayManager that takes care of the SoA data for ObjectData/Transforms and goes fast through them using SIMD in MovableObject::cullFrustum() to check for visibility.

PCZSceneManager assumes there are zones that are connected through portals and each zone knows about the Nodes that are currently in that zone. I am thinking that it might make more sense that instead of using vectors to add/remove nodes as they move around It might be faster to have each zone have its own NodeArrayManager. And when nodes move between zones they get removed from the current zone's node manager and added to the next one's node manager.

Would exploring this solution make any sense? Or is portal rendering itself considered obsolete?

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…

Hotshot5000
OGRE Contributor
OGRE Contributor
Posts: 233
Joined: Thu Oct 14, 2010 12:30 pm
x 58

Re: PCZSceneManager in Ogre-Next

Post by Hotshot5000 »

When a MovableObject's ObjectMemoryManager gets changed( setStatic() for example ) I see that the parent node also gets its NodeMemoryManager changed to static. And also all of the node's attachements get moved to static ObjectMemoryManager.

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().
Turns out I was wrong as NodeMemoryManagers don't control the mEntitiesMemoryManagerCulledList where the actual object culling takes place.

So I also created ObjectMemoryManagers for each zone. I ended up with not rendering things that should be rendered and things that shouldn't be rendered ended up being visible.

What is the relationship between NodeMemoryManagers and ObjectMemoryManagers? Do they need to be completely in sync (as setStatic() shows)?
I've tried to keep one NodeMemoryManager while MovableObjects get moved from one ObjectMemoryManager to another. This also seems to not work. Probably I'm doing something wrong as I'm not calling all notify*() methods.

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5429
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1337

Re: PCZSceneManager in Ogre-Next

Post by dark_sylinc »

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:

  1. 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
  2. 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).

Hotshot5000
OGRE Contributor
OGRE Contributor
Posts: 233
Joined: Thu Oct 14, 2010 12:30 pm
x 58

Re: PCZSceneManager in Ogre-Next

Post by Hotshot5000 »

Thank you very much for your response. The game that I am working on is a space shooter where just normal frustum culling works. The idea was to include like a "planet" where you would enter from one place and exit through another. And inside this "level" you would avoid rendering unnecessary parts of the level, or of the outside world. But the inside level is not supposed to contain 10ks of objects, neither is the outside.

So your Culling the battlefield link means that I don't really have to worry about minimizing the number of rendered things... The target is a iPhone 13 and newer so probably performance is good enough. I am talking about mines of about a few hundreds objects in each few rooms (think something of the game Descent from Parallax Software but in a more modern tech setting).

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5429
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1337

Re: PCZSceneManager in Ogre-Next

Post by dark_sylinc »

Hotshot5000 wrote: Sun Jul 07, 2024 9:57 pm

means that I don't really have to worry about minimizing the number of rendered things

Pretty much.

Of course less is always better; but it's important that to get to that lower value you don't spend more cycles than what you save.

Hotshot5000 wrote: Sun Jul 07, 2024 9:57 pm

The target is a iPhone 13 and newer so probably performance is good enough. I am talking about mines of about a few hundreds objects in each few rooms (think something of the game Descent from Parallax Software but in a more modern tech setting).

A few things:

  1. The iPhone 13 is a beast of a phone. It is in "compare it with laptops" category. It is just that powerful. With the caveat that you need to watch out for thermals & battery (whereas laptops have a bit more headroom).
  2. iOS is a TBDR architecture which means that you don't have to worry too much about overdraw (unless you use alpha testing or alpha blending; if you do, put them in a high render queue so that they happen last).
  3. TBDR architectures are weaker at dealing with high vertex count levels (though the iPhone 13 is, again, a beast). If this happens to be a problem, a simple distance-based LOD tends to work great (which OgreNext supports).
  4. If you do happen to target low end Android (e.g. the extremely-weak but extremely-popular-right-now PowerVR 8320), then you'll have to lower graphics to minimum (low resolution, bias LOD to reduce vertex count). For reference the PVR 8320 has a measly 0.04TFLOPs, whereas the iPhone 13 gets 1.37 TLFOPs. That's a 35x difference just in raw numbers (actual difference is even higher due to driver optimizations, bandwidth & cache differences).
Hotshot5000 wrote: Sun Jul 07, 2024 9:57 pm

And inside this "level" you would avoid rendering unnecessary parts of the level, or of the outside world. But the inside level is not supposed to contain 10ks of objects, neither is the outside.

Put inside objects in a lower render queue ID. If you're inside, the walls will quickly fill the Z buffer and thus outside objects (e.g. terrain) will be rejected.

If you're outside, the objects will be rendered first and chunks of the terrain will still be rejected.

The only case where the terrain would make to be rendered first is if everything is behind a hill or mountain, which tends to be rarer on average than the opposite. Furthermore if they are so far away that they're behind a mountain, use MovableObject::setRenderingDistance to make OgreNext disappear objects that are far away.

If you happen to easily & cheaply know that a whole category of objects can be toggled off, you can leverage visibility masks to easily toggle them off. They will still burn CPU cycles for iterating through them, but they won't be sent to the GPU.

Just follow hints like these that don't cost much of your time, apply common sense; and go optimize hard if profiling reveals it to be a big bottleneck.

Hotshot5000
OGRE Contributor
OGRE Contributor
Posts: 233
Joined: Thu Oct 14, 2010 12:30 pm
x 58

Re: PCZSceneManager in Ogre-Next

Post by Hotshot5000 »

dark_sylinc wrote: Mon Jul 08, 2024 3:28 am
  1. The iPhone 13 is a beast of a phone. It is in "compare it with laptops" category. It is just that powerful. With the caveat that you need to watch out for thermals & battery (whereas laptops have a bit more headroom).

I am playing with an iPhone 15 pro max running hw accelerated ray tracing. It warms up quickly and destroys the battery but for a few minutes it's absolutely incredible to see RT on a phone at pretty great fps. There is a sample demo in the AppStore Pong-RT I think was the name. It even runs on older phones without HW RT decently.