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

Author Topic: VertexArray accepts coordinates one beyond?  (Read 702 times)

0 Members and 1 Guest are viewing this topic.

MichelangeloSFML/

  • Newbie
  • *
  • Posts: 17
    • View Profile
VertexArray accepts coordinates one beyond?
« on: June 07, 2022, 01:13:35 pm »
Thanks in advance.

1) I am going through this book that uses a sprite sheet that is 50x200, with 4 sprites each 50x50.
Book says each of the corner Quads coordinates are as follows:

IMAGE 1:
0,0      49,0

0,49      49,49

IMAGE 2:
0,50       49,50

0,99       49,99

IMAGE 3:
0,100   49,100

0,149   49,149

IMAGE 4:
0,150   49,150

0,199   49,199 




So for a 50x50 image coordinates go from 0-49 on width & 0-49 on height, BUT THEN the program uses a VertexArray to accept .positon for coordinates between 0-50 for both width & height. I assumed that such a request would go 1 pixel beyond the width & height and give an error, but instead the code runs perfectly and displays the tiles on the screen. So I am just wondering does the VertexArray class accept one beyond for mathematical convenience, or is there something else that I am missing? 

Here is a partial cout of the coord from the for loop:

.position:
  • = (0, 0)
  • [1] = (50, 0)
    [2] = (50, 50)
    [3] = (0, 50)

    [4] = (0, 50)
    [5] = (50, 50)
    [6] = (50, 100)
    [7] = (0, 100)

    [8] = (0, 100)
    [9] = (50, 100)
    [10] = (50, 150)
    [11] = (0, 150)

    [12] = (0, 150)
    [13] = (50, 150)
    [14] = (50, 200)
    [15] = (0, 200)

    [16] = (0, 200)
    [17] = (50, 200)
    [18] = (50, 250)
    [19] = (0, 250)

    [20] = (0, 250)
    [21] = (50, 250)
    [22] = (50, 300)
    [23] = (0, 300)

    [24] = (0, 300)
    [25] = (50, 300)
    [26] = (50, 350)
    [27] = (0, 350)
    _____________________________

.textCoords:
  • = (0, 150)
  • [1] = (50, 150)
    [2] = (50, 200)
    [3] = (0, 200)

    [4] = (0, 150)
    [5] = (50, 150)
    [6] = (50, 200)
    [7] = (0, 200)

    [8] = (0, 150)
    [9] = (50, 150)
    [10] = (50, 200)
    [11] = (0, 200)

    [12] = (0, 150)
    [13] = (50, 150)
    [14] = (50, 200)
    [15] = (0, 200)

    [16] = (0, 150)
    [17] = (50, 150)
    [18] = (50, 200)
    [19] = (0, 200)

    [20] = (0, 150)
    [21] = (50, 150)
    [22] = (50, 200)
    [23] = (0, 200)

    [24] = (0, 150)
    [25] = (50, 150)
    [26] = (50, 200)
    [27] = (0, 200)


    2) I am also curious why do I have to add the "textRect.top" to the height "textRect.top + textRect.height / 2.0f" to get the origin? What does the .top for the textRect FloatRect represent? Is it the empty space between the top to the point where it hits the first pixel of the font? So in my example below...

    textRect.top = 12

    ...means that there are 12 empty rows of pixels from the top until it reaches a font pixel. If that is the case, why am I adding the "textRect.top + textRect.height / 2.0f", shouldn't I be subtracting those 12 empty pixels instead so I can get the TRUE mid point/origin?

    ________________
    // Position the text
    FloatRect textRect = messageText.getLocalBounds();

    messageText.setOrigin(textRect.left + textRect.width / 2.0f, textRect.top + textRect.height / 2.0f);

    messageText.setPosition(1920 / 2.0f, 1080 / 2.0f);

    scoreText.setPosition(20, 20);

    ________________
    COUT FROM CODE:

    Window x = 1920
    Window y = 1080

    BEFORE FloatRect formed:
    messageText.getLocalBounds().left = 0
    messageText.getLocalBounds().top = 12
    messageText.getLocalBounds().height = 64
    messageText.getLocalBounds().width = 935

    AFTER FloatRect formed:
    textRect.left = 0
    textRect.top = 12
    textRect.height = 64
    textRect.width = 935

    messageText.getLocalBounds().left = 0
    messageText.getLocalBounds().top = 12
    messageText.getLocalBounds().height = 64
    messageText.getLocalBounds().width = 935

    messageText.getGlobalBounds().left = 0
    messageText.getGlobalBounds().top = 12
    messageText.getGlobalBounds().height = 64
    messageText.getGlobalBounds().width = 935

