Search code examples
iosopengl-escocos2d-iphonegame-physicsparticles

Falling sand particle physic


I'm working on iOS app with sand particles simulation. Here is a video of alpha version showing the logic of it http://www.youtube.com/watch?v=cYgw6jHx6QE

But I have a problem with particle algorithm performance.

Now I'm doing it in the following way (app is made on cocos2d, but it does not really matter):

Every 0.03 seconds I get screen pixel data with

glReadPixels(0,0,WindowSize.width,WindowSize.height,GL_RGBA,GL_UNSIGNED_BYTE,&ScreenBuffer);

I also have a function to compare pixel color with background color

- (BOOL) GetColorAtPoint: (int) GetX : (int)GetY
{
    int YSize = (int)WindowSize.width*4;

    Byte R = ScreenBuffer[(YSize*GetY) + 0 + (4 * GetX)];
    Byte G = ScreenBuffer[(YSize*GetY) + 1 + (4 * GetX)];
    Byte B = ScreenBuffer[(YSize*GetY) + 2 + (4 * GetX)];
    Byte A = ScreenBuffer[(YSize*GetY) + 3 + (4 * GetX)];

    return (R==255 && G == 0 && B == 0 && A == 255);
}

I define struct for particles and have array for them

struct SandParticle
{
    CGPoint Position;

    BOOL CMTop;
    BOOL CMBottom;
    BOOL CMLeft;
    BOOL CMRight;
};

struct SandParticle SandMatrix[5000];

int ParticlesCounter;

So, my logic is following. Every 0.03 seconds I create new particle with SandParticle struct and add it to the SandMatrix array and increase ParticlesCounter. Then I iterate over SandMatrix array and for each particle I get background color (using GetColorAtPoint method mentioned above) on positions Y-1 for bottom, Y-1 X-1 for left, Y-1 X+1 for right. If background color is red, then particle can go down, left or right.

Full code for that is available here https://gist.github.com/8e6c4710950d17ed3d3c#L122 (do not judge strictly, it is a draft version)

The main problem is, that I have frame-rate drops on iOS device (everything is ok in Simulator) for particles quantity over ±800. The problem is an iteration cycle (UpdateParticles method). But I don't have any idea how I can make it in another way. Is there anything I can do here?


Solution

  • I don't know exactly the algo, but usually good random generators are rather slow; maybe you could avoid that call, doing it at the initialization phase, filling an array and getting the value by index like

           int Randomized = precomputed_arc4rand_unif2[CPLoop];
    

    Supposing optimizations are at their best, I think rearranging code shouldn't give important benefits in term of performance, except maybe you can check if to continue before copying into CurrentParticle, and in general you could avoid such a copy, if you want a shorter way to write it, use a define or go through a pointer (but maybe optimization saves this too), i.e.

          struct SandParticle *CurrentParticle = &SandMatrix[CPLoop];
    

    and then you do CurrentParticle-> instead of CurrentParticle. and delete the final "copy-back" of CurrentParticle, which is not needed.

    But I don't know if it would make the performance so much better.