sf::Texture applied in a wrong way
Asked Answered
P

1

14

In my 2D isometric engine, I have the following classes:

maps(variable)/layers(variable)/cubes(variable)/sides(6)/points(4)/coordinates(3)

enter image description here

  • Each sides contains 4 points(1 point = 1 coordinate(x, y, z)).
  • Each cubes contains 6 sides.
  • I can create a map with the size I want with cubes(same, the size I want).

Folders:

assets/numTexture/numLight.png

I calculate with numTexture and numLight a number which is the textureNumberEntry(I loaded all numLight.png(textures) in an array).

But texturing goes wrong:

enter image description here

I define my cubes coordinates in the layer class:

for(int J = 0; J < mapSize; J++)
{
    for(int I = 0; I < mapSize; I++)
    {
        x = (J - I) * (cubeSize/2);
        y = (J + I) * (cubeSize/4);

        c = new cube(cubeSize, x, y, z, I, J);
        cs.push_back(*c);
    }
}

In side.cpp, I have a switch on sideType(if it's the top, left, etc... I define differently my points' coordinates). I have 6 of them for each cubes(only data here)

Like this:

    switch(typeSide)
        {
            case 0://DOWN_SIDE
                light = 0;
    
                tmp_x = x + (size/2);
                tmp_y = y + (size/2);
                p0 = new point(tmp_x, tmp_y, tmp_z);
    
                tmp_x = x + size;
                tmp_y = y + (3 * (size/4));
                p1 = new point(tmp_x, tmp_y, tmp_z);
    
                tmp_x = x + (size/2);
                tmp_y = y + size;
                p2 = new point(tmp_x, tmp_y, tmp_z);
    
                tmp_x = x;
                tmp_y = y + (3 * (size/4));
                p3 = new point(tmp_x, tmp_y, tmp_z);
                break;

//ETC. ....

And function display() to display the map:

void GRAPHICS_HANDLER::display()
{
    x = 0;
    y = 0;

    if(maps.size() > 0 && maps[0].layers().size() > 0)//If there is any map and layers to display
    {
        for(int l = 0; l <= getCurrentLayerID(); l++)//FOR EACH LAYER, WE STOP TO THE CURRENT EDITED LAYER
        {
            for(unsigned int c = 0; c < maps[currentMapID].layers()[l].cubes().size(); c++)//FOR EACH CUBES
            {
                if(maps[currentMapID].layers()[l].cubes()[c].getFlat())//If flat mode is enabled: to draw texture like grass, etc...(cf. screen): We draw only one side
                {
                    for(unsigned int p = 0; p < 4; p++)//FOR EACH POINTS
                    {
//--------------------------------------------------------------------------------------LOAD MAP-----------------------------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------CUBE CLICK DETECTION::TEXTURE CHANGE--------------------------------------------------//
                        if(cubeClicked || brushMode && currentSelectedCube > -1 && currentSelectedCube < maps[currentMapID].layers()[maps[currentMapID].currentLayerId()].cubes().size())
                        {
                            maps[currentMapID].layers()[maps[currentMapID].currentLayerId()].cubes()[currentSelectedCube].setTexture(currentSelectedTexture);

                            if(!brushMode)
                                cubeClicked = false;
                        }
//--------------------------------------------------------------------------CUBE CLICK DETECTION::TEXTURE CHANGE--------------------------------------------------//
//--------------------------------------------------------------------------------------CURSOR - NOT WORKING-----------------------------------------------------------------------------------------------------------------//
                        //...
//--------------------------------------------------------------------------------------CURSOR - NOT WORKING-----------------------------------------------------------------------------------------------------------------*/

                        if(enableOffset)
                        {
                            x = maps[currentMapID].layers()[l].cubes()[c].sides()[0]->pointPosition(p)[0] + offsetLeft;//it's like doing something like point[p].x + offset left
                            y = maps[currentMapID].layers()[l].cubes()[c].sides()[0]->pointPosition(p)[1] + offsetTop;
                        }
                        else
                        {
                            x = maps[currentMapID].layers()[l].cubes()[c].sides()[0]->pointPosition(p)[0];//it's like doing something like point[p].x + offset left
                            y = maps[currentMapID].layers()[l].cubes()[c].sides()[0]->pointPosition(p)[1];
                        }

                        points[p].position = sf::Vector2f(x, y);
                        points[p].texCoords = sf::Vector2f(x, y);

//--------------------------------------------------------------------------------------GRID-----------------------------------------------------------------------------------------------------------------//
                        //GRID DISPLAY //MISS AN EDGE .
                        isoGrid[p].position = points[p].position;
                        isoGrid[p].color = sf::Color(195, 195, 195, gridOpacity);
//--------------------------------------------------------------------------------------GRID-----------------------------------------------------------------------------------------------------------------//

                        maps[currentMapID].layers()[l].cubes()[c].sides()[0]->setLight(5);
                        textureEntryNumber = (maps[currentMapID].layers()[l].cubes()[c].sides()[0]->getTexture() - 1) * 9 + (maps[currentMapID].layers()[l].cubes()[c].sides()[0]->getLight() - 1);//WRONG
//--------------------------------------------------------------------------------------GRID-----------------------------------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------LOAD MAP-----------------------------------------------------------------------------------------------------------//
                    }
//--------------------------------------------------------------------------------------DISPLAY MAP-----------------------------------------------------------------------------------------------------------//
                    if(grid && maps[currentMapID].layers()[l].cubes()[c].sides()[0]->getTexture() <= 1)//IF GRID = TRUE OR TEXTURE LESS OR EQUAL TO 1 => DISPLAY GRID
                    {
                        if(l == maps[currentMapID].currentLayerId())
                        {
                            window->draw(isoGrid);
                        }
                    }
                    else if(maps[currentMapID].layers()[l].cubes()[c].sides()[0]->getTexture() > 1)//IF THERE IS ANY TEXTURE TO DISPLAY(>1) => DISPLAY TEXTURE
                    {
                        window->draw(points, &textures[textureEntryNumber]);
                    }
//--------------------------------------------------------------------------------------DISPLAY MAP-----------------------------------------------------------------------------------------------------------//
                }
                else
                {
                    for(unsigned int s = 0; s < 6; s++)//FOR EACH SIDES(side number will always be 6, no need to make this dynamic
                    {
                        for(unsigned int p = 0; p < 4; p++)//FOR EACH POINTS
                        {
//--------------------------------------------------------------------------------------LOAD MAP-----------------------------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------CUBE CLICK DETECTION::TEXTURE CHANGE--------------------------------------------------//
                            if(cubeClicked || brushMode && currentSelectedCube > -1 && currentSelectedCube < maps[currentMapID].layers()[maps[currentMapID].currentLayerId()].cubes().size())
                            {
                                maps[currentMapID].layers()[maps[currentMapID].currentLayerId()].cubes()[currentSelectedCube].setTexture(currentSelectedTexture);

                                if(flatMode)
                                    maps[currentMapID].layers()[maps[currentMapID].currentLayerId()].cubes()[currentSelectedCube].setFlat(true);
                                else
                                    maps[currentMapID].layers()[maps[currentMapID].currentLayerId()].cubes()[currentSelectedCube].setFlat(false);


                                if(!brushMode)
                                    cubeClicked = false;
                            }
//--------------------------------------------------------------------------CUBE CLICK DETECTION::TEXTURE CHANGE--------------------------------------------------//
//--------------------------------------------------------------------------------------CURSOR - NOT WORKING-----------------------------------------------------------------------------------------------------------------//
                            //...
//--------------------------------------------------------------------------------------CURSOR - NOT WORKING-----------------------------------------------------------------------------------------------------------------*/

                            if(enableOffset)
                            {
                                x = maps[currentMapID].layers()[l].cubes()[c].sides()[s]->pointPosition(p)[0] + offsetLeft;//it's like doing something like point[p].x + offset left
                                y = maps[currentMapID].layers()[l].cubes()[c].sides()[s]->pointPosition(p)[1] + offsetTop;
                            }
                            else
                            {
                                x = maps[currentMapID].layers()[l].cubes()[c].sides()[s]->pointPosition(p)[0];//it's like doing something like point[p].x + offset left
                                y = maps[currentMapID].layers()[l].cubes()[c].sides()[s]->pointPosition(p)[1];
                            }

                            points[p].position = sf::Vector2f(x, y);
                            points[p].texCoords = sf::Vector2f(x, y);

//--------------------------------------------------------------------------------------GRID-----------------------------------------------------------------------------------------------------------------//
                            //GRID DISPLAY //MISS AN EDGE
                            if(s ==3)
                            {
                                isoGrid[p].position = points[p].position;
                                isoGrid[p].color = sf::Color(195, 195, 195, gridOpacity);
                            }
//--------------------------------------------------------------------------------------GRID-----------------------------------------------------------------------------------------------------------------//

                            textureEntryNumber = (maps[currentMapID].layers()[l].cubes()[c].sides()[s]->getTexture() - 1) * 9 + (maps[currentMapID].layers()[l].cubes()[c].sides()[s]->getLight() - 1);//WRONG
//--------------------------------------------------------------------------------------GRID-----------------------------------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------LOAD MAP-----------------------------------------------------------------------------------------------------------//
                        }
//--------------------------------------------------------------------------------------DISPLAY MAP-----------------------------------------------------------------------------------------------------------//
                        if(grid && maps[currentMapID].layers()[l].cubes()[c].sides()[s]->getTexture() <= 1)//IF GRID = TRUE OR TEXTURE LESS OR EQUAL TO 1 => DISPLAY GRID
                        {
                            if(l == maps[currentMapID].currentLayerId())
                            {
                                window->draw(isoGrid);
                            }
                        }
                        else if(maps[currentMapID].layers()[l].cubes()[c].sides()[s]->getTexture() > 1)//IF THERE IS ANY TEXTURE TO DISPLAY(>1) => DISPLAY TEXTURE
                        {
                            window->draw(points, &textures[textureEntryNumber]);
                        }
//--------------------------------------------------------------------------------------DISPLAY MAP-----------------------------------------------------------------------------------------------------------//
                    }
                }
            }
        }
    }

    window->display();
}

Scroll this one to see comments, and the labels

Problems:

  • Texture enlarged only when texture with details, no problem with one color texture(probably the vertex bounding together, even from different sf::VertexArray.

Note: class like maps/layers/cubes/etc. ... are only data.

Textures(numLIght) images which should be displayed in the screen look like this: enter image description hereenter image description hereenter image description here

EDIT: Textures work when the picture is only a color, without details :

enter image description here

I don't know anymore what's wrong with my code. Maybe, I'll recode the function display()...

Poncho answered 22/11, 2015 at 6:10 Comment(7)
How do you set the texture coordinates? And loading the same texture over and over again is bad, but shouldn't cause this.Thorlie
@Thorlie I edited my post about how i set the coordinates and how i display the whole thing. Loading it again and again can cause lags ?Poncho
@Thorlie Thanks to you, i resolved my lags problem, now i understand why loading textures again and again was wrong thanks :). But it didn't resolved the texture problem, it may come from the vertex ? maybe some points are joint together since cubes have some identical points due to the isometric view ?Poncho
A finely written question MadzPhysiography
Thanks to you :), unfortunately, i'm not sure there is a solution if the problem come from vertex :/Poncho
Could you try a checkerboard texture? That might give you more of a hint what is going on.Forecastle
Are you sure that your point calculations in the switch are correct? The code you've given seems to produce the same coordinates in two positions. Also, make sure that you're not combining sizes in pixels with tile coordinates anywhere.Rarebit
M
3

