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

Author Topic: Deleting a dynamically allocated (large) array of sprites at shutdown?  (Read 12454 times)

0 Members and 1 Guest are viewing this topic.

jd.russell

  • Newbie
  • *
  • Posts: 19
    • View Profile
Hi, I'm new here, and I'm creating a game using SFML. It's a 2D isometric game with coherent terrain generation using perlinnoise. What I am doing is creating a dynamically allocated array of sf::Sprite objects to draw to the screen during my render method. The array is somewhere in the neighborhood of 65k elements in the current state (this will probably be a medium sized map and will increase to upwards of 300k if possible). So I'm having to dynamically allocate the memory before assigning the sprite textures and positions in isometric 2d space. My question is this... won't I have to delete the array at program shutdown? I tried doing so but, no matter where I put the delete statement the debug output says I'm trying to delete an invalid pointer. Do I have to delete this array or is SFML doing that for me? And while I'm at it I should probably ask if there is a better way to do what I'm doing?

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Make it an array of smart pointers (std::unique_ptr most likely, alternatively std::shared_ptr if you need shared ownership). Then when the array goes out of scope the shared pointers will take care of deleting the objects they point to.

See also: Why RAII rocks

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
What about using a std::vector?

Also with that amount of sprites, it might be better to use a vertex array. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

jd.russell

  • Newbie
  • *
  • Posts: 19
    • View Profile
Ok, options are as I see it based on responses:

1. std::unique_ptr <-- I've never used this before though I do know about it a little bit. So I'm at a loss here as to how I would use this for my purposes.

2. std::vector <-- I've used this extensively before in the past in other applications. I really like it for keeping track of dynamic lists of things.  I think this would probably suite my purposes a bit better, but question is does this handle memory allocation for me? I forget.

3. vertex array <-- I remember reading about this somewhere, but I don't remember what it is and even less how to use it for what I'm doing. Could someone give me a small run-down on what this is exactly, it's not like a vertex buffer from OpenGL / DirectX is it?

Are there any other options here that I should be aware of? And another question is what would be the comparable performance gains for the above methods?

jd.russell

  • Newbie
  • *
  • Posts: 19
    • View Profile
Ok, I've already answered Question number 3 about vertex arrays. They are apparently similiar to vertex buffers that I'm used to working with before to create mesh objects. Question is how would I dynamically create a mesh that could display my 2D textures in the right positions? Would it need to be Triangles or a TriangleStrips? I'm a bit confused as to how to proceed.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Take a look at the article Jesper linked (RAII).
However in your case I don't think an unique_ptr would make sense.

A vector is basically a dynamic array, so yes, no need to manually management memory.
Also this is basic C++, you should really learn C++ first properly.

See the tutorials about the vertex array.

My personal suggestion is to use a std::vector<sf::Vertex>.

Sprites are essentially just Quads, so that'd probably be the best primitive.
« Last Edit: April 20, 2015, 03:50:45 pm by eXpl0it3r »
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

jd.russell

  • Newbie
  • *
  • Posts: 19
    • View Profile
Well, I am self taught. I'm sorry if I came off as incompetent. I just couldn't remember if std::vectors were dynamically allocated or not. I have been programming C++ and C# and Java and many other languages now for at least 10 years off and on... I think I know enough about the basics for the most part. And this is not my first game project, but it certainly the most complex project I've under taken.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
It doesn't really matter how many other programming languages you know or how long you've been working with these. Because none of these other languages have the C++ standard library and regardless of how long you've been writing C#, you won't magical know it either. Keep in mind here, I'm not trying to offend you, but I'm trying to help you. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

jd.russell

  • Newbie
  • *
  • Posts: 19
    • View Profile
Also, just to clarify my post earlier, I already looked up the documentation on the Vertex Arrays. I understand better now, these are very similar or practically the same as Vertex Buffers in DirectX and OpenGL with the addition of dynamic memory allocation (and I'm assuming a few other features) built in. My question was, how do I go about building a mesh object with this that could display all of the isometric pixel art textures that I've created in the correct order (to keep the appearance of 2D). I understand how to use it in a basic fashion just based on reading the docs.

What I really need to know is if I would get more performance from using triangles (for separated Quads) quads (for separated Quads) or trianglestrips ( for connected Quads)? And if it is the last one, I'm at a complete loss as to how to go about creating a mesh with connected Quads that would actually display the textures in the fashion that I want. Does anyone have a resource I could look at that deals with this exact issue?

I'm not asking to be spoon fed just looking for some help here.

jd.russell

  • Newbie
  • *
  • Posts: 19
    • View Profile
It doesn't really matter how many other programming languages you know or how long you've been working with these. Because none of these other languages have the C++ standard library and regardless of how long you've been writing C#, you won't magical know it either. Keep in mind here, I'm not trying to offend you, but I'm trying to help you. ;)

