Pixel perfect collision

Like in topic. I want to make very accurate collision system, so I’m trying to use pixel perfect collision. I think I tried to find a solution almost everywhere, but I haven’t found any satisfactory solution. I am writing in Java.

This is my current algorithm:

protected boolean accurateTest(int object1, int object2) {
        glClear(GL_STENCIL_BUFFER_BIT);

        glStencilFunc(GL_ALWAYS, 1, 1);
        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

        Core.List.get(object1).Draw;

        glStencilFunc(GL_EQUAL, 1, 1);
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

        glBeginQuery(GL_SAMPLES_PASSED, occquery);

        Core.List.get(object2).Draw;

        glEndQuery(GL_SAMPLES_PASSED);

        
        do {
            glGetQueryObject(occquery, GL_QUERY_RESULT_AVAILABLE, samples);
        } while (samples.get(0) == 0);
        
        glGetQueryObject(occquery, GL_QUERY_RESULT, samples);
        
        return samples.get(0) > 0;
    }

This algorithm works well, but it has one very big drawback - I can only specify the number of pixels that have collided, but not collision coordinates. Outside that, I’m not sure this will work outside screen.

Now the question - is it possible to make pixel perfect collision (or at least very accurate collision detection for irregular shapes) and get coordinates of pixel(s) that have collided? If yes, I would be very grateful if someone will give a link to examples or show how can I handle this problem.

You can use glReadPixels, and loop through the results to check which ones are hitting. You can then derive the coordinates from it.

You can also do it entirely in software, including storing the texture. SFML’s sf::Image class does this AFAIK: sf::Image Class Reference (SFML / Learn / 2.0 Documentation)

I wouldn’t recommend using an occlusion query for this. It is very slow. But then again, pixel perfect collision detection in general is very slow anyways.

I may not be able to change your mind, but you may want to reconsider using pixel perfect collision detection. It is not commonly used, especially because it is very slow. It is better to use a real physics library for collisions, where you can specify hulls to match shapes (there are even some graphical tools for this) like Box2D: http://box2d.org/

This is the usual trade-off. If you want it perfect, it’s probably not going to be fast - that’s way you don’t find that much bidirectional path-tracing in games as of yet. :wink:

I would ask myself: “Do I really need such a degree of precision? What is it I want to achieve?”

You may now elaborate.

I’ll try to achieve the goal using this method - if it will be too slow, I’ll use jBox2d or jBullet.

My next question - how can I read a bitmap? I found a solution for scene with RGBA values, but I am disabling RGBA before starting collision test, so I can read only stencil data.

Read a bitmap from the hard drive? Read pixels from a texture?

Read pixels from screen. I want to read pixel coordinates from occlusion query. I have switched off color mask (RGBA), because collision detection without it is much faster.

Reading pixels from screen and from a textures (i.e. framebuffer attachment) is essentially the same, only when using FBOs you read from texture memory while otherwise you read from memory provided by the underlying window system
also called the default framebuffer (DFB - note that this abbreviation is NOT common, I just use it here).

You can use glReadPixels()for this purpose. This will read from any color, the depth and/or the stencil attachment in a FBO or the DFB.

You can’t read anything from an occlusion query. You can get the result of a query - which, in case of occlusion queries, is either the number of samples passed (GL_ARB_occlusion_query) or a boolean value if any samples passed (GL_ARB_occlusion_query2).

Why are you doing this? 2D collision dectection on the CPU isn’t that much of a miracle and frankly, I doubt using occlusion queries brute force, then reading back pixels from the stencil buffer and searching for collision coordinates is in any way faster than simple computation on the CPU.