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!