# Problems with Picking using D3DXIntersect()

This topic is 3809 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi all, I'm currently having trouble getting picking to work in my Bezier curve application. The idea is to have a sphere at each of the control points along the bezier curve and I can then click on a sphere to move its respective control point. All the bezier math etc. is fine but I can't get picking to work. I'm using the DirectX August 2007 SDK and C++. First of all each control point is defined:
struct CtrlPoint							//A structure to hold data on a control point
{
D3DXVECTOR3 position;	//Position of the control Point
ID3DXMesh* mesh;		//A mesh which will represent the control point visually
float radius;			//Radius of the sphere (of the mesh which represents the control point)
bool selected;			//Whether the point has been selected by the mouse
D3DXMATRIX world;		//The control point's world matrix (for calculating picking)
}ctrlPoint[NUMCTRLPOINTS];	//Creates an array of control points

Then the sphere displayed at the point is created thus:
D3DXCreateSphere(gd3dDevice,
20,
20,
&ctrlPoint.mesh,
0);

and displayed:
D3DXMatrixIdentity(&I);
//Display a sphere each control point
for(int i=0; i<NUMCTRLPOINTS; i++)	//for each control point
{
D3DXMATRIX T;
//Translate the matrix to the position of the control point
D3DXMatrixTranslation(&T, ctrlPoint.position.x, ctrlPoint.position.y, ctrlPoint.position.z);
//Calculate the total movement/rotation into one matrix
S = I * T;
//Transform to the position/orientation of the matrix
gd3dDevice->SetTransform(D3DTS_WORLD, &S);
//Store the control point's world matrix
gd3dDevice->GetTransform(D3DTS_WORLD, &ctrlPoint.world);
//Set the standard red material for the control point
gd3dDevice->SetMaterial(&Material::RED_MTRL);
//Draw the Sphere
ctrlPoint.mesh->DrawSubset(0);
}

As you can see I translate to the position of each point Set the world matrix and store it then draw the point. Don't think there's any problem there. Then in my main loop I make a call to the pick function which takes in all the necessary paramaters:
//If the left Mouse Button is clicked and wasn't down last frame
if(gDInput->mouseButtonDown(0) && mouseClicked==0)
{
POINT cursorPos;
//Get the position of the cursor
GetCursorPos(&cursorPos);
//Make it relative to the client area window
ScreenToClient(*mainWnd, &cursorPos);

D3DVIEWPORT9 vp;
//Get the current viewport
gd3dDevice->GetViewport(&vp);

D3DXMATRIX proj;
//Get the current Projection matrix
gd3dDevice->GetTransform(D3DTS_PROJECTION, &proj);

D3DXMATRIX view;
//Get the current view matrix from the camera class
camera->getViewMatrix(&view);
//gd3dDevice->GetTransform(D3DTS_VIEW, &view); //Not using this method to get view matrix currently

//Calculate Picking
pick->doPick(cursorPos, vp, proj, view,
bezier[0]->getCtrlPoints(), //Array of control point structs
bezier[0]->getNumCtrlPoints() //Number of control Points
);
}

The view matrix is currently calculated in the camera class (taken from Frank D Luna's DirectX book) and works fine for rotation/translation of the camera etc. As you can see there is a line commented out which gets the view matrix using 'gd3dDevice->GetTransform()' this method gives different results (still doesn't work) when doing the picking calculations even though it should essentially return the camera view matrix anyway as it is updated each frame:
//Update the view matrix representing the cameras new position/orientation.
D3DXMATRIX V;
camera->getViewMatrix(&V);
gd3dDevice->SetTransform(D3DTS_VIEW, &V);

However there must be a problem in my picking function anyway as it still doesn't work no matter which way I get the view matrix. Here's the picking function which is mostly taken from the Toymaker Picking Tutorial
void Pick::doPick(POINT cursorPos, D3DVIEWPORT9 vp, D3DXMATRIX proj, D3DXMATRIX view, Bezier::CtrlPoint* ctrlPoint1,Bezier::CtrlPoint* ctrlPoint2, int numCtrlPoints)
{
for(int i=0; i<numCtrlPoints; i++)	//for each control point
{
D3DXVECTOR3 v;
v.x = ( ( (2.0f * cursorPos.x) / vp.Width) - 1 ) / proj._11;
v.y =-( ( (2.0f * cursorPos.y) / vp.Height) - 1 ) / proj._22;
v.z = 1.0f;

D3DXMATRIX m;
D3DXVECTOR3 rayOrigin,rayDir;

D3DXMatrixInverse( &m, NULL, &view );

// Transform the screen space pick ray into 3D space
ray.direction.x = v.x*m._11 + v.y*m._21 + v.z*m._31;
ray.direction.y = v.x*m._12 + v.y*m._22 + v.z*m._32;
ray.direction.z = v.x*m._13 + v.y*m._23 + v.z*m._33;
ray.origin.x = m._41;
ray.origin.y = m._42;
ray.origin.z = m._43;

// Use inverse of matrix
D3DXMATRIX matInverse;
D3DXMatrixInverse(&matInverse,NULL,&ctrlPoint1.world); //Use the world matrix stored for each control point

// Transform ray origin and direction by inv matrix
D3DXVECTOR3 rayObjOrigin,rayObjDirection;

D3DXVec3TransformCoord(&rayObjOrigin,&ray.origin,&matInverse);
D3DXVec3TransformNormal(&rayObjDirection,&ray.direction,&matInverse);
D3DXVec3Normalize(&rayObjDirection,&rayObjDirection);

//Check for an intersection between ray and control point mesh
BOOL hit=0;
D3DXIntersect(
ctrlPoint1.mesh,
&rayObjOrigin,
&rayObjDirection,
&hit, NULL, NULL, NULL, NULL, NULL, NULL);

if(hit==1) //If there is a hit
{
//Display the point we hit and the screen position which was clicked on
char buffer[256];
sprintf(buffer,"Point %d: X-%ld, Y-%ld\n", i, cursorPos.x, cursorPos.y);
::MessageBox(0, buffer, 0, 0);
ctrlPoint.selected=true; //Set the control point to have been selected
}
}
}

Now the problem I currently have is that I can click anywhere on the screen (even not over any control point) and it will always register me as having clicked on all the control points. When I click over a control point it still registers a hit on all of them. Using the second method of getting the view matrix I mentioned earlier does the exact opposite. It never registers a hit at all. I have no idea where I'm going wrong as I have followed numerous tutorials always having the same outcome, either always registering a hit or never registering one. I guess this is going to be a bit of a mammoth post but hopefully someone can suggest possible reasons for what's happening. Thanks! Here's a screenshot of my App to give you a better understanding of what it looks like, theres a curve, a number of red spheres representing the control points and an object following the curve.

##### Share on other sites
Regarding GetTransform, if you use a pure device (D3DCREATE_PUREDEVICE), many 'get' methods, including this one, won't work. That's probably what's happening.

Regarding the picking, I'd suggest looking in the debugger at the rays you're testing in D3DXIntersect. If they look the same or similar for all your objects, then you're doing something wrong with the transform.

• 48
• 12
• 10
• 10
• 9
• ### Forum Statistics

• Total Topics
631374
• Total Posts
2999653
×