• Advertisement

Archived

This topic is now archived and is closed to further replies.

D3DXIntersect()

This topic is 4967 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

Ok I''ve tried a lot of things but I can''t find a solution of how to use in the real and useful way this function! I want only to check if my ray is pointing to a mesh. My ray origin must be the camera (I suppose) and the direction is my mouse coordinates. I''ve tried with this: // Controlla se colpito dal mirino bool SottoTiro(POINT Mouse, D3DXMESHCONTAINER_EX *pMesh) { D3DXVECTOR3 vPickRayDir; D3DXVECTOR3 vPickRayOrig; //x, y and z are my camera position GetCursorPos( &Mouse ); ScreenToClient( g_hWndMain, &Mouse ); // Transform the screen space pick ray into 3D space vPickRayDir.x = -(float)Mouse.x; vPickRayDir.y = -(float)Mouse.y; vPickRayDir.z = z-10000; vPickRayOrig.x = x; vPickRayOrig.y = y; vPickRayOrig.z = z; // clear the hit flag bool m_bHit=FALSE; // test for intersection DWORD dwIndex; int Hit; float u,w; float dist; D3DXIntersect(pMesh->pSkinMesh,&vPickRayOrig,&vPickRayDir,&Hit,&dwIndex,&u,&w,&dist,NULL,NULL); if(Hit) m_bHit=false; else m_bHit=true; return m_bHit; } But it doesn''t work! Who could help me to find a real solution to the problem?! THANKS A LOT!!! ^__^ BYE, ----------------------------------------------- - GENTS - "Every man dies, not every man really lives" [William Wallace]

Share this post


Link to post
Share on other sites
Advertisement
Remember that your mesh vertices are stored in model space, not world space. When you perform an intersection test, both your model and the ray have to be in the same coordinate space for it to work.

You have two choices, you can either transform all of your mesh vertices into world space (bad idea because you could end up transforming thousands of verts) or you could just transform your ray from world space into model space (good idea).

To transform your ray into model space, you need to compute the inverse of the original world transform matrix that you used to render your mesh in your 3D scene. You then take this inverse matrix and use it to transform your ray from world space to model space. In code it would look like this:

D3DXMATRIX matInverse;
D3DXMatrixInverse(&matInverse, NULL, &matMeshWorld);

D3DXVECTOR3 vModelSpaceRayPos, vModelSpaceRayDir;
D3DXVec3TransformCoord(&vModelSpaceRayPos, &vPickRayOrig, &matInverse);
D3DXVec3TransformNormal(&vModelSpaceRayDir, &vPickRayDir, &matInverse);

// Use your new ray to intersect with your mesh...

D3DXIntersect(.....)

Hope this helps,
neneboricua

Share this post


Link to post
Share on other sites
Ok, I've tried as you says as you can see...
BUT IT STILL DOESN'T WORK!!!


// Controlla se colpito dal mirino
bool SottoTiro(D3DXMESHCONTAINER_EX *Mesh, CObjCollection Obj, CCamera cam)
{
bool m_bHit=FALSE;
BOOL bHit;
D3DXVECTOR3 vPickRayDir;
D3DXVECTOR3 vPickRayOrig;

D3DXMATRIXA16 matProj;
g_pD3DDevice->GetTransform( D3DTS_PROJECTION, &matProj );

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

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

// Get the inverse of the composite view and world matrix
D3DXMATRIXA16 matView, matWorld, m;
g_pD3DDevice->GetTransform( D3DTS_VIEW, &matView );
g_pD3DDevice->GetTransform( D3DTS_WORLD, &matWorld );

m = matWorld * matView;
D3DXMatrixInverse( &m, NULL, &m );

// 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;

float x, y, z;
cam.GetPosition( x, y, z );
vPickRayOrig.x = x;
vPickRayOrig.y = y;
vPickRayOrig.z = z;



LPD3DXBASEMESH pMesh = Mesh->pSkinMesh;
D3DXMATRIX matInverse, LocMatrix;
Obj.GetLocal( LocMatrix );
D3DXMatrixInverse(&matInverse, NULL, &LocMatrix );
D3DXVECTOR3 vModelSpaceRayOrig, vModelSpaceRayDir;
D3DXVec3TransformCoord(&vModelSpaceRayOrig, &vPickRayOrig, &matInverse);
D3DXVec3TransformNormal(&vModelSpaceRayDir, &vPickRayDir, &matInverse);



// Collect only the closest intersection
DWORD dwFace;
FLOAT fBary1, fBary2, fDist;
D3DXIntersect(pMesh, &vModelSpaceRayOrig, &vModelSpaceRayDir, &bHit, &dwFace, &fBary1, &fBary2, &fDist, NULL, NULL);


if(bHit)
m_bHit=false;
else
m_bHit=true;

return m_bHit;
}




