Hi
Every topic when talking about optimalisation, ppl recommends to batch those nodes what not moving, etc.
Now i wanted to try it out to see how it increases the performance, but couldnt find how to do it.
this is what i tried:
IAnimatedMesh* mesh = ((IAnimatedMeshSceneNode*)newObj->getNode())->getMesh();
if (!batchObj)
{
batchObj = device->getSceneManager()->addMeshSceneNode(mesh);
}
else
{
for (u32 n = 0; n < mesh->getMeshBufferCount(); n++)
{
batchObj->getMesh()->getMeshBuffer(0)->append(mesh->getMeshBuffer(n));
}
}
I guess its doing its job right, but the problem it isnt saving the positions (of course coz meshes dont have positions )
So, how could i batch them, and keep my node positions, rotations, scales?
It's often best to batch things that won't move in relation to each other, which removes your problems. Don't make the mistake of "over-optimizing", such as trying to batch things that don't need to be. Batching is best used when you're drawing lots of small items or identical ones. If you need to batch items together and still maintain their positions, rotations, scales, etc., you could use shader batching.
no, i just want to set the startup positions.
i have a map editor, where u can place a lot of static objects.
and in game, i want to batch them together, coz they wont move a bit
and actually i had a problem with lot of nodes. like trees, there was a huge performance lost, but wasnt so high poly..
The coordinates of each mesh vertex are local coordinates. That means that their values only make sense in relation to each other within the mesh. You want to transform the coordinates of each mesh's vertices to their world coordinates before added them to your big batched mesh.
Each scene node automatically builds a transform matrix for you (AbsoluteTransformation). If you look at the third tutorial, you'll notice that scene nodes set the world transform to it right before rendering. This is because it transforms the local coordinates of the mesh into the correct world space.
Assuming your meshes are in scene nodes, just take the vertices of the mesh in each scene node and multiply them by the AbsoluteTransformation matrix of that scene node. If you want to save time by not putting your meshes into scene nodes, batching the meshes, then deleting the individual scene nodes, you can use empty scene nodes instead and just delete those when you're done.
if (!batchObj)
{
batchObj = device->getSceneManager()->addMeshSceneNode(mesh);
}
else
{
IAnimatedMesh* c = device->getSceneManager()->getMeshManipulator()->createAnimatedMesh(mesh);
device->getSceneManager()->getMeshManipulator()->transform(c, newObj->getNode()->getAbsoluteTransformation());
for (u32 n = 0; n < c->getMeshBufferCount(); n++)
{
batchObj->getMesh()->getMeshBuffer(0)->append(c->getMeshBuffer(n));
}
c->drop();
}
i found a transform operation in the mesh manipulator, so i thought ill try it out.
but its not working (the mesh is in the same position)
and i think its not only not transformating, but only showing the first mesh what got into it
You can use IrrExtensions, it has a batchmesh built-in. However, in reality a batchedMesh is not faster at all as soon as Hardware Buffers are involved. I did a lot of testing some time ago and here are my results for both code snippets rendering the exact same scene:
driver->setMinHardwareBufferVertexCount(0); // always use Hardware Buffers
IBatchMesh* batchtest = smgr->createBatchMesh();
IMesh* hill = smgr->getMesh("hill100c.obj");
for (u32 i = 0; i < 100; i++)
{
for (u32 j = 0; j < 100; j++)
{
batchtest->addMesh(hill, vector3df(i, 0, j));
}
}
batchtest->finalize();
IMeshSceneNode* MergedNode = smgr->addMeshSceneNode(batchtest);
MergedNode->setMaterialFlag(EMF_LIGHTING, false);
batchtest->drop();
for (u32 i = 0; i < MergedNode->getMesh()->getMeshBufferCount(); i++)
{
MergedNode->getMesh()->getMeshBuffer(i)->setHardwareMappingHint(EHM_STATIC); // set to static if the mesh never changes
}
If your meshes are large enough, then hardware buffers will often help enough. However, for very small meshes, batching will help muh better. However, the batch mesh needs to put all the things into one meshbuffer (not just many buffers into one mesh). Don't know if the referenced batchmesh node does this.
I'd guess then, like Hybrid hinted, that the batchMesh doesn't actually combine the mesh buffers themselves, but just the meshes.
Hardware mapping only works well with large numbers of geometry per mesh buffer. In fact, the engine is set to ignore requests to use hardware buffers when a mesh buffer has too few vertices (< 300 IIRC). Your best bet is still to combine the trees into as few mesh buffers as possible.
I utilise the Batching Mesh in my IrrlichtWrapper you can use that as a simple example. When dealing with static objects the CBatchingMesh module can offer really massive frame rate improvements as it gets rid of all of the overhead associated with managing a node and setting up a node for rendering.
There are three simple steps to it: -
1) Create your batching mesh
2) Add your static meshes to your batching mesh
3) Finalize your batching mesh
Essentially you just do the following with it (you should use static meshes for this instead of IAnimatedMesh that is a feature of my code where I hide the concept of static meshes):
well thats just what i did, and it made worse D:
It dropped down from 20 fps to 10 xD
but yeah i didn't use static mesh, i used IAnimatedMesh (coz i dont know how to load static only from b3d...). was that the problem?