« Last Edit: June 07, 2022, 01:44:40 pm by MichelangeloSFML/ »

Stauricus

  • Sr. Member
  • ****
  • Posts: 338
    • View Profile
    • Email
Re: VertexArray accepts coordinates one beyond?
« Reply #1 on: June 07, 2022, 02:18:57 pm »
Quote
I assumed that such a request would go 1 pixel beyond the width & height
what width & height are you talking about? I don't know if I really got your question here

some considerations that may be what you're looking for:
-the VertexArray quad size doesn't have to be the exact size of the original texture. you can use a texture sized as 32x32 and a VertexArray quad like 120x57. things will just be stretched accordingly, kinda like wallpapers can be stretched in a monitor. this is also true for sprites.
-for texCoords, if you use a coordinate bigger than the texture itself, it will just loop around. if the texture file size is 200x50, and you use textCoord set in 210x50, it wil simply be set to 10x50.

MichelangeloSFML/

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: VertexArray accepts coordinates one beyond?
« Reply #2 on: June 07, 2022, 04:31:29 pm »
Ok, that explains the VertexArray.position, thanks & good to know that textCoord loops around too.

In that 50x200 sprite sheet with 4   50x50 sprites, if I wanted to get the coordinates of the top most sprite.

The book implements code like this. Does this not go beyond 50x50, which is zero based (0-49)....but instead goes from (0-50)?
myVectorArray[0].textCoord = Vector2f (0,0);
myVectorArray[1].textCoord = Vector2f(50,0);
myVectorArray[2].textCoord = Vector2f(50,50);
myVectorArray[2].textCoord = Vector2f(0,50);

I thought it should be like this, shouldn't those 50's from above be 49's instead?
myVectorArray[0].textCoord (0,0);
myVectorArray[1].textCoord (49,0);
myVectorArray[2].textCoord (49,49);
myVectorArray[2].textCoord (0,49);


Also, those were two 1) & 2) separate and independent questions.
« Last Edit: June 07, 2022, 04:36:40 pm by MichelangeloSFML/ »

kojack

  • Full Member
  • ***
  • Posts: 202
    • View Profile
Re: VertexArray accepts coordinates one beyond?
« Reply #3 on: June 07, 2022, 05:11:13 pm »
Texture coordinates aren't actually measured in pixels (on the GPU), it's a range of 0-1. SFML scales the coordinates you give it down when rendering.
Because of this, the coordinates can be smaller or larger than a pixel. You have to take into account the size of each pixel. So the left texture coordinate is the left edge of the left most pixels, the right texture coordinate is the right edge (not left edge) of the right most pixels.

So for a 4x4 texture:


The pixels themselves are 0-3, but the coordinates of the rectangle that surrounds the pixels would be 0-4 (because you need to go to the right/bottom edge, not the right/bottom pixel index).

MichelangeloSFML/

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: VertexArray accepts coordinates one beyond?
« Reply #4 on: June 07, 2022, 06:48:10 pm »
So it is like a mesh on top of the original image that is then used for scaling. Thanks, it makes sense now.

My 2nd question restated below.
In this line:
messageText.setOrigin(textRect.left + textRect.width / 2.0f, textRect.top + textRect.height / 2.0f);

Why do we need to add the textRect.top of the FloatRect (textRect) to the textRect.height in order to get the center of the messageText box? What does the .top value really mean (in this case it is = 12). What is within that 12 pixels at the top, is it empty space or does it hold part of the pixels of the font? If it is empty pixels then we should be subtracting from the height, not adding to it? Usually in other program a .top represents where the top starts, but here it obviously does not.