It looks like the texture coordinates might be outside of the texture.

If the pointPosition function refers to the p0, p1, p2, and p3 points in side.cpp, then it also looks like you're using those points as texture coordinates.

Consider how you would might create a 2D square-

//Create a VertexArray as quads.
sf::VertexArray vertices;
vertices.setPrimitiveType(sf::Quads);
vertices.resize(4);

//The square position values (same as sf::Vertex::position).
sf::Vector2f v0 = sf::Vector2f(10,  10);
sf::Vector2f v1 = sf::Vector2f(200, 10);
sf::Vector2f v2 = sf::Vector2f(200, 200);
sf::Vector2f v3 = sf::Vector2f(10,  200);

//The texture coordinates (same as sf::Vertex::texCoords).
sf::Vector2f tv0 = sf::Vector2f(0,                 0              );
sf::Vector2f tv1 = sf::Vector2f(0+tex.getSize().x, 0              );
sf::Vector2f tv2 = sf::Vector2f(0+tex.getSize().x, tex.getSize().y);
sf::Vector2f tv3 = sf::Vector2f(0,                 tex.getSize().y);

//Put them in vertices.
vertices[0] = sf::Vertex(v0,tv0);
vertices[1] = sf::Vertex(v1,tv1);
vertices[2] = sf::Vertex(v2,tv2);
vertices[3] = sf::Vertex(v3,tv3);

The square points don't have to be the same as the texture coordinates, since the texture coordinates will stretch to each square point. If you were to change a point in one of the square points, it may look like this.

BEFORE

enter image description here

AFTER (v2 changed to 200,300)

enter image description here

We don't need to change the texture coordinates at all, just the vertex positions.

I'm not sure if that's exactly what's going on here since I can't see what pointPosition is, but it's my best guess.

Also, trying to draw outside of a texture can result in it looking like the border pixels of the image are stretched (possibly what's happening in your example), and sometimes you can even display data from other information in video memory as a result of going beyond your texture's memory.

Merino answered 29/2, 2016 at 16:14 Comment(2)
I'm rewriting my engine since there was too many problems in there. I didn't know at all that we don't have to change texture's coordinates, thanks a lot for your time !Poncho
No problem. SFML also has a nice tutorial on their site for vertex arrays which can come in handy : sfml-dev.org/tutorials/2.3/graphics-vertex-array.phpMerino

© 2022 - 2024 — McMap. All rights reserved.