ray picking

Started by
0 comments, last by XiotexStudios 17 years, 11 months ago
Hi all Directx9 c++ I have exhausted all possibilities of to this solution to solve it but i can not. Im simply trying to detect if the mouse has clicked on an object. The entire pick code is shown below:
HRESULT Engine::Pick(LPDIRECT3DDEVICE9 g_pd3dDevice)
{
    HRESULT hr;
    D3DXVECTOR3 vPickRayDir;
    D3DXVECTOR3 vPickRayOrig;
	D3DXMATRIX m_inv, ma;
	D3DXVECTOR3 v1_tr, v2_tr;
	D3DXVECTOR3 vLocalRayOrig;
	D3DXVECTOR3 vLocalRayDir;
	D3DXVECTOR3 rayObjOrigin,rayObjDirection;

    // Get the pick ray from the mouse position
    if( GetCapture() )
    {

		D3DVIEWPORT9 m_mainViewport; 
		g_pd3dDevice->GetViewport( &m_mainViewport );
		
        D3DXMATRIX matProj;
        g_pd3dDevice->GetTransform( D3DTS_PROJECTION, &matProj );

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

        // Compute the vector of the pick ray in screen space
        D3DXVECTOR3 v;
		v.x =  ( ( ( 2.0f * ptCursor.x ) / m_mainViewport.Width ) - 1 ) / matProj._11;
        v.y = -( ( ( 2.0f * ptCursor.y ) / m_mainViewport.Height ) - 1 ) / matProj._22;
        v.z =  1.0f;

		D3DXMATRIX matView, m, WorldMatrix, inv_WorldMatrix, matWorldView;
		D3DXVECTOR3 rayOrigin,rayDir;
		g_pd3dDevice->GetTransform( D3DTS_VIEW, &matView );
		D3DXMatrixInverse( &m, NULL, &matView );

		// Transform the screen space pick ray into 3D space
		rayDir.x = v.x*m._11 + v.y*m._21 + v.z*m._31;
		rayDir.y = v.x*m._12 + v.y*m._22 + v.z*m._32;
		rayDir.z = v.x*m._13 + v.y*m._23 + v.z*m._33;
		rayOrigin.x = m._41;
		rayOrigin.y = m._42;
		rayOrigin.z = m._43;

		// Use inverse of matrix
		D3DXMATRIX matInverse, matWorld;
		g_pd3dDevice->GetTransform( D3DTS_WORLD, &matWorld );
		D3DXMatrixInverse(&matInverse,NULL,&matWorld);

		D3DXVec3TransformCoord(&rayObjOrigin,&rayOrigin,&matInverse);
		D3DXVec3TransformNormal(&rayObjDirection,&rayDir,&matInverse);
		D3DXVec3Normalize(&rayObjDirection,&rayObjDirection);


		LPD3DXBASEMESH          pMesh = pDial[0].pModel->GetMesh();

        BOOL bHit;
        FLOAT fDist;
        D3DXIntersect(pMesh, &rayObjOrigin, &rayObjDirection, &bHit, NULL, NULL, NULL, &fDist, 
            NULL, NULL);
        if( bHit )
        {
			int test = 6;
		}
    }
    return S_OK;
}
Pick is called in the render method, does it matter where it is called from? e.g HRESULT hr = Pick(g_pd3dDevice); ALso should the matrix for matView and world etc be specific to each mesh or is it in general termsn from the device? e.g g_pd3dDevice->GetTransform( D3DTS_WORLD, &matWorld ); The meshes themselves are created in a mesh class and controlled by another class. In this class the meshes are positioned via.
void Slider::Render(LPDIRECT3DDEVICE9 g_pd3dDevice)
{
	D3DXMATRIXA16 matWorld, matMove;
	D3DXMatrixTranslation(&matMove, getPosition().x, getPosition().y, getPosition().z);
	D3DXMatrixRotationY( &matWorld, getRotation().y);
	D3DXMatrixMultiply(&matWorld, &matWorld, &matMove);
	g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
	pModel->Render(g_pd3dDevice);
}
Sorry for waffling but i just want to make sure ive given enough information for some help because i am COMPLETELY stuck. Thank you Stuart EDIT: Please remember to use [source] and [code] tags... [Edited by - jollyjeffers on May 21, 2006 2:02:34 PM]
Advertisement

I have dug up some code from long ago that I used for ray-picking. I can't vouch for if it still works:

	D3DXMATRIXA16 matProj;	POINT ptCursor; 	D3DXMATRIXA16 matView, matWorld, m;	D3DXVECTOR3 v;	    GetCursorPos( &ptCursor );    ScreenToClient( m_hWnd, &ptCursor );	    // Compute the vector of the pick ray in screen space	m_pd3dDevice->GetTransform( D3DTS_PROJECTION, &matProj );    v.x =  ( ( ( 2.0f * ptCursor.x ) / m_dwRealWidth  ) - 1 ) / matProj._11;    v.y = -( ( ( 2.0f * ptCursor.y ) / m_dwRealHeight ) - 1 ) / matProj._22;    v.z =  1.0f;    // Get the inverse view matrix	m_pd3dDevice->GetTransform( D3DTS_VIEW, &matView );    D3DXMatrixInverse( &m, NULL, &matView );    // Transform the screen space pick ray into 3D space    m_vRayDir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;    m_vRayDir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;    m_vRayDir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;	D3DXVec3Normalize(&m_vRayDir,&m_vRayDir);    m_vRayPos.x = m._41;    m_vRayPos.y = m._42;    m_vRayPos.z = m._43;	// calc origin as intersection with near frustum	m_vRayPos+=m_vRayDir*NEAR_Z;


And here is how I used that info to intersect:

	if((D3DXIntersectTri(&vc0,&vc1,&vc2,&m_vRayPos,&m_vRayDir,NULL,NULL,&c)) == TRUE)	{		return true;	}


Now, I believe all of the above assumes everything is in world space.
Byron Atkinson-JonesXiotex Studioswww.xiotex.com

This topic is closed to new replies.

Advertisement