Jump to content
  • Advertisement
Sign in to follow this  
Programmer16

Picking class improvments

This topic is 4841 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 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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
Share on other sites
Quote:
Original post by sirob
Definatly 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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by sirob
Two 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!

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!