Search code examples
copengl2dcollision-detectionglut

Two questions about SOIL, OpenGL and GLUT


Two questions about these three:

  1. How can you load only a PART of an image in a texture (GLuint) using SOIL. I can load a full PNG picture but I can't figure out how to load only a PART of it. As in animations. for example HERE which is an animation of a shooting catapult. How do I load only a part of it ? (With known location of pixels needed for that part).

  2. How to do Pixel-per-pixel collision detection using glReadPixels();? I succeeded using the function to read pixels off the screen but I'm not sure when to use it. First I thought about when loading a texture, analyze its limits (the pixels that might collide and not all the pixels) into a certain pattern and then when a grid of a certain PNG crosses another - analyze if the pixels of both textures in the certain X and Y are meant to be touching each other and colliding. I'm not sure how to do that (using glReadPixels or any other function to read pixels off of the PNG texture which ISN'T on screen yet). Any idea to make Pixel-per-pixel 2D collision ? OR a better 2D collision detection algorithm ?


Solution

  • 1) To read only part of an image as a texture, one method is to read the entire image and load it into a texture. You can then create a new texture using the glTexSubImage2D() call. This is particularly convenient for sprites because you can call it repeatedly, changing the x and y offset to pull out the different frames of your animation.

    2) Collision detection is a big topic and too broad to answer in a single question like this. You should look up QuadTrees (or if you're working in 3D, KdTrees). They partition the space so you can compare the bounding boxes of your various sprites efficiently. Once you find 2 sprites whose bounding boxes overlap, you can test them more closely to see if they overlap. Usually you can use some trick such as blitting their 1-bit masks to the same small texture (with the proper relative offsets) using an AND-like blend mode (where the output is 1 only when both inputs are 1) and seeing if any pixels in the resulting texture are turned on. That way you're only scanning an area that is at most the size of the 2 textures, and not the entire window.

    To expand on what I'm trying to describe above with the AND-like blend mode, you have the following scenario:

    2 1-bit sprite masks where each pixel is 0 if the sprite does not cover that pixel and 1 if it does. These are the input textures.

    1 1-bit output texture where the 2 sprites will be drawn

    For each pixel of the output, you have 4 possibilities for the inputs:

    • 0-0 : both sprites are transparent at this output pixel, so they don't touch here
    • 1-0, 0-1: One sprite is transparent at this pixel, the other is not. Hence, they don't overlap
    • 1-1 : Both sprites are solid at this output pixel, so there's a collision

    If you write it as a truth table, it's the same as ANDing the 2 masks:

      | 0 | 1 |
    --+---+---+-
    0 | 0 | 0 |
    --+---+---+-
    1 | 0 | 1 |
    --+---+---+-