Question about internal handling of scene nodes

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
Tassilo
Halfling
Posts: 75
Joined: Thu Apr 28, 2005 9:21 am

Question about internal handling of scene nodes

Post by Tassilo »

Hello,

I have a scene with a fairly complex scene graph consisting of up to several thousand nodes. At the time of writing, I have a test scene of about 11.000 nodes. Of course, only a small fraction of them are shown (~100).

I noticed, however, that nodes that are not shown slow down Ogre noticeably. If I create only the 100 nodes that will get shown, Ogre runs 4 times faster than with 11.000 nodes, where 10.900 are set to "not visible".
I get the same behaviour even if the nodes that are not shown are not even attached to the root.

So, my question is: "What's going on internally with the scene nodes" ? Are they traversed ? Or are they sorted even if they are not shown at all ?

(I noticed, too, that if I zoom into the scene, the engine speeds up a lot - my scene is set up in a way, that, initially, I'm far away from the objects rendered. It would be possible to see all of them if they would be shown. Now, if I zoom into the scene, the view frustum culling, etc... would discard some of the nodes. This of course would speed up the rendering. BUT, the objects are not shown at all, but zooming into the scene has the same effect - perhaps they are tested against the frustum every frame ? Just a thing I noticed, though....

My observations are backed up with PIX - PIX shows me that every frame has exactly the same amount of state switches, of DIP calls, of locks, etc..., but nevertheless, zooming into the empty scene influences the framerate, etc...)


Thank you very much for shedding some light on this. Hope you can make yourself a picture of the scene I'm describing.

PS: I'm not interested in workarounds. I already have a workaround, but this question keeps me wondering...why.....

User avatar
Borundin
Platinum Sponsor
Platinum Sponsor
Posts: 243
Joined: Fri Oct 03, 2003 5:57 am
Location: Sweden
x 2
Contact:

Post by Borundin »

Unfortunately I cant answer whats going on "inside". Hopefully I can be of some help anyway. Im just throwing out an idea here, anyone please correct me if Im wrong :)

You dont say exactly how you are organizing your nodes. If you just attach every 10000 nodes to the same parent node my guess is that Ogre will have to "process" each and every one of them each frame even just to see that they are in fact invisible.

[EDIT: Ooops didnt see your PS about no workarounds, will leave the rest here anyway]
Lets say instead that you create 100 nodes (middle nodes) attached to your root parent node and then create 100 nodes to each one of these (=10000 leaf nodes) then you get a tree. If you then set one (or more) of the middle nodes to invisble Ogre might not process the 100 nodes that are attached to it and this will then presumably save alot of time. I have no idea if this is actually what will happen though :roll:

Another approach that is based on the above and that Im pretty certain will work is to detach the middle nodes that dont have any visible leaf nodes. Then just reattach them when any leaf nodes become visible again.

The third solution that I know will work as long as the nodes are static is to use the StaticGeometry class of course, but thats almost like cheating :D
Image : Image

Tassilo
Halfling
Posts: 75
Joined: Thu Apr 28, 2005 9:21 am

Post by Tassilo »

Hi, thanks for the answer, but...
You dont say exactly how you are organizing your nodes. If you just attach every 10000 nodes to the same parent node my guess is that Ogre will have to "process" each and every one of them each frame even just to see that they are in fact invisible.
In fact, I have a deep and balanced tree. There are 2 nodes attached to the root, and several others attached to these two nodes, etc...
I'm hiding the two nodes connected to the root, so that should be no problem.
Another approach that is based on the above and that Im pretty certain will work is to detach the middle nodes that dont have any visible leaf nodes. Then just reattach them when any leaf nodes become visible again.
I already tried that - same behaviour. That really keeps me scratching my head.
The third solution that I know will work as long as the nodes are static is to use the StaticGeometry class of course, but thats almost like cheating.
That's exactly what I'm doing. I only render the static geometry, but I have to keep the other nodes in memory, for some reasons. So, you see, the nodes that are used to build the static geometry are always hidden.
In order to analyze this slowdown, I threw out the static geometry - just to be sure that that's not the problem. So, I end up with a black screen (since all the nodes are hidden) and that behavior.

