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

Author Topic: VertexArray Isometric  (Read 291 times)

0 Members and 1 Guest are viewing this topic.

SFMLNewGuy

  • Newbie
  • *
  • Posts: 41
    • View Profile
VertexArray Isometric
« on: June 28, 2020, 12:54:20 am »
Hello,

I don't know why I can't find information on this anywhere. But using the example tutorial on displaying tiles with VertexArray (simple square) how would you set up an outline of an isometric tile? I have a nice looking square texture that I'd like to assign to an isometric outline. It should paste it on the isometric tile correct?

   
                 // define its 4 corners (from tutorial page) how to make a correct isometric tile
                quad[0].position = sf::Vector2f(i * tileSize.x, j * tileSize.y);
                quad[1].position = sf::Vector2f((i + 1) * tileSize.x, j * tileSize.y);
                quad[2].position = sf::Vector2f((i + 1) * tileSize.x, (j + 1) * tileSize.y);
                quad[3].position = sf::Vector2f(i * tileSize.x, (j + 1) * tileSize.y);
 

Also, at what point does using sf::VertexArray over sf::sprite really shows noticeable differences?

Thanks

SFMLNewGuy

  • Newbie
  • *
  • Posts: 41
    • View Profile
Re: VertexArray Isometric
« Reply #1 on: June 30, 2020, 09:30:38 am »
Can anyone guide me to what I'm looking for? I'm trying to figure out the consistent coordinates to create an isometric shape.

Paul

  • Newbie
  • *
  • Posts: 44
    • View Profile
Re: VertexArray Isometric
« Reply #2 on: June 30, 2020, 01:16:59 pm »
Isometric math is different from Cartesian system. Like everything else, you can do it in different ways, there is no ultimate approach. Plus there is diamond shape (Age of Empires) and staggered map (Civilization), both have different calculations.

Isometric tile is something like this:

quad[0].position = sf::Vector2f(x + tileSize.x / 2, y);
quad[1].position = sf::Vector2f(x + tileSize.x, y + tileSize.y / 2);
quad[2].position = sf::Vector2f(x + tileSize.x / 2, y + tileSize.y);
quad[3].position = sf::Vector2f(x, y +  tileSize.y / 2);

Then you need some formula for distribution and drawing in correct order, just use google.

Hapax

  • Hero Member
  • *****
  • Posts: 2971
  • My number of posts is shown in hexadecimal.
    • View Profile
Re: VertexArray Isometric
« Reply #3 on: July 01, 2020, 05:13:58 pm »
It's worth noting that "distorting" a square/rectangle texture to fit a diamond shape will not be perfect. Using a shader can fix it. An example of this is in Elastic Sprite, which is a part of Selba Ward. Another option is to subdivide into tiny pieces so that the resulting texture distortion is not noticeable (example of that can be seen in Sprite 3D - also a part of Selba Ward) although this is not ideal.

With that said, the easiest approach would be to distort the texture to fit the diamond shape in an image editor and then use those diamonds directly. Remember that texture co-ordinates don't have to be rectangular so they can just fit around those diamonds. With this approach, you can see the resulting image immediately (it's stored in the texture like that). You don't even have to store them contained within their rectangles in the texture, the diamonds can be fit more tightly than that.
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

Paul

  • Newbie
  • *
  • Posts: 44
    • View Profile
Re: VertexArray Isometric
« Reply #4 on: July 01, 2020, 06:54:44 pm »
It's worth noting that "distorting" a square/rectangle texture to fit a diamond shape will not be perfect.

Which kind of distortion? If you use square texture (64 x 64 pix) and isometric cell with 2/1 ratio (64 x 32 pix) then mapped texture will have correct proportions.

If you want connected cells and create an illusion of 3d terrain, different sizes of cells and such dynamics things use quads + textures. If you want pixel perfect look, use isometric bitmaps/sprites which fits exactly to the dimensions of the cell.

Hapax

  • Hero Member
  • *****
  • Posts: 2971
  • My number of posts is shown in hexadecimal.
    • View Profile
Re: VertexArray Isometric
« Reply #5 on: July 02, 2020, 10:48:15 pm »
True, if it's a perfect diamond, there shouldn't be any distortion. Apologies.
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

SFMLNewGuy

  • Newbie
  • *
  • Posts: 41
    • View Profile
