4
\$\begingroup\$

If I have an arbitrary plane (center and normal) or a quad (center, normal and width and height) and a camera (frustum, projection & view matrix, etc). Then how would I go about calculating if the plane/quad is visible to the camera?

Additionally how would I calculate to check if it's the front or the back of the plane/quad that is visible to the camera?


My first idea was to do some ray vs plane intersection, but then I realized that it of course wan't going to work!

bool plane_visible = false;
const float denom = plane_normal.dot(camera.getLook());

if (abs(denom) > 0.0001f)
{
    const float t = (plane_position - camera.getPosition()).dot(plane_normal) / denom;

    plane_visible = (t >= 0.0f);
}

Using the dot product of the plane/quads normal and the camera's look direction. Will give wrong results!

For instance, use the following image as an example! A dot product will tell me that I'm looking at the face that's facing outwards of the frustum. Though the face that I'm actually looking on is face facing inwards the frustum/towards the camera!

\$\endgroup\$
2
\$\begingroup\$

For determining if the plane is 'looking' towards or away from the camera, you already have some of the code. The dot product between the camera "looking" and the plane normal will be > 0 if they are facing each other, and < 0 if looking away.

As for detecting if the plane is within the view frustum, you could try calculating bounds over the entire view from camera to max_distance and checking if any of the vertices in the plane are in the volume?

\$\endgroup\$
  • \$\begingroup\$ thanks for answering, but that is incorrect use of the dot product. (Look at my updated question) \$\endgroup\$ – Vallentin Feb 20 '15 at 17:54
  • \$\begingroup\$ I pretty sure he's got it right. In your example image the, red, plane line would be facing semi-towards that green line next to it. Visually imagining that line, and putting it at the base of your, blue, camera facing line, that puts it at more than 90 degrees difference. If you pull up a calculator, plug in cos(91 deg), it'll turn up negative. \$\endgroup\$ – Wolfgang Skyler Nov 19 '15 at 20:37
1
\$\begingroup\$

The robust solution is to build a frustum of planes symbolising the camera and check the plane against all of them.

The first part involves creating the frustum which can be a bit tricky if you're lacking in basic linear algebra;

Start with transposing the matrix you're using to transform from worldspace to projected space, the reason for this is because we're going to transform Next, create the 6 projected normals and multiply them by the cameras transpose view matrix:

  1. nNear = (0,0,1,1) X tvm
  2. nFar = (0,0,-1,1) X tvm
  3. nRight = (-1,0,0,1) X tvm
  4. nLeft = (1,0,0,1) X tvm
  5. nTop = (-1,0,0,1) X tvm
  6. nBottom = (1,0,0,1) X tvm

I'm assuming directx coordinates here. This gives us the frustum planes normals in worldspace and lets us proceed into the next step.

For the second part I'll assume the plane is of limited size, infinite planes are a bit different.

Divide the plane into four points and for each point draw a vector from the point to each frustum plane and check if the dot product of that vector and the frustum planes normal is greater or equal to zero,

v0 · pn >= 0 where v0 = point->plane

Unless all points result in less then zero and are behind any of the frustums plane the plane will be visible to the camera.

Thirdly to find out the direction of the plane use the dot product of the normal and the vector from the plane to the viewpoint, any point on the plane will suffice.

v1 · pn >= 0 where v1 = plane->eye

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.