Skip to main content
gamedev.net
🔒 Locked

Ray pick ?

Started by Mythar Apr 5, 2005 at 9:38 AM 6 replies 1.5k views
Original Post
Mythar
Mythar
Hi all, i was trying to add ray picking to my terrain, but i cant get it to work.

  GetTransform(D3DTS_PROJECTION, m);
  GetViewport(vp);

  v.x :=  ( ( ( 2.0 * x ) / vp.Width ) - 1 ) / m._00;
  v.y := -( ( ( 2.0 * y ) / vp.Height ) - 1 ) / m._11;
  v.z :=  1.0;

  GetTransform(D3DTS_VIEW, m2);
  D3DXMatrixInverse( m, nil, m2);

  rayDir.x := v.x*m._00 + v.y*m._10 + v.z*m._20;
  rayDir.y := v.x*m._01 + v.y*m._11 + v.z*m._21;
  rayDir.z := v.x*m._02 + v.y*m._12 + v.z*m._22;
  rayOrigin.x := m._30;
  rayOrigin.y := m._31;
  rayOrigin.z := m._32;

  GetTransform(D3DTS_WORLD, m2);
  D3DXMatrixInverse( m, nil, m2);

  D3DXVec3TransformCoord(rayObjOrigin, rayOrigin, m);
  D3DXVec3TransformNormal(rayObjDir, rayDir, m);
  D3DXVec3Normalize(rayObjDir, rayObjDir);


did I overlook something ?
matthughson
matthughson
Since you haven't got a response yet, I'll just post a potentially unhelpful link: Ray Picking.

It's the tutorial I used to get picking working, and aside from some updating from the old D3DMath_ functions, I was able to get things working with no probalems.

So take a look, and maybe you can compare your code to it.

Matt Hughson
__________________________________[ Website ] [ Résumé ] [ [email=contact[at]matthughson[dot]com]Contact[/email] ][ Have I been Helpful? Hook me up! ]
Mythar
Mythar
Thx Matt, this helped.

However I have a few things I would like to be able to do.

First I would like to be able to extract the FOV,NEAR and FAR, directly from
the PROJECTION matrix. (as I would like this to work for any PROJECTION used, how do I do that ? )

The ASPECT I can get by using GetViewport, ( Width / Height ).

2ndly I would need to Transform the p1 and p2 according to the WORLD (model space) matrix.
Lord_Taren
Lord_Taren
Here is the function I created to do the ray picking for me. It's written in c#. The function calculates a picking ray based on a set of screen coordinates. I hope this helps. If you have any questions, let me know.

//*****************************************************************************
//* calcPickingRay
//*
//* Calculate a Picking ray based on a set of screen coordinates.
//*****************************************************************************
private rdRay calcPickingRay(System.Int32 x, System.Int32 y)
{
Direct3D.Viewport vp;
DirectX.Matrix proj;

rdRay xTmpRay;

System.Single px = 0.0f;
System.Single py = 0.0f;

//* Get the viewport and the projection matrix
vp = m_dxDevice.Viewport;
proj = m_dxDevice.Transform.Projection;

px = (((2.0f * x) / vp.Width) - 1.0f) / proj.M11;
py = (((-2.0f * y) / vp.Height) + 1.0f) / proj.M22;

xTmpRay = new rdRay();
xTmpRay.origin = new Vector3(0, 0, 0);
xTmpRay.direction = new Vector3(px, py, 1);

return xTmpRay;
}

Here's the definition of rdRay
//*****************************************************************************
//* rdRay
//*
//* A ray contains an origin and a direction.
//*****************************************************************************
public struct rdRay
{
public DirectX.Vector3 origin;
public DirectX.Vector3 direction;
};
-------------------Emil Diegoediego@miami.edu
matthughson
matthughson
Quote:
Original post by Mythar
First I would like to be able to extract the FOV,NEAR and FAR, directly from
the PROJECTION matrix. (as I would like this to work for any PROJECTION used, how do I do that ? )


Hmm, does your FOV and clipping planes change dynaically in game? I don't see why they would (maybe FOV if u have a zoom feature), but if not can't you just save them when you initialize Direct3D?

Quote:
Original post by Mythar
2ndly I would need to Transform the p1 and p2 according to the WORLD (model space) matrix.


I can't seem to find what p1 and p2 represent in that question?

