Should I use the D3DXVec3Unproject 2 times to get a ray for theD3DXIntersectTri func

Started by
7 comments, last by ankhd 16 years, 11 months ago
Hey all, well still doing damn ray inersections, well the mesh intersect now works good and I thought I would try one with triangles so I looked it up, set one up fine, should work no,??????? Now the question is, is it how I create my ray this is how its done Call D3DXVec3Unproject two times, once with MouseX,MouseY,0 and MouseX,MouseY,1. This returns you two points in 3d space which form a ray. Use that ray to do intersection tests.

		rt = D3DXVec3Unproject(&tempdir,//rayDir,//D3DXVECTOR3 *pOut,
							&vmouse,//CONST D3DXVECTOR3 *pV,
							ViewPort,//CONST D3DVIEWPORT9 *pViewport,
							matProj,//CONST D3DXMATRIX *pProjection,
							matView,//CONST D3DXMATRIX *pView,
							pWorld);//CONST D3DXMATRIX *pWorld

		if(rt == NULL)
		{
			
			return false;
		}


	

	
		vmouse.z = 1;//ViewPort->MaxZ;//0.99f;

	


		rt = D3DXVec3Unproject(&RayPos,//rayOrigin,//D3DXVECTOR3 *pOut,
				       &vmouse,//CONST D3DXVECTOR3 *pV,
								ViewPort,//CONST D3DVIEWPORT9 *pViewport,
		matProj,//CONST D3DXMATRIX *pProjection,
		matView,//CONST D3DXMATRIX *pView,
		pWorld);//CONST D3DXMATRIX *pWorld

		if(rt == NULL)
		{
			
			return false;//error
		}


RayDir = tempdir - RayPos;

//OK THATS THE RAY CREATED

		//ok lock the vertex buffer and get the positions of the verties for the first triangle
		//fill the vertex buffers 
		COLUM_VERTEX *pvertices = NULL;
		if(FAILED(VBuff->Lock(0, 0, (void**)&pvertices, 0 ) ) )
			return false;
   

		short *indexdata = NULL;
		if(FAILED(IBuff->Lock(0,0, (void**)&indexdata,0)))
		{
			VBuff->Unlock();
			MessageBeep(MB_OK);
			return false;//error
		}


		//memcpy(indexdata, &indices, sizeof(indices));
			 //indexdata[0] = 0;
			 //indexdata[1] = 1;
			 //indexdata[2] = 3;

			 //indexdata[3] = 3;
			 //indexdata[4] = 1;
			 //indexdata[5] = 2;
			 
		 

		
		p0 = pvertices[indexdata[0]].p;
		p1 = pvertices[indexdata[1]].p;
		p2 = pvertices[indexdata[2]].p;
		//pvertices[1] = vertices[1];
		//pvertices[2] = vertices[2];
		//pvertices[3] = vertices[3];

    
		VBuff->Unlock();
		IBuff->Unlock();


		BOOL val = D3DXIntersectTri(&p0,//const D3DXVECTOR3 *p0,
									&p1,//const D3DXVECTOR3 *p1,
									&p2,//const D3DXVECTOR3 *p2,
	&RayPos,
	&RayDir,
									&u,//FLOAT *pU,
									&v,//FLOAT *pV,
									&dist);//FLOAT *pDist


and here is the triangles vertices V0 = {-1,-1,0} V1 = {-1,1,0} V2 = {1,-1,0} The Rays Position = {-0.39046, 0.27304, 0.99310} RayDirection = {0,0,0} it looks like is a ccw triangle could it be the winding order may be it is that I'll look into that now
Advertisement
On the whole, your code looks okay, but something's clearly amiss: (0, 0, 0) isn't a valid ray direction. Are you sure vmouse.z is being initialised to 0 before the first unprojection?

