Get pixels from sprite/texture?

Started by
3 comments, last by Evil Steve 16 years, 3 months ago
Hi all, I've been trying to create an engine that detects collisions between two ID3DXSprite sprites. I have done bounding square and a bounding circle collision detection, but I also want to test collisions in a different way. If the sprites are overlapping each other in a transparent zone, then it should not detect a collision. Is there any possible way of detecting the transparent zones of a sprite/texture? Looked the documentation for something on that and the only thing I've found was: IDirect3DTexture9::LockRect, which returns a D3DLOCKED_RECT structure. Can the data be obtained through this? Thanks in advance...
http://sagito.wordpress.com
Advertisement
You'd have to lock both textures (With LockRect()) and read the data out that way. Transparent pixels will have an alpha value of 0, opaque will be 255 (Assuming you loaded the texture with D3DXCreateTextureFromFile() and used a colour key).

However, that's something you'll want to do at load time, since doing it every frame will be pretty slow. The data you get back from the lock depends on your texture format. If you're using D3DFMT_A8R8G8B8, then you can cast the pBits member of the D3DLOCKED_RECT struct to a DWORD* and read each pixel as a 4-byte DWORD value, where the top bits (0xff000000) are alpha, the next (0x00ff0000) are red, the next (0x0000ff00) are green and the last (0x000000ff) are blue.

If you're using a different texture format, the pixel data will have a different meaning.

Sample code (untested, assuming D3DFMT_A8R8G8B8):
// Lock textureD3DLOCKED_RECT d3dRect;HRESULT hResult = pTexture->LockRect(0, &d3dRect, NULL, D3DLOCK_READONLY);if(FAILED(hResult)){   // Error   return false;}for(UINT y=0; y<nHeight; ++y){   DWORD* pBits = (DWORD*)((BYTE*)d3dRect.pBits + y*d3dRect.Pitch));   for(UINT x=0; x<nWidth; ++x)   {      bool bOpaque = (pBits[x]&0xff000000) != 0;      // Do whatever here   }}pTexture->UnlockRect(0);return true;

Assuming you have an LPDIRECT3DTEXTURE9 called pTexture, and two integers nWidth and nHeight containing the width and height of the texture (Which you can get from the texture via IDirect3DTexture9::GetDesc() if you need to).
You could do this without locking. One way I can think of (but haven't tested) is to draw one sprite, setting stencil where a pixel is drawn (transparent won't be drawn, assuming you use alpha testing). Then draw the other only where the stencil is set, and use an occlusion query. If the occlusion query returns > 0, then there's a collision.

Thanks for your replies... =D

As I've never used D3DLOCKED_RECT for this effect, if I lock it, save the DWORD* and then unlock it, can I use the saved DWORD* for later use, so that I don't need to keep locking the RECT? (This is probably a noob question)...

Concerning the second method, if I understood well what you've said, that would work for a sprite even if it was transformed, am I correct? (I had that problem using the first method). I've never used stencil very much, but I'll try to look in the documentation for tips on how to place the stencil and use an occlusion query (never tried that before on 2D graphics).

Thanks again... (^^,)
http://sagito.wordpress.com
Quote:Original post by Sagito

Thanks for your replies... =D

As I've never used D3DLOCKED_RECT for this effect, if I lock it, save the DWORD* and then unlock it, can I use the saved DWORD* for later use, so that I don't need to keep locking the RECT? (This is probably a noob question)...
Nope. The pointer is only valid while the texture is locked. If you want to keep the data around, you'll have to copy the data out of the pointer into a buffer.

Quote:Original post by Sagito
Concerning the second method, if I understood well what you've said, that would work for a sprite even if it was transformed, am I correct? (I had that problem using the first method). I've never used stencil very much, but I'll try to look in the documentation for tips on how to place the stencil and use an occlusion query (never tried that before on 2D graphics).
Yes it would, although to be honest, I think an occlusion query is overkill here. So long as your sprites don't rotate, my method should be pretty simple. If they do rotate though, an occlusion query may be a better option.

This topic is closed to new replies.

Advertisement