Also, here's my function for creating a ray from a point in pixel space. It's based on a tutorial out there; not sure which one though =(

void pixelToWorld(float x, float y, D3DXVECTOR3 &rayDir, D3DXVECTOR3 &rayOrigin){	// Singletons	CDX_D3DWrapper* pD3DMan		= CDX_D3DWrapper::getInstance();	CDX_Text* pTxtMan			= CDX_Text::getInstance();	CDX_Camera* pCamMan			= CDX_Camera::getInstance();	// Get the screen res	D3DXVECTOR2 v2WindDim		= pD3DMan->getWindowDimensions();	D3DXVECTOR2 v2WindDimHalf	= v2WindDim * 0.5f;	// Get the aspect ration	float fAspect = v2WindDim.x / v2WindDim.y;	D3DXVECTOR3 v;	v.x =  ( ( ( 2.0f * x ) / v2WindDim.x ) - 1 ) / pD3DMan->m_matProj._11;	v.y = -( ( ( 2.0f * y ) / v2WindDim.y ) - 1 ) / pD3DMan->m_matProj._22;	v.z =  1.0f;		D3DXMATRIXA16 m;	D3DXMATRIX matView;	pCamMan->getMatrix(&matView);	D3DXMatrixInverse( &m, NULL, &matView );	// Transform the screen space pick ray into 3D space	rayDir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;	rayDir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;	rayDir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;	rayOrigin.x = m._41;	rayOrigin.y = m._42;	rayOrigin.z = m._43;	D3DXVec3Normalize(&rayDir, &rayDir);}


Let me know how things go!
Matt Hughson
__________________________________[ Website ] [ Résumé ] [ [email=contact[at]matthughson[dot]com]Contact[/email] ][ Have I been Helpful? Hook me up! ]
Mythar
Mythar
OK here is what i got so far.

Method 1:
  GetTransform(D3DTS_PROJECTION, m);  GetViewport(vp);  v.x :=  ( ( ( 2.0 * x ) / vp.Width ) - 1 ) / m._11;  v.y := -( ( ( 2.0 * y ) / vp.Height ) - 1 ) / m._22;  v.z :=  1.0;   GetTransform(D3DTS_VIEW, matView);  D3DXMatrixInverse( m, NULL, matView );  rayDir.x  := v.x*m._11 + v.y*m._21 + v.z*m._31;  rayDir.y  := v.x*m._12 + v.y*m._22 + v.z*m._32;  rayDir.z  := v.x*m._13 + v.y*m._23 + v.z*m._33;  rayOrigin.x := m._41;  rayOrigin.y := m._42;  rayOrigin.z := m._43;


Method 2:
  GetViewport(vp);  ASPECT := vp.Width / vp.Height;  // FOV in rads  dx := tan(FOV*0.5)*(x/(vp.Width*0.5)-1.0)/ASPECT;  dy := tan(FOV*0.5)*(1.0-y/(vp.Height*0.5));  GetTransform(D3DTS_VIEW, matView);  D3DXMatrixInverse( m, NULL, matView );  rayOrigin := Vector(dx*NEAR,dy*NEAR,NEAR);  rayDir := Vector(dx*FAR,dy*FAR,FAR);  VectorMatrixMultiply(rayOrigin,rayOrigin,m);  VectorMatrixMultiply(rayDir,rayDir,m);  rayDir := DirectionVector(rayDir,rayOrigin);


When using M1 : Im forced to use D3DXMatrixPerspectiveFovLH, to make it work.

When using M2 : I can use any projection matrix i want, BUT it only works on "Y", the "x" aspect is not correct (it's too "wide").

I would prefer to use M2, as this gives me more freedom when it comes to the projection matrix.

I usealy create my projection matrix like this :
  c := cos(fov*0.5);  s := sin(fov*0.5);  Q := s/(1.0 - near_plane/far_plane);  ZeroMemory(@m, sizeof(D3DMATRIX));  m._11 := c;  m._22 := c;  m._33 := Q;  m._43 := -Q*near_plane;  m._34 := s;


I now need to figure out why M2 mess up on the "x" aspect ??
Mythar
Mythar
hmm, it seems there was a bug in the ray pick link (http://www.mvps.org/directx/articles/rayproj.htm) you posted.

That tut. calc. dx as :
dx=tan(FOV*0.5f)*(x/WIDTH_DIV_2-1.0f)/ASPECT

But it seems that it should have been :
dx=tan(FOV*0.5f)*(x/WIDTH_DIV_2-1.0f)

This seems to fix the "x" aspect :)

Now I only need to take the WORLD matrix into account also ?
Instruo
Instruo
tag
"Game Programming" in an of itself does not exist. We learn to program and then use that knowledge to make games.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.