Also, according to MSDN, D3DXVec3Unproject isn't allowed to return NULL, so that test is redundant.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
I'm not good with C++ but here is my code for VB/MDX, maybe it will help.

        Dim vN As Vector3 ' near vector        Dim vF As Vector3 ' far vector        Dim vD As Vector3 ' direction vector        ' get near and far vectors by unprojecting mouse        vN = Vector3.Unproject(New Vector3(e.X, e.Y, 0), dev.Viewport, dev.Transform.Projection, dev.Transform.View, dev.Transform.World)        vF = Vector3.Unproject(New Vector3(e.X, e.Y, 1), dev.Viewport, dev.Transform.Projection, dev.Transform.View, dev.Transform.World)        ' get direction vector        vD = Vector3.Subtract(vF, vN)        ' check for intersection        Dim temphit as IntersectInformation        If Geometry.IntersectTri(v0, v1, v2, vN, vD, temphit) Then            Console.WriteLine(temphit.Dist)        End If


[Edited by - iosys on May 7, 2007 5:29:25 PM]
______________________________Perry Butler aka iosysiosys Website | iosys Music | iosys Engine
The Ray Direction is zero because the two D3DXVec3Unproject calls return the same value How can this be I set vmouse.z to 0 first and then 1 and it returns the same value whats wrong with it.
Quote:Original post by ankhd
The Ray Direction is zero because the two D3DXVec3Unproject calls return the same value How can this be I set vmouse.z to 0 first and then 1 and it returns the same value whats wrong with it.

What value is being returned? Is it realistic? For example, if the ray being cast is contained on the screen, do the unprojected coordinates reflect this?

I've seen D3DXVec3Unproject fail in the past, and it seems to return nonsense values. This will happen if you pass it an invalid parameter. Trace your code and rigorously check the function arguments: Make sure that the world, view and projection matrices look right - no floating point exceptions in the matrices - and that the viewport has znear < zfar. If the IDirect3DDevice9->GetViewport call succeeds (you are calling it, right?), then it should be fine.

If you're still stuck, show us an example case including values for all the matrices, the viewport and the input & output vectors.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Hey thanks all,
Here is the out put
ViewPort
Width = 800
Hieght = 600
Maxz = 1.0f
MinZ = 0.0f

ViewPort Checks ok

Projection
_11 = 1.8106600
_22 = 2.4142134
_33 = 1.0101010
_34 = 1.0000000
_43 = 10.101009

all other members = 0.0000000
looks ok to me

View
checks out ok

but the world has large values
World
_11 = 19.696
_12 = -3.4729
-22 = 120.00
_41 = -120.00 //x
_42 = 50.000 //y
_43 = 15.00 //z
_44 = 1.000


vectors
direction = {0.39283931, 0.28449842, 0.99309124}
Pos = {0.39283931, 0.28449842, 0.99309124}
then I do this to get the direction
RayDir = tempdir - RayPos;

this is = 0,0,0
would it have any thing to to with the culling mode
the triangles are ccw I think
p0 = pvertices[indexdata[0]].p;
p1 = pvertices[indexdata[1]].p;
p2 = pvertices[indexdata[2]].p;

Vector transformations have nothing to do with culling modes.

But everything there seems to be in order, so we'll need to zoom out a little. Post a bigger sample of code, so that we can see where vmouse is assigned. Also show us where you create the projection matrix.

I'm not sure if it's indicative of a deeper misunderstanding or not, but your variable naming is very confusing:

RayPos and tempdir aren't really the ray's position and direction, but two points along the ray. They'd be better named near_point and far_point or something. This is a little cosmetic, perhaps, but good habits are always wise.

Also, I trust matProj and matView are indeed pointers to matrices, as pWorld is, or it wouldn't compile. You should strive to be more consistent in your notation.

