I'm developing a picking system that will use rays that intersect volumes and I'm having trouble with ray intersection versus a plane. I was able to figure out spheres fairly easily, but planes are giving me trouble. I've tried to understand various sources and get hung up on some of the variables used within their explanations.

Here is a snippet of my code:

   bool Picking()
  D3DXVECTOR3 vec;
  D3DXVECTOR3 vRayDir;
  D3DXVECTOR3 vRayOrig;
  D3DXVECTOR3 vROO, vROD; // vect ray obj orig, vec ray obj dir
  D3DXMATRIX mInverse;
  D3DXMATRIX worldMat;

                // Obtain project matrix
  D3DXMATRIX pMatProj =   CDirectXRenderer::GetInstance()->Director()->Proj();
                // Obtain mouse position
  D3DXVECTOR3 pos = CGUIManager::GetInstance()->GUIObjectList.front().pos;

                // Get window width & height
  float w = CDirectXRenderer::GetInstance()->GetWidth();
  float h = CDirectXRenderer::GetInstance()->GetHeight();

                // Transform vector from screen to 3D space
  vec.x =  (((2.0f * pos.x) / w) - 1.0f) / pMatProj._11;
  vec.y = -(((2.0f * pos.y) / h) - 1.0f) / pMatProj._22;
  vec.z = 1.0f;

                // Create a view inverse matrix
  D3DXMatrixInverse(&m, NULL, &CDirectXRenderer::GetInstance()->Director()->View());

                // Determine our ray's direction
  vRayDir.x = vec.x * m._11 + vec.y * m._21 + vec.z * m._31;
  vRayDir.y = vec.x * m._12 + vec.y * m._22 + vec.z * m._32;
  vRayDir.z = vec.x * m._13 + vec.y * m._23 + vec.z * m._33;

                // Determine our ray's origin
  vRayOrig.x = m._41;
  vRayOrig.y = m._42;
  vRayOrig.z = m._43;

  //worldMat = aliveActors[0]->GetTrans();
  D3DXMatrixInverse(&mInverse, NULL, &worldMat); 

  D3DXVec3TransformCoord(&vROO, &vRayOrig, &mInverse);
  D3DXVec3TransformNormal(&vROD, &vRayDir, &mInverse);
  D3DXVec3Normalize(&vROD, &vROD);

When using this code I'm able to detect a ray intersection via a sphere, but I have questions when determining an intersection via a plane. First off should I be using my vRayOrig & vRayDir variables for the plane intersection tests or should I be using the new vectors that are created for use in object space?

When looking at a site like this for example: http://www.tar.hu/gamealgorithms/ch22lev1sec2.html

I'm curious as to what D is in the equation AX + BY + CZ + D = 0 and how does it factor in to determining a plane intersection?

Any help will be appreciated, thanks.


1 Answer 1


For your first question, about vRayOrig & vRayDir, you should use what you need to use -- certainly the plane and the ray must be defined in the same space, or the results you get out of the intersection test will be meaningless. So you need to either define or transform the plane into the same space as the ray, or the other way around.

For the second question, that's the implicit equation of a plane. D itself is just some constant for the plane; when the plane is normalized, it can be interpreted as "the distance to the origin" (A, B and C can be interpreted as the X, Y, Z components of the plane's normal), but you need to be careful with that.

Look at it like this. A plane can be defined by some normal vector N, and a point P. All points in the plane will be perpendicular to the normal vector, which is to say the vector from P to any point T will be (T - P) and will be perpendicular to N. The dot product of two perpendicular vectors is zero. Thus:

                          N dot (T - P) = 0
Nx(Tx - Px) + Ny(Ty - Py) + Nz(Tz - Pz) = 0    (dot product)
NxTx - NxPx + NyTy - NyPy + NzTz - NzPz = 0    (distribute)
NxTx + NyTy + NzTz - NxPx - NyPy - NzPz = 0    (collect and group)

In case it's not clear, "Nx" is the X component of N, et cetera. Now that we've got that expansion, remember that (A,B,C) are often the names of the plane's normal's components, so we can rename:

ATx + BTy + CTz - APx - BPy - CPz = 0    (collect and group)

That should look a little more familiar. If we call the whole second half of the equation D, we end up with ATx + BTy + CTz + D = 0 or in general Ax + By + Cz + D = 0 -- so D, is in fact (-APx - BPy - CPz) where P is the point that defines the plane.

This is useful for ray intersection because it will be zero for any (x,y,z) on the plane -- and the point that the ray passes through the plane will be on the plane. That's the computation that the page you linked to is demonstrating. For any point (x,y,z) that isn't on the plane, the evaluation of (Ax + By + Cz + D) will be nonzero.

  • \$\begingroup\$ I'd like to say thanks for your help and I actually went with an intersect triangle test. For me this was a lot easier to understand as well as it was really all I needed to use for my picking, instead of needing a plane. I was using this picking code to determine an intersection of a navigation mesh and I would then convert the barycentric coordinates I obtained from the test into an actual world position that I could use. After realizing that I have the 4 vertices from the navigation mesh I wouldn't need to check picking vs. a plane (I was making it hard on myself). Thank you very much. \$\endgroup\$
    – joelretdev
    Jan 20, 2011 at 8:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .