Jump to content
  • Advertisement
Sign in to follow this  
foursticksj

Pixel level collision with DirectX textures

This topic is 3248 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm working on an engine for a new project, and realized I will probably need pixel-level collision. The reason for this is that some of the game objects are irregular shapes like boomarangs, where a ball must stick to the object wherever it makes contact. Each image is loaded into a Direct3DTexture9, where it is stored along with the image properties in a seperate class. I beleive I must add an array containing the color information of each pixel to this class as well. Given this information of both images, I would compare the overlapped region (determined by bounding rectangles) and decide if there are any pixels which do not match either of the image's transparent color keys. How would I create this array, or how would I get DirectX to compare the overlapped region? Thanks in advance for help with this.

Share this post


Link to post
Share on other sites
Advertisement
Here's a way of doing it to study. I admittedly yanked this one out of a workshop. [embarrass]

//-----------------------------------------------------------------------------
// Name : SpritesIntersect () (Private)
// Desc : Determine if the two specified sprites intersect.
//-----------------------------------------------------------------------------
bool CGameApp::SpritesIntersect( RECT rcSprite1, LPDIRECT3DTEXTURE9 pSprite1, bool bFlipped1, RECT rcSprite2, LPDIRECT3DTEXTURE9 pSprite2, bool bFlipped2 )
{
RECT rcOverlap;
RECT rcLock1, rcLock2;
D3DLOCKED_RECT Lock1, Lock2;
ULONG *pData1, *pData2;
int x, y, nOffset1, nOffset2, nWidth1, nWidth2, nTemp;
bool bIntersecting = false;

// First determine if the two sprite rectangles intersect (broadphase / early out).
// Also computes the rectangle that describes how the two sprites overlap.
if ( IntersectRect( &rcOverlap, &rcSprite1, &rcSprite2 ) == FALSE )
return false;

// Transform the overlapping rectangle into "texture space" so that we can
// lock and process only the pixels of the texture which fall within the
// overlapping area.
nWidth1 = rcSprite1.right - rcSprite1.left;
rcLock1.left = rcOverlap.left - rcSprite1.left;
rcLock1.top = rcOverlap.top - rcSprite1.top;
rcLock1.right = rcOverlap.right - rcSprite1.left;
rcLock1.bottom = rcOverlap.bottom - rcSprite1.top;
nWidth2 = rcSprite2.right - rcSprite2.left;
rcLock2.left = rcOverlap.left - rcSprite2.left;
rcLock2.top = rcOverlap.top - rcSprite2.top;
rcLock2.right = rcOverlap.right - rcSprite2.left;
rcLock2.bottom = rcOverlap.bottom - rcSprite2.top;

// Flip locations of locking rectangles if sprites are flipped
if ( bFlipped1 == true )
{
nTemp = nWidth1 - rcLock1.right;
rcLock1.right = nWidth1 - rcLock1.left;
rcLock1.left = nTemp;

} // End if Sprite1 flipped

if ( bFlipped2 == true )
{
nTemp = nWidth2 - rcLock2.right;
rcLock2.right = nWidth2 - rcLock2.left;
rcLock2.left = nTemp;

} // End if Sprite2 flipped

// Lock the two textures
pSprite1->LockRect( 0, &Lock1, &rcLock1, D3DLOCK_READONLY );
pSprite2->LockRect( 0, &Lock2, &rcLock2, D3DLOCK_READONLY );

// Iterate through overlapping pixel data and determine if any
// non-transparent pixels overlap. (Assumes D3DFMT_A8R8G8B8)
pData1 = (ULONG*)Lock1.pBits; pData2 = (ULONG*)Lock2.pBits;
for ( y = 0; y < rcOverlap.bottom - rcOverlap.top; ++y )
{
for ( x = 0; x < rcOverlap.right - rcOverlap.left; ++x )
{
// Compute offsets to take into account if the sprite is flipped horizontally
if ( bFlipped1 == true )
nOffset1 = (nWidth1 - 1) - x;
else
nOffset1 = x;

if ( bFlipped2 == true )
nOffset2 = (nWidth2 - 1) - x;
else
nOffset2 = x;

// If both pixels have a non zero alpha value at this location
// then we have detected a pixel intersection.
if ( (pData1[nOffset1] & 0xFF000000) != 0 && (pData2[nOffset2] & 0xFF000000) != 0 )
{
bIntersecting = true;
break;

} // End if both alpha != 0

} // Next Row

// We can bail immediately if we found an intersection.
if ( bIntersecting == true )
break;

// Move texture data down to next row
pData1 += Lock1.Pitch / sizeof(ULONG);
pData2 += Lock2.Pitch / sizeof(ULONG);

} // Next Row

// Clean up
pSprite1->UnlockRect(0);
pSprite2->UnlockRect(0);

// Sprites intersect?
return bIntersecting;
}


Hope this helps.
Cheers!
-Zyro

Share this post


Link to post
Share on other sites
An occlusion query should work. Only problem is that getting the result can take time to arrive, so it'd slow things down (because you're syncing the CPU and GPU). You can do it on the CPU, but store the data outside the textures, unlike what zyrolasting's example does. Locking the textures to get the data will sync the CPU and GPU and doesn't have the benefit of the GPU doing the work, so it's inferior to other solutions.

For the CPU side solution, you can represent each collision image with one bit or one byte per pixel. One bit per pixel works well if you have a small image (up to 64 pixels in width), because then you can use bit shifting and anding to test collision.

Share this post


Link to post
Share on other sites
Quote:
Original post by ET3D
For the CPU side solution, you can represent each collision image with one bit or one byte per pixel. One bit per pixel works well if you have a small image (up to 64 pixels in width), because then you can use bit shifting and anding to test collision.
I'd do it this way too - you can always calculate the collision mask at load time if you want.
Personally, I'd do this for any size sprite - a 512x512 sprite would take up 16 unsigned ints per scanline (32KB of data in total for collision versus 1MB of image data), and checking for collisions is still going to just be bit shifts and masks.

Share this post


Link to post
Share on other sites
Thanks for the help.
I set up the engine to store the collision mask array at loadtime. I have not yet started on comparing the two arrays for the collision method because I want to take into account sprite rotation. Every sprite will be rotated about the center of the image. I have no idea where to start since the overlapped region could be a wide variety of shapes. Is there a somewhat efficient way to detect pixel level collision between rotated sprites?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!