Skip to main content
gamedev.net
🔒 Locked

intersect a mesh code

Started by DarkZoulz 2 replies 400+ views
Original Post
DarkZoulz
DarkZoulz
I''m trying to get the users mouse click to see if he selected a mesh. I know that I need to project a ray into the world to achieve this. But i''m having trouble doing just that. This is the code i''m using:
bool Frost_Engine::Intersect_Mesh(void *pMesh, Frost_Vector &start, Frost_Vector &end)
{
	BOOL		isHit;
	float		dist, u, v;
	DWORD		hitFace;
	D3DXVECTOR3	vecDir, vecDif, vecStart = Convert_FrostVector(start), vecEnd = Convert_FrostVector(end);
	Frost_Mesh	*fMesh = (Frost_Mesh*)pMesh;

	vecDif = D3DXVECTOR3(vecEnd.x - vecStart.x, vecEnd.y - vecStart.y, vecEnd.z - vecStart.z);
	D3DXVec3Normalize(&vecDir, &vecDif);
	D3DXIntersect(fMesh->mesh, &vecStart, &vecDir, &isHit, &hitFace, &u, &v, &dist, NULL, NULL);

	if(isHit) return true;
	else return false;
}

//	Convert a screen coord to world coord.
void Frost_Engine::Screen_To_World(float x, float y, float z, Frost_Vector &vector)
{
	D3DXVECTOR3	tmp;
	D3DXVec3Unproject(&tmp, &D3DXVECTOR3(x, y, z), &viewport, &proj_matrix, &view_matrix, &camera_matrix);

	vector.x = tmp.x;
	vector.y = tmp.y;
	vector.z = tmp.z;
}
 
		Frost_Vector src, dest;

		frost->Screen_To_World(mousePos.x, mousePos.y, 0.0f, src);
		frost->Screen_To_World(mousePos.x, mousePos.y, 1.0f, dest);

		if(frost->Intersect_Mesh(mymesh, src, dest))
			MessageBox(HWND_DESKTOP, "um....works?", "World", MB_OK);
 
Frost_Vector is just a standard D3DXVECTOR3 struct. I first convert the mouse position into 2 world vectors, one source and one destination. I then try to run them through the intersect function. Can anyone tell me what i''m doing wrong?
kVandaele
kVandaele
I''m in no way an expert (sorry if this post is useless) but don''t you need the vector of the camera? (not sure why you''re giving 0 and 1 as Z values, that would be assuming you''re always watching from the front of it - which, I guess, is possible)

the fastest way to do this would be to use the camera''s vector, follow it, and if it gets within a radius of a mesh''s origin assume the mesh was clicked. Radius could be a sphere, and oval sphere, a cube, ...
S1CA
S1CA
The following is a snippet of code from the "Pick" sample from the DirectX SDK:


HRESULT hr;
D3DXVECTOR3 vPickRayDir;
D3DXVECTOR3 vPickRayOrig;

m_dwNumIntersections = 0L;

// Get the pick ray from the mouse position

if( GetCapture() )
{
D3DXMATRIXA16 matProj;
m_pd3dDevice->GetTransform( D3DTS_PROJECTION, &matProj );

POINT ptCursor;
GetCursorPos( &ptCursor );
ScreenToClient( m_hWnd, &ptCursor );

// Compute the vector of the pick ray in screen space

D3DXVECTOR3 v;
v.x = ( ( ( 2.0f * ptCursor.x ) / m_d3dsdBackBuffer.Width ) - 1 ) / matProj._11;
v.y = -( ( ( 2.0f * ptCursor.y ) / m_d3dsdBackBuffer.Height ) - 1 ) / matProj._22;
v.z = 1.0f;

// Get the inverse view matrix

D3DXMATRIXA16 matView, m;
m_pd3dDevice->GetTransform( D3DTS_VIEW, &matView );
D3DXMatrixInverse( &m, NULL, &matView );

// Transform the screen space pick ray into 3D space

vPickRayDir.x = v.x*m._11 + v.y*m._21 + v.z*m._31;
vPickRayDir.y = v.x*m._12 + v.y*m._22 + v.z*m._32;
vPickRayDir.z = v.x*m._13 + v.y*m._23 + v.z*m._33;
vPickRayOrig.x = m._41;
vPickRayOrig.y = m._42;
vPickRayOrig.z = m._43;
}

// Get the picked triangle

if( GetCapture() )
{
LPD3DXBASEMESH pMesh = m_pObject->GetLocalMesh();
LPDIRECT3DVERTEXBUFFER9 pVB;
LPDIRECT3DINDEXBUFFER9 pIB;

pMesh->GetVertexBuffer( &pVB );
pMesh->GetIndexBuffer( &pIB );

WORD* pIndices;
D3DVERTEX* pVertices;

pIB->Lock( 0, 0, (void**)&pIndices, 0 );
pVB->Lock( 0, 0, (void**)&pVertices, 0 );

// Collect only the closest intersection

BOOL bHit;
DWORD dwFace;
FLOAT fBary1, fBary2, fDist;
D3DXIntersect(pMesh, &vPickRayOrig, &vPickRayDir, &bHit, &dwFace, &fBary1, &fBary2, &fDist,
NULL, NULL);
if( bHit )
{
m_dwNumIntersections = 1;
m_IntersectionArray[0].dwFace = dwFace;
m_IntersectionArray[0].fBary1 = fBary1;
m_IntersectionArray[0].fBary2 = fBary2;
m_IntersectionArray[0].fDist = fDist;
}
else
{
m_dwNumIntersections = 0;
}


How does the way you get the mouse position differ from the above? - Have you remembered to call ScreenToClient() for example (assuming you''re testing this in windowed mode).

Usually what I do in situations like this is display some 3D lines on screen for debugging so I can tell what the ray, intersection point and mouse position actually "looks" like.


Simon O''Connor
Game Programmer &
Microsoft DirectX MVP
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site
DarkZoulz
DarkZoulz
I've checked the two points I get and they seem to be correct. So the conversion from screen to world coords seems to be working. But my intersect function does not return true all the times when it should.

The pick sample only seems to confuse me. I've already had a look at it.

[edited by - DarkZoulz on May 17, 2004 4:00:17 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.