Jump to content
  • Advertisement

Archived

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

GENTS

D3DXIntersect()

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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!