I NEED HELP, PLEASE!!!!

^__^

THANKS A LOT!!!

-----------------------------------------------
- GENTS -

"Every man dies, not every man really lives"
[William Wallace]




[edited by - GENTS on June 9, 2004 2:41:43 PM]

Share this post


Link to post
Share on other sites
There could be other things wrong with the code you''ve posted. For example, you''re using IDirect3DDevice :: GetTransform. This function will only work if you''re using a non-pure device.

What I mean is when you created your original D3D device, if you did NOT use the PURE flag, then using GetTransform is ok. If you DID youse the PURE flag, then you can''t use GetTransform because a pure device does not store the matrices you set.

For the sake of performance, most people use PURE devices and keep track of their own states. If you used a PURE device, then the results from GetTransform are "undefined."

Also, you really should check the return values of the DirectX functions you''re calling to see if any of them fail. When doing any kind of DX development, you should ALWAYS use the Debug Runtime. If you don''t know what I''m talking about, please see the Forum FAQ.

neneboricua

Share this post


Link to post
Share on other sites
Ok you''re right!!!

I''ve done a debug check and my D3DXIntersect Function doesn''t return never D3D_OK...

But still now I can''t find the bug of my program!!!

I''ve free memory so I can''t think it''s a less-memory problem!!!

Could anyone help me?!

Im trying to find a solution, but I think it still doesn''t work!!!



// Check if the ray of the mouse intersect a mesh
bool SottoTiro(D3DXMESHCONTAINER_EX *Mesh, CCamera cam)
{
bool m_bHit=FALSE;
BOOL bHit;
HRESULT hr;
D3DXVECTOR3 vPickRayDir;
D3DXVECTOR3 vPickRayOrig;

D3DXMATRIXA16 matProj;
g_pD3DDevice->GetTransform( D3DTS_PROJECTION, &matProj );

D3DXVECTOR3 vModelSpaceRayOrig, vModelSpaceRayDir;
LPD3DXBASEMESH pMesh = (LPD3DXBASEMESH) Mesh->pSkinMesh;


// Compute the vector of the pick ray in screen space with mouse coords
D3DXVECTOR3 v;
v.x = ( ( ( 2.0f * MousePoint.x ) / g_WinWidth ) - 1 ) / matProj._11;
v.y = -( ( ( 2.0f * MousePoint.y ) / g_WinHeight ) - 1 ) / matProj._22;
v.z = 1.0f;

// Get the inverse of the composite view and world matrix
D3DXMATRIX matView, matWorld, m;

hr = g_pD3DDevice->GetTransform( D3DTS_VIEW, &matView );
if( FAILED ( hr ) )
{
SetError( "Impossible ottenere D3DTS_VIEW" );
}

hr = g_pD3DDevice->GetTransform( D3DTS_WORLD, &matWorld );
if( FAILED ( hr ) )
{
SetError( "Impossible ottenere D3DTS_WORLD" );
}

m = matWorld * matView;
D3DXMatrixInverse( &m, NULL, &m );

// 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;
D3DXVec3Normalize(&vPickRayDir, &vPickRayDir);

vPickRayOrig.x = m._41;
vPickRayOrig.y = m._42;
vPickRayOrig.z = m._43;
D3DXMATRIX matInverse;
D3DXMatrixInverse(&matInverse, NULL, &Mesh->matCombined );
D3DXVec3TransformCoord(&vModelSpaceRayOrig, &vPickRayOrig, &matInverse);
D3DXVec3TransformNormal(&vModelSpaceRayDir, &vPickRayDir, &matInverse);

// Collect only the closest intersection
hr = D3DXIntersect(pMesh, &vModelSpaceRayOrig, &vModelSpaceRayDir, &bHit, NULL, NULL, NULL, NULL,NULL, NULL);
if( hr != D3D_OK )
{
SetError( "Impossible to use D3DXIntersect()" );
}

if(!bHit)
m_bHit=true;
else
m_bHit=false;


return m_bHit;
}