Thanks anyway
Last edited by Tassilo on Thu Aug 25, 2005 10:08 am, edited 1 time in total.

User avatar
:wumpus:
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3067
Joined: Tue Feb 10, 2004 12:53 pm
Location: The Netherlands
x 1

Re: Question about internal handling of scene nodes

Post by :wumpus: »

Tassilo wrote: So, my question is: "What's going on internally with the scene nodes" ? Are they traversed ? Or are they sorted even if they are not shown at all ?
Not really, scene nodes that aren't shown shouldn't be traversed; hence it should make no difference if you attach all scene nodes to the root or in a 'balanced tree'. Ogre doesn't use the scene graph for spatial culling or queries, that's done by putting the leaf entities in a octree seperate from the node structure.

I don't understand why your program becomes so slow with many nodes.

User avatar
Borundin
Platinum Sponsor
Platinum Sponsor
Posts: 243
Joined: Fri Oct 03, 2003 5:57 am
Location: Sweden
x 2
Contact:

Post by Borundin »

Intresting. I have a vauge memory of a similar problem in a thread some time ago but cant seem to find it now :(
Image : Image

Tassilo
Halfling
Posts: 75
Joined: Thu Apr 28, 2005 9:21 am

Post by Tassilo »

Ogre doesn't use the scene graph for spatial culling or queries, that's done by putting the leaf entities in a octree seperate from the node structure.
Please correct me if I'm wrong....
Does this mean that even if I hide a single node with thousands of child nodes, that ogre has to check all of them in the octree structure, because the two structures are somewhat seperated ?

Anyway - if I get that right.... in order to use the octree you have to traverse the scene graph anyway (in order to get the right world space transformations of the nodes ?) - so the two should be related someway.

Well - I'm still interested in an explanation, but are there any suggestions how to get that right and not only to hack around the problem ? I think the cleanest solution is to write my own scene manager, isn't it (I don't want to modify the Ogre sources themselves - so setting up a scene manager might be the right thing to do) ?

Tassilo
Halfling
Posts: 75
Joined: Thu Apr 28, 2005 9:21 am

Post by Tassilo »

Hello

I'm sorry, I have to make some corrections concerning my initial post.
I get the same behaviour even if the nodes that are not shown are not even attached to the root.
I made a mistake somewhere detaching the nodes - in fact, it works quite well this way. I detached the wrong thing,....

Well, that's a good thing for me, but practically, I see no difference in hiding the nodes instead of detaching it. So the question is - what's ogre doing with the attached, non-visible objects ?

User avatar
:wumpus:
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3067
Joined: Tue Feb 10, 2004 12:53 pm
Location: The Netherlands
x 1

Post by :wumpus: »

Tassilo wrote: Please correct me if I'm wrong....
Does this mean that even if I hide a single node with thousands of child nodes, that ogre has to check all of them in the octree structure, because the two structures are somewhat seperated ?
If objects are hidden they need not be in the 'visible' octree. I'm not sure how it exactly works though. This depends on how smart your scene manager is. If even hidden objects are in the octree then you are right.
Anyway - if I get that right.... in order to use the octree you have to traverse the scene graph anyway (in order to get the right world space transformations of the nodes ?) - so the two should be related someway.
Heh, Ogre is much smarter than that. Nodes have a 'dirty' flag and are only updated if the transform changes.

Anyway I'm happy you solved it.

Tassilo
Halfling
Posts: 75
Joined: Thu Apr 28, 2005 9:21 am

Post by Tassilo »

Hi
If objects are hidden they need not be in the 'visible' octree. I'm not sure how it exactly works though. This depends on how smart your scene manager is. If even hidden objects are in the octree then you are right.
Thanks, I'm using the standard scene manager (using EXTERIOR). Well, perhaps this might be an issue for other projects as well (construction simulators, etc...) but it's possible to roll your own version of the scene manager, though. It should be no problem this way.

Thanks and have a nice day

User avatar
tuan kuranes
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2653
Joined: Wed Sep 24, 2003 8:07 am
Location: Haute Garonne, France
x 4
Contact:

Post by tuan kuranes »

Octree doesn't care much about visibility or node from what I saw in Octree SM code.

Octree culls octree (huge aabox that is known to contains nodes) and work on Nodes.

But "Visibility" flags can only be set at renderable level, and Nodes are not notified of that visibility change.

Perhaps Node should have a visibility Flag and be notified by attached objects and nodes when there's changes (like aabox, pos updates).
That visibility info can even be chained to Octree so that octant containing nodes can be excluded from frustum tests if there's no nodes insides visible.

User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19265
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Post by sinbad »

There's no need for a visibility flag at the node level - just detach the node. This triggers updates to the octree and all is well.

User avatar
:wumpus:
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3067
Joined: Tue Feb 10, 2004 12:53 pm
Location: The Netherlands
x 1

Post by :wumpus: »

Yeah, a visibility flag on nodes would make no sense as the nodes heirarchy is not traversed for determining visibility, culling, and spatial queries (and have only a function for transforms).

Also, the octree keeps MovableObjects not nodes.

Tassilo
Halfling
Posts: 75
Joined: Thu Apr 28, 2005 9:21 am

Post by Tassilo »

Sorry, I do not know Ogre's architecture internally, but isn't that a somewhat problematic behaviour in general ?

I mean - why to check all the nodes in the octree, even if there are nodes that are already hidden ? This prevents users from creating huge outdoor scenes and having a set of nodes they already know for sure that they are hidden (imagine a construction game - somebody constructs a skyscraper - he works on the second floor of 20. floors 3-20 are hidden - and that is something he knows for sure - he doesn't need an octree to verify that - in fact - it won't work with an octree anyway)

Sure, detaching the nodes works, but I don't think its intuitive to have a function setVisible then...

And detaching and reattaching nodes recomputes some bboxes, no ? Of course, this is negligible, but it wouldn't be necessary...

just a suggestion, though - it perfectly works for me the way described, so everything is ok....

User avatar
:wumpus:
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3067
Joined: Tue Feb 10, 2004 12:53 pm
Location: The Netherlands
x 1

Post by :wumpus: »

You could make a scene manager that really removes invisible objects from the spatial heirarchy. This makes setVisibility slower but the rendering a little bit faster. It's all about compromises, we made a different one in our SM.

On the other hand, doing things like sector-to-sector visiblilty culling for buildings can be done much more efficient with other algorithms; there is no need to go fiddling with visibility bits of Entities.

User avatar
tuan kuranes
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2653
Joined: Wed Sep 24, 2003 8:07 am
Location: Haute Garonne, France
x 4
Contact:

Post by tuan kuranes »

I do agree with Tassilo. We're not saying that detaching is not the way, but pointing that it's somewhat counter-intuitive for users particularly when it ends to "Invisibles objects does slow down Ogre."

Perhaps it needs to be documented on "Movable::setVisible()", that for performance reasons, it should rather be detached than be invisible

Or perhaps we should change names here.
"Movable::setVisible()" becomes "Movable::setExcludeFromRender()"

We can even imagine that "Movable::setVisible(false)" calls "Movable::detach()" while keeping a reference to the node from which it detach, and "setVisible" calls attach on the reference keeped ?

It's a problem of user intuition...


:Wumpus: Each Octree has an Octree Nodes list (inherited from scenenodes to have attachedobject BBOX only instead of attachedobjects+childnodes), and that nodes are culled. (in OSM::walkPagingLandScapeOctree), then each movable inside node is culled (in octreenode::_addToRenderQueue ) which doesn't care if they're visible or not. (either by scene visibility flag or mVisible). That's the why of Tassilo SlowDown.

User avatar
:wumpus:
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3067
Joined: Tue Feb 10, 2004 12:53 pm
Location: The Netherlands
x 1

Post by :wumpus: »

tuan kuranes wrote: :Wumpus: Each Octree has an Octree Nodes list (inherited from scenenodes to have attachedobject BBOX only instead of attachedobjects+childnodes), and that nodes are culled. (in OSM::walkPagingLandScapeOctree), then each movable inside node is culled (in octreenode::_addToRenderQueue ) which doesn't care if they're visible or not. (either by scene visibility flag or mVisible). That's the why of Tassilo SlowDown.
Right, I just meant that the Scene Nodes are not used for this, of course the Octree has nodes too but they're somewhat different.

But IMO it should really be a scene manager choice what to do with invisible objects. Our current choice is a valid one, just like detaching hidden movables from the octree is.

That doesn't mean I don't agree that it would sometimes be more useful if invisible objects were removed from the visibility structure (Octree) but still remain attached to the SceneNode structure though.

User avatar
tuan kuranes
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2653
Joined: Wed Sep 24, 2003 8:07 am
Location: Haute Garonne, France
x 4
Contact:

Post by tuan kuranes »

I does agree with the separation renderer != scene manager. (more than that it's the why I love Ogre... and even more Dagon work on that)

It's just a semantic problem the setVisible could be named SetVisibletoRenderer() and add a SetVisibleToSceneManager() method. (that should be used only by scene manager).
SetVisible would then set Both...

User avatar
:wumpus:
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3067
Joined: Tue Feb 10, 2004 12:53 pm
Location: The Netherlands
x 1

Post by :wumpus: »

tuan kuranes wrote: It's just a semantic problem the setVisible could be named SetVisibletoRenderer() and add a SetVisibleToSceneManager() method. (that should be used only by scene manager).
SetVisible would then set Both...
Or maybe add a boolean parameter to setVisible for that, instead of an extra method, because the case "invisible to scene manager, visible to renderer" makes no sense.

User avatar
BlasterN
Gnome
Posts: 378
Joined: Thu Mar 24, 2005 1:07 am
Location: Spain
Contact:

Post by BlasterN »

I only have to say one thing. 11000 nodes are too much memory, about 11000 * 56 bytes (if i dont remember bad i saw this value in the forum) about 600mg (i dont count the movable object attached), so you are runing all the program in Virtual memory and that is slow enought to run down drastically your frame rate.

Run the app in release, that increase fps.

btw: how mush time do you spend to run the app? i really think less than a minute it's quite imposible.
Works:
MapToMesh | Bengine B9 @ www.sourceforge.net/projects/maptoogremesh/
3DWorldStudio exporter@ www.blastern.info

User avatar
tuan kuranes
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2653
Joined: Wed Sep 24, 2003 8:07 am
Location: Haute Garonne, France
x 4
Contact:

Post by tuan kuranes »

:wumpus: agree on bad case. setvisible with 2 paramters can be a solution. As long as it calls internally a "SetVisibleToSceneManager()" that can/should be overloaded by scene managers

BlasterN: there's a scale problem : 11 000 000 nodes would gives 600 megs. (11 000 * 56 bytes => 616 000 bytes => 600 kbytes => 0.5 Mbytes).

User avatar
BlasterN
Gnome
Posts: 378
Joined: Thu Mar 24, 2005 1:07 am
Location: Spain
Contact:

Post by BlasterN »

ups :oops: i forget to divide again.
Works:
MapToMesh | Bengine B9 @ www.sourceforge.net/projects/maptoogremesh/
3DWorldStudio exporter@ www.blastern.info

User avatar
:wumpus:
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3067
Joined: Tue Feb 10, 2004 12:53 pm
Location: The Netherlands
x 1

Post by :wumpus: »

tuan kuranes wrote::wumpus: agree on bad case. setvisible with 2 paramters can be a solution. As long as it calls internally a "SetVisibleToSceneManager()" that can/should be overloaded by scene managers
True, anyway, in the end it's Sinbad that should comment on complicated deeply core stuff like this :)

User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19265
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Post by sinbad »

What you're talking about here is the difference between invisbility through structural change, and invisibility through flags. Neither one is universally faster than the other - it entirely depends on how you use them. Suggestions that MovableObject::setVisible should contain a statement that it's better to detach in all cases is plain wrong.

Detaching a node means that structurally the scene graph changes. Once this change has taken place, the objects / nodes that have been removed have less overhead to the visbility detection pass - so if you do this and leave the objects out of the tree for a long time, it's faster. However, the act of detaching / reattaching nodes is in itself far more expensive than the alternative of setting a visibility flag/mask, since in the latter case structural changes are not made. SceneManagers which build derived structures based on the scene nodes (octree, bsp) may be especially badly affected by frequent changes in node structure. Clearly in many cases it's faster to leave the prebuilt structures alone and just skip over a small number of objects, especially when those objects might re-join a small amount of time later. That's precisely why octree does not make structural changes to the octree for invisbles, only for detaches.

That is why there are alternative ways of achieving invisbility. I am 100% against any change which requires structural modification to the scene graph in all cases, because it's not what everyone needs. Perhaps the manual should be extended to describe the pros/cons in more detail, but the techniques should absolutely not be unified. In some cases it's better to use setVisible (small or frequent changes), in some cases it's best to detach (larger and less frequent changes).

It is also not acceptable to force a recursive scene graph pass every frame, as would be required by a node-level visibility flag that did not alter scene graph structures. Octree and BSP use structures precisely to avoid generic recursion, as do the 'dirty' flags on nodes. The detach / reattach or object visbility flag/mask approach works fine, just in 2 different scenarios - it's up to you to pick which works best for your usage pattern.

I don't really see any benefit from the things suggested in here since they are just alternative ways of expressing what is already available.

User avatar
tuan kuranes
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2653
Joined: Wed Sep 24, 2003 8:07 am
Location: Haute Garonne, France
x 4
Contact:

Post by tuan kuranes »

Thanks a lot for taking time for clarifying situation about the separation between invisbility through structural change, and invisibility through flags.

A documentation changes that have a strong emphasis on the problem seems necessary. (you're second paragraph is just perfect for that.)

Agree with the less structural change is the goal in SM. My first post was plain wrong on that.

I just hope documentation will solve the "semantic" problem, on the user side, when they do not read comments.
Or...
"setVisible" could just change name to "setVisibleTemporary" or something more clear and therefore user would look after comments to find how to detach node for long term invisibility. I know it's an interface break, but it's a may be a needed usability sacrifice...

Tassilo
Halfling
Posts: 75
Joined: Thu Apr 28, 2005 9:21 am

Post by Tassilo »

Sinbad,
What you're talking about here is the difference between invisbility through structural change, and invisibility through flags. Neither one is universally faster than the other - it entirely depends on how you use them. Suggestions that MovableObject::setVisible should contain a statement that it's better to detach in all cases is plain wrong.
you're absolutely right, that a structural change to the octree (or anything like that) is nonsense, but...
Clearly in many cases it's faster to leave the prebuilt structures alone and just skip over a small number of objects, especially when those objects might re-join a small amount of time later. That's precisely why octree does not make structural changes to the octree for invisbles, only for detaches.
... that just isn't the case. If you have lots of objects, there is indeed a problem - if you have a small amount of objects, the overhead for testing if they are visible at all isn't significant anyway.

But, the thing I really don't get here - I never suggested to make structural changes to the octree - IMHO I think it's only very strange to ...
Once this change has taken place, the objects / nodes that have been removed have less overhead to the visbility detection pass
... have invisible nodes in a visibility pass.

I don't want to offend you, but it just seems "intuitive" not to care about invisible objects in a visibility pass.

Post Reply