Sign in to follow this  
stewypeza

ray picking

Recommended Posts

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]

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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