Sign in to follow this  
stewypeza

D3DXIntersect and pick ray.

Recommended Posts

stewypeza    122
Hey, This problem is driving me crazy. I have used the code from the Pick example with the directx9 sdk, and put it into my program. I have changed it to fit with my engine but im having a bit of a problem. The ray origin and the direction seem to be created correctly from the mouse. The problem i am having is that D3DXIntersect is only showing a collison when the ray is cast at the origin. This is where the models started but have been translated into their positions. There is only a collison at the origin and never at the actual models position. It is as though the models have not actually moved. Any help will be much appreciated. Stuart P.s I have read similar topics about inversing the ray but i dont know why this would be necessary in this case because the ray produced is correct, its just as tho the models have not actually moved. I am using c++ directX 9.0

Share this post


Link to post
Share on other sites
thezbuffer    706
Sounds like you are not transforming the ray back through the inverse of the world matrix. To get to object space you have to unproject thr ray through projection, view and world. You can only omit one of those if it happens to be the identity

Share this post


Link to post
Share on other sites
stewypeza    122
"Sounds like you are not transforming the ray back through the inverse of the world matrix."


Do you have any sample code of how to do that. sorry this is new to me and not quite sure how to do it?

Thanks

Share this post


Link to post
Share on other sites
stewypeza    122
This is my code

HRESULT Engine::Pick()
{
HRESULT hr;
D3DXVECTOR3 vPickRayDir;
D3DXVECTOR3 vPickRayOrig;

m_dwNumIntersections = 0L;

// Get the pick ray from the mouse position
if( GetCapture() )
{
D3DXMATRIXA16 matProj;
g_pd3dDeviceN->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 ) / /*d3dpp.BackBufferWidth*/800 ) - 1 ) / matProj._11;
v.y = -( ( ( 2.0f * ptCursor.y ) / /*d3dpp.BackBufferHeight*/600 ) - 1 ) / matProj._22;
v.z = 1.0f;

// Get the inverse view matrix
D3DXMATRIXA16 matView, m;
g_pd3dDeviceN->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;

}

D3DXIntersect(pMesh, &vPickRayOrig, &vPickRayDir, &bHit, &dwFace, &fBary1, &fBary2, &fDist,
NULL, NULL);

Share this post


Link to post
Share on other sites
stewypeza    122
To the issue of transforming the ray back through the inverse of the world matrix. I have altered the code to be shown below but now im not getting any intersections. Any ideas??


D3DXMATRIXA16 matProj;
g_pd3dDeviceN->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 ) / /*d3dpp.BackBufferWidth*/800 ) - 1 ) / matProj._11;
v.y = -( ( ( 2.0f * ptCursor.y ) / /*d3dpp.BackBufferHeight*/600 ) - 1 ) / matProj._22;
v.z = 1.0f;

// Get the inverse view matrix
D3DXMATRIXA16 matView, m;
g_pd3dDeviceN->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;

D3DXMATRIXA16 m_inv, ma;
D3DXVECTOR3 v1_tr, v2_tr;
g_pd3dDeviceN->SetTransform( D3DTS_WORLD, &ma);
D3DXMatrixInverse( &m_inv, NULL, &ma );
D3DXVec3TransformCoord( &v1_tr, &vPickRayOrig, &m_inv );
D3DXVec3TransformCoord( &v2_tr, &vPickRayDir, &m_inv );

D3DXIntersect(pMesh, &v1_tr, &v2_tr, &bHit, &dwFace, &fBary1, &fBary2, &fDist,
NULL, NULL);

Share this post


Link to post
Share on other sites
DXnut    262
You should use D3DXVec3TransformNormal for the direction vector. You don't want it to get translated.

Share this post


Link to post
Share on other sites
stewypeza    122
Quote:
Original post by stewypeza
"You should use D3DXVec3TransformNormal for the direction vector. You don't want it to get translated."


In what context? Sorry im really new to this and cant quite get my head around it.

Share this post


Link to post
Share on other sites
DXnut    262
Vectors have an implied 0 in the 4th component of a D3DXVECTOR3. Points have an implied 1. Since vectors have direction put no position, you don't want them to be translated. Points have position and need to be translated. The books on 3D math explain this better.

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