THANKS TO EVERYBODY!!!!

(specially to neneboricua19 ^__^ )

-----------------------------------------------
- GENTS -

"Every man dies, not every man really lives"
[William Wallace]


Share this post


Link to post
Share on other sites
Below is my picking function to check if the mouse pointer is over the mesh supplied (with it''s world position matrix) as parameters during the function call:

BOOL CApp::CheckObjectMouse( ID3DXMesh* Mesh, D3DXMATRIX* ObjMatrix )
{
D3DXVECTOR3 vPickRayDir; // Pick ray direction

D3DXVECTOR3 vPickRayOrig; // Pick ray origin

D3DXVECTOR3 v; // Vector used in computation

D3DXMATRIXA16 matProj; // Retrieved projection matrix

D3DXMATRIXA16 matView, m; // Retrieved view and computation matrices

POINT ptCursor; // Cursor position

D3DXVECTOR3 vNear, vDir;
D3DXMATRIX invMat;
BOOL bHit;
DWORD dwIndex;
float uCoord, vCoord;
float dist;
LPDIRECT3DSURFACE9 pBackBuffer = NULL;
D3DSURFACE_DESC Desc;

// Error check

if( m_Graphics.GetDeviceCOM() == NULL ) { return FALSE; }
if( Mesh == NULL ) { return FALSE; }
if( ObjMatrix == NULL ) { return FALSE; }

// Get back buffer description

m_Graphics.GetDeviceCOM()->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
pBackBuffer->GetDesc( &Desc );
pBackBuffer->Release();

// Get the projection matrix

m_Graphics.GetDeviceCOM()->GetTransform( D3DTS_PROJECTION, &matProj );

// Get the cursor position

GetCursorPos( &ptCursor );

// Change coordinates relative to the window which the level is rendered in

ScreenToClient( GethWnd(), &ptCursor );

// Compute the pick ray in screen space

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

// Get the inverse view matrix

m_Graphics.GetDeviceCOM()->GetTransform( D3DTS_VIEW, &matView );
D3DXMatrixInverse( &m, NULL, &matView );

// Transform the screen space pick ray in to 3D coordinates

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;

// Calclate the origin as intersection with the near frustum plane

vPickRayOrig += vPickRayDir * 1.0f;

// Convert the ray to model space

D3DXMatrixInverse( &invMat, NULL, ObjMatrix );
D3DXVec3TransformCoord( &vNear, &vPickRayOrig ,&invMat);
D3DXVec3TransformNormal( &vDir, &vPickRayDir, &invMat);

// Test for intersection

D3DXIntersect( Mesh, &vNear, &vDir, &bHit, &dwIndex, &uCoord, &vCoord, &dist, NULL, NULL );

if( bHit == TRUE )
{
// Check that we''re close to the object

if( dist > 8.0f )
return FALSE;
else
return TRUE;
}
else
return FALSE;
}


Hope that helps.

Share this post


Link to post
Share on other sites
quote:
Original post by GENTS
Ok you''re right!!!

