1
\$\begingroup\$

How to performantly display a hex/pent grid on a subdivided icosahedron?

I have a subdivided icosahedron planet used as the "board" for a strategy game. It usually has anywhere between a few thousand and a hundred thousand tiles depending on the size the user inputs to the map generator.

Basically, I cannot brute force this and do a simple bounds and depth check, because of the sheer numbers of tiles.

I am storing the grid in a 2D array for simplicity. I understand that, on a 2D map, you simply do something like the following to draw a hex map:

for(int x = cameraX; x < viewportWidth; x++)
{
    for(int y = cameraY; y < viewportHeight; y++)
    {
        if(x % 2 == 0) //For the 2D array to work properly we have to offset every other row by +1 world coordinate (assuming each tile is 1*1 world coordinates)
           grid[x][y].render(x+tile_width, y);
        else
            grid[x][y].render(x, y);
    }
}

And that to draw a wrap-around world you would check the absolute distance from the camera's position.

Eg:

//This sets up the variable that tells the game what hex tiles to draw.
if(camera.x - viewportWidth < 0)
{
    camera_rX = camera.x - viewportWidth;
    cameraX = grid.length + camera_rX; //We will add this to the cameraX value because the result should be a negative value if the prerequisite if statement is met. The "cameraX" variable is used for viewing calculations, while the "camera.x" variable is used for camera positioning. Err... I think this makes sense.
}
\$\endgroup\$
2

1 Answer 1

2
\$\begingroup\$

First question that comes to mind: does the hex-planet change a lot during gameplay? If the planet is mostly static, and just the inhabitants on it move around a lot, I would definitely not render the tiles separately.

I've made a hex-planet game myself. And in this game the planet is just two draw calls, one to draw its faces, and one to draw the edges.

This way I don't have to iterate over the tiles to render them.

For the stuff on top (trees, rocks, etc) I use instanced-rendering, so that in one drawcall, all pine-trees e.g. are rendered in a single go. I am not sure what you are using for rendering (question tags don't mention a render system), but if it is OpenGL or OpenGLES3 then look into glVertexAttribDivisor() and glDrawArraysInstanced().

It gets trickier if the tiles change a lot during gameplay. Let's say you frequently change the colour of the tiles in the world. Then I would still have a single VBO to represent the entire planet, and just update that VBO every frame with the correct colours before rendering, as described above.

\$\endgroup\$
1
  • \$\begingroup\$ I'm using libGdx to abstract a lot of the low-level graphics API's and save on development time (I probably should have named the engine, but I thought this was more of a mathematical problem). I already considered drawing the planet in a single draw call, but unfortunately there is a lot of change going on on the planet surface (eg, tile color change with ownership). I have considered drawing colored, faded meshes over the top of the rendered planet, and sply disallowing the user to zoom closer, but I still have to find which tiles are visible to do that. \$\endgroup\$
    – Jax
    Oct 13, 2017 at 4:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .