scene nodes for each submesh?

Problems building or running the engine, queries about how to use features etc.
Post Reply
wizumwalt
Gnoblar
Posts: 3
Joined: Sat Apr 27, 2019 11:06 pm

scene nodes for each submesh?

Post by wizumwalt » Wed Jun 05, 2019 12:55 am

I am building several manual mesh objects in 2.1.

Code: Select all

Ogre::MeshPtr Mesher::buildManualMesh()
{
	// create a mesh
	Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual(...);

	// create a submesh
	Ogre::SubMesh *smesh = mesh->createSubMesh();

	// ...

	return mesh;
}
My question is if I'm doing this correctly. In the loop below, I create a new item from the meshptr and attach it to a scene node. Therefore, I only ever have one submesh per sceneNode. Something bothers me about that, and I'm not sure what the implications are.

Code: Select all

        for (...)
	{        
            Ogre::MeshPtr mesh = buildManualMesh();
            
            Ogre::Item *newItem = sceneManager->createItem(mesh, Ogre::SCENE_DYNAMIC);             
            
            Ogre::SceneNode *node = sceneManager->getRootSceneNode(Ogre::SCENE_DYNAMIC)->createChildSceneNode(Ogre::SCENE_DYNAMIC);

            node->attachObject(newItem);
            node->setPosition(Ogre::Vector3(0.0f, 0.0f, 0.0f));

            meshes.push_back(mesh);
        }   
Is this normal, or should each subMesh belong to the same sceneNode. Say, for example, submesh A is a wall, and submesh B is a window, they're all part of the same object. Is there anything wrong here?
0 x

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

Re: scene nodes for each submesh?

Post by dark_sylinc » Wed Jun 05, 2019 4:40 am

"It depends". It's all a balancing act.

Ogre was designed around the idea that you have a Mesh, and that Mesh may be instantiated many times. A mesh could be a house, and the same house repeated multiple times but with different position, rotation, size and/or materials is an Item.

If for some particular reason each Item must have unique geometry, then you would end up with one Mesh per Item.
If two meshes are identical, then you shouldn't create two meshes. You should use two Items sharing the same mesh.

A mesh/item can have multiple submeshes/subitems.
The main reason to split a single mesh into multiple submeshes is because they have different materials.
Other reasons could be because the submeshes need a different vertex format (not recommended), or because certain vertices have a lot more morph targets or bones per vertex than the rest, thus for performance reasons those vertices are split apart (e.g. avoid 100 vertices that need 4 bones per vertex to penalize an entire mesh of 1 million vertices that only need 1 bone per vertex).

If two submeshes use the same materials, same vertex format, etc; then they should merge together so that the mesh contains only submesh.

Now... should you make a wall and a window into 2 Meshes? Or should you make them 2 submeshes that belong to the same mesh?

2 submeshes of the same mesh:
Pros:
  1. There's only one scene node, thus less CPU work and less memory consumption
  2. Frustum culling is performed at Mesh/Item level. This is faster for the CPU
Cons:
  1. Windows often require transparency. Sometimes you want to fine tune render order via Item::setRenderQueueGroup, which happens at Item level, not SubItem. You still have SubItem::setSubRenderQueueGroup, but it's less flexible (you only have a few bits, and it only lets you control render order between objects that belong to the same render queue group)
  2. Frustum culling has coarser granularity. This is fine for a wall and a window, but for two different walls, we frustum cull against the AABB that encloses both walls. This can make the AABB get bigger quickly. This is bad for the GPU
2 separate meshes is almost a mirror of the previous one:
Pros:
  1. There's two scene nodes, so you can move the window anywhere (probably this isn't much use for a window, but it may be use in other cases such as when you have 2 walls).
  2. You can control the render order of the window in a flexible way, which is important for transparent objects
  3. Frustum culling granularity is finer, this is good for the GPU.
Cons:
  1. You now have two Items being culled against frustum culling separately. This is slower for the CPU.
  2. There's two scene nodes, thus more CPU work and more memory consumption. Technically you can make two Items share the same SceneNode though (but you lose the pro #1). Frustum culling still happens per Mesh/Item even if they share the same SceneNode.
I started saying this a balancing act, but I haven't yet explained why: Multiple separate meshes gives you finer frustum culling and more scene nodes. This takes more CPU work, but alleviates the GPU (since the job of frustum culling is to prevent useless work from objects that are off camera from being sent to the GPU).
On the other hand, making a single mesh composed of multiple submeshes gives you worse frustum culling and fewer scene nodes. This alleviates the CPU, but gives more work to the GPU.

The optimal point is when adding more work to the CPU to take it off from the GPU no longer increases your framerate, and adding more work to the GPU to take it off from the CPU also no longer increases your framerate (note that this depends on whether you have a high GPU paired with a low end CPU, or vice versa).

Note that GPUs don't benefit from rendering submeshes with very low vertex count. So if you have 4 submeshes or meshes that have e.g. 20 vertices each; try to merge them together to make a single 80-vertex submesh (unless you're forced to split them due to having different materials).

You may also be limited by other concerns (such as higher memory consumption from having many scene nodes, or if you absolutely need setRenderQueueGroup to control render order)

Try to keep Item count below 50k. Ideally up to 10k. Don't try to frustum cull too aggressive. For example if you're doing interior rendering, I'd probably put all 4 walls in the same mesh (if possible) so that wall frustum cull happens at per-room granularity. Trying to frustum cull each wall individually can add very quickly (specially if you have a lot of walls and you're rendering multiple houses).
I'm assuming these walls have a low geometry count (e.g. 4 to 60 vertices per wall). If your walls have a crazy high vertex count (e.g. 40.000 vertices per wall???) then you'd want to frustum cull them individually. Like I said, a balancing act.

Cheers
Matias
1 x

Post Reply