I have a quick question about flattening: I’ve read a lot about it and about what it does, but I haven’t found the answer to this. Performance-wise only, when is it ok do flatten several nodes together, and when is it not ?
More specifically, this is what I want to know: I have 4 different nodepathes: A, B, C and D. A and B were loaded from the same egg file. If I flatten A with C, and B with D, did I just increase the number of meshes to render ?
Or are the only things to take in account are that the nodepath won’t be able to be moved and rendered separately ? (thus forcing us to only flatten objects that either don’t move or only move together, and to make sure not to group objects that are too far away from each other).
Flattening will never increase the number of meshes. It may only reduce it.
You do need to take into account culling considerations. If you have two groups of trees on opposite sides of the map, then flattening them all together is a bad idea, because the bounding volume for them will stretch the entire map! Looking at one group of trees would cause Panda to render the other as well, then. In this case, flattening the groups of trees individually is a good idea.
Indeed, you cannot independently move nodes that have been flattened together (In general, you should expect to only be able to manipulate the root of the flattened tree, ie. the node you called flattenStrong() on, after the flatten operation.) If you want to retain the ability to manipulate an individual sub-node, you should insert a ModelNode in the scene graph in that location, you can use it to specify special flattening considerations for that arc of the scene graph.
Note that all loaded models initially have a ModelNode at their roots, that prevents them from being flattened with other models. You need to call clearModelNodes() to get rid of this and allow different models to be flattened together.
Alright, that’s good news !
So, if I want to minimize the amount of mesh while keeping fairly low bounding volumes, I can:
- Find nodepathes using the same texture and render attributes
- Check if merging the combined space wouldn’t create an object bigger than a given threshold
- For node path that matches this, reparent them all to a single node path, call clearModelNodes on each of those, then flattenStrong on the root.
If nothing goes wrong during that process, only a single node should remain. Which I can then set as the PandaNode behind all the NodePathes of the nodes that have been destroyed in the process, so that further state changes get applied on the root rather than empty NodePathes.
Thank you for the answer, very helpful !
Panda3D already takes care of (1). If you call flattenStrong() on a bunch of nodes, it will only merge nodes that share the same texture and material.
As for (2): in general, the more things are grouped together, the better, as long as you don’t group objects together that aren’t going to be in view at the same time.
This is most effective when the models share textures and materials, such as a range of trees in a forest or buildings in a village, so you should probably focus on that when grouping.
So the strategy should probably be: find groups of similar geometry that remain static with respect to each other, and flatten them together. If your scene is already in octree or quadtree format, this is fairly easy; flatten all the leaf nodes at the n’th level, where n represents a trade-off between culling and drawing performance.
It should be noted that it is not always the case that a single node remains. As stated earlier, Panda can’t flatten together nodes with different textures, or materials, or render attributes in general. (A workaround is to use bigger textures and UV map different model parts to different segments of the same texture.) In the worst case, which is if every piece of geometry has a different material, the number of geoms remains completely untouched, which should be noted also happens if the model structure is already as compact as can be.