Re: VertexArray Isometric
« Reply #6 on: July 03, 2020, 10:08:17 pm »
Hey,

I couldn't log in for whatever reason earlier. But I appreciate all the help!

What I did was this:

 
_shape.setPointCount(4);
            _shape.setPoint(0,sf::Vector2f(_width/2,0));
            _shape.setPoint(1,sf::Vector2f(_width,_height/2.0));
            _shape.setPoint(2,sf::Vector2f(_width/2.0,_height));
            _shape.setPoint(3,sf::Vector2f(0,_height/2.0));

            _shape.setOrigin(_width/2.0,_height/2.0);

            _shape.setScale(scale,scale);
   

then used functions like

 
sf::Vector2f mapCoordsToPixel(const sf::Vector2i& coord) const
{
    const float sw = _scale * _width/2.0;
     const float sh = _scale * _height/2.0;

       return sf::Vector2f((coord.x-coord.y) * sw,
                                (coord.x + coord.y) * sh);
 }

 sf::Vector2i mapPixelToCoords(const sf::Vector2f& coord) const
  {
            return round(sf::Vector2f(
                                      (coord.x/_width + coord.y/_height)/ _scale,
                                      (-coord.x/_width + coord.y/_height)/_scale)
                         );
}
             

Which was something I found on github after looking through isometric projects? I have a bunch of formulas for positioning isometric tiles, but drawing the outline stumped me. After looking at that example it makes complete sense based on positioning by half width and half height.

I know that isometric is different, which is why I was confused about how to draw the diamond shape. The sprites are 64x96, when the sprites are not the same size does this often cause problems? I have a few isometric formulas and some seem to not work as well as others depending on the size. For example, sometimes I see people divide by 4 on the Y-axis. Sometimes I see people multiply by the tile size width on both axis. While other times I see it multiply according to the axis tile size.

Can anyone explain the ratio bit? I see this a lot when dealing with isometric. I recall an SDL Isometric engine (Flare) that used this ratio float into the equation. 64/96 = 0.66...What is the significance of knowing this value?

As far as the texture looking distorted. I don't really need to shrink it, but just capture the middle since the size is way bigger. But I've come to the conclusion it's better to just hop on photoshop and make it an isometric tile.

Have a great day!

Thanks, everyone.
« Last Edit: July 03, 2020, 10:10:59 pm by SFMLNewGuy »

Hapax

  • Hero Member
  • *****
  • Posts: 2971
  • My number of posts is shown in hexadecimal.
    • View Profile
Re: VertexArray Isometric
« Reply #7 on: July 04, 2020, 07:51:10 pm »
The "ratio" is the ratio between width and height of the diamond shape.

True isometric requires all length to be equal in each direction and so all angles are to be equal (30 degree elevation). This would require a "ratio" of (1 / sqrt(3)) - approx 0.57735, meaning the height of the diamond would be ~0.577 times the width of that diamond.

An easier type of orthographic projection uses very close to isometric projection with a slight change of angles. Only two of the angles are the same (instead of three) so it's called a form of "dimetric" projection. It's very similar and tends to be refered to as isometric as a general term. This special type of dimetric makes the height 0.5 of the width, allowing for simple calculations and makes it possible for older devices or pixel art to look pleasing.
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

Paul

  • Newbie
  • *
  • Posts: 44
    • View Profile
