The idea is that it is faster for the engine to detect if a simple volume, like a box, is on or off the screen, and decide whether to draw it or not on that basis. Since you are already drawing something simple (cubes) maybe you could group your cubes into 10x10 units or something like that?
Wow, I thought I'd already implemented that, but apparently it isn't working. Each one of the Blocks is a SharedMesh, and I set it up like this:
...
Block shareBlock = new Block(("WorldBlock"), new Vector3f(0,0,0), 1.0f, 1.0f, 1.0f);
shareBlock.setModelBound(new BoundingBox());
shareBlock.updateModelBound();
...
worldBlocks[i][j][k] = new SharedMesh(shareBlock);
worldBlocks[i][j][k].setLocalTranslation(new Vector3f(i*2,k*2,j*2));
worldBlocksTextureStates[i][j][k] = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
terrainNode.attachChild(worldBlocks[i][j][k]); //attached to worldRoot
worldBlocksTextureStates[i][j][k].setTexture(orangeTexture);
worldBlocks[i][j][k].setRenderState(worldBlocksTextureStates[i][j][k]);
worldBlocks[i][j][k].updateRenderState();
worldBlocks[i][j][k].setModelBound(new BoundingBox());
worldBlocks[i][j][k].updateModelBound();
...
worldRoot.updateModelBound(); //worldRoot is the root node of the gamestate
CullState cs = DisplaySystem.getDisplaySystem().getRenderer().createCullState();
cs.setCullFace(Face.Back);
worldRoot.setRenderState(cs);
...
worldRoot.updateRenderState();
worldRoot.updateWorldBound();
I'm pretty sure I updateModelBound more often than I need to, but I'm not sure what else to try. After the terrain finishes loading, I have the game output the number of triangles and vertices, and both remain the same whether or not I set the cullstate (which is why I think I've done it incorrectly).
Cullstate won’t affect the number of verts and faces in the scene, just whether or not they are rendered. (ie, if you went inside your model, you wouldn’t be able to see it from the inside out, because you would be looking at the back of the faces.)
I’m not all that familiar with jME, so I can’t suggest much beyond what I said before about grouping your boxes into larger bounding boxes. Maybe having a bounding box for every single cube is too heavy. If you created one for every group of 10x10 cubes it might help. It’s just an idea though.
Another idea might be not to use separate objects for every cube. If the topology of the land is not changing in realtime, perhaps you could merge them into a single mesh? Not sure, but I would expect the overhead of all those meshes to add some slowdown. (??? jme experts, can you confirm ??? )
This page on the wiki shows how to create geometry from scratch:
Not sure, but I would expect the overhead of all those meshes to add some slowdown. (??? jme experts, can you confirm ??? )
I'm not an expert, but I can confirm. The number of objects you have in your scenegraph is killer for every scenegraph API. The deeper or broader the scenegraph gets the more the framerates will drop.
If your terrain doesn't constantly change, your very best bet for FPS boost is
worldRoot.lock(); // worldRoot.lockBranch(); and worldRoot.lockMeshes(); are called in there and are most important to you here
If you at any point want to change your terrain, you can call worldRoot.unlock(); make changes and updateGeometricState(), etc. and lock() again.
Thanks for the ideas, but my terrain will need to change in real time. I've already written the terrain generator to only create the cubes it needs to not have holes in the world, but if there is a way to not render what you can't see (like what's behind you, what's behind mountains, etc…), that would be ideal!
Well, If your terrain does not change for one second or so, you can achieve large FPS gains with locking and unlocking before changing and then locking again.
If thats not the case, that is if you change your terrain EVERY FRAME, you can still add BoundingBoxes to all your boxes and have them being culled dynamically, also backface culling is a good way to go:
If you group 10 or so of your boxes together under one Node and give that node a boundingbox as well, the whole node can be culled quite easily, giving you more performance. But just test around with the options above.
You can change it even with ym emthod, just create some helper methods, removing the one, and then regenrating the terrain around it. (Let me guess works style game?)
the locking WARNING is normal. When you lock a mesh jme creates display lists which let the geometry render faster. When you lock again without unlocking before, the warning just tells you that the display list is already there.
Btw. I really think we should get rid of that warning or at least reduce it to INFO.
Ok, if I understand right, if I would like to implement octree culling algorithm for example I would just have to split all the elements in scene properly to octreenodes, and make bounding volumes for them and they would get culled automatically?
I think my problem was with how my code was structured… a little cleaning and I haven't seen that particular problem since.
My problem now is with the skybox. I set the camera's farFrustum to 150, which gives reasonable performance and viewing distance, and I set the skybox to a size of 200200200. The idea is that everything but the skybox is culled by the camera after a certain distance, but the problem is that the skybox still gets culled. I've tried setting a cullState for the box set to not cull, I've tried setting the cullHint to Never, I've tried setLastFrustumIntersection(FrustumIntersect.Inside). None of these seem to work. What is the correct way to do this?
For some reason, setting lockMeshes() still removes all textures from my Blocks, even when done after everything is rendered with SceneMonitor.
Thanks for using Scene Monitor! Be sure you test your locking problem without Scene Monitor running, because I make no guarantee that SM doesn't interfere in some way. Just a thought. ;)