Sign in to follow this  
deadstar

Problems with D3DXIntersect on a transformed object

Recommended Posts

Hi all, I'm trying to detect a ray collision with a crosshair for an FPS type game. Using D3DXIntersect() on a transformed model seems to have a common problem, and some Googling tells me that transforming the ray's position and direction vectors by the model's world inverse supposedly does the trick, but I can't seem to get it working. Here is how I transform the model. WorldMatrix is a private member of MODEL and is kept for the CheckRayIntersect() function.
void MODEL::Transform()
{
	//Matrices
	D3DXMATRIX TransMatrix, RotMatrix, RotX, RotY, RotZ;

	//Setup rotation matrix
	D3DXMatrixRotationX(&RotX, Rotation.x);
	D3DXMatrixRotationY(&RotY, Rotation.y);
	D3DXMatrixRotationZ(&RotZ, Rotation.z);

	//Setup translation matrix
	D3DXMatrixTranslation(&TransMatrix, Position.x, Position.y, Position.z);

	//Reset the world matrix
	D3DXMatrixIdentity(&WorldMatrix);

	//Multiply the translation and rotation matrices
	WorldMatrix = (RotX * RotY * RotZ) * TransMatrix;

	//Apply the world matrix
	Engine->Direct3DDevice->SetTransform(D3DTS_WORLD, &WorldMatrix);
}

Here is how I'm checking for ray intersection. I'm simply passing my camera's position and forward vectors, which should be exactly the centre of the screen.
bool MODEL::CheckRayIntersect(D3DXVECTOR3 RayPosition, D3DXVECTOR3 RayDirection)
{
	D3DXMATRIX WorldInverseMatrix;
	BOOL Hit;

	//Transform ray by model's inverse world matrix
	D3DXMatrixInverse(&WorldInverseMatrix, NULL, &WorldMatrix);
	D3DXVec3TransformCoord(&RayPosition, &RayPosition, &WorldInverseMatrix);
	D3DXVec3TransformCoord(&RayDirection, &RayDirection, &WorldInverseMatrix);

	//Check for ray intersection
	D3DXIntersect(Mesh->Mesh, &RayPosition, &RayDirection, &Hit, NULL, NULL, NULL, NULL, NULL, NULL);

	return Hit;
}

It works fine on a model that hasn't been transformed, so I can confirm that by just passing the camera's position and forward vectors works. I'm pointing my finger at my model's Transform() function, since I am rusty at matrix maths and probably have done it the wrong way completely. Thanks in advance for any tips.

Share this post


Link to post
Share on other sites
You don't want to translate your ray direction, you only want to rotate it. There are two ways to accomplish this:


// Use a W component of zero for the ray direction
D3DXVECTOR4 RayDirection4 (RayDirection, 0.0f);
D3DXVec4Transform(&RayDirection4 , &RayDirection4 , &WorldInverseMatrix);
RayDirection = D3DXVECTOR3(RayDirection4.x, RayDirection4.y, RayDirection4.z);
D3DXVec3Normalize(&RayDirection, &RayDirection);

// Set the translation portion of the inverse world matrix to zero
D3DXMatrixInverse(&WorldInverseMatrix, NULL, &WorldMatrix);
D3DXVec3TransformCoord(&RayPosition, &RayPosition, &WorldInverseMatrix);
WorldInverseMatrix._41 = WorldInverseMatrix._42 = WorldInverseMatrix._43 = 0;
D3DXVec3TransformCoord(&RayDirection, &RayDirection, &WorldInverseMatrix);
D3DXVec3Normalize(&RayDirection, &RayDirection);

Share this post


Link to post
Share on other sites
Perfect, thank you.

I opted for the second method. 'W' components are way out of my league until I start reading up on this vector and matrix stuff properly.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this