# Picking class improvments

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

## Recommended Posts

I made a simple picking sample for mouse detection and I encapsulated it into a class. I was looking for improvements, suggestions, etc. I also have 4 questions: 1) Will I be able to use this class for anything other else? 2) Is this one of those things that I shouldn't put into a class? 3) Does calling GetTransform() slow it down any (on a hardware vp HAL device)? 4) Is there a way that I could modify it to check for a quad, without calling IntersectsTriangle() twice?
class MousePicker
{
IDirect3DDevice9*	m_pDevice;
float				m_fWidth, m_fHeight;
D3DXVECTOR3			m_RayOrigin, m_RayDirection;
public:
MousePicker()
{
m_pDevice = 0;
}

MousePicker(IDirect3DDevice9* pDevice)
{
m_pDevice = pDevice;
if(m_pDevice)
{
D3DVIEWPORT9 ViewPort;
IDirect3DDevice9* m_pDevice;
m_pDevice->GetViewport(&ViewPort);
m_fWidth = (float)ViewPort.Width;
m_fHeight = (float)ViewPort.Height;
}
}

void SetDevice(IDirect3DDevice9* pDevice)
{
m_pDevice = pDevice;
if(m_pDevice)
{
D3DVIEWPORT9 ViewPort;
m_pDevice->GetViewport(&ViewPort);
m_fWidth = (float)ViewPort.Width;
m_fHeight = (float)ViewPort.Height;
}
}

void CreateRay(float fMouseX, float fMouseY)
{
D3DXMATRIX ViewMtx, ProjMtx;
m_pDevice->GetTransform(D3DTS_VIEW, &ViewMtx);
m_pDevice->GetTransform(D3DTS_PROJECTION, &ProjMtx);

D3DXMATRIX	Matrix;
D3DXVECTOR3 Vector = D3DXVECTOR3(0.0f, 0.0f, 0.0f);

Vector.x = (((2.0f * fMouseX) / m_fWidth) - 1.0f) / ProjMtx._11;
Vector.y = -(((2.0f * fMouseY) / m_fHeight) - 1.0f) / ProjMtx._22;
Vector.z = 1.0f;

D3DXMatrixInverse(&Matrix, 0, &ViewMtx);
m_RayDirection.x = Vector.x * Matrix._11 + Vector.y * Matrix._21 + Vector.z * Matrix._31;
m_RayDirection.y = Vector.x * Matrix._12 + Vector.y * Matrix._22 + Vector.z * Matrix._32;
m_RayDirection.z = Vector.x * Matrix._13 + Vector.y * Matrix._23 + Vector.z * Matrix._33;
m_RayOrigin.x = Matrix._41;
m_RayOrigin.y = Matrix._42;
m_RayOrigin.z = Matrix._43;
}

bool IntersectsTriangle(void* pVertices, unsigned int nOffset, float* pHitDistance)
{
D3DXMATRIX InverseMtx;
D3DXMATRIX WorldMtx;
m_pDevice->GetTransform(D3DTS_WORLD, &WorldMtx);
D3DXMatrixInverse(&InverseMtx, 0, &WorldMtx);

D3DXVECTOR3 RayObjOrigin = D3DXVECTOR3(0.0f, 0.0f, 0.0f), RayObjDirection = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
D3DXVec3TransformCoord(&RayObjOrigin, &m_RayOrigin, &InverseMtx);
D3DXVec3TransformNormal(&RayObjDirection, &m_RayDirection, &InverseMtx);
D3DXVec3Normalize(&RayObjDirection, &RayObjDirection);

return D3DXIntersectTri((D3DXVECTOR3*)pVertices, &((D3DXVECTOR3*)pVertices)[nOffset + 1], &((D3DXVECTOR3*)pVertices)[nOffset + 2], &RayObjOrigin, &RayObjDirection, 0, 0, pHitDistance) != 0;
}
};


Thanks!

##### Share on other sites
Definatly add intersection with a sphere and with an AABB. For speed's sake :).

Also, I think a NON-pure device, calling GetTransform doesn't actually get it from the card, but rather gets a copy of the matrices stored in system memory, so it should be quite quick.

EDIT: (sorry I'm editing after you replied, keep thinking of stuff)

If you're uncertain about using GetTransform, you could easily create a Frame() function, which performs the GetTransform once per frame, and saves the values for the entire frame's checking. This would solve problems on pure devices, too.

##### Share on other sites
Quote:
 Original post by sirobDefinatly add intersection with a sphere and with an AABB. For speed's sake :).

Ok, thanks! I'll have to research it, but it shouldn't be too hard [wink].

##### Share on other sites
Ok, I've run into a problem with the class. I added a variable to my vertex class (diffuse), so now it has x,y,z and diffuse. But, now it doesn't detect my intersection. I'm thinking the problem is with my casting for D3DXIntersectTri().

Any suggestions?

Edit: Ok, I fixed it. I was correct, it was an error with my casting.

I tried adding a stride parameter to IntersectsRect(), then using that to "step over" the extra variable, but that didn't work.

##### Share on other sites
Two options, really:

1) modify your vert struct, so the position is already a D3DXVECTOR3:
struct Vert {     D3DXVECTOR3 Pos;     D3DCOLOR Diffuse;}

Then, you'd just pass it in as Vert.Pos with no casting.

or 2) Simply use D3DXVECTOR3(float x, float y, float z) to convert your verts to D3DXVECTOR3s, like so:
        D3DXVECTOR3 Vec1 = D3DXVECTOR3(pVertices.x, pVertices.y, pVertices.z);        // Then pass in &Vec1 to the D3DXIntersectTri function.

EDIT Yes, again, sorry:
You also seem to have a small mistake (I think) in the last line of code you posted, as you don't use [nOffset] on the first vertex, but use [nOffset + 1] on the second and [nOffset + 2] on the third.

##### Share on other sites
Quote:
 Original post by sirobTwo options, really:1) modify your vert struct, so the position is already a D3DXVECTOR3:*** Source Snippet Removed ***Then, you'd just pass it in as Vert.Pos with no casting.or 2) Simply use D3DXVECTOR3(float x, float y, float z) to convert your verts to D3DXVECTOR3s, like so:*** Source Snippet Removed ***EDIT Yes, again, sorry:You also seem to have a small mistake (I think) in the last line of code you posted, as you don't use [nOffset] on the first vertex, but use [nOffset + 1] on the second and [nOffset + 2] on the third.

Thank you for pointing that out (I hadn't noticed that.) I guess I'll just go with 1. Thanks for your help!

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 13
• 10
• 9
• 34
• 16
• ### Forum Statistics

• Total Topics
634125
• Total Posts
3015666
×