Madz Madz - 2 months ago 11
C++ Question

sf::Texture applied in a wrong way

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).



Folers:

assets/numTexture/numLight.png


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

But texturing gones 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 bouding 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()...

Ben Ben
Answer

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.