Frustum Culling

Started by
3 comments, last by CRACK123 20 years, 5 months ago
Hey, I am trying to do culling using Frustum Culling. However what seems to be happening is nothing seems to be getting rendered. I get no models rendered at all when I use frustum culling. I am not sure if I am understanding it right. However this is the code I have for frustum culling. The header file

class FrustrumCulling {
	public :
		vector3 m_vector;
		vector4 m_FOVTopPlane;
		vector4 m_FOVBottomPlane;
		vector4 m_FOVRightPlane;
		vector4 m_FOVLeftPlane;
		float g_FOVFrontClip;
		float g_FOVBackClip;
		matrix44 m_viewTransform;

	public :
		void SetupFOVClipPlanes(float angle, float aspect, float frontClip, float backClip);
		bool MeshFOVCheck(vector3 bSpherePos, float bSphereRadius, vector3 *pViewPos);

	protected :
		void PlaneFromPoints(vector3 *p1, vector3 *p2, vector3 *p3, vector4 *plane);
};
The source file

void FrustrumCulling ::PlaneFromPoints(vector3 *p1, vector3 *p2, vector3 *p3, vector4 *plane)
{
	vector3 v0, v1, v2;

	v0.x = p2->x - p1->x;
	v0.y = p2->y - p1->y;
	v0.z = p2->z - p1->z;

	v1.x = p3->x - p1->x;
	v1.y = p3->y - p1->y;
	v1.z = p3->z - p1->z;

	v2 = CrossProduct(v1, v2);
	v2.normalize();

	plane->x = v2.x;
	plane->y = v2.y;
	plane->z = v2.z;
	plane->w = -(v2.x * p1->x + v2.y * p1->y + v2.z * p1->z);

}

void FrustrumCulling ::SetupFOVClipPlanes(float angle, float aspect, float frontClip, float backClip)
{
	vector3 p0, p1, p2;
	
	// calculate left plane

	p0.set(0, 0, 0);

	p1.x = -backClip * ((float)tan(angle * 0.5) / aspect);
	p1.y = -backClip * ((float)tan(angle * 0.5));
	p1.z = backClip;

	p2.x = p1.x;
	p2.y = -p1.y;
	p2.z = p1.z;
	this->PlaneFromPoints(&p0, &p1, &p2, &this->m_FOVLeftPlane);


	// calculate right plane

	p0.set(0, 0, 0);
	p1.x = backClip * ((float)tan(angle * 0.5) / aspect);
	p1.y = backClip * ((float)tan(angle * 0.5));
	p1.z = backClip;

	p2.x = p1.x;
	p2.y = -p1.y;
	p2.z = p1.z;
	this->PlaneFromPoints(&p0, &p1, &p2, &this->m_FOVRightPlane);

	// calculate top plane

	p0.set(0, 0, 0);
	p1.x = -backClip * ((float)tan(angle * 0.5) / aspect);
	p1.y = backClip * ((float)tan(angle * 0.5));
	p1.z = backClip;

	p2.x = -p1.x;
	p2.y = p1.y;
	p2.z = p1.z;
	this->PlaneFromPoints(&p0, &p1, &p2, &this->m_FOVTopPlane);

	// calculate bottom plane

	p0.set(0, 0, 0);
	p1.x = backClip * ((float)tan(angle * 0.5) / aspect);
	p1.y = -backClip * ((float)tan(angle * 0.5));
	p1.z = backClip;

	p2.x = -p1.x;
	p2.y = p1.y;
	p2.z = p1.z;
	this->PlaneFromPoints(&p0, &p1, &p2, &this->m_FOVBottomPlane);

}

bool FrustrumCulling ::MeshFOVCheck(vector3 bSpherePos, float bSphereRadius, vector3 *pViewPos)
{
	float Dist;

	// transform z into view space

	pViewPos->z = this->m_viewTransform.col[0][2] * bSpherePos.x +
				  this->m_viewTransform.col[1][2] * bSpherePos.y +
				  this->m_viewTransform.col[2][2] * bSpherePos.z +
				  this->m_viewTransform.col[3][2];

	// behind front clip plane ? 

	if( (pViewPos->z + bSphereRadius) <  this->g_FOVFrontClip) 
		return false;

	// behind back clip plane ?

	if( (pViewPos->z - bSphereRadius) >  this->g_FOVBackClip) 
		return false;

	// transform x into view space

	pViewPos->x = this->m_viewTransform.col[0][0] * bSpherePos.x +
				  this->m_viewTransform.col[1][0] * bSpherePos.y +
				  this->m_viewTransform.col[2][0] * bSpherePos.z +
				  this->m_viewTransform.col[3][0]; 

	// test against left clip plane

	Dist = (pViewPos->x * this->m_FOVLeftPlane.x) + (pViewPos->z + this->m_FOVLeftPlane.z);
	if(Dist > bSphereRadius) return false;

	// test against right clip plane

	Dist = (pViewPos->x * this->m_FOVRightPlane.x) + (pViewPos->z + this->m_FOVRightPlane.z);
	if(Dist > bSphereRadius) return false;

	// transform y into view space

	pViewPos->y = this->m_viewTransform.col[0][1] * bSpherePos.x +
				  this->m_viewTransform.col[1][1] * bSpherePos.y +
				  this->m_viewTransform.col[2][1] * bSpherePos.z +
				  this->m_viewTransform.col[3][1]; 

	// test against top clip plane

	Dist = (pViewPos->y * this->m_FOVTopPlane.y) + (pViewPos->z + this->m_FOVTopPlane.z);
	if(Dist > bSphereRadius) return false;

	// test against right clip plane

	Dist = (pViewPos->x * this->m_FOVTopPlane.x) + (pViewPos->z + this->m_FOVTopPlane.z);
	if(Dist > bSphereRadius) return false;

	return true;
}
I tried to debug the code and check. It always seems to fail on left clip plane and return false. I dont know why though. I am not sure if I am doing calculations correctly. Also this is how I am calling it.

	FrustrumCullingClass.SetupFOVClipPlanes(45.0f, 800/600, 1.0f, 100.0f);  

