Picking Accuracy Problem

Started by
2 comments, last by Evil Steve 14 years, 2 months ago
What I am trying to do is output some code when I mouse over one of my meshes on the screen. It seems to be very accurate when I have a mesh close to my camera. As my camera moves away from the mesh it becomes less and less accurate. I am moving away in the z direction both the camera position and it's look at position. Sounds like to me it has something to do with my projection matrix, but I can't see the problem. Or is this inaccuracy common when moving away from meshes? Here is the function. I pass in the mouse X/Y pos, get the ray, then see if it intersects with any of my meshes.

D3DXVECTOR3 * World::checkForMeshHit(long mouseX, long mouseY){
	D3DXMATRIX matProjection, matView, matWorld, matInverse;
	LPDIRECT3DDEVICE9 * d3ddev = d3d->getD3ddev();
	(*d3ddev)->GetTransform(D3DTS_PROJECTION, &matProjection);
	(*d3ddev)->GetTransform(D3DTS_VIEW, &matView);
	float xAngle = (((2.0f * mouseX) / d3d->getScreenWidth()) - 1.0f) / matProjection._11;
	float yAngle  = (((-2.0f * mouseY) / d3d->getScreenHeight()) + 1.0f) / matProjection._22;
	D3DXVECTOR3 * direction = new D3DXVECTOR3(xAngle, yAngle, 1.0f);
	
	for(int i = 0; i < units.size(); i++){
                BOOL hit = false;
		direction = new D3DXVECTOR3(xAngle, yAngle, 1.0f);
		
		D3DXVECTOR3 origin = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
		EnemyUnit * unit = units;
		matWorld = (*unit->getMeshModel()->getWorldMat());
		
		D3DXMatrixInverse(&matInverse, NULL, &(matWorld*matView));
		D3DXVec3TransformCoord(&origin, &origin, &matInverse);
		D3DXVec3TransformNormal(direction, direction, &matInverse);
		D3DXVec3Normalize(direction, direction);
	
		D3DXIntersect(unit->getMeshModel()->getMesh(), &origin, direction, &hit, NULL, NULL, NULL, NULL, NULL, NULL);
		if(hit){	
			cout << "says its mousing over the object " << endl;
			break;
		} 
	}
	return NULL;  
}




Here is initial camera code if that matters.

void D3DCreator::setupCamera(void){
	D3DXMATRIX matView;    // the view transform matrix
    D3DXMatrixLookAtLH(&matView,
    &D3DXVECTOR3 (cameraPosX, cameraPosY, cameraPosZ),    // the camera position
    &D3DXVECTOR3 (cameraLookAtX, cameraLookAtY, cameraLookAtZ), // the look-at position
	
    &D3DXVECTOR3 (0.0f, 1.0f, 0.0f));    // the up direction
    d3ddev->SetTransform(D3DTS_VIEW, &matView);    // set the view transform to matView 

    // set the projection transform
    D3DXMATRIX matProjection;    // the projection transform matrix
    D3DXMatrixPerspectiveFovLH(&matProjection,
                               D3DXToRadian(45),    // the horizontal field of view
                               (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio
                               1.0f,   // the near view-plane
                               100.0f);    // the far view-plane
    d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection); // set the projection
}


Advertisement
float yAngle  = (((-2.0f * mouseY) / d3d->getScreenHeight()) + 1.0f) / matProjection._22;


Shouldn't that be -1.0f on the last float? commented code does help a lot as well.

Also what is causing your problem is that D3DXIntersect intersects a model positioned at (0,0,0) with no rotation, you should adjust your ray origin and ray direction accordingly.
One thing I encountered in the past is the case when the mouse coords aren't what you think. That may be the case if you're using a window and getting the mouse coords from the outer frame and not the inner one, so the borders don't get counted. If you're using a window, I'd suggest you check that (for example, draw something where your program thinks the mouse is, see if there's an offset). If you're doing full screen, that won't happen, so it's another problem.
I'm with ET3D here; it sounds like you're not calling AdjustWindowRect when you setup your window.

This topic is closed to new replies.

Advertisement