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 12435 times)

0 Members and 1 Guest are viewing this topic.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10815
    • View Profile
    • development blog
    • Email
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #15 on: April 23, 2015, 04:44:15 pm »
It looks more like the vertex position is off. Run your debugger and check the values, or cout them and check it manually.
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
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #16 on: April 23, 2015, 05:19:01 pm »
Yeah I'm pretty sure that it has to do with the way I am referencing elements of the vertex array. I'm trying to treat the vertex array which is 1 dimensional like a 4 dimensional array where the dimensions are chunks, x position in chunk, y position in chunk, and vertex index. I have found alot of ways to reference 2 or 3 dimensions as a 1 dimensional array but not 4 dimensions. Any tip on how to do this? Or am I going about this completely wrong?

jd.russell

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #17 on: April 23, 2015, 05:25:53 pm »
This is how I am declaring my vertex array:

In class header:
sf::VertexArray terrain;

In setup function:
terrain.setPrimitiveType(sf::Quads);
// chunks * chunk width * chunk height * number of vertices per quad
terrain.resize(16 * 64 * 64 * 4);

Is this incorrect?

Edit: Also, one other thought had occurred to me. Can I make an array of VertexArrays? If I can do this then I can simplify my code to treat each chunk individually and use the per chunk info as a 3d array. I like this option because it makes a bit more sense to me... and I don't really want to proceed until I know for sure how to go about doing this because I am dealing with large objects and I'm worried about memory and performance problems.
« Last Edit: April 23, 2015, 05:30:26 pm by jd.russell »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #18 on: April 23, 2015, 06:40:46 pm »
Can I make an array of VertexArrays?
Yes, vertex arrays are ordinary C++ objects, so you can put them wherever you like. I would use STL containers instead of raw arrays however. And if you have too many arrays, you're essentially defeating the point of using sf::VertexArray for fewer draw calls.

// chunks * chunk width * chunk height * number of vertices per quad
terrain.resize(16 * 64 * 64 * 4);

Is this incorrect?
Generally, multiplying each dimension seems correct. Since I don't know exactly what you mean with chunks and if you have everything uniformly spaced, I can't tell.

But you completely ignored eXpl0it3r's advice of having a look at the debugger. By doing so, you'll immediately find out if you do something wrong. For "mathematical" stuff like index calculation, it sometimes also helps to draw the problem in a simplified way on paper and verify if you're thinking correctly.
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 #19 on: April 23, 2015, 07:01:05 pm »
Oh I didn't ignore his advice, I just didn't mention that I looked at the debugger after I realized something was probably wrong with the indexing. :)

Something is indeed wrong with the indexing and I've almost fixed it but not quite (at least the cubes are not being stretched across the screen now lol):
terrain[(c * chunks) + (x * blockCount) + (y * blockCount) + 0].position = sf::Vector2f(isoX, isoY);
terrain[(c * chunks) + (x * blockCount) + (y * blockCount) + 1].position = sf::Vector2f(isoX + blockSize, isoY);
terrain[(c * chunks) + (x * blockCount) + (y * blockCount) + 2].position = sf::Vector2f(isoX + blockSize, isoY + blockSize);
terrain[(c * chunks) + (x * blockCount) + (y * blockCount) + 3].position = sf::Vector2f(isoX, isoY + blockSize);

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

Is what I'm using at the moment to input the positions and texture coordinates to each quad. Something's still not right, so I'm going to probably output a section of the indexes and find out what the indexes actually are being set as.

As far as what chunks mean, I'm planning on rendering the groups of blocks as "chunks" (term used in voxel games such as minecraft to denote the block of the level that is actually loaded to the screen). This way I can have a large map without incurring huge performance issues from having too many quads being drawn. In this instance my chunks are 2d sections of Quads that I want to render (i.e. the stuff the player is actually looking at).

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #20 on: April 23, 2015, 07:19:28 pm »
Yes, the indexing is wrong.

This time, you ignored my advice :P
Take pen and paper and check for a simple example why the indexing is wrong, and how you could improve it. That's how you solve problems as a programmer -- imagination, pen&paper, debugger... they're all engineering tools that you need to combine.

You said:
I have found alot of ways to reference 2 or 3 dimensions as a 1 dimensional array but not 4 dimensions.
If you know how to do it for 3D, you'll recognize the pattern, and you can extend it for 4D easily ;)

