Menu

pmask improvements

Anonymous
2009-05-02
2013-01-01
  • Anonymous

    Anonymous - 2009-05-02

    Hello!

    First, I would really like to thank you for your pmask library.
    I had searched for such a library for a long time, finding sdl-collide *very* unefficient.

    I wanted to use this library with SDL_image with an alpha channel, and I easily managed to modify the code to make it work, with something like:

    if(((SDL_Surface*)surface)->format->BitsPerPixel == 32) {
        if ( ((func(surface, x3, y+_y) >> 24) & 0xff) >= 128) {
            m |= 1;
        }
    }

    I tried the collisions with two relativly large pictures (190x181 and 174x175), and the collision occured perfectly. However, when I asked the collision position using check_pmask_collision_position, most of the points were accurate, but a few points weren't. I tried to read through the code what was wrong, but it took me time to understand what was going on, due to the very few comments in the code.
    I managed to find it: Somewhere in the code, you are calling:

    if( (raw1[py] >> dx) & raw2[py] )
    {
        rx += bsf((raw1[py] >> dx) & raw2[py]);
        goto found;
    }

    But the bsf function happen to read it's argument to 0, returning -1, which gives a very strange collision point. This was actually due to the type of arguments of bsf - you wrote:

    int bsf ( int a );

    Correcting to:

    int bsf ( long unsigned int a );

    solved the bug. However, this is not the end, as I still had from time to time random strange points, but this time only when I was compiling on my AMD64 architecture. After a few time I found the bsf function was still in cause, because the 0xFFFFFFFF mask was not tested. Here is the complete generic rewritten bsf function which doesn't seem to give me any more bugs both on x86 and amd64:

    int bsf ( long unsigned int a )
    {
            int r = 0;
            long unsigned int mask = -1;
            int i = (int)(log(mask)/log(2.0))+1;

            do
            {
                    if(!(a & mask))
                    {
                            r += i;
                            a >>= i;
                    }

                    i /= 2;
                    mask >>= i;
            }
            while(mask != 0x1);

            if(!(a & mask))
            {
                    r += i;
                    a >>= i;
            }

            return r;
    }

    As everything seem to be working, I'm trying to make the thing more fun by writing a function that could give the normal of the collided object, but I'm still not sure how to do it.

    Thank you for your great work :)

     
  • - 2011-03-15

    Sorry I didn't notice your post… I kinda forgot about pmask a while ago. 

    bsf bug:
    The bsf function is indeed supposed to operate on an PMASK_WORD_TYPE, not an integer, I'll fix that.  The bug would cause incorrect results for _check_pmask_collision_position and check_pmask_collision_position when sizeof(int) > 4 and/or when sizeof(int) < sizeof(PMASK_WORD_TYPE). 

    normal vector:
    You can move the masks around one pixel at a time to get a rough guestimate of the normal vector, but the limitations on that kind of operation are severe.  If the objects in question tend to be convex then it will probably be simpler, faster, and more accurate to simply assume that the normal vector is equal to the vector from from one center of gravity to the other.  That is the approach that I use in the 2nd test program (the one with 8000 asteroids bouncing around). 

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.