Advice on pixel collision detection

Started by
5 comments, last by LilBudyWizer 18 years, 4 months ago
Hello, I am using SDL and OpenGL to draw 2d sprites on the screen. I use SDL to load a bitmap and then I save the texture to my texture manager which uses opengl GLuint to keep track of it. After this I load and apply the texture (or a portion of it depending on what I load from my texture manager) and display that on an opengl quad. A portion of the quad will end up being translucent. Let's say I have two quads set up as described above. I know where both of their positions are and I've already determined that the quads are overlapping eachother via a bounding box method. How would I determine if the non-translucent pixels of one were hitting the non-translucent pixels of the other and get the positions for the pixels touching eachother? Is there an easy way to do this, or will I have to somehow manually go through each of the GLuint textures and check them against eachother (factoring in the rotation and positioning of each of the quads) to determine pixel collisions? I'm not very familiar with the how opengl stores it's textures, and I don't really need to know exactly how if someone has an example of how to simply store the information of one in a 2d array or to even directly access one per pixel for detections like this. Any advice? I was planning on looking into GLuint and writing something to read that into an easily comparable format, but I figured it would be better to ask first and see if anyone had any better ideas on how to go about this. Here is an example of how I was going to approach this from an abstract level (any advice or examples on how to implement this would be appreciated as well.)


     /\ _______
    /  \|POLY 2|
   /    \--    |
  /POLY1|\v|   |
  \     |v\|   |
   \    |v/|   |
    \   |/v|   |
     \  /---   |
      \/|      |
        |______|




The squared off area of 'v's would be the section I'm looking at making a temporary array of. Basically a box surrounding the complete area of collision possibility. From here I would read in first the values from poly 1. I would store a 1 in each position which is opaque. Then I would read in poly 2 and increment each cell of the array by 1. Then, I would take the resulting array and would check to see which positions contained a 2. Each position containing a 2 would be counted as a point of collision and I would pass a list of coordinates of collisions (taken from the array and translated back into real screen coordinates) to the proper function to handle the collision. Does this sound silly? If not, how should I go about reading the textures? I can rotate them myself if I have to, the main problem for me is that I don't know the format they are stored in and I really want to be sure I'm doing this properly before I try implementing it. I should mention that OpenGL is set up for 2d and I'm going based off pixel coordinates rather than an arbitrary unit, but it's not terribly vital to know this. I'm also posting in OpenGL rather than the math and physics section because it's not necisserally the collision detection that I'm worrying about most, but the proprietary texture format for OpenGL, but if the moderators think it should go to math and physics that's alright. *EDIT: I totally forgot to mention that I'll be loading PNGs later, not BMPs as I currently am. Sorry if anyone misses this before an answer. SDL can load PNGs, I've never done it though. I need a way of keeping track of the transparancy too, I know you can automatically use a PNG's transparancy, does SDL do this automatically? Does OpenGL manage to read that when it stores the texture or what do I have to do to get it to store that? This question is kind of two fold. 1: How do I read individual pixels for transparancy and 2: How do I keep transparancy from a PNG and make it work with OpenGL after loading it with SDL? [Edited by - M2tM on December 16, 2005 2:17:14 PM]
_______________________"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
Advertisement
Description too long?

Summary:

Problem 1:
need to load a PNG with transparancy in sdl (or a cross platform method)
need to load that PNG into opengl maintaining transparancy
need to display the png on a quad as a texture with transparancy

Problem 2:
Need to detect which non-transparent pixels overlap between two quads in 2d space with OpenGL.
We can assume the quads are partially or wholly overlapping.

I have a theory on how to do this and I can do the math behind the collisions, I just don't know how to read portions of GLint stored textures and figure out their transparancy on a pixel by pixel basis.
_______________________"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
Not too long, just no easy answer. Just as an example you can use blending. You use GL_SRC_ALPHA for the source to draw the first and GL_DEST_ALPHA to draw the second with GL_ZERO for the destination in both. Within the overlap region the only pixels set at the end are the ones opaque in both and those are set to the values from the second image. You then have to read back the overlap region. That reading back means you would most likely do it faster in the program. Particularly since you are using the frame buffer as a work area for collision detection and have to clear it when you are done. That the images are rotated means doing it in the program isn't a particularly easy task, especially to reproduce to the pixel what you would have gotten from the blending which will match what you see. So personally I can think if many ways to do it, but none I would consider good.
Keys to success: Ability, ambition and opportunity.
Quote:Original post by LilBudyWizer
So personally I can think if many ways to do it, but none I would consider good.


Yup, that's exactly what I was thinking.

I was thinking that there would possibly be a blending method to somehow visually represent the solution, but I'm an OpenGL noob and wasn't sure if there would be any way to get the "answer" from the visual representation. That lead me to deciding to approach this programatically which would probably still be messy, but at least I'd have all the information (whereas I have no idea how I'd grab the info from the screen with blending especially with backgrounds factored in...)