Code: [Select]
// Position the text
FloatRect textRect = messageText.getLocalBounds();

messageText.setOrigin(textRect.left + textRect.width / 2.0f, textRect.top + textRect.height / 2.0f);

messageText.setPosition(1920 / 2.0f, 1080 / 2.0f);

scoreText.setPosition(20, 20);

OUTPUT FROM CODE when you print to screen below (just to show coordinates):
Code: [Select]
Window x = 1920
Window y = 1080

BEFORE FloatRect formed:
messageText.getLocalBounds().left = 0
messageText.getLocalBounds().top = 12
messageText.getLocalBounds().height = 64
messageText.getLocalBounds().width = 935

AFTER FloatRect formed:
textRect.left = 0
textRect.top = 12
textRect.height = 64
textRect.width = 935

messageText.getLocalBounds().left = 0
messageText.getLocalBounds().top = 12
messageText.getLocalBounds().height = 64
messageText.getLocalBounds().width = 935

messageText.getGlobalBounds().left = 0
messageText.getGlobalBounds().top = 12
messageText.getGlobalBounds().height = 64
messageText.getGlobalBounds().width = 935
« Last Edit: June 07, 2022, 06:49:51 pm by MichelangeloSFML/ »

Arcade

  • Full Member
  • ***
  • Posts: 229
    • View Profile
Re: VertexArray accepts coordinates one beyond?
« Reply #5 on: June 07, 2022, 09:57:40 pm »
The 'top' variable is indeed empty space above your letters and the value is dependent on which letters/characters you are using in your Text object. The value of top will be small if you have tall characters in your text, and vice versa.

Going off of memory here, but I believe a Text object's height represents the height of the characters that are currently being used, not the height of the tallest possible character within your font (hopefully someone corrects me if I have this backwards). So, height + top would give you the height of the tallest possible character.

It's useful to know the size of the tallest possible character so that you can prevent your characters, which are aligned at their baseline, from visibly bouncing up and down as new characters with different heights are added or removed from your text. Or at least you can choose how you want to use the combination of 'height' and 'top' to do your positioning when dealing with characters of different heights.

kojack

  • Full Member
  • ***
  • Posts: 202
    • View Profile
Re: VertexArray accepts coordinates one beyond?
« Reply #6 on: June 07, 2022, 11:54:00 pm »
I just did some single stepping through the text object code.

Let's say we're using the bluehigh.ttf font (because I am) with a character size of 30 (the default).
The baseline for the text (which characters sit on) will be placed at y=30.
The code loops over every character in the current string and gets it's glyph.
The glyph is a description of the character in the font, and includes the top and bottom offsets from the baseline.
The glyph for the letter "T" has a top of -17 and a bottom of 0. So it sits on the baseline and goes 17 above it.
This is then added to the baseline value of 30. So the bounds of the text object will be top=13, height=17 (that's what you get from the getLocalBounds if "T" is the only letter in the string).
The glyph for the letter "h" has a top of -18 (it's a fraction taller than a T) and bottom of 0, so it's local bounds are top=12 height=18.
The glyph for the letter "p" has a top of -13 and a bottom of 6, it drops below the baseline. It's local bounds will be top=17 height=19.
And so on.
The minimum and maximum top and bottom (and therefore height) are found for all the characters in the current string. That's what getLocalBounds actually returns, for the string "Thp" it would be top=12 (from the "h") and height=24 (the "p" has a bottom of 36).

Hopefully that's correct, I'm running on insomnia and caffeine at the moment. :)

So overall: local bounds are based on the characters actually in the current string (updates whenever the string changes). Therefore textRect.top + textRect.height / 2.0f will give you the centre of the visible characters, not the centre of all potential (but unused) characters.

MichelangeloSFML/

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: VertexArray accepts coordinates one beyond?
« Reply #7 on: June 11, 2022, 07:22:14 pm »
Thanks.