for(int i = 0; i < this->m_numModels; i++) {
		if(FrustrumCullingClass.MeshFOVCheck(this->m_pos[i], this->m_radius, &CameraClass.GetCameraView()))  {
			glTranslatef(this->m_pos[i].x, this->m_pos[i].y, this->m_pos[i].z);
			glCallList(this->m_list);
			this->nEnemies++;
		}
		
	}
I hope someone can point me into the right direction. Thank you
The more applications I write, more I find out how less I know
Advertisement
I usually set up my clip-planes from the row-vectors of the projection_matrix * model_view_matrix. I think it makes the code cleaner.
Anyway, I think that the p1.y in the calculations of the left plane shouldn't have the sign, so it should be:
p1.y = backClip * ((float)tan(angle * 0.5));

This is however just a guess, debugging frustum-culling takes hours...sigh...

[edited by - amag on October 25, 2003 12:06:40 PM]
That''s an awefully complicated way to get the planes to check. How about this? I assume you are using OpenGL by the use of your own matrix structure.

void Frustum::CalculateViewFrustum() {	float   proj[16];	float   modl[16];	float   clip[16];	float   t;		glGetFloatv(GL_PROJECTION_MATRIX,proj);	glGetFloatv(GL_MODELVIEW_MATRIX,modl);		// combine the matrices	clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];	clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];	clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];	clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];		clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];	clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];	clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];	clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];		clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];	clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];	clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];	clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];		clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];	clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];	clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];	clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];		// right plane	planes[0].a = clip[ 3] - clip[ 0];	planes[0].b = clip[ 7] - clip[ 4];	planes[0].c = clip[11] - clip[ 8];	planes[0].d = clip[15] - clip[12];	// normalize	t = sqrt( planes[0].a * planes[0].a + planes[0].b * planes[0].b + planes[0].c * planes[0].c );	planes[0].a /= t;	planes[0].b /= t;	planes[0].c /= t;	planes[0].d /= t;	// left plane	planes[1].a = clip[ 3] + clip[ 0];	planes[1].b = clip[ 7] + clip[ 4];	planes[1].c = clip[11] + clip[ 8];	planes[1].d = clip[15] + clip[12];	// normalize	t = sqrt( planes[1].a * planes[1].a + planes[1].b * planes[1].b + planes[1].c * planes[1].c );	planes[1].a /= t;	planes[1].b /= t;	planes[1].c /= t;	planes[1].d /= t;		// bottom plane	planes[2].a = clip[ 3] + clip[ 1];	planes[2].b = clip[ 7] + clip[ 5];	planes[2].c = clip[11] + clip[ 9];	planes[2].d = clip[15] + clip[13];	// normalize	t = sqrt( planes[2].a * planes[2].a + planes[2].b * planes[2].b + planes[2].c * planes[2].c );	planes[2].a /= t;	planes[2].b /= t;	planes[2].c /= t;	planes[2].d /= t;		// top plane	planes[3].a = clip[ 3] - clip[ 1];	planes[3].b = clip[ 7] - clip[ 5];	planes[3].c = clip[11] - clip[ 9];	planes[3].d = clip[15] - clip[13];	// normalize	t = sqrt( planes[3].a * planes[3].a + planes[3].b * planes[3].b + planes[3].c * planes[3].c );	planes[3].a /= t;	planes[3].b /= t;	planes[3].c /= t;	planes[3].d /= t;		// far plane	planes[4].a = clip[ 3] - clip[ 2];	planes[4].b = clip[ 7] - clip[ 6];	planes[4].c = clip[11] - clip[10];	planes[4].d = clip[15] - clip[14];	// normalize	t = sqrt( planes[4].a * planes[4].a + planes[4].b * planes[4].b + planes[4].c * planes[4].c );	planes[4].a /= t;	planes[4].b /= t;	planes[4].c /= t;	planes[4].d /= t;		// near plane	planes[5].a = clip[ 3] + clip[ 2];	planes[5].b = clip[ 7] + clip[ 6];	planes[5].c = clip[11] + clip[10];	planes[5].d = clip[15] + clip[14];	// normalize	t = sqrt( planes[5].a * planes[5].a + planes[5].b * planes[5].b + planes[5].c * planes[5].c );	planes[5].a /= t;	planes[5].b /= t;	planes[5].c /= t;	planes[5].d /= t;}
____________________________________________________________AAAAA: American Association Against Adobe AcrobatYou know you hate PDFs...
The uncredited code posted above by Raloth was written by Mark Morley. Please show some respect and give credit where it is due.
To Raloth

I have tried it that way. It does not seem to work. It actually was not even updating the frustum values even if I called it every frame.

Thanks for the help. I''ll keep trying, I will get it right someday

The more applications I write, more I find out how less I know

This topic is closed to new replies.

Advertisement