Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Triangle Fan Hex Map  (Read 5376 times)

0 Members and 1 Guest are viewing this topic.

Greysuit

  • Newbie
  • *
  • Posts: 9
    • View Profile
    • Email
Triangle Fan Hex Map
« on: July 26, 2013, 10:10:59 pm »
I'm trying to program a hexagon tile map by adapting the tile map code from the vertex tutorial to use sf::TriangleFan hexes. Unfortunately, I'm getting some weird distortions of the tiles. I attached a screenshot. In the code I define the centre of the fan and then use trigonometry to define the corners of the hexagons. The math I used for that is from here.. The texture is 110 x 64 pixels, white on the left half, red on the right half.

If anyone has an idea what's going with this I would be grateful.

#include <SFML/Graphics.hpp>
#include <cmath>

const double PI  =3.141592653589793238462;

class TileMap : public sf::Drawable, public sf::Transformable
{
public:

    bool load(const std::string& tileset, int hex_size, const int* tiles,
        unsigned int map_width, unsigned int map_height, int relative_offset)
    {

                int offset = relative_offset * hex_size;
                float height = hex_size * 2;
                float width  = std::sqrt(3) * hex_size;


        // load the tileset texture
        if (!m_tileset.loadFromFile(tileset))
            return false;

        // resize the vertex array to fit the level size
        m_vertices.setPrimitiveType(sf::TrianglesFan);
        m_vertices.resize(map_width * map_height * 8);

        // populate the vertex array, with one fan per tile
        for (unsigned int i = 0; i < map_width; ++i)
            for (unsigned int j = 0; j < map_height; ++j)
            {
                // get the current tile number
                int tileNumber = tiles[i + j * map_width];

                // find its position in the tileset texture
                int tx = tileNumber % (m_tileset.getSize().x / (int) width);
                int ty = tileNumber / (m_tileset.getSize().x / width);

                // get a pointer to the current tile's hex
                sf::Vertex* hex = &m_vertices[(i + j * width) * 8];


                // define its  centre
                        hex[0].position= sf::Vector2f ( offset + i * width, offset + j * height);

                        //define its corners
                        for (int k = 1; k < 7; k++)
                        {
                                float angle = 2 * PI / 6 * (k + 0.5);
                                hex[k].position = sf::Vector2f (
                                    hex[0].position.x + hex_size * cos(angle),
                                    hex[0].position.y + hex_size * sin(angle) );
                        }
                        hex[7].position = hex[1].position;



                // define its texture centre
                hex[0].texCoords = sf::Vector2f(  
                    (width/2) + (tx * width),  hex_size + (ty * height)  ) ;
               
                //define its corners
                for (int k = 1; k < 7; k++)
                        {
                                float angle = 2 * PI / 6 * (k + 0.5);
                                hex[k].texCoords = sf::Vector2f (
                                    hex[0].texCoords.x + hex_size * cos(angle),
                                    hex[0].texCoords.y + hex_size * sin(angle) );
                        }
                hex[7].texCoords = hex[1].texCoords;

            }

        return true;
    }

private:

    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
    {
        // apply the transform
        states.transform *= getTransform();

        // apply the tileset texture
        states.texture = &m_tileset;

        // draw the vertex array
        target.draw(m_vertices, states);
    }

    sf::VertexArray m_vertices;
    sf::Texture m_tileset;
};



int main()
{
    // create the window
    sf::RenderWindow window(sf::VideoMode(512, 256), "Tilemap");

    // define the level with an array of tile indices
    const int level[] =
    {
        0, 0, 1//, 0//, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
    };

    // create the tilemap from the level definition
    TileMap map;
    if (!map.load("tileset.png", 32, level, 3, 1, 2))
        return -1;

    // run the main loop
    while (window.isOpen())
    {
        // handle events
        sf::Event event;
        while (window.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
                window.close();
        }

        // draw the map
        window.clear();
        window.draw(map);
        window.display();
    }

    return 0;
}
« Last Edit: July 26, 2013, 10:22:19 pm by Greysuit »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Triangle Fan Hex Map
« Reply #1 on: July 26, 2013, 10:16:36 pm »
You're trying to put several fans into a single vertex array, but it can only contain one. How would the graphics card know that every 8 vertices, a new fan starts? It takes the first vertex as the center, and all other vertices as the outline.
Laurent Gomila - SFML developer

Greysuit

  • Newbie
  • *
  • Posts: 9
    • View Profile
    • Email
Re: Triangle Fan Hex Map
« Reply #2 on: July 26, 2013, 10:55:22 pm »
Thanks very much Laurent. That totally makes sense. I guess the only practical way to get all the hexagons into one vertex array would be to use sf::Triangles (since I think sf::TriangleStrip would make indexing the hexes awkward once there's more than one row of them). At what number of hexes would drawing each hex separately become a significant demand on modern video cards?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Triangle Fan Hex Map
« Reply #3 on: July 27, 2013, 08:58:33 am »
Quote
I guess the only practical way to get all the hexagons into one vertex array would be to use sf::Triangles
Yes.

Quote
At what number of hexes would drawing each hex separately become a significant demand on modern video cards?
This kind of question is always hard to answer. It depends on so many things :-\
Laurent Gomila - SFML developer

Ancurio

  • Jr. Member
  • **
  • Posts: 66
    • View Profile
Re: Triangle Fan Hex Map
« Reply #4 on: July 27, 2013, 08:00:20 pm »
At what number of hexes would drawing each hex separately become a significant demand on modern video cards?

Honestly, don't worry about it. Unless you're literally drawing millions at once it will not matter. Remember, triangle strips are not there to alleviate the GPU from drawing "less" stuff; a GPU always renders triangles, so your fans are going to be broken up into triangles anyway. The only thing it saves is a little bit of memory bandwidth and transform cost, but as I said, for your demands it is most likely negligible.