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
\$\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\$
  • \$\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\$ – JDSweetBeat Oct 13 '17 at 4:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.