Oh, and use functions to compute the index, code duplication is terrible.
« Last Edit: April 23, 2015, 07:23:06 pm by Nexus »
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 #21 on: April 23, 2015, 07:21:17 pm »
I decided to cout all the indices since it was becoming a bit of a pain to compare in debugger each step, it's giving me output like this small section of indices:

608, 609, 610, 611
608, 609, 610, 611
608, 609, 610, 611
384, 385, 386, 387
400, 401, 402, 403
416, 417, 418, 419
416, 417, 418, 419
432, 433, 434, 435
432, 433, 434, 435
432, 433, 434, 435

Each row of four is an index being referenced inside the "z" loop (or the last loop of the terrain generation) so it is the 1st to 4th element in the array at that block location if that makes sense.

This tells me that there is still something wrong with the indexing of the array elements as I can see that the numbers are being repeated frequently (meaning the blocks are being drawn ontop of eachother). Still experimenting with ways to fix this, I am close but still missing something.

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #22 on: April 23, 2015, 07:21:38 pm »
Just want to mention a quick thing in relation to the original post.
If we are talking about "shutdown" as in "terminating the application", then it can sometimes make perfect sense to purposely leak objects. If the destructors of the objects are either trivial or otherwise perform no work that is persistent and we are terminating the application anyway, then leaking the memory and letting the OS clean up can be a perfectly valid (and fast) strategy.
I know the topic of this thread has moved on, just wanted to make that one point.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #23 on: April 23, 2015, 07:28:36 pm »
This tells me that there is still something wrong with the indexing of the array elements
Yes, read my post; I extended it afterwards.

Don't get it wrong, I consider it absolutely crucial that you learn how to solve such problems on your own, because you'll encounter them again and again as a programmer. (And btw, it has nothing to do with SFML, again...)

One possible approach is also to solve the problem starting with small pieces: compute indices for 2D, then 3D, then 4D. As I said the pattern is always the same.

Still experimenting with ways to fix this, I am close but still missing something.
Don't just "experiment" (aka random trial and error), approach the solution systematically.
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 #24 on: April 24, 2015, 12:20:51 pm »
Alright, it's fixed! Yay finally. Thought I'd share the result for those interested. This is the working relevant code I'm working on:

void Game::generateTerrain()
{
    noise::module::Perlin perlinNoise;

    cout<< "Generating Terrain: " << endl;

        // Initialize the map variables.
        mapWidth = 4;
        mapHeight = 4;
        chunkWidth = 8;
        chunkHeight = 8;
        blockSize = 32;
        mapDepth = 5;
        layer = 0;

    for(int mx = 0; mx < mapWidth; mx++)
    {
        for(int my = 0; my < mapHeight; my++)
        {
                        for(int x = 0; x < chunkWidth; x++)
                        {
                                for(int y = 0; y < chunkHeight; y++)
                                {
                                        // Get the depth value using Perlin Noise.
                                        float nOffX = ((float)x + (float)mx) / (float)(chunkWidth - 1.0f);
                                        float nOffY = ((float)y + (float)my) / (float)(chunkHeight - 1.0f);
                                        float nX = 128.0f + nOffX * (256.0f - 128.0f);
                                        float nY = 128.0f + nOffY * (256.0f - 128.0f);
                                        int depth = lround(perlinNoise.GetValue(nX,nY, 0.0f) * 10.0f);
                                        depth = noise::ClampValue(depth, 0, mapDepth);

                                        for(int z = -1; z < depth - layer; z++)
                                        {
                                                // Calculate the isometric x and y coordinates
                                                // Each corner of the rectangle that holds the cube forms a right triangle with an opposite side of 16 pixels.
                                                // We know this because the whole side of the rectangle is 32 pixels long and the side we can easily measure
                                                // is half of that length (where the cube's bottom point meets the line.
                                                // This opposite side is at an approximate 26.565 degree angle, which is the angle of 2:1 resolution isometric projection.
                                                // This gives us the equation (adjacent) a / 16 = tan(26.565) or solving for a = 16 * tan(26.565) which equates to approximately 8 pixels.
                                                // This means that our adjacent side is roughly 1/4 of our rectangle side.
                                                // To get our isometric values we want the rectangles to overlap so that we have an "overlap rectangle of 16 x 8 pixels.
                                                // This is the same as saying because we have a 2:1 perspective we need the overlap rectangle to be twice as wide as high.
                                                // Or the equation is 1/2 width x 1/4 height or 1/8 x width X height for the area of the overlap rectangle.
                                                // So to get the "isometricX" value we adjust along both the x and y 2D axis like this: ((x - y) * (blockSize / 2))
                                                // And to get the "isometricY" value we adjust along both the x and y 2D axis like this: ((x + y) * (blockSize / 4))
                                                // To input the z or "depth" value we adjust along both the x and y 2D axis like this:
                                                // isoX = ((x - y) * blockSize / 2) + (z * blockSize / 2)
                                                // isoY = ((y + x) * blockSize / 4) + (z * blockSize / 2)
                                                // chunkOffsetX = (mx - my) * chunkWidth * blockSize / 2
                                                // chunkOffsetY = (mx + my) * chunkHeight * blockSize / 4
                                                int isoX = ((mx - my) * chunkWidth * blockSize / 2) + ((x - y) * blockSize / 2);
                                                int isoY = ((mx + my) * chunkHeight * blockSize / 4) + ((x + y) * blockSize / 4) - (z * blockSize / 2);
                                                cout << isoX << ", " << isoY << endl;
                                                sf::Vertex v1, v2, v3, v4;
                                                v1.position = sf::Vector2f(isoX                         , isoY);
                                                v2.position = sf::Vector2f(isoX + blockSize     , isoY);
                                                v3.position = sf::Vector2f(isoX + blockSize     , isoY + blockSize);
                                                v4.position = sf::Vector2f(isoX                         , isoY + blockSize);
                                                v1.texCoords = sf::Vector2f(0, 0);
                                                v2.texCoords = sf::Vector2f(32, 0);
                                                v3.texCoords = sf::Vector2f(32, 32);
                                                v4.texCoords = sf::Vector2f(0, 32);
                                                terrain.append(v1);
                                                terrain.append(v2);
                                                terrain.append(v3);
                                                terrain.append(v4);
                                        }
                                }
                        }
        }
    }
}