I have both the textures, I have both their positions and both their rotations, and from there I figured if there was some easy way to read the pixels individually from each texture I could solve the problem from there. I'm not worried about "figuring out" how to manually do the rotations and check the results once I have the textures loaded into an easily checkable format (such as my array where transparant pixels are 0 and opaque are 1), but the performance might not be ideal. My plan is to try implementing before optimizing though. It is just a 2d game afterall and we cut down a lot on the testing by only performing the per-pixel manual test on already colliding quads.

*edit: PS, thank you for your words. I'm definitly + ranking anyone with help.
_______________________"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
Does it have to be a pixel-based solution? Or would a geometric solution be an option? If you're interested in other options, here are a couple of questions:

1. What kinds of shapes are you dealing with for your sprites? Are they convex shapes (like a circle or box) or concave/arbitrary (like an asteroid, spaceship, or character)?

2. What do you intend to do with the collision information? Do you want to resolve the collision (i.e. move the objects by the shortest vector that will resolve the interpenetration), or just blow them up (like in an asteroids game)?

If you're still looking for options, the answers to those questions will help in making reasonable suggestions.
Another option would be to store polygon information about the shape of the limbs. But I'd have to do this for each different texture which I want to avoid.

What I have being set up:
-Skeleton system with joints and bones.
-Bones are represented by textured quads.
-the textures on the quads (and the width and length of those quads) can be swapped as the skeleton shifts positions based on desired keyframe positions. (Ex: player looks towards us, then turns which squashes the quad's width (width is the perpendicular scale to length where length of the quad is equal to the length of the bone) the quad representing the torso and flips to a different texture)
-attacks are to be precise as the character's arm has a lot of control and it's the combat system which will be the main innovation.

I'm toying with the idea of damage as well. Damage could be indicated by detachable limbs if the joint is smacked hard enough (or an area around the joint rather) and could be indicated by blood as well... The difficulty with blood splatters is the high dynamic nature of the characters and the fact that the textures change to reflect position. Example. character faces us, then turns and faces away from the camera which should obscure the blood. How to represent this? I'll work on that, perhapse storing actual pseudo 3d rotation of the blood splatters as well and factoring those in somehow... But that's just an idea and I'll look into it after I get collisions.

Detachable limbs is a definite and per-pixel collisions is important to me because it can also be used to figure out how much damage is done. Sword intercepts with 30 pixels does more damage than 10 pixels. Modify that by the body part attacked (ie: arms do less damage than head or torso) and the damage system could be fairly good too.

The shape of the actual textures on the quads is arbitrary and may include concave shapes (picture spikes on armour which hook up and back, or fingers) however ultimately I need to know how to read the textures pixel by pixel and that's all I need to know, it's not the same as creating a polygon and detecting the collision unless you derive a polygon from the textures and then run an operation, but since the textures exist in a limited amount of pixels I think it would be more efficient to just compare pixels and be done with it. I was just looking for someone who might have done some similar pixel by pixel reading from the opengl texture format before, and hopefully finding out the included alpha value of those individual pixels if there is one on opengl textures.


In essence, assume I know that I want pixel based collisions as I am dealing with textures, not polys. I've thought about approximations with the polys being stored along with each texture, but that will take more setup for each character and will not be as accurate (though it might be faster.)

I'm pretty sure I want what I've described. I'm not 100% against other options or somehow detecting the edges of the textures, that's fine too, but I don't think it will be easier than just reading the pixels for the portions that are intercepting.

I am not asking about collision detection primarily, that's just what I'm accomplishing with this.


I'm asking about how to iterate through an opengl texture's individual pixels and how to determine the alpha value if that's stored or not.

*edit: has anyone ever drawn on a texture with the mouse or a tablet? Like a painting program? I'd assume you'd need to know how to do something like this for that to work.

[Edited by - M2tM on December 16, 2005 6:30:54 PM]
_______________________"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
Well, you use glGetTexImage to read the pixels of a texture. You specify a format and data type just as you did when you loaded the texture. What the original format was or how it is stored internally doesn't matter. It will be returned in the format you specified.

One thought is don't rotate your quads. Rather scale your quads so they can completely contain the rotated texture. Give the textures a transparent border color and clamp them. Then use the texture coordinates to actually rotate the textures. Then you always draw screen aligned quads. All you have to do is read the overlapped regions back.

If multiple sprites may collide it would most likely be best to draw all of them before you start reading back the overlapped regions. That might help the concurrency between the GPU and the CPU, i.e. it can be drawing quads while you are calculating quads. You're going to sync on the read though so you might as well do all your reads at once so it is logically one sync point.

With a bit of planning you might be able to avoid a clear and complete redraw. Draw all your sprites, deal with the overlap and just redraw those. I think you can use the alpha test to draw the background last. I believe the transparent pixels set the depth even though they are not visible so the depth test would leave blank the transparent pixels.

It most likely wouldn't make a differance with a middle of the road 3D graphics accelerator, but it might make a big differance with a 2D graphics card. Using quads and textures may mean you don't use the blitting hardware at all which would make your fillrate downright brutal. If so then you don't want to redraw anything you don't have to.
Keys to success: Ability, ambition and opportunity.

This topic is closed to new replies.

Advertisement