# Compute frustum planes from corner points

This topic is 2607 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Guys, you have to help me, this is driving me crazy. I've implemented frustum culling a while ago, based on the article by lighthouse3D. Computing the frustum planes from the view and projection matrices directly works perfectly fine; but I'd like to compute them from the frustum corners instead as I need those for debug rendering and the generation of portal frustums.

The clip space approach creates a perfect frustum (original source: http://www.lighthous...tation-details/)

 void Frustum::compute( const mat4 &viewMatrix, const mat4 &projectionMatrix ) { const mat4 &v = viewMatrix; const mat4 &p = projectionMatrix; mat4 clipMatrix; clipMatrix[0][0] = v[0][0]*p[0][0]+v[0][1]*p[1][0]+v[0][2]*p[2][0]+v[0][3]*p[3][0]; clipMatrix[1][0] = v[0][0]*p[0][1]+v[0][1]*p[1][1]+v[0][2]*p[2][1]+v[0][3]*p[3][1]; clipMatrix[2][0] = v[0][0]*p[0][2]+v[0][1]*p[1][2]+v[0][2]*p[2][2]+v[0][3]*p[3][2]; clipMatrix[3][0] = v[0][0]*p[0][3]+v[0][1]*p[1][3]+v[0][2]*p[2][3]+v[0][3]*p[3][3]; clipMatrix[0][1] = v[1][0]*p[0][0]+v[1][1]*p[1][0]+v[1][2]*p[2][0]+v[1][3]*p[3][0]; clipMatrix[1][1] = v[1][0]*p[0][1]+v[1][1]*p[1][1]+v[1][2]*p[2][1]+v[1][3]*p[3][1]; clipMatrix[2][1] = v[1][0]*p[0][2]+v[1][1]*p[1][2]+v[1][2]*p[2][2]+v[1][3]*p[3][2]; clipMatrix[3][1] = v[1][0]*p[0][3]+v[1][1]*p[1][3]+v[1][2]*p[2][3]+v[1][3]*p[3][3]; clipMatrix[0][2] = v[2][0]*p[0][0]+v[2][1]*p[1][0]+v[2][2]*p[2][0]+v[2][3]*p[3][0]; clipMatrix[1][2] = v[2][0]*p[0][1]+v[2][1]*p[1][1]+v[2][2]*p[2][1]+v[2][3]*p[3][1]; clipMatrix[2][2] = v[2][0]*p[0][2]+v[2][1]*p[1][2]+v[2][2]*p[2][2]+v[2][3]*p[3][2]; clipMatrix[3][2] = v[2][0]*p[0][3]+v[2][1]*p[1][3]+v[2][2]*p[2][3]+v[2][3]*p[3][3]; clipMatrix[0][3] = v[3][0]*p[0][0]+v[3][1]*p[1][0]+v[3][2]*p[2][0]+v[3][3]*p[3][0]; clipMatrix[1][3] = v[3][0]*p[0][1]+v[3][1]*p[1][1]+v[3][2]*p[2][1]+v[3][3]*p[3][1]; clipMatrix[2][3] = v[3][0]*p[0][2]+v[3][1]*p[1][2]+v[3][2]*p[2][2]+v[3][3]*p[3][2]; clipMatrix[3][3] = v[3][0]*p[0][3]+v[3][1]*p[1][3]+v[3][2]*p[2][3]+v[3][3]*p[3][3]; m_planes[PLANE_RIGHT].x = clipMatrix[3][0]-clipMatrix[0][0]; m_planes[PLANE_RIGHT].y = clipMatrix[3][1]-clipMatrix[0][1]; m_planes[PLANE_RIGHT].z = clipMatrix[3][2]-clipMatrix[0][2]; m_planes[PLANE_RIGHT].w = clipMatrix[3][3]-clipMatrix[0][3]; m_planes[PLANE_LEFT].x = clipMatrix[3][0]+clipMatrix[0][0]; m_planes[PLANE_LEFT].y = clipMatrix[3][1]+clipMatrix[0][1]; m_planes[PLANE_LEFT].z = clipMatrix[3][2]+clipMatrix[0][2]; m_planes[PLANE_LEFT].w = clipMatrix[3][3]+clipMatrix[0][3]; m_planes[PLANE_BOTTOM].x = clipMatrix[3][0]+clipMatrix[1][0]; m_planes[PLANE_BOTTOM].y = clipMatrix[3][1]+clipMatrix[1][1]; m_planes[PLANE_BOTTOM].z = clipMatrix[3][2]+clipMatrix[1][2]; m_planes[PLANE_BOTTOM].w = clipMatrix[3][3]+clipMatrix[1][3]; m_planes[PLANE_TOP].x = clipMatrix[3][0]-clipMatrix[1][0]; m_planes[PLANE_TOP].y = clipMatrix[3][1]-clipMatrix[1][1]; m_planes[PLANE_TOP].z = clipMatrix[3][2]-clipMatrix[1][2]; m_planes[PLANE_TOP].w = clipMatrix[3][3]-clipMatrix[1][3]; m_planes[PLANE_BACK].x = clipMatrix[3][0]-clipMatrix[2][0]; m_planes[PLANE_BACK].y = clipMatrix[3][1]-clipMatrix[2][1]; m_planes[PLANE_BACK].z = clipMatrix[3][2]-clipMatrix[2][2]; m_planes[PLANE_BACK].w = clipMatrix[3][3]-clipMatrix[2][3]; m_planes[PLANE_FRONT].x = clipMatrix[3][0]+clipMatrix[2][0]; m_planes[PLANE_FRONT].y = clipMatrix[3][1]+clipMatrix[2][1]; m_planes[PLANE_FRONT].z = clipMatrix[3][2]+clipMatrix[2][2]; m_planes[PLANE_FRONT].w = clipMatrix[3][3]+clipMatrix[2][3]; for( int i = 0; i < 6; i++ ) { m_planes = glm::normalize( m_planes ); }}

The geometric approach, which computes the frustums corners first, fails.. my geometry is sometimes clipped when it shouldn't and not clipped when it should be (source: http://www.lighthous...implementation/)

vec4 planeFromPoints( vec3 &v1, vec3 &v2, vec3 &v3) { vec3 aux1, aux2; aux1 = v1 - v2; aux2 = v3 - v2; vec3 normal = glm::normalize(aux2 * aux1); float d = (glm::dot(normal, v2)); return vec4( normal, d); } #define ANG2RAD 3.14159265358979323846/180.0f void Frustum::compute( const mat4 &viewMatrix, float angle, float ratio, float nearD, float farD ) { float tang = (float)tan( ANG2RAD * angle * 0.5 ) ; float nh = nearD * tang; float nw = nh * ratio; float fh = farD * tang; float fw = fh * ratio; // this is the only thing i've changed: // extract view vectors from view matrix vec3 s = vec3( viewMatrix[0] ); vec3 u = vec3( viewMatrix[1] ); vec3 f = vec3( viewMatrix[2] ); vec3 eye = vec3( -viewMatrix[3] ); vec3 nc = eye - f * nearD; vec3 fc = eye - f * farD; // near plane corners vec3 ntl = nc + u * nh - s * nw; vec3 ntr = nc + u * nh + s * nw; vec3 nbl = nc - u * nh - s * nw; vec3 nbr = nc - u * nh + s * nw; // far plane corners vec3 ftl = fc + u * fh - s * fw; vec3 ftr = fc + u * fh + s * fw; vec3 fbl = fc - u * fh - s * fw; vec3 fbr = fc - u * fh + s * fw; m_planes[PLANE_TOP] = planeFromPoints( ntr, ntl, ftl ); m_planes[PLANE_BOTTOM] = planeFromPoints( nbl, nbr, fbr ); m_planes[PLANE_LEFT] = planeFromPoints( ntl, nbl,fbl ); m_planes[PLANE_RIGHT] = planeFromPoints( nbr, ntr, fbr ); m_planes[PLANE_BACK] = planeFromPoints( ntl, ntr, nbr ); m_planes[PLANE_FRONT] = planeFromPoints( ftr, ftl, fbl );}

I just can't spot the error - do you see what's wrong? Thank you!

##### Share on other sites
This is not answering your question, but you could stick with calculating the frustum from the view * proj matrix and get the corner points by intersecting the planes instead. That is how I do it.

Otherwise, have you checked that your planes are all facing the right direction?

##### Share on other sites
would you show me how you calculate[color=#1C2837][size=2] the corner points by intersecting the planes? i could then render the "working" frustum planes to narrow down the problem.

##### Share on other sites
This is the code I am using:
 static Vector3 intersection(const Plane &p0, const Plane &p1, const Plane &p2) { Vector3 n1(p0.a, p0.b, p0.c); float d1 = p0.d; Vector3 n2(p1.a, p1.b, p1.c); float d2 = p1.d; Vector3 n3(p2.a, p2.b, p2.c); float d3 = p2.d; // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 ) //P = ------------------------------------------------ // N1 . ( N2 * N3 ) return -(d1 * cross(n2, n3) + d2 * cross(n3, n1) + d3 * cross(n1, n2)) / dot(n1, (cross(n2, n3))); } 

Maybe you have to invert the sign of the resulting point.

##### Share on other sites
great, thank you!

1. 1
2. 2
Rutin
19
3. 3
khawk
15
4. 4
5. 5
A4L
13

• 13
• 26
• 10
• 11
• 44
• ### Forum Statistics

• Total Topics
633743
• Total Posts
3013644
×