Ok well, I have worked with the std library pretty extensively and I've used vectors before, I just forgot that they were dynamically allocated because I haven't used them in a while. This is not to say I do not understand the concept of a dynamic array because I do. And I don't think anyone even fully refreshed on the topic knows every single aspect of standard library off the top of their head. At least I don't even though I've worked with it pretty extensively, I have to refresh myself especially if I am coming back from a hiatus from programming. I do not particularly think this means I don't know C++, just that I have memory issues. There is a difference in my mind between refreshing my memory in one aspect of the standard library and "you need to learn C++" which yeah does seem like a bit of an insult. It's really ok though, I'm over it. I just want some help here on my project.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #10 on: April 20, 2015, 05:01:31 pm »
I understand better now, these are very similar or practically the same as Vertex Buffers in DirectX and OpenGL with the addition of dynamic memory allocation (and I'm assuming a few other features) built in.
No, OpenGL Vertex Buffer Objects (VBOs) are a different concept, they reside completely in video memory on the graphics card.

What I really need to know is if I would get more performance from using triangles (for separated Quads) quads (for separated Quads) or trianglestrips ( for connected Quads)?
It really depends on your hardware and even more on your driver, it's difficult to say that in general. Chances are that quads are split into triangles anyway. I would use the simplest geometry (quads) unless you get real performance issues. Of course, you can also do a benchmark.

And don't be upset about the C++ comment, we advise everybody who's not certain at the STL and memory management to refresh those topics, as they're really crucial, and knowing them well can save you a lot of trouble and time :)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

jd.russell

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #11 on: April 20, 2015, 05:10:51 pm »
Yeah, I apologize for getting upset. It probably is good advice, to refresh myself on these concepts and will do so as I go along.

Anyways moving on, that's very interesting that you say they are a completely different concept from VBOs, so these Vertex Arrays give access to the CPU as well I take it and that's why they would be manipulated alot easier? Any resource you could give me that might clarify the difference? I'd really like to understand as much about the Vertex Arrays as possible before I move on. And I did read all the documentation page on them but I must be missing something fundamental here.

Also, someone on another forum suggested I map the textures on to small 3d cube primitives by unwrapping them in a isometric style orthographic projection, but I am unclear on some of the details on that. Any ideas what might be the advantages of doing that over using Quads or sprites?

And about the benchmark. I'm reading on the SFML clock class right now. Would I do a benchmark measuring the framerate with that or are you just talking in general? Because this is a project I'll eventually want to make commercial (if it turns out well) I'd probably have to do some testing on different systems then to get a minimum system specs requirement.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #12 on: April 20, 2015, 05:57:20 pm »
so these Vertex Arrays give access to the CPU as well I take it and that's why they would be manipulated alot easier?
Their vertex data is just stored in RAM like any dynamic array (in fact, sf::VertexArray stores a std::vector<sf::Vertex>). When the vertices are drawn, the whole vertex data is uploaded to the graphics card. The corresponding code can be found here. The functions glVertexPointer, glColorPointer and glTexCoordPointer specify where the data for vertex positions, vertex colors and texture coordinates lies. Upon calling glDrawArrays, this data is loaded from the RAM to the graphics card's memory.

Any resource you could give me that might clarify the difference?
You could have a look at the documentation of the above-mentioned functions on www.opengl.org, for example https://www.opengl.org/sdk/docs/man/html/glDrawArrays.xhtml. Or https://www.opengl.org/wiki/Vertex_Specification. Don't confuse this technique with Vertex Array Objects (VAOs) -- it's merely a way of passing all the data to the graphics card at once, instead of once for each attribute in each primitive (old-school glBegin/glEnd rendering).


Also, someone on another forum suggested I map the textures on to small 3d cube primitives by unwrapping them in a isometric style orthographic projection, but I am unclear on some of the details on that.
Why would you need a cube for 2D rendering? I don't know what he meant.

And about the benchmark. I'm reading on the SFML clock class right now. Would I do a benchmark measuring the framerate with that or are you just talking in general?
Don't measure frame rates, they're not expressive. Measure times. Yes, you can use sf::Clock for that.

But keep in mind that a proper benchmark must fulfill the following conditions:
  • The operation to measure must take up most of the time while measuring
  • The operation must be repeated a sufficient number of times (you can't measure a single function call)
  • Make sure the order of operation doesn't affect the result, randomize where necessary
  • Compile in release mode, and without running debugger, and with full optimizations
And to be honest, I think you should invest your time better than deciding between quads and triangles. First, there are most likely other performance bottlenecks in your application. Second, if you find out that this should be a real issue, you can still change it within minutes. Of course, that requires you to build a reasonable abstraction so that you don't deal with raw sf::VertexArrays in hundreds of places, but separating graphics from the game logic is a good idea anyway.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
However in your case I don't think an unique_ptr would make sense.
unique_ptr may not be the best fit, but that suggestion was triggered by the original question mentioning an array of dynamically allocated types. And for dynamically (heap) allocated objects std::unique_ptr is very often the natural thing to use :-)

Ohh and btw, I completely agree with using a std::vector (or sometimes a std::array) over a build-in array in most situations. Vector is definately the "go-to" container unless you have special needs and really know what you are doing and why. :-)
« Last Edit: April 20, 2015, 07:06:23 pm by Jesper Juhl »