And the output looks like this so far:



So once I realized there was an append method to the VertexArray it was rather easy to add the Quads at the correct index. Don't know if this will cause problems later with trying to reference the blocks for removal or adding new blocks but I think I'm on the right track at least. :)

Right now the terrain is not looking the way I want but that is more due to the noise algorithm setup I'm using I think. And of course if you look carefully all the chunks are the same (which is not what I want) so I need to fix that as well.

On a side note, running this program makes my graphics card "hum" or whistle very faintly ( at least I think this is the graphics card ), I don't know if this because of Linux or if it is because of something else (perhaps I'm doing something wrong). The total number of vertices for this map is something like 20000 (well below the limits of a modern graphics card like mine). So I'm confused as to why it is doing this. Anyways I will test the code in windows, to see if the problem is the same there.

jd.russell

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #25 on: April 24, 2015, 03:38:17 pm »
Ok, so I did some more research on the buzzing or humming noise I was experiencing yesterday... I think it may be coil vibrations from the graphics card. Surely this is not normal for an application with so few quads being rendered. Could this possibly be due to me not limiting the framerate yet? I also read that vsync can be related to this problem in some way.

I haven't tested on windows yet but will do that shortly.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10815
    • View Profile
    • development blog
    • Email
AW: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #26 on: April 24, 2015, 03:48:42 pm »
Yes, that's most likely coil whining and it probably happwns because you're maxing your GPU by not limiting the framerate. VSync will help since it limits the framerate as well.
Just don't mix setVerticalsyncEnabled and setFramerateLimit!

You most likely also hear it when you run a graphics heavy game without framerate limitation. ;)
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
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #27 on: April 24, 2015, 03:59:57 pm »
I've never noticed it before, but it sounds like I need to limit the frame rate regardless and it may remove the problem. I can't very well be maxing out peoples graphics cards while playing my game and causing noise issues. I mean after all I am just displaying about 5000ish quads which is not much for a modern game. :P

Ok, back to the tutorials on how to set and limit framerate. Also, with the don't mix the enable vsync and limit framerate options you are saying don't mix those? I don't plan on it but why don't I want to do that (just for my knowledge).

G.

  • Hero Member
  • *****
  • Posts: 1592
    • View Profile
Re: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #28 on: April 24, 2015, 04:03:25 pm »
Enabling vsync already limits the framerate, it wouldn't mean anything to mix both.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10815
    • View Profile
    • development blog
    • Email
AW: Deleting a dynamically allocated (large) array of sprites at shutdown?
« Reply #29 on: April 24, 2015, 04:08:36 pm »
VSync is done in the graphics driver and the framelimit is implemented in SFML with putting a thread to sleep. Having both active will lead to the mechanisms to counteract.
Learn about both more and it will be logical. ;)

Also not every GPU suffers from coil whining.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

 

anything