Jump to content
  • Advertisement
Sign in to follow this  
Vexator

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.

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!