SFML community forums

Help => Graphics => Topic started by: sparkon on September 04, 2012, 05:57:43 pm

Title: Sprite and Texture errors
Post by: sparkon on September 04, 2012, 05:57:43 pm
Ok this might seem another post like : "The RenderWindow draws a sprite as a white box" and actually that's what is happening, but it's different!. I have got a simple std::vector<sf::Texture> that contains ~20 textures and it is stored in the class so it's not destroyed at the end of the scope. Then i've got a class for each Sprite, i'm using a class because i need to store a lot of thing.
The constructor from my sprite class is :
SpaceElement::SpaceElement(sf::Texture& t,unsigned short int Level) // don't look at Level is a game variable
{
        // Getting values
        Sprite.setTexture(t);
}
 
i'm simply setting the texture to the sprite withOUT losing the reference, because the Texture t is saved in a std::vector in my main class.
Great! everything is fine until here. Every frame i call the _draw() method from each sprite class
SpaceElement::_draw(sf::RenderWindow& Window)
{
    Window.draw(Sprite); // The sprite is the same of the initialization
}
 
and this is supposed to work, and it works! but just for 5-6 sprites, while i have almost 20 sprites in the vector, for the first ~12 textures it displays a white box, for the other 8 it displays the actual Texture, how is that possible?
I was thinking about some memory change but i have no clue... i'm in your hands
Title: Re: Sprite and Texture errors
Post by: FRex on September 04, 2012, 06:30:13 pm
Derive from sf::drawable for easier syntax. than your _draw.
Do you add textures to vector after setting some sprites? If yes then vector might realocated your textures already before you drew them.
Title: Re: Sprite and Texture errors
Post by: Mario on September 04, 2012, 06:45:22 pm
How is your vector defined? And when do you pass the reference to the texture (do you pass the vector's entry or the texture you copy into the vector)?

I think you're storing a copy of the texture in the vector, but you're somehow still referencing the original texture object, that's been destroyed.
Title: Re: Sprite and Texture errors
Post by: FRex on September 04, 2012, 06:50:10 pm
Content of vectors realocate after push_back if they run out of reserved memory(invalidates all pointers and references). Try using list, map or vector of pointers instead.
Title: Re: Sprite and Texture errors
Post by: sparkon on September 04, 2012, 07:11:36 pm
Frex so i shoul use a vector of pointer to the textures? Anyway after i created all the sprites after filling the vector with textures
Title: Re: Sprite and Texture errors
Post by: Nexus on September 04, 2012, 07:18:49 pm
Anyway after i created all the sprites after filling the vector with textures
Assuming the first "after" is there by accident: Make sure the sprites really refer to the textures in the vector, and that this vector remains untouched as soon as you assign the first textures to the sprites.

Otherwise, minimize your code until the error becomes obvious. You can also use a debugger.
Title: Re: Sprite and Texture errors
Post by: FRex on September 04, 2012, 07:19:33 pm
Try use std::list instead of vector and see if it fixes anything. Just replace std::vector<sf::Texture> with std::list<sf::Texture>, they have same interfaces, it shouldn't break any code.
Title: Re: Sprite and Texture errors
Post by: sparkon on September 04, 2012, 07:29:06 pm
Frex. with list it works! is there anyway to make it working with vectors, because i need indexing ( i know i could make it without indexing but it would be much slower)
Title: Re: Sprite and Texture errors
Post by: FRex on September 04, 2012, 07:34:22 pm
Use vector of raw pointers or smart pointers or try do: vector.reserve() with int amount of textures you will ever load(but if you load more than that the vector will realocate and any removal will invalidate pointers to all elements after removed element). If reserve doesn't work then just go with some pointers.
Title: Re: Sprite and Texture errors
Post by: sparkon on September 04, 2012, 07:35:38 pm
ok i'll go for that. But can you briefly explain me why that happened?
Title: Re: Sprite and Texture errors
Post by: FRex on September 04, 2012, 07:43:22 pm
Vectors are guaranteed to lay their contents like c-style arrays did(one after another, so random acess is fast) and they reserve a bit of extra space for few objects when they get constructed but if you add too many they will run out of this extra space and then realocate their content to another chunk of space, bigger than the last to prepare for next push_backs.
You can check how many objects there are with size() and how much more space is ready for next objects with capacity().
Title: Re: Sprite and Texture errors
Post by: eXpl0it3r on September 04, 2012, 07:48:06 pm
Vectors are guaranteed to lay their contents like c-style arrays did(one after another, so random acess is fast) and they reserve a bit of extra space for few objects when they get constructed but if you add too many they will run out of this extra space and then realocate their content to another chunk of space, bigger than the last to prepare for next push_backs.
You can check how many objects there are with size() and how much more space is ready for next objects with capacity().
Well just a reallocation shouldn't drop the validity of the content (I class won't get newly initialized).
The part the problems appears (I guess) is when the textures get copied from the old space to the new space and OpenGL somehow releases the texture, but I'm not quite sure...

Often one uses a std::map (or std::unordered_map) so one can connect a logical key to each texture.
Title: Re: Sprite and Texture errors
Post by: FRex on September 04, 2012, 07:53:44 pm
Quote
OpenGL somehow releases the texture
Don't be cussin like that around me. ;)
void Sprite::draw(RenderTarget& target, RenderStates states) const
{
    if (m_texture)
    {
        states.transform *= getTransform();
        states.texture = m_texture;
        target.draw(m_vertices, 4, Quads, states);
    }
}
But sprite holds pointer to sf texture not anything opengl and draws like that so there is garbage in the space where old texture pointer points to(maybe)?
Title: Re: Sprite and Texture errors
Post by: sparkon on September 04, 2012, 08:00:12 pm
FRex you said i should use drawable instead of passing the window reference, what do you mean?
Title: Re: Sprite and Texture errors
Post by: FRex on September 04, 2012, 08:01:18 pm
http://www.sfml-dev.org/documentation/2.0/classsf_1_1Drawable.php#details
Title: Re: Sprite and Texture errors
Post by: sparkon on September 04, 2012, 08:05:46 pm
FRex thank you for your time ! I've already changed my code :P
Title: Re: Sprite and Texture errors
Post by: eXpl0it3r on September 04, 2012, 08:18:20 pm
But sprite holds pointer to sf texture not anything opengl and draws like that so there is garbage in the space where old texture pointer points to(maybe)?
Oh I had somehow the impression you were talking about textures in a vector...
I don't see any reason why a reallocation & copy of a sprite vector should cause any problwm (unless there's no copy constructor forthe sprite).
Title: Re: Sprite and Texture errors
Post by: FRex on September 04, 2012, 08:21:10 pm
We were talking about textures in a vector. If vector realocates then sprites that held pointers to it's elements now contain garbage pointers.
Title: Re: Sprite and Texture errors
Post by: eXpl0it3r on September 04, 2012, 08:24:23 pm
We were talking about textures in a vector. If vector realocates then sprites that held pointers to it's elements now contain garbage pointers.
I see.
Sorry should've probably read the whole conversation in detail. ;-)
Title: Re: Sprite and Texture errors
Post by: FRex on September 04, 2012, 08:27:39 pm
Yeah ;) Also the copy c-tor of texture seems quite heavy so this idea is getting worse by the minute.