Sign in to follow this  

Picking Ray without D3DXIntersect

This topic is 3593 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 have a series of vertex buffers and I am trying to do a picking ray so I can select one of these vertex buffers. Is there an alternative solution to using D3DXIntersect?

Share this post


Link to post
Share on other sites
I assume you're concerned with the speed of picking.

If so, and if the data from which you create the meshes is available ( in a memory array ) you can write your own pick routine which will likely be faster. If not, and you have to lock each vertex buffer to access the data, it may be difficult to write a faster routine.

If the mesh shapes are very complex, you can create a simpler mesh for each complex mesh and pick those at faster speed. That might narrow down which meshes to run through the D3DXIntersect method. If a simple mesh gets hit, shoot the corresponding complex mesh.

If your only consideration is knowing which mesh gets picked and not which face is hit or the distance to the hit, it's almost certain you can write a faster routine or, at least, narrow down which meshes need to be tested further (perhaps with D3DXIntersect). That would save some time.

Store data for the bounding boxes of each mesh and use a formula for the intersection of a vector (the pick ray) and a cube (the bounding box for the mesh). If the ray doesn't intersect the bounding box, no need to shoot that mesh.

If the ray always comes from the same direction (say, you're only interested in what's below a position so the pick ray is always ( 0, -1, 0 ) ), the bounding box test becomes trivial.

Share this post


Link to post
Share on other sites
I do not want to pick meshes though, I want to pick be able to pick a vertex buffer (basically a triangle fan that is being drawn). Here is what I do to render it:

IDirect3DVertexDeclaration9 *m_vdVertexDecl;
IDirect3DTexture9 *m_tSquareTexture;
IDirect3DVertexBuffer9 *m_vbSquareBuff;

struct sWallVertex
{
D3DXVECTOR3 pos;
D3DXVECTOR2 uv;
float size;
D3DCOLOR color;
};

lpD3DDevice->SetVertexDeclaration(m_vdVertexDecl);
lpD3DDevice->SetTexture(0, m_tSquareTexture);

lpD3DDevice->SetStreamSource(0, m_vbSquareBuff, 0, sizeof(sWallVertex));
lpD3DDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 4);

Share this post


Link to post
Share on other sites
You mentioned an alternative to D3DXIntersect, which is for meshes, so I read "mesh" where you clearly said "vertex buffer."

I believe you'll have to write your own pick routine for your VBs. The bounding box method will get you a start and you can follow up with a more precise pick routine if you need to know which face, etc., for a VB that's hit.

Share this post


Link to post
Share on other sites
The two examples on Direct X SDK don't even compile (Pick and Tutorial 04). I wrote a little bit of code to do the picking and I know the actual picking is correct but I am not sure how to check the intersection.

void CPickingRay::Pick(CWall *pShade, BOOL &phit)
{
CMouse *pMouse = CMouse::GetInstance();
int nMouseX = pMouse->GetMouseX();
int nMouseY = pMouse->GetMouseY();
tRay ray;
D3DXMATRIX matView, matWorld, matInverse, tempPick;
CalculatePickingRay(&ray, nMouseX, nMouseY);

CDirect3D::GetInstance()->GetDirect3DDevice()->GetTransform(D3DTS_VIEW, &matView);
matWorld = *D3DXMatrixIdentity(&tempPick);
matWorld._41 = pShade->GetXLocation();
matWorld._42 = pShade->GetYLocation();
matWorld._43 = pShade->GetZLocation();
matWorld *= matView;

D3DXMatrixInverse(&matInverse, 0, &matWorld);
TransformRay(&ray, &ray, &matInverse);

// If the x is inbetween the sides (not a good way to do this).
if(ray.vDirection.x > -matInverse._41 + matView._41)
{
if(ray.vDirection.x < matInverse._41 + pShade->GetWidth())
int a = 0;
}
}

void CPickingRay::TransformRay(tRay *pRayOut, tRay *pRayIn, D3DXMATRIX *pMat)
{
if(!pRayIn || !pMat)
return;

D3DXVec3TransformCoord(&pRayOut->vPosition, &pRayIn->vPosition, pMat);

D3DXVec3TransformNormal(&pRayOut->vDirection, &pRayIn->vDirection, pMat);

D3DXVec3Normalize(&pRayOut->vDirection, &pRayOut->vDirection);
}

void CPickingRay::CalculatePickingRay(tRay *pRayOut, long lX, long lY)
{
LPDIRECT3DDEVICE9 pD3Dev = CDirect3D::GetInstance()->GetDirect3DDevice();

D3DXMATRIX matProj;
D3DVIEWPORT9 vp;
pD3Dev->GetTransform(D3DTS_PROJECTION, &matProj);
pD3Dev->GetViewport(&vp);
pRayOut->vPosition = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

float pX, pY;
pX = (((2.0f * lX) / vp.Width) - 1.0f) / matProj(0, 0);
pY = (((-2.0f * lY) / vp.Height) + 1.0f) / matProj(1, 1);

pRayOut->vDirection = D3DXVECTOR3(pX, pY, 1.0f);
}

Share this post


Link to post
Share on other sites

This topic is 3593 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this