I''ve done a debug check and my D3DXIntersect Function doesn''t return never D3D_OK...

But still now I can''t find the bug of my program!!!

I''ve free memory so I can''t think it''s a less-memory problem!!!


Please use the Debug Runtime. I can''t stress it enough! If you were running with the Debug Runtime, D3D would be able to tell you not only that a function has failed, but also *why* it failed.

neneboricua

Share this post


Link to post
Share on other sites
Thanks you all!!!

I'll now try __Daedalus__ code and then I'd say you results!!!

I'm also installing DirectX Debug Runtime for my and your pleasure!!!

Only a last question for __Daedalus__...

But your model matrix is the one of the loading or you pick it during the game just before of the call to your function?!

THANKS A LOT!!!

PS: I've installed the Debug Runtime but it give me no information!!! [except the memory freed - all other is ok! ]

-----------------------------------------------
- GENTS -

"Every man dies, not every man really lives"
[William Wallace]




[edited by - GENTS on June 11, 2004 7:33:34 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by GENTS
Thanks you all!!!

I''ll now try __Daedalus__ code and then I''d say you results!!!

I''m also installing DirectX Debug Runtime for my and your pleasure!!!

Only a last question for __Daedalus__...

But your model matrix is the one of the loading or you pick it during the game just before of the call to your function?!

THANKS A LOT!!!

PS: I''ve installed the Debug Runtime but it give me no information!!! [except the memory freed - all other is ok! ]

-----------------------------------------------
- GENTS -

"Every man dies, not every man really lives"
[William Wallace]




[edited by - GENTS on June 11, 2004 7:33:34 AM]


Hello,

The mesh you''re trying to pick is the first parameter of the function and it''s orientation matrix is the second parameter (that is the combined translation, rotation and scale matrices).
I am assuming each of your meshes has it''s own matrix to orient it in your world. You would obvioulsly have to update each of your meshes corresponding orientation matrices before testing them in calls to this function.

Share this post


Link to post
Share on other sites
I''m sorry for you all and for ME, but it still doesn''t work!!!

It''s impossible to use in my game!!!

I''m so sad!!!!!!!

THANKS A LOT in any case!!!

-----------------------------------------------
- GENTS -

"Every man dies, not every man really lives"
[William Wallace]


Share this post


Link to post
Share on other sites
quote:
Original post by GENTS
PS: I''ve installed the Debug Runtime but it give me no information!!! [except the memory freed - all other is ok!]


Hmm... if you''re linking to d3dxd.lib, and you''ve got the debug output sliders ramped up to full, it should at least tell you something... weird.

Share this post


Link to post
Share on other sites
Finally THANKS to __Daedalus__ I get it to work!!!

This is my final code:

<!--STARTSCRIPT-->


BOOL SottoTiro( D3DXMESHCONTAINER_EX* Obj, D3DXMATRIX* ObjMatrix)
{
// Pick ray direction
D3DXVECTOR3 vPickRayDir;
// Pick ray origin
D3DXVECTOR3 vPickRayOrig;
// Vector used in computation
D3DXVECTOR3 v;
// Retrieved computation matrix
D3DXMATRIXA16 m;

// Cursor position
POINT ptCursor;
D3DXVECTOR3 vNear, vDir;
D3DXMATRIX invMat;
BOOL bHit;
DWORD dwIndex;
float uCoord, vCoord;
float dist;
LPDIRECT3DSURFACE9 pBackBuffer = NULL;
D3DSURFACE_DESC Desc;
ID3DXMesh* Mesh = Obj->MeshData.pMesh;

// Get back buffer description
g_pD3DDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
pBackBuffer->GetDesc( &Desc );
pBackBuffer->Release();

g_pD3DDevice->GetTransform( D3DTS_PROJECTION, &matProj );

// Create a local copy of where your Zen mouse postion is (not using the windows mouse)
ptCursor = MousePoint;

// Change coordinates relative to the window which the level is rendered in
ScreenToClient( g_hWndMain, &ptCursor );

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

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

// Transform the screen space pick ray in to 3D coordinates
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;

// Calclate the origin as intersection with the near frustum plane
vPickRayOrig += vPickRayDir * 1.0f;

// Convert the ray to model space
D3DXMatrixInverse( &invMat, NULL, ObjMatrix );
D3DXVec3TransformCoord( &vNear, &vPickRayOrig ,&invMat);
D3DXVec3TransformNormal( &vDir, &vPickRayDir, &invMat);

// Test for intersection
D3DXIntersect( Mesh, &vNear, &vDir, &bHit, &dwIndex, &uCoord, &vCoord, &dist, NULL, NULL );

// I took out the distance check here from my source on your Gamedev thread.
// This would only have returned TRUE if you were within 8 units of the
// dresser when picking it.
if( bHit == TRUE )
{
return TRUE;
}
else{
return FALSE;
}


}


<!--ENDSCRIPT-->


It's almost identical to __Daedalus__ code...

THANKS TO ALL!!!

I hope this'll help other newbie as me!!!

Byez

-----------------------------------------------
- GENTS -

"Every man dies, not every man really lives"
[William Wallace]




[edited by - GENTS on June 13, 2004 4:55:34 AM]

Share this post


Link to post
Share on other sites
Finally THANKS to __Daedalus__ I get it to work!!!

This is my final code:

<!--STARTSCRIPT-->


BOOL SottoTiro( D3DXMESHCONTAINER_EX* Obj, D3DXMATRIX* ObjMatrix)
{
// Pick ray direction
D3DXVECTOR3 vPickRayDir;
// Pick ray origin
D3DXVECTOR3 vPickRayOrig;
// Vector used in computation
D3DXVECTOR3 v;
// Retrieved computation matrix
D3DXMATRIXA16 m;

// Cursor position
POINT ptCursor;
D3DXVECTOR3 vNear, vDir;
D3DXMATRIX invMat;
BOOL bHit;
DWORD dwIndex;
float uCoord, vCoord;
float dist;
LPDIRECT3DSURFACE9 pBackBuffer = NULL;
D3DSURFACE_DESC Desc;
ID3DXMesh* Mesh = Obj->MeshData.pMesh;

// Get back buffer description
g_pD3DDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
pBackBuffer->GetDesc( &Desc );
pBackBuffer->Release();

g_pD3DDevice->GetTransform( D3DTS_PROJECTION, &matProj );

// Create a local copy of where your Zen mouse postion is (not using the windows mouse)
ptCursor = MousePoint;

// Change coordinates relative to the window which the level is rendered in
ScreenToClient( g_hWndMain, &ptCursor );

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

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

// Transform the screen space pick ray in to 3D coordinates
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;

// Calclate the origin as intersection with the near frustum plane
vPickRayOrig += vPickRayDir * 1.0f;

// Convert the ray to model space
D3DXMatrixInverse( &invMat, NULL, ObjMatrix );
D3DXVec3TransformCoord( &vNear, &vPickRayOrig ,&invMat);
D3DXVec3TransformNormal( &vDir, &vPickRayDir, &invMat);

// Test for intersection
D3DXIntersect( Mesh, &vNear, &vDir, &bHit, &dwIndex, &uCoord, &vCoord, &dist, NULL, NULL );

// I took out the distance check here from my source on your Gamedev thread.
// This would only have returned TRUE if you were within 8 units of the
// dresser when picking it.
if( bHit == TRUE )
{
return TRUE;
}
else{
return FALSE;
}


}


<!--ENDSCRIPT-->


It''s almost identical to __Daedalus__ code...

THANKS TO ALL!!!

I hope this''ll help other newbie as me!!!

Byez

-----------------------------------------------
- GENTS -

"Every man dies, not every man really lives"
[William Wallace]


Share this post


Link to post
Share on other sites

  • Advertisement