# How to get the blocks seen by the player?

I'm writing a Minecraft-like game using Ogre engine and I have a problem. I must optimize my game, because when I try draw 10000 blocks, I have 2 FPS... So, I got the idea that blocks display of the plane and to hide the invisible blocks. But I have a problem - how do I know which blocks at a time are visible to the player?

And - if you know of other optimization methods for such a game, write what and how to use them in Ogre.

Well, Ogre already implements frustum culling (which basically does not draw anything that couldn't be seen from the camera) but I think your problem is a different one.

You should not really be displaying 10000 blocks, what is commonly done (or at least, in the few Ogre3d based minecraft like clones I've seen (of which I am making one too), and in the original ) is creating a mesh (of some NxNxN region of chunks) which has the outer faces of the cubes shown. That is, when you put 2 cubes side by side, the 2 faces touching can't be seen and therefore don't need to be drawn.

These faces should also be drawn in something like this: http://www.ogre3d.org/tikiwiki/tiki-index.php?page=DynamicGrowingBuffers as modern video cards prefer one mesh of 100000 polygons versus 1000 meshes of 100 polygons.

There are a couple of aspects to this problem. Firstly, how are you drawing your 10000 blocks? Are you actually drawing them as 10000 seperate object? If so this is almost certainly your bottle neck, not the lack of occlusion culling. You should group these blocks into a smaller number of meshes (perhaps a few thousand per mesh) in order to reduce draw calls.

As for your actual question, there are three types of occlusion culling which spring to mind.

1) Blocks outside the view frustum. This means blocks which are behind you or two the side. Ogre already removes these via view frustum culling.

2) Blocks which are 'underground' or completely surrounded by other blocks so they can never be seen from any angle. You can identify these by looking at the siz neighbouring blocks. If they are all solid your block is hidden. The GPU should never even hear about these blocks - they should be skipped when you are building the mesh which represent your surface.

3) Blocks which are on the surface and can be seen from some positions in the level, but which are currently hidden by a hill (or something). This is the trickiest case which I haven't addressed myself, but there's a good chance that hardware occlusion queries can be used for this case.

It's a shameless plug, but I have a fairly mature library which several people are using to develop Minecraft clones, including some using Ogre. You define the contents of the volume and it generates the surface mesh which you can then render. Here is the home page:

http://www.thermite3d.org/

And here is a video of someone else's project which is using it:

You can use backface culling to cull vertices and their associated pixels that don't face the player. Depth buffering should take care of the rest. 10k blocks really isn't a lot, my 5770 can render 100k verts at 1500fps. I think that you're doing something else pretty badly wrong.

• I agree. This is propably problem with anything else. – Notabene Feb 4 '11 at 10:59

If you have 10000 separate objects, the bottleneck is probably primitive count, not vertex, polygon, or fill. Bake your objects into smaller number of higher polygon objects for speed.

Minecraft has a concept of blocks of cubes, but I can't find the reference at the moment.

Here's also my experiments on drawing tons of cubes with various techniques. Doesn't include baking (yet).

What I do, is after I create my array of blocks, but before I create the vertices, I run a sub called UpdateBlockVisiblility.

The sub simply checks the neighbours to the block, and updates the Blocks facevisible boolean accordingly.

#define BLOCKFACE_NORTH 0

#define BLOCKFACE_SOUTH 1

etc etc etc

if(IsBlockAt(NorthOfBlock))
Blocks[Whatever].facevisible[BLOCKFACE_NORTH] = false;


Then I only create the vertices for the face if it is visible! Simple :)