Re: VertexArray Isometric
« Reply #8 on: July 05, 2020, 12:48:17 am »
If you use correct math (http://clintbellanger.net/articles/isometric_math/) then no matter which dimensions/ratio your tiles have (code bellow), it's universal. Tile selection by mouse cursor works according to the screen to grid formula in article.

If you use any offsets like people who are dividing Y by something for some reason then you must correct all calculations. Anyway it's easier forget about offsets, scales - stuff like sf::Shape, setOrigin or setScale. I really see no big point using it, it's only confusing.

For example you can stay with plain math, draw all needed map tiles (those that are visible on screen) to their true world positions, use sf::View for moving around world and for zooming if you need, use window.mapPixelToCoords(..) for mouse screen/world coords conversion.

sf::Vertex vertex[4];
sf::Vector2f pos;
sf::Color color;       

int map_w = 32;
int map_h = 32;
int cell_w = 96;
int cell_h = 64;

sf::VertexArray va_Quads;
va_Quads.clear();

for (int y = 0; y < map_h; y++)
{
        for (int x = 0; x < map_w; x++)
        {      
                color = sf::Color(50 + (unsigned char)round((155 / w) * x), 50 + (unsigned char)round((155 / h) * y), 50 + (unsigned char)round((155 / h) * y));

                pos.x = (x - y) * cell_w / 2;
                pos.y = (x + y) * cell_h / 2;

                vertex[0].position.x = pos.x + cell_w / 2;
                vertex[0].position.y = pos.y;
                vertex[0].color = color;
                       
                vertex[1].position.x = pos.x + cell_w;
                vertex[1].position.y = pos.y + cell_h / 2;
                vertex[1].color = color;
                       
                vertex[2].position.x = pos.x + cell_w / 2;
                vertex[2].position.y = pos.y + cell_h;
                vertex[2].color = color;
                       
                vertex[3].position.x = pos.x;
                vertex[3].position.y = pos.y + cell_h / 2;
                vertex[3].color = color;
                       
                va_Quads.append(vertex[0]);
                va_Quads.append(vertex[1]);
                va_Quads.append(vertex[2]);
                va_Quads.append(vertex[3]);
        }
}

window.draw(va_Quads);
 
« Last Edit: July 05, 2020, 12:56:15 am by Paul »

SFMLNewGuy

  • Newbie
  • *
  • Posts: 41
    • View Profile
Re: VertexArray Isometric
« Reply #9 on: July 05, 2020, 06:51:36 am »
Hey, thanks Paul and Hapax. Appreciate the response.

Going back to the ratio thing, my tiles are actually 64x64, something in this giant folder must have been 64x96 when I quickly checked the properties. So for clarity, finding out that ratio and multiplying it when placing the tiles is going to offset it as if it was a "true" isometric?

Here is an example I've found from one of my ancient books on an isometric checkers game.

The screen position of each tile is calculated as follows:
tile X = BOARD_X – (row*TEXTURE_SIZE/2) + (col*TEXTURE_SIZE/2),
tile Y = BOARD_Y + (row*TEXTURE_SIZE/4) + (col*TEXTURE_SIZE/4)
 

That is a direct example of something I see occasionally when looking at source code. I'm assuming the tiles were the same size here.

Appreciate the example Paul, I'm just trying to cover some of these questions I've had in the past. It is for sure better to just keep it simple. I've just always wondered why, depending on the source, I come across different ways of doing isometric, and if it has to do with the ratio being different and as a result that Flare Engine, added a ratio variable to suit the user's needs. Or perhaps it was to include tiles that do not have the same sides (like that 64x96 tile).
« Last Edit: July 05, 2020, 06:54:22 am by SFMLNewGuy »

Hapax

  • Hero Member
  • *****
  • Posts: 2971
  • My number of posts is shown in hexadecimal.
    • View Profile
Re: VertexArray Isometric
« Reply #10 on: July 05, 2020, 04:58:38 pm »
Remember that the ratio is only really defining the shape/size of the diamond not the actual textures used inside them. If you place a square image inside a diamond shape, it will rotate, skew and stretch to fit.

The only reason I mentioned "true" isometric is that the simpler version is not "technically" isometric but is often just considered it as it's close enough. There's no real requirement to use the correct term unless you're being very clear about it to people that know the difference.

Generally, just go with whatever ratio looks good/right to you. 1/2 is common and simple for calculations. 2/3 is relatively simple but may feel "a bit high from the ground". 1/(sqrt(3)) is a pretty complex value and your tiles would never be anywhere near integers, which are always easier to deal with.

I've only been addressing the shape of the diamond, not the layout of the grid nor efficiency.

Maybe one day, I'll add an 'isometric' tile map to Selba Ward... :-\
Selba Ward - SFML drawables
Kairos - Timing Library
Rectangular Boundary Collision - Rectangular SAT Collision

@Hapaxiation - Hapaxia on Twitter

SFMLNewGuy

  • Newbie
  • *
  • Posts: 41
    • View Profile
Re: VertexArray Isometric
« Reply #11 on: July 05, 2020, 11:12:07 pm »
Alright thanks!

Coincidentally, I've just been checking out Selba again! I think this is a destiny meeting to add isometric to it.

DO IT, I DARE YOU.  ;) :-X