D3DXIntersect()

Started by
14 comments, last by GENTS 19 years, 10 months ago
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]
----------------------------------------------- - GENTS -"Every man dies, not every man really lives"[William Wallace] - visit my website: GENTS.it -- Using Effect files with DirectX 9 Basics Tutorial -- MilkShape 3D models and OpenGL ES Tutorial -
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
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]
----------------------------------------------- - GENTS -"Every man dies, not every man really lives"[William Wallace] - visit my website: GENTS.it -- Using Effect files with DirectX 9 Basics Tutorial -- MilkShape 3D models and OpenGL ES Tutorial -
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
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 meshbool 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]


----------------------------------------------- - GENTS -"Every man dies, not every man really lives"[William Wallace] - visit my website: GENTS.it -- Using Effect files with DirectX 9 Basics Tutorial -- MilkShape 3D models and OpenGL ES Tutorial -
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.
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
There''s even a debug D3DX runtime to link to, use d3dx9d.lib or whatever.

Why you shouldn''t use iostream.h - ever! | A Good free online C++ book
The Forum FAQ explains how to set up / use the debug runtime.

Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse

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]
----------------------------------------------- - GENTS -"Every man dies, not every man really lives"[William Wallace] - visit my website: GENTS.it -- Using Effect files with DirectX 9 Basics Tutorial -- MilkShape 3D models and OpenGL ES Tutorial -

This topic is closed to new replies.

Advertisement