Clip Space Approach – Extracting the Planes
Prev: Source Code | Next: Implementation Details |
In here another approach to extract the view frustum planes is presented based on the properties of clip space.
Consider a point p =(x,y,z,1) on the 3D world. Consider also a modelview matrix M and a projection matrix P. The point p is transformed by matrices M and P as point pc =(xc,yc,zc,wc) in clip space using:
The point pc is in homogeneous coordinates, and when normalised becomes pcn:
In normalised clip space the view frustum is an axis aligned box centered in the origin, and bounded by the following planes:
- Left Plane: x’ = -1
- Right Plane: x’ = 1
- Top Plane: y’ = 1
- Bottom Plane: y’ = -1
- Near Plane: z’ = -1
- Far Plane: z’ = 1
This implies that the point pcn =(x’,y’,z’) is inside the view frustum if:
Then the point pc, in non-normalized coordinates, must obbey the following conditions in order to be inside the view frustum:
Based on this information it is possible to extract the six planes, in world coordinates, that bound the view frustum. The point pc is on the “right” side of the left plane if
Consider p and A=MP as described below
Then xc and wc can be defined as a function of p = (x,y,z,w), and A.
Therefore the following inequation must be true if p is on the right side of the left plane.
A little algebraic manipulation gives
So the left plane (Ax+By+Cz+D=0) is defined as:
where col1 and col4 are the first and forth columns of matrix A, respectively.
If the only objective is to find out if a point is inside or outside of the frustum then the plane as defined is ok. However when testing spheres, which require computing the distance from the center of the sphere to the plane, it is advisable to normalize the plane.
The right plane can be obtained in a similar manner:
The following coefficients are obtained for the right plane:
The remaining planes are obtained as follows:
Prev: Source Code | Next: Implementation Details |
4 Responses to “Clip Space Approach – Extracting the Planes”
Leave a Reply Cancel reply
This site uses Akismet to reduce spam. Learn how your comment data is processed.
I’m using OpenGL and GLM and for some reason I had to negate the plane coefficients for culling to work. I do not understand why. It took me four days and about 10 hours of trial and error and a lot of frustum drawings to figure this out. I hope it will help someone. And if anybody could explain what is going on here I would really like to hear it.
// Extracting the planes.
mat4 matrix = projection * view;
vec4 rowX = glm::row(matrix, 0);
vec4 rowY = glm::row(matrix, 1);
vec4 rowZ = glm::row(matrix, 2);
vec4 rowW = glm::row(matrix, 3);
planes[0] = normalize(rowW + rowX);
planes[1] = normalize(rowW - rowX);
planes[2] = normalize(rowW + rowY);
planes[3] = normalize(rowW - rowY);
planes[4] = normalize(rowW + rowZ);
planes[5] = normalize(rowW - rowZ);
// Normalizing the planes.
vec3 normal(plane.x, plane.y, plane.z);
float length = glm::length(normal);
return -plane / length; // Notice the negation. I don't know why I needed that!!
// Sphere intersection test.
for (vec4 plane : planes)
{
float dist = plane.x * center.x + plane.y * center.y + plane.z * center.z + plane.w - radius;
if (dist > 0) return false;
}
return true;
The extracting from the planes is time consuming and the
testing later problematic in my opinion.
If have found another solution.
My destination was, to found a good way to make frustum
clipping with a bounding sphere.
Based on the fact, that the objects center lies already in a
modelviewprojection matrix, i use it for my culling.
Here the method (in java):
public boolean isSphereInFrustum( double fieldOfView, double nearPlaneDistance, double aspectRatio, Vector4d center, double radius )
{
// the center from the bounding sphere, taken from the
// modelviewprojection matrix
double px = center.x;
double py = center.y;
double pz = center.z;
// make positive
if ( pz<0.0)
pz = -pz;
// scaling to screen
double scale = nearPlaneDistance/(nearPlaneDistance+pz);
// make positive
if ( px<0.0)
px = -px;
// the sphere-width on screen
double tmpX = 2.0*(px+radius)*scale;
if ( py<0.0)
py = -py;
// the sphere-height on screen
double tmpY = 2.0*(py+radius)*scale;
// test for objectsize on screen, goes out if sphere only a pixel
if ( tmpX<1.0 && tmpYx || py>y || pz>80 || pz<0.1 )
return false;
return true;
}
Hi
I use the opengl column-major matrix layout :
a00 a10 a20 a30
a01 a11 a21 a31
a02 a12 a22 a32
a03 a13 a23 a33
————————
col1 col2 col3 col4
Now, if i take the planes from my modelViewProjection-Matrix
i got for the left plane = col1+col4 a plane that lies in the xz-plane.
must the left plane not be in the yz-plane?
Hi Marvin,
The left plane in clip space is parallel to the yz plane.