One last thought is to make sure you have the Direct3D debug runtimes enabled. If D3DX is failing for some reason, it would probably let you know in the output window.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Thanks for your time all, here is the code
void Camera2::getViewMatrix(D3DXMATRIX* V){	D3DXMatrixIdentity(V);	// Keep camera's axes orthogonal to eachother	D3DXVec3Normalize(&_look, &_look);	D3DXVec3Cross(&_up, &_look, &_right);	D3DXVec3Normalize(&_up, &_up);	D3DXVec3Cross(&_right, &_up, &_look);	D3DXVec3Normalize(&_right, &_right);	// Build the view matrix:	float x = -D3DXVec3Dot(&_right, &_pos);	float y = -D3DXVec3Dot(&_up, &_pos);	float z = -D3DXVec3Dot(&_look, &_pos);	(*V)(0,0) = _right.x; (*V)(0, 1) = _up.x; (*V)(0, 2) = _look.x; (*V)(0, 3) = 0.0f;	(*V)(1,0) = _right.y; (*V)(1, 1) = _up.y; (*V)(1, 2) = _look.y; (*V)(1, 3) = 0.0f;	(*V)(2,0) = _right.z; (*V)(2, 1) = _up.z; (*V)(2, 2) = _look.z; (*V)(2, 3) = 0.0f;	(*V)(3,0) = x;        (*V)(3, 1) = y;     (*V)(3, 2) = z;       (*V)(3, 3) = 1.0f;}//end getViewMatrix////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Camera->getViewMatrix(&matView);Device->SetTransform(D3DTS_VIEW, &matView);		    // For the projection matrix, we set up a perspective transform (which    // transforms geometry from 3D view space to 2D viewport space, with    // a perspective divide making objects smaller in the distance). To build    // a perpsective transform, we need the field of view (1/4 pi is common),    // the aspect ratio, and the near and far clipping planes (which define at    // what distances geometry should be no longer be rendered).    //D3DXMATRIXA16 matProj;	FLOAT      fAspect = (FLOAT)Window.Width / (FLOAT)Window.Height;	D3DXMatrixIdentity(&matProj);    D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, fAspect, 1.0f, 10000.0f);    Device->SetTransform( D3DTS_PROJECTION, &matProj );//-----------------------------------------------------------------------------//this will do collision for the columns//-----------------------------------------------------------------------------void intersect(D3DXMATRIXA16 *World){	if(GetCapture() == NULL)		return;//no mouse    	POINT ptCursor = {0, 0};    GetCursorPos(&ptCursor );    ScreenToClient(Window.Hwnd, &ptCursor);	bool val = Columns.ColumnInersect(ptCursor.x, ptCursor.y,//the mouse location								&ViewPort,								&matProj,								&matView,								World);}//end intersect////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////BOOL ColumnInersect(int x, int y,//the mouse location						D3DVIEWPORT9 *ViewPort,						D3DXMATRIX *matProj,						D3DXMATRIX *matView,						D3DXMATRIX *pWorld)	{		D3DXVECTOR3 p0, p1, p2;		D3DXVECTOR3 RayPos, RayDir;		FLOAT u, v, dist; 		//build the ray		//ok we can set the rays locations based on the mouse points		POINT ptCursor = {x, y};   			D3DXVECTOR3 *rt = NULL;//returned from call		D3DXVECTOR3 vmouse, tempdir;		vmouse.x = (FLOAT)ptCursor.x;// + GetSystemMetrics(SM_CXSIZEFRAME);		vmouse.y = (FLOAT)ptCursor.y;		vmouse.z = ViewPort->MinZ;//0.001f;//campos->z;				//Call D3DXVec3Unproject two times, once with MouseX,MouseY,0 and MouseX,MouseY,1.		//This returns you two points in 3d space which form a ray. Use that ray to do intersection tests.		rt = D3DXVec3Unproject(&tempdir,//rayDir,//D3DXVECTOR3 *pOut,							&vmouse,//CONST D3DXVECTOR3 *pV,							ViewPort,//CONST D3DVIEWPORT9 *pViewport,							matProj,//CONST D3DXMATRIX *pProjection,							matView,//CONST D3DXMATRIX *pView,							pWorld);//CONST D3DXMATRIX *pWorld		//if(rt == NULL)		//{		//	MessageBeep(MB_OK);		//	return false;		//}				vmouse.z = 1.0f;//ViewPort->MaxZ;//0.99f;	//Camera->getLook(&vmouse);		rt = D3DXVec3Unproject(&RayPos,//rayOrigin,//D3DXVECTOR3 *pOut,								&vmouse,//CONST D3DXVECTOR3 *pV,								ViewPort,//CONST D3DVIEWPORT9 *pViewport,							matProj,//CONST D3DXMATRIX *pProjection,							matView,//CONST D3DXMATRIX *pView,							pWorld);//CONST D3DXMATRIX *pWorld		//if(rt == NULL)		//{		//	MessageBeep(MB_OK);		//	return false;//error		//}		//vector_3d acts as a dummy vector here and does nothing//D3DXVec3Project( &vector_2d, &vector_3d, &d3dvp, &proj_matrix, &view_matrix, &world_matrix );//vector_2d holds accurate screen coords//D3DXVec3Unproject( &vector_3d, &vector_2d, &d3dvp, &proj_matrix, &view_matrix, &world_matrix );//vector_3d holds accurate world (object) coords		 //Camera->getPosition(&RayPos);		 //Camera->getLook(&tempdir);//_look;		RayDir =RayPos - tempdir ;//OK THATS THE RAY CREATED		//ok lock the vertex buffer and get the positions of the verties for the first triangle		//fill the vertex buffers 		COLUM_VERTEX *pvertices = NULL;		if(FAILED(VBuff->Lock(0, 0, (void**)&pvertices, 0 ) ) )			return false;   		short *indexdata = NULL;		if(FAILED(IBuff->Lock(0,0, (void**)&indexdata,0)))		{			VBuff->Unlock();			MessageBeep(MB_OK);			return false;//error		}		//memcpy(indexdata, &indices, sizeof(indices));			 //indexdata[0] = 0;			 //indexdata[1] = 1;			 //indexdata[2] = 3;			 //indexdata[3] = 3;			 //indexdata[4] = 1;			 //indexdata[5] = 2;			 		 				p0 = pvertices[indexdata[0]].p;		p1 = pvertices[indexdata[1]].p;		p2 = pvertices[indexdata[2]].p;		//pvertices[1] = vertices[1];		//pvertices[2] = vertices[2];		//pvertices[3] = vertices[3];    		VBuff->Unlock();		IBuff->Unlock();		BOOL val = D3DXIntersectTri(&p0,//const D3DXVECTOR3 *p0,									&p1,//const D3DXVECTOR3 *p1,									&p2,//const D3DXVECTOR3 *p2,									&RayPos,									&RayDir,									&u,//FLOAT *pU,									&v,//FLOAT *pV,									&dist);//FLOAT *pDist//				//BOOL val = IntersectTriangle(RayPos,//const D3DXVECTOR3& orig,       //                              RayDir,//  const D3DXVECTOR3& dir,		//							 p0,//D3DXVECTOR3& v0,        //                             p1, p2,// D3DXVECTOR3& v1, D3DXVECTOR3& v2,        //                              &dist, &u, &v );if(val == FALSE)			return false;		MessageBox(NULL,"Hello there","Nope it not me", MB_OK);		return true;//it was a hit	}//end ColumnInersect	//////////////////////////////////////////////////////////////////////////////////////	//////////////////////////////////////////////////////////////////////////////////////


Hey all thanks for all your time I HAVE FOUND THE PROBLEM
it was in the objects world matix scale I had the z sacale to 0 and this did all that hmmm.
Any one know why.

D3DXMatrixScaling(&scale,
20,
120,
0); //Rx


all = (scale * Ry) * trans;

This topic is closed to new replies.

Advertisement