jd.russell

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #14 on: April 23, 2015, 04:14:53 pm »
Ok, I'm back with a few more questions. This time about the Vertex Arrays. Should I make a separate post to be asking this stuff since this problem is basically resolved or is it ok to post here?

Anyways, I need a bit of help with the output I'm getting from the draw call to the VertexArray.

I'm using this code so far to create the vertex array:

    int chunks = 16;
    int blockCount = 64;
    int blockSize = 32;
    int depth = 10;
    int layer = 0;
    noise::module::Perlin perlinNoise;

    for(int c = 0; c < chunks; c++)
    {
        for (int x = 0; x < blockCount; x++)
        {
            for (int y = 0; y < blockCount; y++)
            {
                // Get the depth value.
                float nOffX = (float)x / (float)(blockCount - 1);
                float nOffY = (float)y / (float)(blockCount - 1);
                float nX = 128.0f + nOffX * (256.0f - 128.0f);
                float nY = 128.0f + nOffY * (256.0f - 128.0f);
                int maxDepth = lround(perlinNoise.GetValue(nX,nY, 0) * 10);
                maxDepth = noise::ClampValue(maxDepth, 0, depth);

                for (int z = -1; z < maxDepth - layer; z++)
                {
                    // Adjust for Isometric Coordinates.
                    int isoX = (((x - (z * 2)) + y) *  blockSize / 4);
                    int isoY = ((y - x) * blockSize / 2);
                    isoX += (blockCount * blockSize / 2) - (blockSize / 2);
                    isoY += (blockCount * blockSize / 2) - (blockSize / 2);

                    terrain[0 + (c * (x * blockCount + y))].position = sf::Vector2f(isoX, isoY);
                    terrain[1 + (c * (x * blockCount + y))].position = sf::Vector2f(isoX + blockSize, isoY);
                    terrain[2 + (c * (x * blockCount + y))].position = sf::Vector2f(isoX + blockSize, isoY + blockSize);
                    terrain[3 + (c * (x * blockCount + y))].position = sf::Vector2f(isoX, isoY + blockSize);

                    terrain[0 + (c * (x * blockCount + y))].texCoords = sf::Vector2f(0.0f, 0.0f);
                    terrain[1 + (c * (x * blockCount + y))].texCoords = sf::Vector2f(32.0f, 0.0f);
                    terrain[2 + (c * (x * blockCount + y))].texCoords = sf::Vector2f(32.0f, 32.0f);
                    terrain[3 + (c * (x * blockCount + y))].texCoords = sf::Vector2f(0.0f, 32.0f);
                }
            }
        }
    }

And I'm getting a very stretched output that seems to stem from the origin of the grid.



What am I doing wrong here? I don't think it's the texture coordinates although I could be wrong, the docs say that the texture coordinates are not normalized and that they are in pixel coordinates of the desired texture (mine is a 32x32 isometric pixel art block).

So I'm wondering if it's not the way I'm plugging in my isometric coordinates for the blocks.

 

anything