Archived

This topic is now archived and is closed to further replies.

CRACK123

Frustum Culling

Recommended Posts

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

Share this post


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

Share this post


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

}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The uncredited code posted above by Raloth was written by Mark Morley. Please show some respect and give credit where it is due.

Share this post


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

Share this post


Link to post
Share on other sites